Skip to content

Commit 7aef415

Browse files
committed
Skip widenSingletons in widenInferred if the inferred type is too large
1 parent 0ea0eba commit 7aef415

File tree

4 files changed

+2190
-6
lines changed

4 files changed

+2190
-6
lines changed

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)