@@ -1479,9 +1479,39 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
14791479
14801480 /** Like tp1 <:< tp2, but returns false immediately if we know that
14811481 * 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.
14821489 */
14831490 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
14851515 // println(s"useless subtype: $tp1 <:< $tp2")
14861516 false
14871517 else isSubType(tp1, tp2, approx.addLow)
@@ -2091,19 +2121,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
20912121 tp1.parent.asInstanceOf [RefinedType ],
20922122 tp2.parent.asInstanceOf [RefinedType ], limit))
20932123
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-
21072124 /** Defer constraining type variables when compared against prototypes */
21082125 def isMatchedByProto (proto : ProtoType , tp : Type ): Boolean = tp.stripTypeVar match {
21092126 case tp : TypeParamRef if constraint contains tp => true
0 commit comments