@@ -53,7 +53,7 @@ object TypeTestsCasts {
5353 * 6. if `P = T1 | T2` or `P = T1 & T2`, checkable(X, T1) && checkable(X, T2).
5454 * 7. if `P` is a refinement type, "it's a refinement type"
5555 * 8. if `P` is a local class which is not statically reachable from the scope where `X` is defined, "it's a local class"
56- * 9. if `X` is `T1 | T2`, checkable(T1, P) && checkable(T2, P) or (isCheckDefinitelyFalse(T1, P) && checkable(T2, P)) or (checkable(T1, P) && isCheckDefinitelyFalse(T2, P)) .
56+ * 9. if `X` is `T1 | T2`, checkable(T1, P) && checkable(T2, P).
5757 * 10. otherwise, ""
5858 */
5959 def whyUncheckable (X : Type , P : Type , span : Span )(using Context ): String = atPhase(Phases .refchecksPhase.next) {
@@ -132,42 +132,8 @@ object TypeTestsCasts {
132132
133133 }
134134
135- /** Whether the check X.isInstanceOf[P] is definitely false? */
136- def isCheckDefinitelyFalse (X : Type , P : Type )(using Context ): Boolean = trace(s " isCheckDefinitelyFalse( ${X .show}, ${P .show}) " ) {
137- X .widenDealias match
138- case AndType (x1, x2) =>
139- isCheckDefinitelyFalse(x1, P ) || isCheckDefinitelyFalse(x2, P )
140-
141- case x =>
142- P .widenDealias match
143- case AndType (p1, p2) =>
144- isCheckDefinitelyFalse(x, p1) || isCheckDefinitelyFalse(x, p2)
145-
146- case p =>
147- val pSpace = Typ (p)
148- val xSpace = Typ (x)
149- if pSpace.canDecompose then
150- val ps = pSpace.decompose.map(_.tp)
151- ps.forall(p => isCheckDefinitelyFalse(x, p))
152- else if xSpace.canDecompose then
153- val xs = xSpace.decompose.map(_.tp)
154- xs.forall(x => isCheckDefinitelyFalse(x, p))
155- else
156- if x.typeSymbol.isClass && p.typeSymbol.isClass then
157- val xClass = effectiveClass(x)
158- val pClass = effectiveClass(p)
159-
160- val bothAreClasses = ! xClass.is(Trait ) && ! pClass.is(Trait )
161- val notXsubP = ! xClass.derivesFrom(pClass)
162- val notPsubX = ! pClass.derivesFrom(xClass)
163- bothAreClasses && notXsubP && notPsubX
164- || xClass.is(Final ) && notXsubP
165- || pClass.is(Final ) && notPsubX
166- else
167- false
168- }
169-
170- def recur (X : Type , P : Type ): String = (X <:< P ) ||| (P .dealias match {
135+ def recur (X : Type , P : Type ): String = trace(s " recur( ${X .show}, ${P .show}) " ) {
136+ (X <:< P ) ||| P .dealias.match
171137 case _ : SingletonType => " "
172138 case _ : TypeProxy
173139 if isAbstract(P ) => i " it refers to an abstract type member or type parameter "
@@ -176,32 +142,19 @@ object TypeTestsCasts {
176142 case defn.ArrayOf (tpE) => recur(tpE, tpT)
177143 case _ => recur(defn.AnyType , tpT)
178144 }
179- case tpe : AppliedType =>
145+ case tpe @ AppliedType (tycon, targs) =>
180146 X .widenDealias match {
181147 case OrType (tp1, tp2) =>
182148 // This case is required to retrofit type inference,
183149 // which cut constraints in the following two cases:
184150 // - T1 <:< T2 | T3
185151 // - T1 & T2 <:< T3
186152 // See TypeComparer#either
187- val res1 = recur(tp1, P )
188- val res2 = recur(tp2, P )
189-
190- if res1.isEmpty && res2.isEmpty then
191- res1
192- else if res2.isEmpty then
193- if isCheckDefinitelyFalse(tp1, P ) then res2
194- else res1
195- else if res1.isEmpty then
196- if isCheckDefinitelyFalse(tp2, P ) then res1
197- else res2
198- else
199- res1
153+ recur(tp1, P ) && recur(tp2, P )
200154
201- case _ =>
155+ case x =>
202156 // always false test warnings are emitted elsewhere
203- X .classSymbol.exists && P .classSymbol.exists &&
204- ! X .classSymbol.asClass.mayHaveCommonChild(P .classSymbol.asClass)
157+ TypeComparer .provablyDisjoint(x, tpe.derivedAppliedType(tycon, targs.map(_ => WildcardType )))
205158 || typeArgsTrivial(X , tpe)
206159 ||| i " its type arguments can't be determined from $X"
207160 }
@@ -215,7 +168,7 @@ object TypeTestsCasts {
215168 if P .classSymbol.isLocal && foundClasses(X ).exists(P .classSymbol.isInaccessibleChildOf) => // 8
216169 i " it's a local class "
217170 case _ => " "
218- })
171+ }
219172
220173 val res = recur(X .widen, replaceP(P ))
221174
0 commit comments