Skip to content

Commit 065cf0b

Browse files
committed
WIP fix for overloading resolution
1 parent cdb6250 commit 065cf0b

File tree

5 files changed

+89
-10
lines changed

5 files changed

+89
-10
lines changed

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

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,15 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
12931293
val formals1 =
12941294
if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramInfos.map(_.repeatedToSingle)
12951295
else tp1.paramInfos
1296-
isApplicable(alt2, formals1, WildcardType) ||
1296+
1297+
class IsAsSpecific(methRef: TermRef, args: List[Type], resultType: Type)(implicit ctx: Context)
1298+
extends ApplicableToTypes(methRef, args, resultType) {
1299+
override def argOK(arg: TypedArg, formal: Type): Boolean =
1300+
// simulate X* not being in subtyping relationship with any other type
1301+
!(arg.isRepeatedParam || formal.isRepeatedParam) && super.argOK(arg, formal)
1302+
}
1303+
1304+
ctx.test(ctx => new IsAsSpecific(alt2, formals1, WildcardType)(ctx).success) ||
12971305
tp1.paramInfos.isEmpty && tp2.isInstanceOf[LambdaType]
12981306
case tp1: PolyType => // (2)
12991307
val nestedCtx = ctx.fresh.setExploreTyperState()
@@ -1420,24 +1428,45 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
14201428
if (winsType1 || !winsType2) 1 else 0
14211429
else if (ownerScore == -1)
14221430
if (winsType2 || !winsType1) -1 else 0
1423-
else if (winsType1)
1431+
else if (winsType1)
14241432
if (winsType2) 0 else 1
14251433
else
14261434
if (winsType2) -1 else 0
14271435
}
14281436

1429-
val fullType1 = widenImplied(alt1.widen, alt1)
1430-
val fullType2 = widenImplied(alt2.widen, alt2)
1437+
def paramInfos(tp: Type): List[Type] = tp.stripPoly match {
1438+
case mt: MethodType => mt.paramInfos
1439+
case _ => Nil
1440+
}
1441+
1442+
@annotation.tailrec def lengthCompare(xs: List[_], ys: List[_]): Int = (xs, ys) match {
1443+
case (_ :: xs, _ :: ys) => lengthCompare(xs, ys)
1444+
case (Nil, Nil) => 0
1445+
case (_, Nil) => 1
1446+
case (Nil, _) => -1
1447+
}
1448+
1449+
val wideAlt1 = alt1.widen
1450+
val wideAlt2 = alt2.widen
1451+
val fullType1 = widenImplied(wideAlt1, alt1)
1452+
val fullType2 = widenImplied(wideAlt2, alt2)
14311453
val strippedType1 = stripImplicit(fullType1)
14321454
val strippedType2 = stripImplicit(fullType2)
14331455

14341456
val result = compareWithTypes(strippedType1, strippedType2)
1435-
if (result != 0) result
1436-
else if (strippedType1 eq fullType1)
1437-
if (strippedType2 eq fullType2) 0 // no implicits either side: its' a draw
1438-
else 1 // prefer 1st alternative with no implicits
1439-
else if (strippedType2 eq fullType2) -1 // prefer 2nd alternative with no implicits
1440-
else compareWithTypes(fullType1, fullType2) // continue by comparing implicits parameters
1457+
if (result != 0) result else {
1458+
val varArgLengthTiebreaker =
1459+
if (wideAlt1.isVarArgsMethod || wideAlt2.isVarArgsMethod)
1460+
lengthCompare(paramInfos(wideAlt1), paramInfos(wideAlt2))
1461+
else 0
1462+
1463+
if (varArgLengthTiebreaker != 0) varArgLengthTiebreaker
1464+
else if (strippedType1 eq fullType1)
1465+
if (strippedType2 eq fullType2) 0 // no implicits either side: its' a draw
1466+
else 1 // prefer 1st alternative with no implicits
1467+
else if (strippedType2 eq fullType2) -1 // prefer 2nd alternative with no implicits
1468+
else compareWithTypes(fullType1, fullType2) // continue by comparing implicits parameters
1469+
}
14411470
}}
14421471

14431472
def narrowMostSpecific(alts: List[TermRef])(implicit ctx: Context): List[TermRef] = track("narrowMostSpecific") {
@@ -1674,6 +1703,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
16741703
candidates.flatMap(cloneCandidate)
16751704
}
16761705

1706+
import config.Printers.debug
1707+
debug.println(i"candidates=\n\t$candidates%\n\t%")
16771708
val found = narrowMostSpecific(candidates)
16781709
if (found.length <= 1) found
16791710
else pt match {

tests/neg/overload_repeated.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test {
2+
def foo(a: Any) = a
3+
def foo(s: String*) = s
4+
foo("") // error
5+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class C {
2+
def foo(xs: Int*): Int = xs.toSeq.head
3+
def foo(x: Int): Int = x
4+
foo(2)
5+
6+
def fooT[T](xs: T*): T = xs.toSeq.head
7+
def fooT[T](x: T): T = x
8+
fooT(2)
9+
10+
def f[T](x: T): T = x
11+
def f[T](x: T, xs: T*): T = x
12+
13+
f(5)
14+
}

tests/pos/t4775/JavaClass.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
public class JavaClass {
2+
public static class Element {
3+
4+
}
5+
6+
public static <T extends Element> int foo(Element a, Class<T> b, boolean c, Class<? extends T>... d) {
7+
return 1;
8+
}
9+
10+
public static <T extends Element> int foo(Element a, Class<? extends T> b, boolean c) {
11+
return 2;
12+
}
13+
14+
public static <T extends Element> int foo(Element a, Class<? extends T>... b) {
15+
return 3;
16+
}
17+
18+
public static <T extends Element> int foo(Element a, boolean b, Class<? extends T>... c) {
19+
return 4;
20+
}
21+
22+
static {
23+
foo(new Element(), Element.class, false);
24+
}
25+
}

tests/pos/t4775/Test.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Test {
2+
import JavaClass._
3+
foo(new Element, classOf[Element], false)
4+
}

0 commit comments

Comments
 (0)