Skip to content

Commit 8617586

Browse files
noti0na1tgodzik
authored andcommitted
Skip widenSingletons in widenInferred if the inferred type is too large
1 parent 98b374a commit 8617586

File tree

4 files changed

+2200
-5
lines changed

4 files changed

+2200
-5
lines changed

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

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -657,11 +657,24 @@ trait ConstraintHandling {
657657
* as those could leak the annotation to users (see run/inferred-repeated-result).
658658
*/
659659
def widenInferred(inst: Type, bound: Type, widenUnions: Boolean)(using Context): Type =
660+
def typeSize(tp: Type): Int = tp match
661+
case tp: AndOrType => typeSize(tp.tp1) + typeSize(tp.tp2)
662+
case _ => 1
663+
660664
def widenOr(tp: Type) =
661665
if widenUnions then
662-
val tpw = tp.widenUnion
663-
if (tpw ne tp) && !isTransparent(tpw, traitOnly = false) && (tpw <:< bound) then tpw else tp
664-
else tp.hardenUnions
666+
val tpw = tp.widenUnion
667+
if tpw ne tp then
668+
if tpw.isTransparent() then
669+
// Now also widen singletons of soft unions. Before these were skipped
670+
// since we widenUnion on soft unions is independent of whether singletons
671+
// are widened or not. This avoids an expensive subtype check in widenSingle,
672+
// see 19907_*.scala for test cases.
673+
tp.widenSingletons()
674+
else if tpw <:< bound then tpw
675+
else tp
676+
else tp
677+
else tp.hardenUnions
665678

666679
def widenSingle(tp: Type) =
667680
val tpw = tp.widenSingletons
@@ -674,8 +687,16 @@ trait ConstraintHandling {
674687
val wideInst =
675688
if isSingleton(bound) then inst
676689
else
677-
val widenedFromSingle = widenSingle(inst)
678-
val widenedFromUnion = widenOr(widenedFromSingle)
690+
val widenedFromUnion =
691+
if widenUnions && typeSize(inst) > 64 then
692+
// If the inferred type `inst` is too large, the subtype check for `bound` in `widenSingle`
693+
// can be expensive due to comparisons between large union types, so we avoid it by
694+
// `widenUnion` directly here.
695+
// See issue #19907.
696+
widenOr(inst)
697+
else
698+
val widenedFromSingle = widenSingle(inst)
699+
if widenUnions then widenOr(widenedFromSingle) else widenedFromSingle.hardenUnions
679700
val widened = dropTransparentTraits(widenedFromUnion, bound)
680701
widenIrreducible(widened)
681702

0 commit comments

Comments
 (0)