scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
232 stars 21 forks source link

Misleading error message due to same signature definitions #11929

Open soronpo opened 4 years ago

soronpo commented 4 years ago

reproduction steps

Use the following code:

  trait TwoFaceInt[T] {
    type Out = T
  }
  object TwoFaceInt {
    def apply[T <: Int with Singleton](implicit value : T) : TwoFaceInt[T] = ???
    implicit def apply[T <: Int with Singleton](value : T) : TwoFaceInt[T] = ???
  }
  trait Fooish[T]
  class Foo {
    final def foo : Fooish[4] = ???
    final def foo[T](value : TwoFaceInt[T]) : Fooish[value.Out] = ???
  }
  val a = new Foo
  val b : Fooish[2] = a.foo(2)

problem

The error generated is very misleading:

Error: overloaded method value fooy with alternatives:
  [T](value: TwoFaceInt[T])Fooish[value.Out] <and>
  => Fooish[2]
 cannot be applied to (Int)
  val b : Fooish[2] = a.fooy(2)

It should be noted that if we remove final def foo : Fooish[4] = ???, no error would have been generated.

expectation

The actual source of the problem is that inside TwoFaceInt the two methods have the same signature. In dotty we get an error as expected:

Double definition:
def apply: [T <: Int & Singleton](implicit value: T): TwoFaceInt[T] in object TwoFaceInt at line 10 and
implicit def apply: [T <: Int & Singleton](value: T): TwoFaceInt[T] in object TwoFaceInt at line 11
have the same type after erasure.
som-snytt commented 4 years ago

-Vimplicits says:

t11929.scala:15: TwoFaceInt.<apply: error> is not a valid implicit value for 2 => TwoFaceInt[?T] because:
ambiguous reference to overloaded definition,
both method apply in object TwoFaceInt of type [T <: Int with Singleton](value: T)TwoFaceInt[T]
and  method apply in object TwoFaceInt of type [T <: Int with Singleton](implicit value: T)TwoFaceInt[T]
match argument types (Int) and expected result type TwoFaceInt[?T]
  val b : Fooish[2] = a.foo(2.asInstanceOf[2])
      ^
t11929.scala:15: TwoFaceInt.<apply: error> is not a valid implicit value for (=> 2) => TwoFaceInt[?T] because:
ambiguous reference to overloaded definition,
both method apply in object TwoFaceInt of type [T <: Int with Singleton](value: T)TwoFaceInt[T]
and  method apply in object TwoFaceInt of type [T <: Int with Singleton](implicit value: T)TwoFaceInt[T]
match argument types (Int) and expected result type TwoFaceInt[?T]
  val b : Fooish[2] = a.foo(2.asInstanceOf[2])
      ^
t11929.scala:15: error: overloaded method value foo with alternatives:
  [T](value: TwoFaceInt[T])Fooish[value.Out] <and>
  => Fooish[4]
 cannot be applied to (Int)
  val b : Fooish[2] = a.foo(2.asInstanceOf[2])
                        ^
one error found

It will plow through that:

trait Helper
object Helper {
  implicit def helper[T <: Int with Singleton with Helper](value : T) : TwoFaceInt[T] = ???
}
object Test extends App {
  val a = new Foo
  val b : Fooish[2 with Helper] = a.foo(2.asInstanceOf[2 with Helper])
}

then

t11929.scala:6: error: double definition:
def apply[T <: Int with Singleton](implicit value: T): TwoFaceInt[T] at line 5 and
implicit def apply[T <: Int with Singleton](value: T): TwoFaceInt[T] at line 6
have same type after erasure: (value: Int)TwoFaceInt
  implicit def apply[T <: Int with Singleton](value : T) : TwoFaceInt[T] = ???
               ^
one error found