Multiversal Equality by odersky · Pull Request #1246 · scala/scala3 (original) (raw)
There was one test that failed under new rules: run/t2030.scala. It was moved to pos-scala2.
The two possible implicits are scala.collection.immutable.SortedSet.newCanBuildFrom
and scala.collection.immutable.TreeSet.newCanBuildFrom
, previously the first one was chosen, but now they're ambiguous. I was curious about what was going on here so I minimized it and explained it, this could be added as a testcase:
// Minimized from t2030.scala
class Both[-A, +B]
trait Factory[A] { implicit def make: Both[A, A] = new Both[A, A] }
trait X object X extends Factory[X] { override implicit def make: Both[X, X] = super.make }
class Y extends X object Y extends Factory[Y] { // override implicit def make: Both[Y, Y] = super.make }
object Test { def get(implicit ev: Both[Y, X]) = ev
// There are two possible implicits here: X.make and Y.make, neither are
// subtype of each other, so who wins?
// - Under the old scheme it's X.make because isAsGood
sees that X.make is defined
// in X whereas Y.make is defined in Factory
// - Under the new scheme it's ambiguous because we replace contravariance by covariance
// in top-level type parameters so Y.make is treated as a subtype of X.make
// In both schemes we can get Y.make to win by uncommenting the override for make in Y
// (Y wins against X because isDerived
also considers the subtyping relationships
// of companion classes)
get
}
This means that we can fix the issue in the standard library by adding an override of newCanBuildFrom
in TreeSet
, as a bonus this means that res1
in t2030.scala
gets the inferred type TreeSet[Int]
instead of SortedSet[Int]
.