Skip to content

Commit 7ff0f34

Browse files
authored
Merge pull request #15016 from dotty-staging/fix-15000
Refine condition when to report errors in an inserted apply
2 parents ef59012 + cc2ecb7 commit 7ff0f34

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
@@ -3192,12 +3192,26 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
31923192
case _ => false
31933193
}
31943194

3195+
var assumeApplyExists = false
3196+
// if true, issue any errors about the apply instead of `fallBack`,
3197+
// since they are more likely to be informative.
3198+
31953199
def tryApply(using Context) = {
31963200
val pt1 = pt.withContext(ctx)
31973201
val sel = typedSelect(untpd.Select(untpd.TypedSplice(tree), nme.apply), pt1)
31983202
.withAttachment(InsertedApply, ())
3199-
if (sel.tpe.isError) sel
3200-
else try adapt(simplify(sel, pt1, locked), pt1, locked) finally sel.removeAttachment(InsertedApply)
3203+
if sel.tpe.isError then
3204+
// assume the apply exists if qualifier has a hidden search failure of type
3205+
// FailedExtension or NestedFailure
3206+
sel match
3207+
case Select(qual, _) =>
3208+
assumeApplyExists = qual.getAttachment(Typer.HiddenSearchFailure).exists(
3209+
_.exists(_.reason.isInstanceOf[FailedExtension | NestedFailure]))
3210+
case _ =>
3211+
sel
3212+
else
3213+
assumeApplyExists = true
3214+
try adapt(simplify(sel, pt1, locked), pt1, locked) finally sel.removeAttachment(InsertedApply)
32013215
}
32023216

32033217
def tryImplicit(fallBack: => Tree) =
@@ -3217,11 +3231,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
32173231
if (isApplyProto(pt) || isMethod(tree) || isSyntheticApply(tree)) tryImplicit(fallBack)
32183232
else tryEither(tryApply) { (app, appState) =>
32193233
tryImplicit {
3220-
if (tree.tpe.member(nme.apply).exists) {
3221-
// issue the error about the apply, since it is likely more informative than the fallback
3234+
if assumeApplyExists then
32223235
appState.commit()
32233236
app
3224-
}
32253237
else fallBack
32263238
}
32273239
}

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)