@@ -1488,30 +1488,18 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1488
1488
* See #17465.
1489
1489
*/
1490
1490
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 .bothHaveOr(covered1, covered2) then
1515
1503
// println(s"useless subtype: $tp1 <:< $tp2")
1516
1504
false
1517
1505
else isSubType(tp1, tp2, approx.addLow)
@@ -3008,6 +2996,31 @@ object TypeComparer {
3008
2996
end ApproxState
3009
2997
type ApproxState = ApproxState .Repr
3010
2998
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 min that
3018
+
3019
+ inline def bothHaveOr (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
+
3011
3024
def topLevelSubType (tp1 : Type , tp2 : Type )(using Context ): Boolean =
3012
3025
comparing(_.topLevelSubType(tp1, tp2))
3013
3026
0 commit comments