Skip to content

Commit a917c93

Browse files
committed
Fix #4297: handle type param reference
1 parent baedc50 commit a917c93

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

compiler/src/dotty/tools/dotc/transform/IsInstanceOfChecker.scala

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,35 @@ object Checkable {
8888
}
8989
}
9090

91+
def maximize(implicit ctx: Context) = new ApproximatingTypeMap {
92+
def apply(tp: Type): Type = tp match {
93+
case tp: TypeRef if tp.underlying.isInstanceOf[TypeBounds] =>
94+
val lo = this(tp.info.loBound)
95+
val hi = this(tp.info.hiBound)
96+
if (variance == 0) range(lo, hi)
97+
else if (variance == 1) hi
98+
else lo
99+
case _ =>
100+
mapOver(tp)
101+
}
102+
}
103+
91104
def isClassDetermined(X: Type, P: AppliedType)(implicit ctx: Context) = {
92105
val AppliedType(tycon, _) = P
93106
val typeLambda = tycon.ensureLambdaSub.asInstanceOf[TypeLambda]
94107
val tvars = constrained(typeLambda, untpd.EmptyTree, alwaysAddTypeVars = true)._2.map(_.tpe)
95108
val P1 = tycon.appliedTo(tvars)
96109

97-
debug.println("P : " + P.show)
98-
debug.println("P1 : " + P1.show)
99-
debug.println("X : " + X.show)
110+
debug.println("P : " + P)
111+
debug.println("P1 : " + P1)
112+
debug.println("X : " + X)
113+
114+
P1 <:< X // constraint P1
100115

101-
P1 <:< X // may fail, ignore
116+
// use fromScala2x to avoid generating pattern bound symbols
117+
maximizeType(P1, pos, fromScala2x = true)
102118

103-
val res = isFullyDefined(P1, ForceDegree.noBottom) && P1 <:< P
119+
val res = P1 <:< P
104120
debug.println("P1 : " + P1)
105121
debug.println("P1 <:< P = " + res)
106122

@@ -116,7 +132,9 @@ object Checkable {
116132
case defn.ArrayOf(tpE) => recur(tpE, tpT)
117133
case _ => recur(defn.AnyType, tpT)
118134
}
119-
case tpe: AppliedType => isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState())
135+
case tpe: AppliedType =>
136+
isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState()) ||
137+
isClassDetermined(maximize.apply(X), tpe)(ctx.fresh.setNewTyperState())
120138
case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
121139
case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
122140
case AnnotatedType(t, _) => recur(X, t)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Test {
2+
def test[X <: Option[Int]](x: X) = x.isInstanceOf[Some[Int]]
3+
def test1[Y <: Int, X <: Option[Y]](x: X) = x.isInstanceOf[Some[Int]]
4+
def test2(x: Any) = x.isInstanceOf[Function1[Nothing, _]]
5+
def test3a(x: Any) = x.isInstanceOf[Function1[Any, _]] // error
6+
def test3b(x: Any) = x.isInstanceOf[Function1[Int, _]] // error
7+
def test4[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, _]] // error
8+
def test5[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, Unit]] // error
9+
def test6[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[Int, Any]] // error
10+
def test7[Y <: Int, X <: Function1[Y, Unit]](x: X) = x.isInstanceOf[Function1[_, Unit]]
11+
}

0 commit comments

Comments
 (0)