Skip to content

Commit 612ba92

Browse files
committed
Alternative scheme that does not require a size limit
1 parent c5c94f0 commit 612ba92

File tree

3 files changed

+28
-27
lines changed

3 files changed

+28
-27
lines changed

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

+16-17
Original file line numberDiff line numberDiff line change
@@ -648,16 +648,23 @@ 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-
655651
def widenOr(tp: Type) =
656-
val tpw = tp.widenUnion
657-
if (tpw ne tp) && !tpw.isTransparent() && (tpw <:< bound) then tpw else tp
652+
if widenUnions then
653+
val tpw = tp.widenUnion
654+
if tpw ne tp then
655+
if tpw.isTransparent() then
656+
// Now also widen singletons of soft unions. Before these were skipped
657+
// since we widenUnion on soft unions is independent of whether singletons
658+
// are widened or not. This avoids an expensive subtype check in widenSingle,
659+
// see 19907_*.scala for test cases.
660+
tp.widenSingletons()
661+
else if tpw <:< bound then tpw
662+
else tp
663+
else tp
664+
else tp.hardenUnions
658665

659666
def widenSingle(tp: Type) =
660-
val tpw = tp.widenSingletons
667+
val tpw = tp.widenSingletons(skipSoftUnions = widenUnions)
661668
if (tpw ne tp) && (tpw <:< bound) then tpw else tp
662669

663670
def isSingleton(tp: Type): Boolean = tp match
@@ -667,16 +674,8 @@ trait ConstraintHandling {
667674
val wideInst =
668675
if isSingleton(bound) then inst
669676
else
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
677+
val widenedFromSingle = widenSingle(inst)
678+
val widenedFromUnion = widenOr(widenedFromSingle)
680679
val widened = dropTransparentTraits(widenedFromUnion, bound)
681680
widenIrreducible(widened)
682681

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
487487
def widenOK =
488488
(tp2.widenSingletons eq tp2)
489489
&& (tp1.widenSingletons ne tp1)
490-
&& inFrozenGadtAndConstraint(recur(tp1.widenSingletons, tp2))
490+
&& inFrozenGadtAndConstraint(recur(tp1.widenSingletons(), tp2))
491491

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

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

+11-9
Original file line numberDiff line numberDiff line change
@@ -1377,15 +1377,15 @@ object Types extends TypeUtils {
13771377
* and going to the operands of & and |.
13781378
* Overridden and cached in OrType.
13791379
*/
1380-
def widenSingletons(using Context): Type = dealias match {
1380+
def widenSingletons(skipSoftUnions: Boolean = false)(using Context): Type = dealias match {
13811381
case tp: SingletonType =>
13821382
tp.widen
13831383
case tp: OrType =>
1384-
val tp1w = tp.widenSingletons
1384+
val tp1w = tp.widenSingletons(skipSoftUnions)
13851385
if (tp1w eq tp) this else tp1w
13861386
case tp: AndType =>
1387-
val tp1w = tp.tp1.widenSingletons
1388-
val tp2w = tp.tp2.widenSingletons
1387+
val tp1w = tp.tp1.widenSingletons(skipSoftUnions)
1388+
val tp2w = tp.tp2.widenSingletons(skipSoftUnions)
13891389
if ((tp.tp1 eq tp1w) && (tp.tp2 eq tp2w)) this else tp1w & tp2w
13901390
case _ =>
13911391
this
@@ -3619,8 +3619,8 @@ object Types extends TypeUtils {
36193619
else tp1n.atoms | tp2n.atoms
36203620

36213621
private def computeWidenSingletons()(using Context): Type =
3622-
val tp1w = tp1.widenSingletons
3623-
val tp2w = tp2.widenSingletons
3622+
val tp1w = tp1.widenSingletons()
3623+
val tp2w = tp2.widenSingletons()
36243624
if ((tp1 eq tp1w) && (tp2 eq tp2w)) this else TypeComparer.lub(tp1w, tp2w, isSoft = isSoft)
36253625

36263626
private def ensureAtomsComputed()(using Context): Unit =
@@ -3633,9 +3633,11 @@ object Types extends TypeUtils {
36333633
ensureAtomsComputed()
36343634
myAtoms
36353635

3636-
override def widenSingletons(using Context): Type =
3637-
ensureAtomsComputed()
3638-
myWidened
3636+
override def widenSingletons(skipSoftUnions: Boolean)(using Context): Type =
3637+
if isSoft && skipSoftUnions then this
3638+
else
3639+
ensureAtomsComputed()
3640+
myWidened
36393641

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

0 commit comments

Comments
 (0)