Skip to content

Commit 63605ca

Browse files
committed
Turn mismatch given errors into given not found errors for $conforms[Nothing] and <:<.refl[Nothing]
Fixes #8053 When a given candidate turns out to not be applicable we used to report that there is a mismatch between the candidate type and the expected type. The goal is to report an error as precise as possible to the user. However, in some cases showing the inferred candidate brings no value to the user, especially when the candidate is uninhabited. I’ve changed the failure to be a `NoMatchingImplicitsFailure` instead of a mismatch when `$conforms[Nothing]` or `<:<.refl` are inferred because these values are uninhabited and might be confusing for end users.
1 parent f3518f1 commit 63605ca

10 files changed

+54
-19
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ class Definitions {
390390
@tu lazy val Predef_undefined: Symbol = ScalaPredefModule.requiredMethod(nme.???)
391391

392392
def SubTypeClass(implicit ctx: Context): ClassSymbol = ctx.requiredClass("scala.<:<")
393+
@tu lazy val SubType_refl: Symbol = SubTypeClass.companionModule.requiredMethod(nme.refl)
393394

394395
def DummyImplicitClass(implicit ctx: Context): ClassSymbol = ctx.requiredClass("scala.DummyImplicit")
395396

compiler/src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ object StdNames {
549549
val productIterator: N = "productIterator"
550550
val productPrefix: N = "productPrefix"
551551
val raw_ : N = "raw"
552+
val refl: N = "refl"
552553
val reflect: N = "reflect"
553554
val reflectiveSelectable: N = "reflectiveSelectable"
554555
val reify : N = "reify"

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,11 +1407,15 @@ trait Implicits { self: Typer =>
14071407
}
14081408
if (ctx.reporter.hasErrors) {
14091409
ctx.reporter.removeBufferedMessages
1410-
SearchFailure {
1411-
adapted.tpe match {
1412-
case _: SearchFailureType => adapted
1413-
case _ => adapted.withType(new MismatchedImplicit(ref, pt, argument))
1414-
}
1410+
adapted.tpe match {
1411+
case _: SearchFailureType => SearchFailure(adapted)
1412+
case _ =>
1413+
// Special case for `$conforms` and `<:<.refl`. Showing them to the users brings
1414+
// no value, so we instead report a `NoMatchingImplicitsFailure`
1415+
if (adapted.symbol == defn.Predef_conforms || adapted.symbol == defn.SubType_refl)
1416+
NoMatchingImplicitsFailure
1417+
else
1418+
SearchFailure(adapted.withType(new MismatchedImplicit(ref, pt, argument)))
14151419
}
14161420
}
14171421
else {

tests/neg/implicitSearch.check

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-- Error: tests/neg/implicitSearch.scala:13:12 -------------------------------------------------------------------------
2+
13 | sort(xs) // error (with a partially constructed implicit argument shown)
3+
| ^
4+
| no implicit argument of type Test.Ord[List[List[T]]] was found for parameter o of method sort in object Test.
5+
| I found:
6+
|
7+
| Test.listOrd[T](Test.listOrd[T](/* missing */implicitly[Test.Ord[T]]))
8+
|
9+
| But no implicit values were found that match type Test.Ord[T].
10+
-- Error: tests/neg/implicitSearch.scala:15:38 -------------------------------------------------------------------------
11+
15 | listOrd(listOrd(implicitly[Ord[T]] /*not found*/)) // error
12+
| ^
13+
| no implicit argument of type Test.Ord[T] was found for parameter ev of method implicitly in object DottyPredef

tests/neg/implicitSearch.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
object Test {
22

3-
type T = String
4-
53
class Ord[T]
64
implicit def listOrd[T](implicit o: Ord[T]): Ord[List[T]] = ???
75
implicit def intOrd: Ord[Int] = ???

tests/neg/missing-implicit3.check

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- Error: tests/neg/missing-implicit3.scala:3:37 -----------------------------------------------------------------------
2+
3 |val sortedFoos = List(new Foo).sorted // error
3+
| ^
4+
| No implicit Ordering defined for B
5+
|
6+
| where: B is a type variable with constraint >: Foo
7+
| ..
8+
| I found:
9+
|
10+
| scala.math.Ordering.ordered[A](/* missing */implicitly[scala.math.Ordering.AsComparable[B]])
11+
|
12+
| But no implicit values were found that match type scala.math.Ordering.AsComparable[B].
13+
|
14+
| One of the following imports might make progress towards fixing the problem:
15+
|
16+
| import math.Ordering.comparatorToOrdering
17+
| import math.Ordering.ordered
18+
|

tests/neg/missing-implicit3.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Foo
2+
3+
val sortedFoos = List(new Foo).sorted // error

tests/neg/subtyping.check

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,8 @@
11
-- Error: tests/neg/subtyping.scala:8:27 -------------------------------------------------------------------------------
22
8 | implicitly[B#X <:< A#X] // error: no implicit argument
33
| ^
4-
| Cannot prove that B#X <:< A#X..
5-
| I found:
6-
|
7-
| <:<.refl[Nothing]
8-
|
9-
| But method refl in object <:< does not match type B#X <:< A#X.
4+
| Cannot prove that B#X <:< A#X.
105
-- Error: tests/neg/subtyping.scala:12:27 ------------------------------------------------------------------------------
116
12 | implicitly[a.T <:< a.U] // error: no implicit argument
127
| ^
13-
| Cannot prove that a.T <:< a.U..
14-
| I found:
15-
|
16-
| <:<.refl[Nothing]
17-
|
18-
| But method refl in object <:< does not match type a.T <:< a.U.
8+
| Cannot prove that a.T <:< a.U.

tests/neg/summon-function.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-- Error: tests/neg/summon-function.scala:2:23 -------------------------------------------------------------------------
2+
2 | summon[Int => String] // error
3+
| ^
4+
| No implicit view available from Int => String.

tests/neg/summon-function.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
object Test {
2+
summon[Int => String] // error
3+
}

0 commit comments

Comments
 (0)