Skip to content

Commit 49c56c9

Browse files
committed
throw error
1 parent c90ad6b commit 49c56c9

File tree

4 files changed

+112
-17
lines changed

4 files changed

+112
-17
lines changed

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

Lines changed: 24 additions & 9 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,15 @@ trait Applications extends Compatibility {
19201926
else resolve(alts)
19211927
end resolveOverloaded
19221928

1929+
def isApplicableTerm(argTypes: List[Type], resultType: Type, argMatch: ArgMatch)(using Context): TermRef => Boolean =
1930+
onMethod(_, argTypes.nonEmpty):
1931+
isApplicableMethodRef(_, argTypes, resultType, argMatch)
1932+
1933+
def isApplicableTerm(argTypes: List[Tree], resultType: Type, keepConstraint: Boolean, argMatch: ArgMatch)(using Context): TermRef => Boolean =
1934+
onMethod(_, argTypes.nonEmpty):
1935+
isApplicableMethodRef(_, argTypes, resultType, keepConstraint, argMatch)
1936+
1937+
19231938
/** This private version of `resolveOverloaded` does the bulk of the work of
19241939
* overloading resolution, but does neither result adaptation nor apply insertion.
19251940
* It might be called twice from the public `resolveOverloaded` method, once with
@@ -1955,7 +1970,8 @@ trait Applications extends Compatibility {
19551970
}
19561971

19571972
def narrowByTypes(alts: List[TermRef], argTypes: List[Type], resultType: Type): List[TermRef] =
1958-
alts.filterConserve(isApplicableMethodRef(_, argTypes, resultType, ArgMatch.CompatibleCAP))
1973+
alts.filterConserve:
1974+
isApplicableTerm(argTypes, resultType, ArgMatch.CompatibleCAP)
19591975

19601976
/** Normalization steps before checking arguments:
19611977
*
@@ -2030,9 +2046,8 @@ trait Applications extends Compatibility {
20302046
alts
20312047

20322048
def narrowByTrees(alts: List[TermRef], args: List[Tree], resultType: Type): List[TermRef] =
2033-
alts.filterConserve(alt =>
2034-
isApplicableMethodRef(alt, args, resultType, keepConstraint = false, ArgMatch.CompatibleCAP)
2035-
)
2049+
alts.filterConserve:
2050+
isApplicableTerm(args, resultType, keepConstraint = false, ArgMatch.CompatibleCAP)
20362051

20372052
record("resolveOverloaded.FunProto", alts.length)
20382053
val alts1 = narrowBySize(alts)

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3673,8 +3673,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
36733673
/** Search for an alternative that does not take parameters.
36743674
* If there is one, return it, otherwise emit an error.
36753675
*/
3676-
def tryParameterless(alts: List[TermRef])(error: => tpd.Tree): Tree =
3677-
alts.filter(_.info.isParameterless) match
3676+
def noApplyNoParams: TermRef => Boolean =
3677+
alt => alt.info.isParameterless && !alt.info.member(nme.apply).exists
3678+
3679+
def tryNoApplyParameterless(alts: List[TermRef])(error: => tpd.Tree): Tree =
3680+
alts.filter(noApplyNoParams) match
36783681
case alt :: Nil => readaptSimplified(tree.withType(alt))
36793682
case _ =>
36803683
if altDenots.exists(_.info.paramInfoss == ListOfNil) then
@@ -3701,7 +3704,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
37013704
// insert apply or convert qualifier, but only for a regular application
37023705
tryInsertApplyOrImplicit(tree, pt, locked)(errorNoMatch)
37033706
case _ =>
3704-
tryParameterless(alts)(errorNoMatch)
3707+
tryNoApplyParameterless(alts)(errorNoMatch)
37053708

37063709
case ambiAlts =>
37073710
// If there are ambiguous alternatives, and:
@@ -3728,11 +3731,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
37283731
tree.withType(UnspecifiedErrorType)
37293732
else
37303733
pt match
3731-
case _: FunProto =>
3732-
errorAmbiguous
3733-
case _ =>
3734-
tryParameterless(alts)(errorAmbiguous)
3735-
3734+
case _: FunProto => errorAmbiguous
3735+
case _ => tryNoApplyParameterless(alts)(errorAmbiguous)
37363736
end match
37373737
end adaptOverloaded
37383738

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)