@@ -648,11 +648,13 @@ trait ConstraintHandling {
648
648
* as those could leak the annotation to users (see run/inferred-repeated-result).
649
649
*/
650
650
def widenInferred (inst : Type , bound : Type , widenUnions : Boolean )(using Context ): Type =
651
+ def typeSize (tp : Type ): Int = tp match
652
+ case tp : AndOrType => typeSize(tp.tp1) + typeSize(tp.tp2)
653
+ case _ => 1
654
+
651
655
def widenOr (tp : Type ) =
652
- if widenUnions then
653
- val tpw = tp.widenUnion
654
- if (tpw ne tp) && ! tpw.isTransparent() && (tpw <:< bound) then tpw else tp
655
- else tp.hardenUnions
656
+ val tpw = tp.widenUnion
657
+ if (tpw ne tp) && ! tpw.isTransparent() && (tpw <:< bound) then tpw else tp
656
658
657
659
def widenSingle (tp : Type ) =
658
660
val tpw = tp.widenSingletons
@@ -665,8 +667,16 @@ trait ConstraintHandling {
665
667
val wideInst =
666
668
if isSingleton(bound) then inst
667
669
else
668
- val widenedFromSingle = widenSingle(inst)
669
- val widenedFromUnion = widenOr(widenedFromSingle)
670
+ val widenedFromUnion =
671
+ if widenUnions && typeSize(inst) > 64 then
672
+ // If the inferred type `inst` is too large, the subtype check for `bound` in `widenSingle`
673
+ // can be expensive due to comparisons between large union types, so we avoid it by
674
+ // `widenUnion` directly here.
675
+ // See issue #19907.
676
+ widenOr(inst)
677
+ else
678
+ val widenedFromSingle = widenSingle(inst)
679
+ if widenUnions then widenOr(widenedFromSingle) else widenedFromSingle.hardenUnions
670
680
val widened = dropTransparentTraits(widenedFromUnion, bound)
671
681
widenIrreducible(widened)
672
682
0 commit comments