Skip to content

Commit 613e6e5

Browse files
oderskytgodzik
authored andcommitted
Alternative scheme that does not require a size limit
1 parent 6ef1e8d commit 613e6e5

File tree

3 files changed

+29
-39
lines changed

3 files changed

+29
-39
lines changed

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

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -657,27 +657,23 @@ 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-
664660
def widenOr(tp: Type) =
665661
if widenUnions then
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
662+
val tpw = tp.widenUnion
663+
if tpw ne tp then
664+
if tpw.isTransparent() then
665+
// Now also widen singletons of soft unions. Before these were skipped
666+
// since we widenUnion on soft unions is independent of whether singletons
667+
// are widened or not. This avoids an expensive subtype check in widenSingle,
668+
// see 19907_*.scala for test cases.
669+
tp.widenSingletons()
670+
else if tpw <:< bound then tpw
671+
else tp
672+
else tp
673+
else tp.hardenUnions
678674

679675
def widenSingle(tp: Type) =
680-
val tpw = tp.widenSingletons
676+
val tpw = tp.widenSingletons(skipSoftUnions = widenUnions)
681677
if (tpw ne tp) && (tpw <:< bound) then tpw else tp
682678

683679
def isSingleton(tp: Type): Boolean = tp match
@@ -687,16 +683,8 @@ trait ConstraintHandling {
687683
val wideInst =
688684
if isSingleton(bound) then inst
689685
else
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
686+
val widenedFromSingle = widenSingle(inst)
687+
val widenedFromUnion = widenOr(widenedFromSingle)
700688
val widened = dropTransparentTraits(widenedFromUnion, bound)
701689
widenIrreducible(widened)
702690

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
479479
def widenOK =
480480
(tp2.widenSingletons eq tp2)
481481
&& (tp1.widenSingletons ne tp1)
482-
&& inFrozenGadtAndConstraint(recur(tp1.widenSingletons, tp2))
482+
&& inFrozenGadtAndConstraint(recur(tp1.widenSingletons(), tp2))
483483

484484
def joinOK = tp2.dealiasKeepRefiningAnnots match {
485485
case tp2: AppliedType if !tp2.tycon.typeSymbol.isClass =>

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,15 +1365,15 @@ object Types extends TypeUtils {
13651365
* and going to the operands of & and |.
13661366
* Overridden and cached in OrType.
13671367
*/
1368-
def widenSingletons(using Context): Type = dealias match {
1368+
def widenSingletons(skipSoftUnions: Boolean = false)(using Context): Type = dealias match {
13691369
case tp: SingletonType =>
13701370
tp.widen
13711371
case tp: OrType =>
1372-
val tp1w = tp.widenSingletons
1372+
val tp1w = tp.widenSingletons(skipSoftUnions)
13731373
if (tp1w eq tp) this else tp1w
13741374
case tp: AndType =>
1375-
val tp1w = tp.tp1.widenSingletons
1376-
val tp2w = tp.tp2.widenSingletons
1375+
val tp1w = tp.tp1.widenSingletons(skipSoftUnions)
1376+
val tp2w = tp.tp2.widenSingletons(skipSoftUnions)
13771377
if ((tp.tp1 eq tp1w) && (tp.tp2 eq tp2w)) this else tp1w & tp2w
13781378
case _ =>
13791379
this
@@ -3532,8 +3532,8 @@ object Types extends TypeUtils {
35323532
else tp1.atoms | tp2.atoms
35333533

35343534
private def computeWidenSingletons()(using Context): Type =
3535-
val tp1w = tp1.widenSingletons
3536-
val tp2w = tp2.widenSingletons
3535+
val tp1w = tp1.widenSingletons()
3536+
val tp2w = tp2.widenSingletons()
35373537
if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else TypeComparer.lub(tp1w, tp2w, isSoft = isSoft)
35383538

35393539
override def atoms(using Context): Atoms =
@@ -3542,11 +3542,13 @@ object Types extends TypeUtils {
35423542
if !isProvisional then atomsRunId = ctx.runId
35433543
myAtoms
35443544

3545-
override def widenSingletons(using Context): Type =
3546-
if widenedRunId != ctx.runId then
3547-
myWidened = computeWidenSingletons()
3548-
if !isProvisional then widenedRunId = ctx.runId
3549-
myWidened
3545+
override def widenSingletons(skipSoftUnions: Boolean)(using Context): Type =
3546+
if isSoft && skipSoftUnions then this
3547+
else
3548+
if widenedRunId != ctx.runId then
3549+
myWidened = computeWidenSingletons()
3550+
if !isProvisional then widenedRunId = ctx.runId
3551+
myWidened
35503552

35513553
def derivedOrType(tp1: Type, tp2: Type, soft: Boolean = isSoft)(using Context): Type =
35523554
if ((tp1 eq this.tp1) && (tp2 eq this.tp2) && soft == isSoft) this

0 commit comments

Comments
 (0)