Skip to content

Commit bb4d4e2

Browse files
Instantiate type vars which occur in arguments applications
1 parent b1b0372 commit bb4d4e2

File tree

3 files changed

+44
-19
lines changed

3 files changed

+44
-19
lines changed

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

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -391,37 +391,45 @@ object Inferencing {
391391
* - The prefix `p` of a selection `p.f`.
392392
* - The result expression `e` of a block `{s1; .. sn; e}`.
393393
*/
394-
def tvarsInParams(tree: Tree, locked: TypeVars)(using Context): List[TypeVar] = {
395-
@tailrec def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = tree match {
396-
case Apply(fn, _) => boundVars(fn, acc)
397-
case TypeApply(fn, targs) =>
398-
val tvars = targs.filter(_.isInstanceOf[InferredTypeTree]).tpes.collect {
399-
case tvar: TypeVar
400-
if !tvar.isInstantiated &&
401-
ctx.typerState.ownedVars.contains(tvar) &&
402-
!locked.contains(tvar) => tvar
403-
}
404-
boundVars(fn, acc ::: tvars)
405-
case Select(pre, _) => boundVars(pre, acc)
406-
case Block(_, expr) => boundVars(expr, acc)
407-
case _ => acc
394+
def tvarsInParams(tree: Tree, locked: TypeVars)(using Context): List[TypeVar] = trace.log(i"tvarsInParams $tree") {
395+
// @tailrec
396+
def boundVars(tree: Tree, acc: List[TypeVar]): List[TypeVar] = trace.log(i"boundVars $tree") {
397+
tree match {
398+
case Apply(fn, args) =>
399+
val argTpVars = args.flatMap(boundVars(_, Nil))
400+
boundVars(fn, acc ++ argTpVars)
401+
case TypeApply(fn, targs) =>
402+
val tvars = targs.filter(_.isInstanceOf[InferredTypeTree]).tpes.collect {
403+
case tvar: TypeVar
404+
if !tvar.isInstantiated &&
405+
ctx.typerState.ownedVars.contains(tvar) &&
406+
!locked.contains(tvar) => tvar
407+
}
408+
boundVars(fn, acc ::: tvars)
409+
case Select(pre, _) => boundVars(pre, acc)
410+
case Block(_, expr) => boundVars(expr, acc)
411+
case _ => acc
412+
}
408413
}
409-
@tailrec def occurring(tree: Tree, toTest: List[TypeVar], acc: List[TypeVar]): List[TypeVar] =
414+
// @tailrec
415+
def occurring(tree: Tree, toTest: List[TypeVar], acc: List[TypeVar]): List[TypeVar] = trace.log(i"occurring $tree") {
410416
if (toTest.isEmpty) acc
411417
else tree match {
412-
case Apply(fn, _) =>
418+
case Apply(fn, args) =>
419+
val argOcc = args.flatMap(occurring(_, toTest, Nil))
413420
fn.tpe.widen match {
414421
case mtp: MethodType =>
415422
val (occ, nocc) = toTest.partition(tvar => mtp.paramInfos.exists(tvar.occursIn))
416-
occurring(fn, nocc, occ ::: acc)
423+
occurring(fn, nocc, occ ::: acc ::: argOcc)
417424
case _ =>
418-
occurring(fn, toTest, acc)
425+
occurring(fn, toTest, acc ::: argOcc)
419426
}
420427
case TypeApply(fn, targs) => occurring(fn, toTest, acc)
421428
case Select(pre, _) => occurring(pre, toTest, acc)
422429
case Block(_, expr) => occurring(expr, toTest, acc)
423430
case _ => acc
424431
}
432+
}
425433
occurring(tree, boundVars(tree, Nil), Nil)
426434
}
427435

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3845,7 +3845,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38453845
}
38463846
}
38473847

3848-
def adaptNoArgsImplicitMethod(wtp: MethodType): Tree = {
3848+
def adaptNoArgsImplicitMethod(wtp: MethodType): Tree = trace.log(i"adaptNoArgsImplicitMethod $wtp") {
38493849
assert(wtp.isImplicitMethod)
38503850
val tvarsToInstantiate = tvarsInParams(tree, locked).distinct
38513851
def instantiate(tp: Type): Unit = {

tests/pos/i18578.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
trait Animal
3+
class Dog extends Animal
4+
5+
trait Ev[T]
6+
7+
given Ev[Dog] = ???
8+
given Ev[Animal] = ???
9+
given[T: Ev]: Ev[Set[T]] = ???
10+
11+
def f[T: Ev](v: T): Unit = ???
12+
13+
def main =
14+
val s = Set(new Dog)
15+
// f(s) // WORKS
16+
f(Set(new Dog)) // FAILS
17+
// instantiates to

0 commit comments

Comments
 (0)