@@ -1293,7 +1293,15 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1293
1293
val formals1 =
1294
1294
if (tp1.isVarArgsMethod && tp2.isVarArgsMethod) tp1.paramInfos.map(_.repeatedToSingle)
1295
1295
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) ||
1297
1305
tp1.paramInfos.isEmpty && tp2.isInstanceOf [LambdaType ]
1298
1306
case tp1 : PolyType => // (2)
1299
1307
val nestedCtx = ctx.fresh.setExploreTyperState()
@@ -1420,24 +1428,45 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1420
1428
if (winsType1 || ! winsType2) 1 else 0
1421
1429
else if (ownerScore == - 1 )
1422
1430
if (winsType2 || ! winsType1) - 1 else 0
1423
- else if (winsType1)
1431
+ else if (winsType1)
1424
1432
if (winsType2) 0 else 1
1425
1433
else
1426
1434
if (winsType2) - 1 else 0
1427
1435
}
1428
1436
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)
1431
1453
val strippedType1 = stripImplicit(fullType1)
1432
1454
val strippedType2 = stripImplicit(fullType2)
1433
1455
1434
1456
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
+ }
1441
1470
}}
1442
1471
1443
1472
def narrowMostSpecific (alts : List [TermRef ])(implicit ctx : Context ): List [TermRef ] = track(" narrowMostSpecific" ) {
@@ -1674,6 +1703,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
1674
1703
candidates.flatMap(cloneCandidate)
1675
1704
}
1676
1705
1706
+ import config .Printers .debug
1707
+ debug.println(i " candidates= \n\t $candidates% \n\t % " )
1677
1708
val found = narrowMostSpecific(candidates)
1678
1709
if (found.length <= 1 ) found
1679
1710
else pt match {
0 commit comments