Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better error message for "implicit search must be more specific" #15747

Merged
merged 1 commit into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`