Skip to content

Commit 32676de

Browse files
committed
Improve variable instantiation when member is missing
The `couldInstantiateTypeVar` method instantiated only type variables that were the constructor of an applied type. But sometimes we might also need to instantiate the argument(s), since doing so can influence the members of the applied type. This happens in two cases 1. The applied type's rhs is a match type 2. The applied type's result is one of its type parameters i11236.scala tests the first case, the additions to i9567.scala the second. Fixes #11236
1 parent ce684de commit 32676de

File tree

4 files changed

+46
-6
lines changed

4 files changed

+46
-6
lines changed

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,23 @@ object Inferencing {
9999
&& tvar.hasLowerBound =>
100100
tvar.instantiate(fromBelow = true)
101101
true
102-
case AppliedType(tycon, _) =>
102+
case AppliedType(tycon, args) =>
103+
// The argument in `args` that may potentially appear directly as result
104+
// and thereby influence the members of this type
105+
def argsInResult: List[Type] = tycon match
106+
case tycon: TypeRef =>
107+
tycon.info match
108+
case MatchAlias(_) => args
109+
case TypeBounds(_, upper: TypeLambda) =>
110+
upper.resultType match
111+
case ref: TypeParamRef if ref.binder == upper =>
112+
args.lazyZip(upper.paramRefs).collect {
113+
case (arg, pref) if pref eq ref => arg
114+
}.toList
115+
case _ => Nil
116+
case _ => Nil
103117
couldInstantiateTypeVar(tycon)
118+
|| argsInResult.exists(couldInstantiateTypeVar)
104119
case RefinedType(parent, _, _) =>
105120
couldInstantiateTypeVar(parent)
106121
case tp: AndOrType =>

compiler/test/dotc/pos-test-pickling.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ i7868.scala
3232
i7872.scala
3333
6709.scala
3434
6687.scala
35+
i11236.scala
3536

3637
# Opaque type
3738
i5720.scala

tests/pos/i11236.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Test {
2+
val tup: Char #: Int #: String #: TupleK = ???
3+
val x: String #: TupleK = (tup.tail: Int #: String #: TupleK).tail
4+
val a = tup.tail
5+
val b = a.tail
6+
val y: String #: TupleK = tup.tail.tail
7+
val z: Unit = tup.tail.tail
8+
}
9+
10+
trait TupleK
11+
12+
object TupleK {
13+
type Tail[X <: NonEmptyTupleK] <: TupleK = X match {
14+
case _ #: xs => xs
15+
}
16+
}
17+
18+
trait NonEmptyTupleK extends TupleK {
19+
/*inline*/ def tail[This >: this.type <: NonEmptyTupleK]: TupleK.Tail[This] = ???
20+
}
21+
22+
abstract class #:[+H, +T <: TupleK] extends NonEmptyTupleK

tests/pos/i9567.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
// val x: Int => Int = identity
33
// }
44

5-
trait Foo[F[_]] {
5+
trait Foo[F[_], I[X] <: X] {
6+
type Id[X] <: X
67
def foo[G[x] >: F[x]]: G[Unit]
8+
def foo2[X >: F[String]]: Id[X]
9+
def foo3[X >: F[String]]: I[X]
710
}
811

912
trait M[A] {
@@ -12,11 +15,10 @@ trait M[A] {
1215
}
1316

1417
object Test {
15-
def bar(x: Foo[M]): Unit = {
16-
// error: value bla is not a member of G[Unit], where: G is a type variable with constraint >: M and <: [x] =>> Any
18+
def bar(x: Foo[M, [X] =>> X]): Unit = {
1719
x.foo.bla
18-
19-
// error: value bla is not a member of G[Unit], where: G is a type variable with constraint >: M and <: [x] =>> Any
2020
x.foo.baz(x => x)
21+
x.foo2.bla
22+
x.foo3.bla
2123
}
2224
}

0 commit comments

Comments
 (0)