@@ -31,7 +31,7 @@ object TypeTestsCasts {
31
31
import typer .Inferencing .maximizeType
32
32
import typer .ProtoTypes .constrained
33
33
34
- /** Whether `(x:X).isInstanceOf[P]` can be checked at runtime?
34
+ /** Whether `(x: X).isInstanceOf[P]` can be checked at runtime?
35
35
*
36
36
* First do the following substitution:
37
37
* (a) replace `T @unchecked` and pattern binder types (e.g., `_$1`) in P with WildcardType
@@ -48,7 +48,8 @@ object TypeTestsCasts {
48
48
* (c) maximize `pre.F[Xs]` and check `pre.F[Xs] <:< P`
49
49
* 6. if `P = T1 | T2` or `P = T1 & T2`, checkable(X, T1) && checkable(X, T2).
50
50
* 7. if `P` is a refinement type, FALSE
51
- * 8. otherwise, TRUE
51
+ * 8. if `P` is a local class which is not statically reachable from the scope where `X` is defined, FALSE
52
+ * 9. otherwise, TRUE
52
53
*/
53
54
def checkable (X : Type , P : Type , span : Span )(using Context ): Boolean = atPhase(Phases .refchecksPhase.next) {
54
55
// Run just before ElimOpaque transform (which follows RefChecks)
@@ -58,7 +59,7 @@ object TypeTestsCasts {
58
59
def apply (tp : Type ) = tp match {
59
60
case tref : TypeRef if tref.typeSymbol.isPatternBound =>
60
61
WildcardType
61
- case AnnotatedType (_, annot) if annot.symbol == defn.UncheckedAnnot =>
62
+ case tp if tp.hasAnnotation( defn.UncheckedAnnot ) =>
62
63
WildcardType
63
64
case _ => mapOver(tp)
64
65
}
@@ -123,11 +124,6 @@ object TypeTestsCasts {
123
124
124
125
}
125
126
126
- lazy val scrutineeIsUnchecked = X .widenTermRefExpr.existsPart {
127
- case AnnotatedType (_, annot) if annot.symbol == defn.UncheckedAnnot => true
128
- case _ => false
129
- }
130
-
131
127
def recur (X : Type , P : Type ): Boolean = (X <:< P ) || (P .dealias match {
132
128
case _ : SingletonType => true
133
129
case _ : TypeProxy
@@ -157,26 +153,13 @@ object TypeTestsCasts {
157
153
case AnnotatedType (t, _) => recur(X , t)
158
154
case tp2 : RefinedType => recur(X , tp2.parent) && TypeComparer .hasMatchingMember(tp2.refinedName, X , tp2)
159
155
case tp2 : RecType => recur(X , tp2.parent)
160
- case tp2
161
- if tp2.typeSymbol.isLocal && ! scrutineeIsUnchecked =>
162
- val sym = tp2.typeSymbol
163
- val methodSymbol = sym.owner
164
- val tpSyms = typer.ErrorReporting .substitutableTypeSymbolsInScope(sym).toSet
165
- def isAccessible (sym : Symbol ): Boolean = sym == methodSymbol || sym.isType && isAccessible(sym.owner)
166
- val seen = scala.collection.mutable.Set .empty[Type ]
167
- def hasPoison (tp : Type ): Boolean =
168
- seen += tp
169
- tp.baseClasses.filter(isAccessible).exists { sym =>
170
- sym.info.decls.exists { sym =>
171
- sym.info.existsPart(tp => tpSyms.contains(tp.typeSymbol))
172
- || ! seen.contains(sym.info) && isAccessible(sym.info.typeSymbol.maybeOwner) && hasPoison(sym.info)
173
- }
174
- }
175
- ! hasPoison(tp2)
156
+ case _
157
+ if P .classSymbol.isLocal && P .classSymbol.isInaccessibleChildOf(X .classSymbol) => // 8
158
+ false
176
159
case _ => true
177
160
})
178
161
179
- val res = recur(X .widen, replaceP(P ))
162
+ val res = X .widenTermRefExpr.hasAnnotation(defn. UncheckedAnnot ) || recur(X .widen, replaceP(P ))
180
163
181
164
debug.println(i " checking ${X .show} isInstanceOf ${P } = $res" )
182
165
0 commit comments