@@ -43,11 +43,18 @@ object Checkable {
4343
4444 /** Whether `(x:X).isInstanceOf[P]` can be checked at runtime?
4545 *
46- * Replace `T @unchecked` and pattern binder types (e.g., `_$1`) in P with WildcardType, then check:
46+ * First do the following substitution:
47+ * (a) replace `T @unchecked` and pattern binder types (e.g., `_$1`) in P with WildcardType
48+ * (b) replace pattern binder types (e.g., `_$1`) in X:
49+ * - variance = 1 : hiBound
50+ * - variance = -1 : loBound
51+ * - variance = 0 : OrType(Any, Nothing)
52+ *
53+ * Then check:
4754 *
4855 * 1. if `X <:< P`, TRUE
4956 * 2. if `P` is a singleton type, TRUE
50- * 3. if `P` refers to an abstract type member or type parameter, `X <:< P`
57+ * 3. if `P` refers to an abstract type member or type parameter, FALSE
5158 * 4. if `P = Array[T]`, checkable(E, T) where `E` is the element type of `X`, defaults to `Any`.
5259 * 5. if `P` is `pre.F[Ts]` and `pre.F` refers to a class which is not `Array`:
5360 * (a) replace `Ts` with fresh type variables `Xs`
@@ -60,7 +67,7 @@ object Checkable {
6067 def checkable (X : Type , P : Type )(implicit ctx : Context ): Boolean = {
6168 def isAbstract (P : Type ) = ! P .dealias.typeSymbol.isClass
6269
63- def replaceBinderMap (implicit ctx : Context ) = new TypeMap {
70+ def replaceP (implicit ctx : Context ) = new TypeMap {
6471 def apply (tp : Type ) = tp match {
6572 case tref : TypeRef
6673 if ! tref.typeSymbol.isClass && tref.symbol.is(Case ) => WildcardType
@@ -70,6 +77,17 @@ object Checkable {
7077 }
7178 }
7279
80+ def replaceX (implicit ctx : Context ) = new TypeMap {
81+ def apply (tp : Type ) = tp match {
82+ case tref : TypeRef
83+ if ! tref.typeSymbol.isClass && tref.symbol.is(Case ) =>
84+ if (variance == 1 ) tref.info.hiBound
85+ else if (variance == - 1 ) tref.info.loBound
86+ else OrType (defn.AnyType , defn.NothingType )
87+ case _ => mapOver(tp)
88+ }
89+ }
90+
7391 def isClassDetermined (X : Type , P : AppliedType )(implicit ctx : Context ) = {
7492 val AppliedType (tycon, _) = P
7593 val typeLambda = tycon.ensureHK.asInstanceOf [TypeLambda ]
@@ -85,6 +103,7 @@ object Checkable {
85103 val res = isFullyDefined(P1 , ForceDegree .noBottom) && P1 <:< P
86104 debug.println(" P1 : " + P1 )
87105 debug.println(" P1 <:< P = " + res)
106+
88107 res
89108 }
90109
@@ -105,7 +124,7 @@ object Checkable {
105124 case _ => true
106125 })
107126
108- val res = recur(X .widen, replaceBinderMap .apply(P ))
127+ val res = recur(replaceX.apply( X .widen), replaceP .apply(P ))
109128
110129 debug.println(i " checking ${X .show} isInstanceOf ${P } = $res" )
111130
0 commit comments