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].