Skip to content

Commit bb0faff

Browse files
committed
Skolemize arguments to dependent methods as necessary.
This was missing before, led to errors not being detected.
1 parent b3d683a commit bb0faff

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
395395
def addTyped(arg: Arg, formal: Type): Type => Type = {
396396
addArg(typedArg(arg, formal), formal)
397397
if (methodType.isParamDependent)
398-
_.substParam(methodType.newParamRef(n), typeOfArg(arg))
399-
else
400-
identity
398+
substArgForParam(_, typeOfArg(arg), methodType.paramRefs(n))
399+
else identity
401400
}
402401

403402
def missingArg(n: Int): Unit = {

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,28 @@ trait TypeAssigner {
315315
}
316316
}
317317

318+
/** Substitute argument type `argType` for parameter `pref` in type `tp`,
319+
* skolemizing the argument type if it is not stable and `pref` occurs in `tp`.
320+
*/
321+
def substArgForParam(tp: Type, argType: Type, pref: ParamRef)(implicit ctx: Context) = {
322+
val tp1 = tp.substParam(pref, argType)
323+
if ((tp1 eq tp) || argType.isStable) tp1
324+
else tp.substParam(pref, SkolemType(argType.widen))
325+
}
326+
318327
def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = {
319328
val ownType = fn.tpe.widen match {
320329
case fntpe: MethodType =>
321-
if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
330+
def substArgsForParams(tp: Type, args: List[Tree], params: List[ParamRef]): Type = params match {
331+
case param :: params1 =>
332+
val tp1 = substArgForParam(tp, args.head.tpe, param)
333+
substArgsForParams(tp1, args.tail, params1)
334+
case Nil =>
335+
tp
336+
}
337+
if (sameLength(fntpe.paramInfos, args) || ctx.phase.prev.relaxedTyping)
338+
if (fntpe.isDependent) substArgsForParams(fntpe.resultType, args, fntpe.paramRefs)
339+
else fntpe.resultType
322340
else
323341
errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramInfos.length}, found: ${args.length}", tree.pos)
324342
case t =>

tests/neg/i2142.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
object Foo {
2+
3+
class A
4+
val a1 = new A()
5+
val a2 = new A()
6+
7+
def f(x: A, y: x.type) = ()
8+
f(a1, a1) // ok
9+
f(a1, a2) // error
10+
f(new A(), new A()) // error
11+
f(new A(), a1) // error
12+
13+
def g(x: A)(y: x.type) = ()
14+
g(a1)(a1) // ok
15+
g(a1)(a2) // error
16+
g(new A())(new A()) // error
17+
g(new A())(a1) // error
18+
19+
val x0 = g(new A()) _
20+
x0 (new A()) // error
21+
22+
class C[T]
23+
24+
def h(x: A): C[x.type] = ???
25+
val x = h(a1)
26+
val y = h(new A())
27+
28+
}

0 commit comments

Comments
 (0)