Skip to content

Commit eec6854

Browse files
committed
Fix #4297: handle type param reference in isInstanceOfCheck
1 parent baedc50 commit eec6854

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

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

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

91+
def stripTypeParam(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+
range(lo, hi)
97+
case _ =>
98+
mapOver(tp)
99+
}
100+
}
101+
91102
def isClassDetermined(X: Type, P: AppliedType)(implicit ctx: Context) = {
92103
val AppliedType(tycon, _) = P
93104
val typeLambda = tycon.ensureLambdaSub.asInstanceOf[TypeLambda]
94105
val tvars = constrained(typeLambda, untpd.EmptyTree, alwaysAddTypeVars = true)._2.map(_.tpe)
95106
val P1 = tycon.appliedTo(tvars)
96107

97-
debug.println("P : " + P.show)
98-
debug.println("P1 : " + P1.show)
99-
debug.println("X : " + X.show)
108+
debug.println("P : " + P)
109+
debug.println("P1 : " + P1)
110+
debug.println("X : " + X)
111+
112+
P1 <:< X // constraint P1
100113

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

103-
val res = isFullyDefined(P1, ForceDegree.noBottom) && P1 <:< P
117+
val res = P1 <:< P
104118
debug.println("P1 : " + P1)
105119
debug.println("P1 <:< P = " + res)
106120

@@ -116,7 +130,9 @@ object Checkable {
116130
case defn.ArrayOf(tpE) => recur(tpE, tpT)
117131
case _ => recur(defn.AnyType, tpT)
118132
}
119-
case tpe: AppliedType => isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState())
133+
case tpe: AppliedType =>
134+
isClassDetermined(X, tpe)(ctx.fresh.setNewTyperState()) ||
135+
isClassDetermined(stripTypeParam.apply(X), tpe)(ctx.fresh.setNewTyperState())
120136
case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
121137
case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
122138
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)