forked from scala/scala
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Downwards comparisons for implicit search and overloading resolution
This is a backport of the following Dotty change to scalac, scala/scala3@8954026 As in the Dotty implementation the specificity comparison which is used for overload resolution and implicit selection is now performed as-if all contravariant positions in top level type constructors were covariant. Currently this breaks test/files/run/t2030.scala in exactly the same way as in Dotty as reported here, scala/scala3#1246 (comment) and in this PR it has been changed to a neg test. However, test/files/run/t2030.scala passes when this PR is combined with, scala#6139 so if/when that is merged it can be switched back to a pos test. Fixes scala/bug#2509. Fixes scala/bug#7768.
- Loading branch information
1 parent
8741bd9
commit 0407d6a
Showing
18 changed files
with
416 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
t2030.scala:5: error: ambiguous implicit values: | ||
both method newCanBuildFrom in object SortedSet of type [A](implicit ord: Ordering[A])scala.collection.generic.CanBuildFrom[scala.collection.immutable.SortedSet.Coll,A,scala.collection.immutable.SortedSet[A]] | ||
and method newCanBuildFrom in class SortedSetFactory of type [A](implicit ord: Ordering[A])scala.collection.generic.CanBuildFrom[scala.collection.immutable.TreeSet.Coll,A,scala.collection.immutable.TreeSet[A]] | ||
match expected type scala.collection.generic.CanBuildFrom[scala.collection.immutable.TreeSet[Int],Int,That] | ||
val res1 = res0.map(x => x) | ||
^ | ||
one error found |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
t2509-2.scala:26: error: ambiguous implicit values: | ||
both value xb in object Test of type => X[B,Int] | ||
and value xa in object Test of type => X[A,Boolean] | ||
match expected type X[B,U] | ||
val fb = f(new B) | ||
^ | ||
one error found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
class A | ||
class B extends A | ||
class C extends B | ||
|
||
trait X[-T, U] { | ||
val u: U | ||
} | ||
|
||
object XA extends X[A, Boolean] { | ||
val u = true | ||
} | ||
|
||
object XB extends X[B, Int] { | ||
val u = 23 | ||
} | ||
|
||
object Test { | ||
implicit def f[T, U](t: T)(implicit x: X[T, U]): U = x.u | ||
implicit val xa: X[A, Boolean] = XA | ||
implicit val xb: X[B, Int] = XB | ||
|
||
val fa = f(new A) | ||
val ffa: Boolean = fa | ||
|
||
// Should be ambiguous | ||
val fb = f(new B) | ||
val ffb: Int = fb | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
t2509-3.scala:31: error: value value is not a member of B | ||
println("B: " + b.value) | ||
^ | ||
one error found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
class A | ||
class B extends A | ||
|
||
trait Y { | ||
def value: String | ||
} | ||
|
||
trait X[-T] { | ||
def y(t: T): Y | ||
} | ||
|
||
trait Z[-T] extends X[T] | ||
|
||
object ZA extends Z[A] { | ||
def y(a: A) = new Y { def value = a.getClass + ": AValue" } | ||
} | ||
|
||
object XB extends X[B] { | ||
def y(b: B) = new Y { def value = b.getClass + ": BValue" } | ||
} | ||
|
||
object Test { | ||
implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) | ||
implicit val za: Z[A] = ZA | ||
implicit val xb: X[B] = XB | ||
|
||
def main(argv: Array[String]): Unit = { | ||
val a = new A | ||
val b = new B | ||
println("A: " + a.value) | ||
println("B: " + b.value) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
t2509-4.scala:31: error: value value is not a member of B | ||
println("B: " + b.value) | ||
^ | ||
one error found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// See https://github.com/lampepfl/dotty/issues/2974 | ||
trait Foo[-T] | ||
|
||
trait Bar[-T] extends Foo[T] | ||
|
||
object Test { | ||
implicit val fa: Foo[Any] = ??? | ||
implicit val ba: Bar[Int] = ??? | ||
|
||
def test: Unit = { | ||
implicitly[Foo[Int]] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
class A | ||
class B extends A | ||
|
||
trait Y { | ||
def value: String | ||
} | ||
|
||
trait X[-T] { | ||
def y(t: T): Y | ||
} | ||
|
||
trait Z[-T] extends X[T] | ||
|
||
object XA extends X[A] { | ||
def y(a: A) = new Y { def value = a.getClass + ": AValue" } | ||
} | ||
|
||
object ZB extends Z[B] { | ||
def y(b: B) = new Y { def value = b.getClass + ": BValue" } | ||
} | ||
|
||
object Test { | ||
implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) | ||
implicit val za: X[A] = XA | ||
implicit val xb: Z[B] = ZB | ||
|
||
def main(argv: Array[String]): Unit = { | ||
val a = new A | ||
val b = new B | ||
println("A: " + a.value) | ||
println("B: " + b.value) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
warning: there was one feature warning; re-run with -feature for details | ||
A: class A: AValue | ||
B: class B: BValue |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
class A | ||
class B extends A | ||
|
||
trait Y { | ||
def value: String | ||
} | ||
|
||
trait X[-T] { | ||
def y(t: T): Y | ||
} | ||
|
||
object XA extends X[A] { | ||
def y(a: A) = new Y { def value = a.getClass + ": AValue" } | ||
} | ||
|
||
object XB extends X[B] { | ||
def y(b: B) = new Y { def value = b.getClass + ": BValue" } | ||
} | ||
|
||
object Test { | ||
implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) | ||
implicit val xa: X[A] = XA | ||
implicit val xb: X[B] = XB | ||
|
||
def main(argv: Array[String]) { | ||
val a = new A | ||
val b = new B | ||
println("A: " + a.value) | ||
println("B: " + b.value) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
warning: there was one feature warning; re-run with -feature for details | ||
A: class A: AValue | ||
B: class B: BValue |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
class A | ||
class B extends A | ||
|
||
trait Y { | ||
def value: String | ||
} | ||
|
||
trait X[-T] { | ||
def y(t: T): Y | ||
} | ||
|
||
trait Z[-T] extends X[T] | ||
|
||
object XA extends Z[A] { | ||
def y(a: A) = new Y { def value = a.getClass + ": AValue" } | ||
} | ||
|
||
object ZB extends Z[B] { | ||
def y(b: B) = new Y { def value = b.getClass + ": BValue" } | ||
} | ||
|
||
object Test { | ||
implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t) | ||
implicit val za: X[A] = XA | ||
implicit val xb: Z[B] = ZB | ||
|
||
def main(argv: Array[String]): Unit = { | ||
val a = new A | ||
val b = new B | ||
println("A: " + a.value) | ||
println("B: " + b.value) | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Inv[A] Inv[B] Inv[C] Inv[D] Inv[E] | ||
Con[A] Con[A] Con[C] Con[C] Con[E] | ||
Cov[E] Cov[E] Cov[E] Cov[E] Cov[E] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
class A | ||
class B extends A | ||
class C extends B | ||
class D extends C | ||
class E extends D | ||
|
||
class Inv[T](override val toString: String) | ||
class Con[-T](override val toString: String) | ||
class Cov[+T](override val toString: String) | ||
|
||
object InvTest { | ||
implicit val a : Inv[A] = new Inv[A]("Inv[A]") | ||
implicit val b : Inv[B] = new Inv[B]("Inv[B]") | ||
implicit val c : Inv[C] = new Inv[C]("Inv[C]") | ||
implicit val d : Inv[D] = new Inv[D]("Inv[D]") | ||
implicit val e : Inv[E] = new Inv[E]("Inv[E]") | ||
} | ||
object ConTest { | ||
implicit val a : Con[A] = new Con[A]("Con[A]") | ||
implicit val c : Con[C] = new Con[C]("Con[C]") | ||
implicit val e : Con[E] = new Con[E]("Con[E]") | ||
} | ||
object CovTest { | ||
implicit val a : Cov[A] = new Cov[A]("Cov[A]") | ||
implicit val c : Cov[C] = new Cov[C]("Cov[C]") | ||
implicit val e : Cov[E] = new Cov[E]("Cov[E]") | ||
} | ||
|
||
object Test { | ||
def f0(): Unit = { | ||
import InvTest._ | ||
println(List( | ||
implicitly[Inv[A]], | ||
implicitly[Inv[B]], | ||
implicitly[Inv[C]], | ||
implicitly[Inv[D]], | ||
implicitly[Inv[E]] | ||
) mkString " ") | ||
} | ||
def f1(): Unit = { | ||
import ConTest._ | ||
println(List( | ||
implicitly[Con[A]], | ||
implicitly[Con[B]], | ||
implicitly[Con[C]], | ||
implicitly[Con[D]], | ||
implicitly[Con[E]] | ||
) mkString " ") | ||
} | ||
def f2(): Unit = { | ||
import CovTest._ | ||
println(List( | ||
implicitly[Cov[A]], | ||
implicitly[Cov[B]], | ||
implicitly[Cov[C]], | ||
implicitly[Cov[D]], | ||
implicitly[Cov[E]] | ||
) mkString " ") | ||
} | ||
|
||
def main(args: Array[String]): Unit = { | ||
f0() | ||
f1() | ||
f2() | ||
} | ||
} | ||
|
||
/*** | ||
Previously: | ||
Inv[A] Inv[B] Inv[C] Inv[D] Inv[E] | ||
Con[A] Con[A] Con[A] Con[A] Con[A] | ||
Cov[E] Cov[E] Cov[E] Cov[E] Cov[E] | ||
Currently (and in Dotty): | ||
Inv[A] Inv[B] Inv[C] Inv[D] Inv[E] | ||
Con[A] Con[A] Con[C] Con[C] Con[E] | ||
Cov[E] Cov[E] Cov[E] Cov[E] Cov[E] | ||
Note that @paulp thinks that f2 should produce, | ||
Cov[A] Cov[C] Cov[C] Cov[E] Cov[E] | ||
I don't think that behaviour would be desirable: in the covariant case the | ||
expectation that the most derived should be selected as the most specific | ||
seems reasonable. | ||
***/ |
Oops, something went wrong.