Skip to content

Commit

Permalink
Merge pull request #15747 from dotty-staging/fix-check-conversion-spe…
Browse files Browse the repository at this point in the history
…cific

Better error message for "implicit search must be more specific"
  • Loading branch information
odersky authored Jul 26, 2022
2 parents 03da9dd + 37886e9 commit b1afa22
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 8 deletions.
6 changes: 0 additions & 6 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions tests/neg/i6336.check
Original file line number Diff line number Diff line change
@@ -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`

0 comments on commit b1afa22

Please sign in to comment.