Skip to content

Commit cc2ecb7

Browse files
committed
Refine condition when to report errors in an inserted apply
Fixes #15000
1 parent 0040417 commit cc2ecb7

File tree

3 files changed

+62
-5
lines changed

3 files changed

+62
-5
lines changed

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3184,12 +3184,26 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
31843184
case _ => false
31853185
}
31863186

3187+
var assumeApplyExists = false
3188+
// if true, issue any errors about the apply instead of `fallBack`,
3189+
// since they are more likely to be informative.
3190+
31873191
def tryApply(using Context) = {
31883192
val pt1 = pt.withContext(ctx)
31893193
val sel = typedSelect(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt1)
31903194
.withAttachment(InsertedApply, ())
3191-
if (sel.tpe.isError) sel
3192-
else try adapt(simplify(sel, pt1, locked), pt1, locked) finally sel.removeAttachment(InsertedApply)
3195+
if sel.tpe.isError then
3196+
// assume the apply exists if qualifier has a hidden search failure of type
3197+
// FailedExtension or NestedFailure
3198+
sel match
3199+
case Select(qual, _) =>
3200+
assumeApplyExists = qual.getAttachment(Typer.HiddenSearchFailure).exists(
3201+
_.exists(_.reason.isInstanceOf[FailedExtension | NestedFailure]))
3202+
case _ =>
3203+
sel
3204+
else
3205+
assumeApplyExists = true
3206+
try adapt(simplify(sel, pt1, locked), pt1, locked) finally sel.removeAttachment(InsertedApply)
31933207
}
31943208

31953209
def tryImplicit(fallBack: => Tree) =
@@ -3209,11 +3223,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
32093223
if (isApplyProto(pt) || isMethod(tree) || isSyntheticApply(tree)) tryImplicit(fallBack)
32103224
else tryEither(tryApply) { (app, appState) =>
32113225
tryImplicit {
3212-
if (tree.tpe.member(nme.apply).exists) {
3213-
// issue the error about the apply, since it is likely more informative than the fallback
3226+
if assumeApplyExists then
32143227
appState.commit()
32153228
app
3216-
}
32173229
else fallBack
32183230
}
32193231
}

tests/neg/i15000.check

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
-- [E006] Not Found Error: tests/neg/i15000.scala:19:11 ----------------------------------------------------------------
2+
19 | str(x, barY) // error
3+
| ^^^^
4+
| Not found: barY
5+
|
6+
| longer explanation available when compiling with `-explain`
7+
-- [E006] Not Found Error: tests/neg/i15000.scala:20:9 -----------------------------------------------------------------
8+
20 | c(x, barY) // error // error
9+
| ^^^^
10+
| Not found: barY
11+
|
12+
| longer explanation available when compiling with `-explain`
13+
-- [E008] Not Found Error: tests/neg/i15000.scala:20:4 -----------------------------------------------------------------
14+
20 | c(x, barY) // error // error
15+
| ^
16+
|value apply is not a member of object ExtensionMethodReproduction.c.
17+
|An extension method was tried, but could not be fully constructed:
18+
|
19+
| apply(ExtensionMethodReproduction.c) failed with
20+
|
21+
| Ambiguous overload. The overloaded alternatives of method apply in object ExtensionMethodReproduction with types
22+
| (c: ExtensionMethodReproduction.C)(x: Int, y: Int): String
23+
| (c: ExtensionMethodReproduction.C)(x: Int, y: String): String
24+
| both match arguments (ExtensionMethodReproduction.c.type)

tests/neg/i15000.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
object ExtensionMethodReproduction {
2+
import scala.language.implicitConversions
3+
class StringExtensions {
4+
def apply(x: Int, y: String): String = "foo"
5+
def apply(x: Int, y: Int): String = "foo"
6+
}
7+
implicit def stringExtensions(m: String): StringExtensions = new StringExtensions()
8+
9+
class C
10+
object c extends C
11+
12+
extension (c: C)
13+
def apply(x: Int, y: String): String = "foo"
14+
def apply(x: Int, y: Int): String = "foo"
15+
16+
val str = "POST"
17+
val x: Int = 1
18+
val fooY: String = "foo"
19+
str(x, barY) // error
20+
c(x, barY) // error // error
21+
}

0 commit comments

Comments
 (0)