Skip to content

Commit bbe749d

Browse files
committed
Special case in TestApplication
1 parent 6bd570d commit bbe749d

File tree

2 files changed

+26
-15
lines changed

2 files changed

+26
-15
lines changed

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

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,27 @@ trait Applications extends Compatibility {
883883
case SAMType(samMeth, samParent) => argtpe <:< samMeth.toFunctionType(isJava = samParent.classSymbol.is(JavaDefined))
884884
case _ => false
885885

886-
isCompatible(argtpe, formal)
886+
// For overload resolution, allow wildcard upper bounds to match their bound type.
887+
// For example, given:
888+
// def blub[T](a: Class[? <: T]): String = "a"
889+
// def blub[T](a: Class[T], ints: Int*): String = "b"
890+
// blub(classOf[Object])
891+
//
892+
// The non-varargs overload should be preferred. While Class[? <: T] is not a
893+
// subtype of Class[T] (Class is invariant), for overload resolution we consider
894+
// Class[? <: T] "applicable" where Class[T] is expected by checking if the
895+
// wildcard's upper bound is a subtype of the formal type parameter.
896+
def wildcardArgOK =
897+
(argtpe, formal) match
898+
case (AppliedType(tycon1, args1), AppliedType(tycon2, args2))
899+
if tycon1 =:= tycon2 && args1.length == args2.length =>
900+
args1.lazyZip(args2).forall {
901+
case (TypeBounds(_, hi), formal) => hi relaxed_<:< formal
902+
case (arg, formal) => arg =:= formal
903+
}
904+
case _ => false
905+
906+
isCompatible(argtpe, formal) || wildcardArgOK
887907
// Only allow SAM-conversion to PartialFunction if implicit conversions
888908
// are enabled. This is necessary to avoid ambiguity between an overload
889909
// taking a PartialFunction and one taking a Function1 because
@@ -2176,20 +2196,7 @@ trait Applications extends Compatibility {
21762196
case 0 =>
21772197
if winsType1 != winsType2 then if winsType1 then 1 else -1
21782198
else if alt1.symbol == alt2.symbol then comparePrefixes
2179-
else
2180-
// Prefer non-varargs methods over varargs methods as a final tiebreaker.
2181-
// While `isAsGood` normally handles this, it can fail when wildcard types are involved.
2182-
// For example, when comparing:
2183-
// def m[T](a: Class[? <: T]): Unit
2184-
// def m[T](a: Class[T], ints: Int*): Unit
2185-
// Both winsType1 and winsType2 are false because Class[? <: T] is not
2186-
// a subtype of Class[T] (Class is invariant). This tiebreaker ensures the
2187-
// non-varargs method is preferred in such cases.
2188-
val tp1IsVarArgs = tp1.isVarArgsMethod
2189-
val tp2IsVarArgs = tp2.isVarArgsMethod
2190-
if tp1IsVarArgs == tp2IsVarArgs then 0
2191-
else if tp1IsVarArgs then -1 // alt2 (non-varargs) wins
2192-
else 1 // alt1 (non-varargs) wins
2199+
else 0
21932200
end compareWithTypes
21942201

21952202
if alt1.symbol.is(PhantomSymbol) && !alt2.symbol.is(PhantomSymbol) then -1

tests/run/overload_repeated/B_2.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ object Test {
1717
def bar5[T](a: Class[? <: T]): Int = 1
1818
def bar5[T](a: Class[T], ints: Int*): Int = 2
1919

20+
def bar6[T](a: Int): Int = 1
21+
def bar6[T](a: Class[T], ints: Int*): Int = 2
22+
2023
def main(args: Array[String]): Unit = {
2124
// In Java, varargs are always less specific than non-varargs (see
2225
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2),
@@ -33,5 +36,6 @@ object Test {
3336
assert(bar3("") == 1) // same in Scala 2
3437
assert(bar4("") == 1) // same in Scala 2
3538
assert(bar5(classOf[Object]) == 1) // same in Scala2
39+
assert(bar6(classOf[Object]) == 2) // same in Scala2
3640
}
3741
}

0 commit comments

Comments
 (0)