@@ -1488,30 +1488,18 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
14881488 * See #17465.
14891489 */
14901490 def isNewSubType (tp1 : Type ): Boolean =
1491-
1492- def isCovered (tp : Type ): (Boolean , Boolean ) =
1493- var containsOr : Boolean = false
1494- @ annotation.tailrec def recur (todos : List [Type ]): Boolean = todos match
1495- case tp :: todos =>
1496- tp.dealiasKeepRefiningAnnots.stripTypeVar match
1497- case tp : TypeRef =>
1498- if tp.symbol.isClass && tp.symbol != NothingClass && tp.symbol != NullClass then recur(todos)
1499- else false
1500- case tp : AppliedType => recur(tp.tycon :: todos)
1501- case tp : RefinedOrRecType => recur(tp.parent :: todos)
1502- case tp : AndType => recur(tp.tp1 :: tp.tp2 :: todos)
1503- case tp : OrType =>
1504- containsOr = true
1505- recur(tp.tp1 :: tp.tp2 :: todos)
1506- case _ => false
1507- case Nil => true
1508- val result = recur(tp :: Nil )
1509- (result, containsOr)
1510-
1511- val (covered1, hasOr1) = isCovered(tp1)
1512- val (covered2, hasOr2) = isCovered(tp2)
1513-
1514- if covered1 && covered2 && ! (hasOr1 && hasOr2) then
1491+ def isCovered (tp : Type ): CoveredStatus =
1492+ tp.dealiasKeepRefiningAnnots.stripTypeVar match
1493+ case tp : TypeRef if tp.symbol.isClass && tp.symbol != NothingClass && tp.symbol != NullClass => CoveredStatus .Covered
1494+ case tp : AppliedType => isCovered(tp.tycon)
1495+ case tp : RefinedOrRecType => isCovered(tp.parent)
1496+ case tp : AndType => isCovered(tp.tp1) combinedWith isCovered(tp.tp2)
1497+ case tp : OrType => isCovered(tp.tp1) combinedWith isCovered(tp.tp2)
1498+ case _ => CoveredStatus .Uncovered
1499+
1500+ val covered1 = isCovered(tp1)
1501+ val covered2 = isCovered(tp2)
1502+ if CoveredStatus .bothCovered(covered1, covered2) && ! CoveredStatus .bothHasOr(covered1, covered2) then
15151503 // println(s"useless subtype: $tp1 <:< $tp2")
15161504 false
15171505 else isSubType(tp1, tp2, approx.addLow)
@@ -3008,6 +2996,31 @@ object TypeComparer {
30082996 end ApproxState
30092997 type ApproxState = ApproxState .Repr
30102998
2999+ /** Result of `isCovered` check. */
3000+ object CoveredStatus :
3001+ opaque type Repr = Int
3002+
3003+ private inline val IsCovered = 2
3004+ private inline val NotHasOr = 1
3005+
3006+ /** The type is not covered. */
3007+ val Uncovered : Repr = 1
3008+
3009+ /** The type is covered and contains OrTypes. */
3010+ val CoveredWithOr : Repr = 2
3011+
3012+ /** The type is covered and free from OrTypes. */
3013+ val Covered : Repr = 3
3014+
3015+ object Repr :
3016+ extension (s : Repr )
3017+ inline def combinedWith (that : Repr ): Repr = s & that
3018+
3019+ inline def bothHasOr (s1 : Repr , s2 : Repr ): Boolean = ~ (s1 | s2 & NotHasOr ) != 0
3020+ inline def bothCovered (s1 : Repr , s2 : Repr ): Boolean = (s1 & s2 & IsCovered ) != 0
3021+ end CoveredStatus
3022+ type CoveredStatus = CoveredStatus .Repr
3023+
30113024 def topLevelSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
30123025 comparing(_.topLevelSubType(tp1, tp2))
30133026
0 commit comments