Skip to content

Commit 1e3cc5a

Browse files
committed
throw error
1 parent 8c311a0 commit 1e3cc5a

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
@@ -1518,13 +1518,20 @@ trait Applications extends Compatibility {
15181518
isApplicableMethodRef(_, args, resultType, ArgMatch.Compatible)
15191519
}
15201520

1521-
private def onMethod(tp: Type, followApply: Boolean)(p: TermRef => Boolean)(using Context): Boolean = tp match {
1521+
1522+
private def onMethod(tp: Type, followApply: Boolean)(p: TermRef => Boolean)(using Context): Boolean =
1523+
def hasApply: Boolean =
1524+
followApply && tp.member(nme.apply).hasAltWith(d => p(TermRef(tp, nme.apply, d)))
1525+
1526+
tp match {
1527+
case expr: TermRef if expr.widenSingleton.isInstanceOf[ExprType] =>
1528+
hasApply
15221529
case methRef: TermRef if methRef.widenSingleton.isInstanceOf[MethodicType] =>
15231530
p(methRef)
15241531
case mt: MethodicType =>
15251532
p(mt.narrow)
15261533
case _ =>
1527-
followApply && tp.member(nme.apply).hasAltWith(d => p(TermRef(tp, nme.apply, d)))
1534+
hasApply
15281535
}
15291536

15301537
/** Does `tp` have an extension method named `xname` with this-argument `argType` and
@@ -1661,7 +1668,7 @@ trait Applications extends Compatibility {
16611668
tp2.isVarArgsMethod
16621669
&& isApplicableMethodRef(alt2, tp1.paramInfos.map(_.repeatedToSingle), WildcardType, ArgMatch.Compatible)
16631670
else
1664-
isApplicableMethodRef(alt2, tp1.paramInfos, WildcardType, ArgMatch.Compatible)
1671+
isApplicableTerm(tp1.paramInfos, WildcardType, ArgMatch.Compatible)(alt2)
16651672
}
16661673
case tp1: PolyType => // (2)
16671674
inContext(ctx.fresh.setExploreTyperState()) {
@@ -1804,8 +1811,7 @@ trait Applications extends Compatibility {
18041811
def narrowMostSpecific(alts: List[TermRef])(using Context): List[TermRef] = {
18051812
record("narrowMostSpecific")
18061813
alts match {
1807-
case Nil => alts
1808-
case _ :: Nil => alts
1814+
case Nil | _ :: Nil => alts
18091815
case alt1 :: alt2 :: Nil =>
18101816
compare(alt1, alt2) match {
18111817
case 1 => alt1 :: Nil
@@ -1937,6 +1943,15 @@ trait Applications extends Compatibility {
19371943
else resolve(alts)
19381944
end resolveOverloaded
19391945

1946+
def isApplicableTerm(argTypes: List[Type], resultType: Type, argMatch: ArgMatch)(using Context): TermRef => Boolean =
1947+
onMethod(_, argTypes.nonEmpty):
1948+
isApplicableMethodRef(_, argTypes, resultType, argMatch)
1949+
1950+
def isApplicableTerm(argTypes: List[Tree], resultType: Type, keepConstraint: Boolean, argMatch: ArgMatch)(using Context): TermRef => Boolean =
1951+
onMethod(_, argTypes.nonEmpty):
1952+
isApplicableMethodRef(_, argTypes, resultType, keepConstraint, argMatch)
1953+
1954+
19401955
/** This private version of `resolveOverloaded` does the bulk of the work of
19411956
* overloading resolution, but does neither result adaptation nor apply insertion.
19421957
* It might be called twice from the public `resolveOverloaded` method, once with
@@ -1972,7 +1987,8 @@ trait Applications extends Compatibility {
19721987
}
19731988

19741989
def narrowByTypes(alts: List[TermRef], argTypes: List[Type], resultType: Type): List[TermRef] =
1975-
alts.filterConserve(isApplicableMethodRef(_, argTypes, resultType, ArgMatch.CompatibleCAP))
1990+
alts.filterConserve:
1991+
isApplicableTerm(argTypes, resultType, ArgMatch.CompatibleCAP)
19761992

19771993
/** Normalization steps before checking arguments:
19781994
*
@@ -2047,9 +2063,8 @@ trait Applications extends Compatibility {
20472063
alts
20482064

20492065
def narrowByTrees(alts: List[TermRef], args: List[Tree], resultType: Type): List[TermRef] =
2050-
alts.filterConserve(alt =>
2051-
isApplicableMethodRef(alt, args, resultType, keepConstraint = false, ArgMatch.CompatibleCAP)
2052-
)
2066+
alts.filterConserve:
2067+
isApplicableTerm(args, resultType, keepConstraint = false, ArgMatch.CompatibleCAP)
20532068

20542069
record("resolveOverloaded.FunProto", alts.length)
20552070
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
@@ -3684,8 +3684,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
36843684
/** Search for an alternative that does not take parameters.
36853685
* If there is one, return it, otherwise emit an error.
36863686
*/
3687-
def tryParameterless(alts: List[TermRef])(error: => tpd.Tree): Tree =
3688-
alts.filter(_.info.isParameterless) match
3687+
def noApplyNoParams: TermRef => Boolean =
3688+
alt => alt.info.isParameterless && !alt.info.member(nme.apply).exists
3689+
3690+
def tryNoApplyParameterless(alts: List[TermRef])(error: => tpd.Tree): Tree =
3691+
alts.filter(noApplyNoParams) match
36893692
case alt :: Nil => readaptSimplified(tree.withType(alt))
36903693
case _ =>
36913694
if altDenots.exists(_.info.paramInfoss == ListOfNil) then
@@ -3712,7 +3715,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
37123715
// insert apply or convert qualifier, but only for a regular application
37133716
tryInsertApplyOrImplicit(tree, pt, locked)(errorNoMatch)
37143717
case _ =>
3715-
tryParameterless(alts)(errorNoMatch)
3718+
tryNoApplyParameterless(alts)(errorNoMatch)
37163719

37173720
case ambiAlts =>
37183721
// If there are ambiguous alternatives, and:
@@ -3739,11 +3742,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
37393742
tree.withType(UnspecifiedErrorType)
37403743
else
37413744
pt match
3742-
case _: FunProto =>
3743-
errorAmbiguous
3744-
case _ =>
3745-
tryParameterless(alts)(errorAmbiguous)
3746-
3745+
case _: FunProto => errorAmbiguous
3746+
case _ => tryNoApplyParameterless(alts)(errorAmbiguous)
37473747
end match
37483748
end adaptOverloaded
37493749

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)