@@ -648,11 +648,13 @@ trait ConstraintHandling {
648648 * as those could leak the annotation to users (see run/inferred-repeated-result).
649649 */
650650 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+
651655 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
656658
657659 def widenSingle (tp : Type ) =
658660 val tpw = tp.widenSingletons
@@ -665,8 +667,16 @@ trait ConstraintHandling {
665667 val wideInst =
666668 if isSingleton(bound) then inst
667669 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
670680 val widened = dropTransparentTraits(widenedFromUnion, bound)
671681 widenIrreducible(widened)
672682
0 commit comments