@@ -1479,9 +1479,39 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
1479
1479
1480
1480
/** Like tp1 <:< tp2, but returns false immediately if we know that
1481
1481
* the case was covered previously during subtyping.
1482
+ *
1483
+ * A type has been covered previously in subtype checking if it
1484
+ * is some combination of TypeRefs that point to classes, where the
1485
+ * combiners are AppliedTypes, RefinedTypes, RecTypes, And/Or-Types or AnnotatedTypes.
1486
+ *
1487
+ * The exception is that if both sides contain OrTypes, the check hasn't been covered.
1488
+ * See #17465.
1482
1489
*/
1483
1490
def isNewSubType (tp1 : Type ): Boolean =
1484
- if (isCovered(tp1) && isCovered(tp2))
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
1485
1515
// println(s"useless subtype: $tp1 <:< $tp2")
1486
1516
false
1487
1517
else isSubType(tp1, tp2, approx.addLow)
@@ -2091,19 +2121,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
2091
2121
tp1.parent.asInstanceOf [RefinedType ],
2092
2122
tp2.parent.asInstanceOf [RefinedType ], limit))
2093
2123
2094
- /** A type has been covered previously in subtype checking if it
2095
- * is some combination of TypeRefs that point to classes, where the
2096
- * combiners are AppliedTypes, RefinedTypes, RecTypes, And/Or-Types or AnnotatedTypes.
2097
- */
2098
- private def isCovered (tp : Type ): Boolean = tp.dealiasKeepRefiningAnnots.stripTypeVar match {
2099
- case tp : TypeRef => tp.symbol.isClass && tp.symbol != NothingClass && tp.symbol != NullClass
2100
- case tp : AppliedType => isCovered(tp.tycon)
2101
- case tp : RefinedOrRecType => isCovered(tp.parent)
2102
- case tp : AndType => isCovered(tp.tp1) && isCovered(tp.tp2)
2103
- case tp : OrType => isCovered(tp.tp1) && isCovered(tp.tp2)
2104
- case _ => false
2105
- }
2106
-
2107
2124
/** Defer constraining type variables when compared against prototypes */
2108
2125
def isMatchedByProto (proto : ProtoType , tp : Type ): Boolean = tp.stripTypeVar match {
2109
2126
case tp : TypeParamRef if constraint contains tp => true
0 commit comments