@@ -43,11 +43,18 @@ object Checkable {
43
43
44
44
/** Whether `(x:X).isInstanceOf[P]` can be checked at runtime?
45
45
*
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:
47
54
*
48
55
* 1. if `X <:< P`, TRUE
49
56
* 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
51
58
* 4. if `P = Array[T]`, checkable(E, T) where `E` is the element type of `X`, defaults to `Any`.
52
59
* 5. if `P` is `pre.F[Ts]` and `pre.F` refers to a class which is not `Array`:
53
60
* (a) replace `Ts` with fresh type variables `Xs`
@@ -60,7 +67,7 @@ object Checkable {
60
67
def checkable (X : Type , P : Type )(implicit ctx : Context ): Boolean = {
61
68
def isAbstract (P : Type ) = ! P .dealias.typeSymbol.isClass
62
69
63
- def replaceBinderMap (implicit ctx : Context ) = new TypeMap {
70
+ def replaceP (implicit ctx : Context ) = new TypeMap {
64
71
def apply (tp : Type ) = tp match {
65
72
case tref : TypeRef
66
73
if ! tref.typeSymbol.isClass && tref.symbol.is(Case ) => WildcardType
@@ -70,6 +77,17 @@ object Checkable {
70
77
}
71
78
}
72
79
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
+
73
91
def isClassDetermined (X : Type , P : AppliedType )(implicit ctx : Context ) = {
74
92
val AppliedType (tycon, _) = P
75
93
val typeLambda = tycon.ensureHK.asInstanceOf [TypeLambda ]
@@ -85,6 +103,7 @@ object Checkable {
85
103
val res = isFullyDefined(P1 , ForceDegree .noBottom) && P1 <:< P
86
104
debug.println(" P1 : " + P1 )
87
105
debug.println(" P1 <:< P = " + res)
106
+
88
107
res
89
108
}
90
109
@@ -105,7 +124,7 @@ object Checkable {
105
124
case _ => true
106
125
})
107
126
108
- val res = recur(X .widen, replaceBinderMap .apply(P ))
127
+ val res = recur(replaceX.apply( X .widen), replaceP .apply(P ))
109
128
110
129
debug.println(i " checking ${X .show} isInstanceOf ${P } = $res" )
111
130
0 commit comments