Skip to content

Commit 968b5da

Browse files
authored
Merge pull request #188 from scala/backport-lts-3.3-19995
Backport "Fix scala#19907: Skip soft unions in widenSingle of widenInferred" to 3.3 LTS
2 parents 71aca20 + 2ea9d6e commit 968b5da

File tree

6 files changed

+2201
-16
lines changed

6 files changed

+2201
-16
lines changed

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -660,11 +660,20 @@ trait ConstraintHandling {
660660
def widenOr(tp: Type) =
661661
if widenUnions then
662662
val tpw = tp.widenUnion
663-
if (tpw ne tp) && !isTransparent(tpw, traitOnly = false) && (tpw <:< bound) then tpw else tp
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 widenUnion on soft unions is independent of whether singletons
667+
// are widened or not. This avoids an expensive subtype check in widenSingle,
668+
// see i19907_*.scala for test cases.
669+
widenSingle(tp, skipSoftUnions = false)
670+
else if tpw <:< bound then tpw
671+
else tp
672+
else tp
664673
else tp.hardenUnions
665674

666-
def widenSingle(tp: Type) =
667-
val tpw = tp.widenSingletons
675+
def widenSingle(tp: Type, skipSoftUnions: Boolean) =
676+
val tpw = tp.widenSingletons(skipSoftUnions)
668677
if (tpw ne tp) && (tpw <:< bound) then tpw else tp
669678

670679
def isSingleton(tp: Type): Boolean = tp match
@@ -674,7 +683,7 @@ trait ConstraintHandling {
674683
val wideInst =
675684
if isSingleton(bound) then inst
676685
else
677-
val widenedFromSingle = widenSingle(inst)
686+
val widenedFromSingle = widenSingle(inst, skipSoftUnions = widenUnions)
678687
val widenedFromUnion = widenOr(widenedFromSingle)
679688
val widened = dropTransparentTraits(widenedFromUnion, bound)
680689
widenIrreducible(widened)

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)