Skip to content

Commit 198750b

Browse files
authored
Fix #19907: Skip soft unions in widenSingle of widenInferred (#19995)
Fix #19907: Skip soft unions in widenSingle of widenInferred
2 parents 7171211 + fd61afb commit 198750b

File tree

6 files changed

+2199
-14
lines changed

6 files changed

+2199
-14
lines changed

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -651,11 +651,20 @@ trait ConstraintHandling {
651651
def widenOr(tp: Type) =
652652
if widenUnions then
653653
val tpw = tp.widenUnion
654-
if (tpw ne tp) && !tpw.isTransparent() && (tpw <:< bound) then tpw else tp
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 widenUnion on soft unions is independent of whether singletons
658+
// are widened or not. This avoids an expensive subtype check in widenSingle,
659+
// see i19907_*.scala for test cases.
660+
widenSingle(tp, skipSoftUnions = false)
661+
else if tpw <:< bound then tpw
662+
else tp
663+
else tp
655664
else tp.hardenUnions
656665

657-
def widenSingle(tp: Type) =
658-
val tpw = tp.widenSingletons
666+
def widenSingle(tp: Type, skipSoftUnions: Boolean) =
667+
val tpw = tp.widenSingletons(skipSoftUnions)
659668
if (tpw ne tp) && (tpw <:< bound) then tpw else tp
660669

661670
def isSingleton(tp: Type): Boolean = tp match
@@ -665,7 +674,7 @@ trait ConstraintHandling {
665674
val wideInst =
666675
if isSingleton(bound) then inst
667676
else
668-
val widenedFromSingle = widenSingle(inst)
677+
val widenedFromSingle = widenSingle(inst, skipSoftUnions = widenUnions)
669678
val widenedFromUnion = widenOr(widenedFromSingle)
670679
val widened = dropTransparentTraits(widenedFromUnion, bound)
671680
widenIrreducible(widened)

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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 11 additions & 9 deletions
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)