diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index e3b35e6b7f73..7629776525a0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -721,12 +721,6 @@ object Checking { else "Cannot override non-inline parameter with an inline parameter", p1.srcPos) - def checkConversionsSpecific(to: Type, pos: SrcPos)(using Context): Unit = - if to.isRef(defn.AnyValClass, skipRefined = false) - || to.isRef(defn.ObjectClass, skipRefined = false) - then - report.error(em"the result of an implicit conversion must be more specific than $to", pos) - def checkValue(tree: Tree)(using Context): Unit = val sym = tree.tpe.termSymbol if sym.isNoValue && !ctx.isJava then diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 9a42babcd38e..e8e49071bf2b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -503,6 +503,14 @@ object Implicits: @sharable val ImplicitSearchTooLargeFailure: SearchFailure = SearchFailure(ImplicitSearchTooLarge, NoSpan)(using NoContext) + /** A failure value indicating that an implicit search for a conversion was not tried */ + class TooUnspecific(target: Type) extends NoMatchingImplicits(NoType, EmptyTree, OrderingConstraint.empty): + override def whyNoConversion(using Context): String = + i""" + |Note that implicit conversions were not tried because the result of an implicit conversion + |must be more specific than $target""" + override def toString = s"TooUnspecific" + /** An ambiguous implicits failure */ class AmbiguousImplicits(val alt1: SearchSuccess, val alt2: SearchSuccess, val expectedType: Type, val argument: Tree) extends SearchFailureType { def explanation(using Context): String = diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 06dc361b9952..2fac5f25d668 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3980,8 +3980,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer case None => tree else tree // other adaptations for selections are handled in typedSelect case _ if ctx.mode.is(Mode.ImplicitsEnabled) && tree.tpe.isValueType => - checkConversionsSpecific(pt, tree.srcPos) - inferView(tree, pt) match + if pt.isRef(defn.AnyValClass, skipRefined = false) + || pt.isRef(defn.ObjectClass, skipRefined = false) + then + recover(TooUnspecific(pt)) + else inferView(tree, pt) match case SearchSuccess(found, _, _, isExtension) => if isExtension then found else diff --git a/tests/neg/i6336.check b/tests/neg/i6336.check new file mode 100644 index 000000000000..a4afb885ec98 --- /dev/null +++ b/tests/neg/i6336.check @@ -0,0 +1,18 @@ +-- [E007] Type Mismatch Error: tests/neg/i6336.scala:2:18 -------------------------------------------------------------- +2 | val a: AnyVal = "foo" // error + | ^^^^^ + | Found: ("foo" : String) + | Required: AnyVal + | Note that implicit conversions were not tried because the result of an implicit conversion + | must be more specific than AnyVal + | + | longer explanation available when compiling with `-explain` +-- [E007] Type Mismatch Error: tests/neg/i6336.scala:3:18 -------------------------------------------------------------- +3 | val b: AnyRef = 1 // error + | ^ + | Found: (1 : Int) + | Required: AnyRef + | Note that implicit conversions were not tried because the result of an implicit conversion + | must be more specific than AnyRef + | + | longer explanation available when compiling with `-explain`