Skip to content

Commit b6b51a3

Browse files
committed
found bug
throw ambiguous error error case fixes fixed overload recovering
1 parent c90ad6b commit b6b51a3

File tree

4 files changed

+104
-11
lines changed

4 files changed

+104
-11
lines changed

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

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,13 +1501,20 @@ trait Applications extends Compatibility {
15011501
isApplicableMethodRef(_, args, resultType, ArgMatch.Compatible)
15021502
}
15031503

1504-
private def onMethod(tp: Type, followApply: Boolean)(p: TermRef => Boolean)(using Context): Boolean = tp match {
1504+
1505+
private def onMethod(tp: Type, followApply: Boolean)(p: TermRef => Boolean)(using Context): Boolean =
1506+
def hasApply: Boolean =
1507+
followApply && tp.member(nme.apply).hasAltWith(d => p(TermRef(tp, nme.apply, d)))
1508+
1509+
tp match {
1510+
case expr: TermRef if expr.widenSingleton.isInstanceOf[ExprType] =>
1511+
hasApply
15051512
case methRef: TermRef if methRef.widenSingleton.isInstanceOf[MethodicType] =>
15061513
p(methRef)
15071514
case mt: MethodicType =>
15081515
p(mt.narrow)
15091516
case _ =>
1510-
followApply && tp.member(nme.apply).hasAltWith(d => p(TermRef(tp, nme.apply, d)))
1517+
hasApply
15111518
}
15121519

15131520
/** Does `tp` have an extension method named `xname` with this-argument `argType` and
@@ -1644,7 +1651,7 @@ trait Applications extends Compatibility {
16441651
tp2.isVarArgsMethod
16451652
&& isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType, ArgMatch.Compatible)
16461653
else
1647-
isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType, ArgMatch.Compatible)
1654+
isApplicableTerm(tp1.paramInfos, WildcardType, ArgMatch.Compatible)(alt2)
16481655
}
16491656
case tp1: PolyType => // (2)
16501657
inContext(ctx.fresh.setExploreTyperState()) {
@@ -1787,8 +1794,7 @@ trait Applications extends Compatibility {
17871794
def narrowMostSpecific(alts: List[TermRef])(using Context): List[TermRef] = {
17881795
record("narrowMostSpecific")
17891796
alts match {
1790-
case Nil => alts
1791-
case _ :: Nil => alts
1797+
case Nil | _ :: Nil => alts
17921798
case alt1 :: alt2 :: Nil =>
17931799
compare(alt1, alt2) match {
17941800
case 1 => alt1 :: Nil
@@ -1920,6 +1926,13 @@ trait Applications extends Compatibility {
19201926
else resolve(alts)
19211927
end resolveOverloaded
19221928

1929+
def isApplicableTerm(argTypes: List[Type], resultType: Type, argMatch: ArgMatch = ArgMatch.CompatibleCAP)(using Context) : TermRef => Boolean = {
1930+
case expr: TermRef if expr.widenSingleton.isInstanceOf[ExprType | AppliedType] =>
1931+
isApplicableType(expr, argTypes, resultType)
1932+
case alt =>
1933+
isApplicableMethodRef(alt, argTypes, resultType, argMatch)
1934+
}
1935+
19231936
/** This private version of `resolveOverloaded` does the bulk of the work of
19241937
* overloading resolution, but does neither result adaptation nor apply insertion.
19251938
* It might be called twice from the public `resolveOverloaded` method, once with
@@ -1955,7 +1968,7 @@ trait Applications extends Compatibility {
19551968
}
19561969

19571970
def narrowByTypes(alts: List[TermRef], argTypes: List[Type], resultType: Type): List[TermRef] =
1958-
alts.filterConserve(isApplicableMethodRef(_, argTypes, resultType, ArgMatch.CompatibleCAP))
1971+
alts.filterConserve { isApplicableTerm(argTypes, resultType) }
19591972

19601973
/** Normalization steps before checking arguments:
19611974
*

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3727,11 +3727,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
37273727
if tree.tpe.isErroneous || pt.isErroneous then
37283728
tree.withType(UnspecifiedErrorType)
37293729
else
3730-
pt match
3731-
case _: FunProto =>
3732-
errorAmbiguous
3733-
case _ =>
3734-
tryParameterless(alts)(errorAmbiguous)
3730+
alts.map(_.widen) match {
3731+
case List(_: AppliedType, _: MethodType) | List(_: MethodType, _: AppliedType) => errorAmbiguous
3732+
case List(ExprType(_: AppliedType), _: MethodType) | List(_: MethodType, ExprType(_: AppliedType)) => errorAmbiguous
3733+
case _ => tryParameterless(alts)(errorAmbiguous)
3734+
}
37353735

37363736
end match
37373737
end adaptOverloaded

tests/neg/i18294.check

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
-- [E051] Reference Error: tests/neg/i18294.scala:18:30 ----------------------------------------------------------------
2+
18 | val test01: Int => String = f1 // error
3+
| ^^
4+
| Ambiguous overload. The overloaded alternatives of method f1 with types
5+
| => Int => String
6+
| (s: Int): String
7+
| both match expected type Int => String
8+
|
9+
| longer explanation available when compiling with `-explain`
10+
-- [E051] Reference Error: tests/neg/i18294.scala:19:30 ----------------------------------------------------------------
11+
19 | val test02: Int => String = f2 // error
12+
| ^^
13+
| Ambiguous overload. The overloaded alternatives of value f2 with types
14+
| Int => String
15+
| (s: Int): String
16+
| both match expected type Int => String
17+
|
18+
| longer explanation available when compiling with `-explain`
19+
-- [E051] Reference Error: tests/neg/i18294.scala:22:36 ----------------------------------------------------------------
20+
22 | val test1: Int => String = DefDef.f4 // error
21+
| ^^^^^^^^^
22+
| Ambiguous overload. The overloaded alternatives of method f4 in object DefDef with types
23+
| => Int => String
24+
| (s: Int): String
25+
| both match expected type Int => String
26+
|
27+
| longer explanation available when compiling with `-explain`
28+
-- [E051] Reference Error: tests/neg/i18294.scala:23:37 ----------------------------------------------------------------
29+
23 | def dtest1: Int => String = DefDef.f4 // error
30+
| ^^^^^^^^^
31+
| Ambiguous overload. The overloaded alternatives of method f4 in object DefDef with types
32+
| => Int => String
33+
| (s: Int): String
34+
| both match expected type Int => String
35+
|
36+
| longer explanation available when compiling with `-explain`
37+
-- [E051] Reference Error: tests/neg/i18294.scala:25:36 ----------------------------------------------------------------
38+
25 | val test2: Int => String = DefVal.f5 // error
39+
| ^^^^^^^^^
40+
| Ambiguous overload. The overloaded alternatives of value f5 in object DefVal with types
41+
| Int => String
42+
| (s: Int): String
43+
| both match expected type Int => String
44+
|
45+
| longer explanation available when compiling with `-explain`
46+
-- [E051] Reference Error: tests/neg/i18294.scala:26:37 ----------------------------------------------------------------
47+
26 | def dtest2: Int => String = DefVal.f5 // error
48+
| ^^^^^^^^^
49+
| Ambiguous overload. The overloaded alternatives of value f5 in object DefVal with types
50+
| Int => String
51+
| (s: Int): String
52+
| both match expected type Int => String
53+
|
54+
| longer explanation available when compiling with `-explain`

tests/neg/i18294.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
def f1(s: Int): String = "a"
2+
def f1: Int => String = _ => "b"
3+
4+
def f2(s: Int): String = "a"
5+
val f2: Int => String = _ => "b"
6+
7+
def f3(s: Int): String = "a"
8+
def f3(): Int => String = _ => "b"
9+
10+
object DefDef:
11+
def f4(s: Int): String = "a"
12+
def f4: Int => String = _ => "b"
13+
object DefVal:
14+
def f5(s: Int): String = "a"
15+
val f5: Int => String = _ => "b"
16+
17+
@main def Test =
18+
val test01: Int => String = f1 // error
19+
val test02: Int => String = f2 // error
20+
val test03: Int => String = f3
21+
22+
val test1: Int => String = DefDef.f4 // error
23+
def dtest1: Int => String = DefDef.f4 // error
24+
25+
val test2: Int => String = DefVal.f5 // error
26+
def dtest2: Int => String = DefVal.f5 // error

0 commit comments

Comments
 (0)