Skip to content

Commit 2dcb01c

Browse files
committed
Simulate Repeated having no sub/supertypes for overloads
1 parent cdb6250 commit 2dcb01c

File tree

5 files changed

+81
-1
lines changed

5 files changed

+81
-1
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,19 @@ 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+
// This is necessary in cases when the last parameter of one method is repeated,
1302+
// and another is, for instance, Any - see neg/overload_repeated.scala.
1303+
// Note that we cannot just say that X* is really not a sub- or supertype of any other type,
1304+
// since that would interfere with typing method bodies.
1305+
!(arg.isRepeatedParam || formal.isRepeatedParam) && super.argOK(arg, formal)
1306+
}
1307+
1308+
ctx.test(ctx => new IsAsSpecific(alt2, formals1, WildcardType)(ctx).success) ||
12971309
tp1.paramInfos.isEmpty && tp2.isInstanceOf[LambdaType]
12981310
case tp1: PolyType => // (2)
12991311
val nestedCtx = ctx.fresh.setExploreTyperState()

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+
}

tests/neg/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/neg/t4775/Test.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class Test {
2+
import JavaClass._
3+
// in Scala2, this is not actually an error (see https://github.com/scala/bug/issues/4775)
4+
// overloading selection needs to decide between:
5+
//
6+
// def foo[T <: Element](a: Element, b: Class[T], c: Boolean, d: Class[_ <: T]*)
7+
// def foo[T <: Element](a: Element, b: Class[_ <: T], c: Boolean)
8+
//
9+
// The first is not as specific as the second, since it has more arguments.
10+
// The second _should_ be as specific as the first,
11+
// but the T parameter would need to capture the wildcard of b.
12+
// Since we don't allow wildcard capture anymore,
13+
// we cannot infer anything for T
14+
// and just say the second is not as specific as the first either.
15+
//
16+
// As a note to whomever will be revisiting this in the future,
17+
// we can select the same overload as Scala2 by selecting the one
18+
// without vararg parameter when neither is more specific.
19+
// The argument is that since one overload has varargs and the other doesn't,
20+
// the callsite must be trying to pass no varargs,
21+
// so we should select the overload that doesn't actually have any.
22+
// This breaks no tests, but potentially allows too much.
23+
foo(new Element, classOf[Element], false) // error
24+
}
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+
}

0 commit comments

Comments
 (0)