Skip to content

Commit 6909021

Browse files
committed
Improve error message for ambiguous extension methods
1 parent c710d81 commit 6909021

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -369,13 +369,16 @@ object Implicits {
369369
/** A "massaging" function for displayed types to give better info in error diagnostics */
370370
def clarify(tp: Type)(implicit ctx: Context): Type = tp
371371

372-
final protected def qualify(implicit ctx: Context): String =
373-
if (expectedType.exists)
374-
if (argument.isEmpty) em"match type ${clarify(expectedType)}"
375-
else em"convert from ${argument.tpe} to ${clarify(expectedType)}"
376-
else
372+
final protected def qualify(implicit ctx: Context): String = expectedType match {
373+
case SelectionProto(name, mproto, _, _) if !argument.isEmpty =>
374+
em"provide an extension method `$name` on ${argument.tpe}"
375+
case NoType =>
377376
if (argument.isEmpty) em"match expected type"
378377
else em"convert from ${argument.tpe} to expected type"
378+
case _ =>
379+
if (argument.isEmpty) em"match type ${clarify(expectedType)}"
380+
else em"convert from ${argument.tpe} to ${clarify(expectedType)}"
381+
}
379382

380383
/** An explanation of the cause of the failure as a string */
381384
def explanation(implicit ctx: Context): String
@@ -425,9 +428,12 @@ object Implicits {
425428
class AmbiguousImplicits(val alt1: SearchSuccess, val alt2: SearchSuccess, val expectedType: Type, val argument: Tree) extends SearchFailureType {
426429
def explanation(implicit ctx: Context): String =
427430
em"both ${err.refStr(alt1.ref)} and ${err.refStr(alt2.ref)} $qualify"
428-
override def whyNoConversion(implicit ctx: Context): String =
429-
"\nNote that implicit conversions cannot be applied because they are ambiguous;" +
430-
"\n" + explanation
431+
override def whyNoConversion(implicit ctx: Context): String = {
432+
val what = if (expectedType.isInstanceOf[SelectionProto]) "extension methods" else "conversions"
433+
i"""
434+
|Note that implicit $what cannot be applied because they are ambiguous;
435+
|$explanation"""
436+
}
431437
}
432438

433439
class MismatchedImplicit(ref: TermRef,

tests/neg/extmethod-overload.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
object Test {
2+
implied A {
3+
def (x: Int) |+| (y: Int) = x + y
4+
}
5+
implied B {
6+
def (x: Int) |+| (y: String) = x + y.length
7+
}
8+
assert((1 |+| 2) == 3) // error ambiguous
9+
10+
locally {
11+
import B.|+|
12+
assert((1 |+| "2") == 2) // OK
13+
}
14+
}

0 commit comments

Comments
 (0)