IDK, but I’ve had a few guesses in the last several minutes.
Maybe it’s because Scala 3 looks at multiple parameter lists in overloading resolution, in order to support extension methods. The doc doesn’t say so, but maybe that includes implicit parameter lists.
Scala 2 only looks at the first parameter list, but that’s after an “applicability” test in which a second implicit parameter list would not disqualify a candidate.
My first thought was more clever: Probably the difference is in type inference described at the bottom here, about inferring the type of a function-valued parameter. Recall that
Int =:= T is just
Int => T. You changed the result type of
A[Int], so I guess the presence of
T helped Scala 2 because the expected type (from
A[Int]. That hypothesis is wrong, so it should have a
* in front of it.
Here is the difference in overloading, which shows the same result without type params.
def f[T](implicit ev: Int =:= T): A[T] = A(1)
val f: A[Int] = A(2)
def g: A[Int] = f
def f2[T](implicit ev: Int =:= T): A[Int] = A(1)
val f2: A[Int] = A(2)
def g2: A[Int] = f2 // scala 2 doesn't know what you mean
T, only Scala 2 takes this as ambiguous, and only if the param is implicit.
def f3()(implicit s: String): A[Int] = A(1)
def f3(): A[Int] = A(2)
def g3: A[Int] = f3()
But isn’t that obviously ambiguous? in so far as
f3() could mean either declaration. But in Scala 3, we only compare the signatures of the eligible members, which now includes all parameter lists.