Skip to content

Commit bccbaf7

Browse files
committed
Keep track of rigid type variables in TyperState
1 parent 7f4af84 commit bccbaf7

File tree

3 files changed

+22
-13
lines changed

3 files changed

+22
-13
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
494494

495495
def hardenTypeVars(tp2: Type): Unit = tp2.dealiasKeepRefiningAnnots match
496496
case tvar: TypeVar if constraint.contains(tvar.origin) =>
497-
tvar.widenUnions = false
497+
state.rigidVars += tvar
498498
case tp2: TypeParamRef if constraint.contains(tp2) =>
499499
hardenTypeVars(constraint.typeVarOfParam(tp2))
500500
case tp2: AndOrType =>

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,22 @@ object TyperState {
2323
.setReporter(new ConsoleReporter())
2424
.setCommittable(true)
2525

26-
opaque type Snapshot = (Constraint, TypeVars, TypeVars)
26+
opaque type Snapshot = (Constraint, TypeVars, TypeVars, TypeVars)
2727

2828
extension (ts: TyperState)
2929
def snapshot()(using Context): Snapshot =
3030
var previouslyInstantiated: TypeVars = SimpleIdentitySet.empty
3131
for tv <- ts.ownedVars do if tv.inst.exists then previouslyInstantiated += tv
32-
(ts.constraint, ts.ownedVars, previouslyInstantiated)
32+
(ts.constraint, ts.ownedVars, previouslyInstantiated, ts.rigidVars)
3333

3434
def resetTo(state: Snapshot)(using Context): Unit =
35-
val (c, tvs, previouslyInstantiated) = state
35+
val (c, tvs, previouslyInstantiated, rvars) = state
3636
for tv <- tvs do
3737
if tv.inst.exists && !previouslyInstantiated.contains(tv) then
3838
tv.resetInst(ts)
3939
ts.ownedVars = tvs
4040
ts.constraint = c
41+
ts.rigidVars = rvars
4142
}
4243

4344
class TyperState() {
@@ -89,6 +90,14 @@ class TyperState() {
8990
def ownedVars: TypeVars = myOwnedVars
9091
def ownedVars_=(vs: TypeVars): Unit = myOwnedVars = vs
9192

93+
/** The set of type variables `tv` such that, if `tv` is instantiated to
94+
* its lower bound, top-level soft unions in the instance type are converted
95+
* to hard unions instead of being widened in `widenOr`.
96+
*/
97+
private var myRigidVars: TypeVars = _
98+
def rigidVars: TypeVars = myRigidVars
99+
def rigidVars_=(tvs: TypeVars): Unit = myRigidVars = tvs
100+
92101
/** Initializes all fields except reporter, isCommittable, which need to be
93102
* set separately.
94103
*/
@@ -99,16 +108,19 @@ class TyperState() {
99108
this.myConstraint = constraint
100109
this.previousConstraint = constraint
101110
this.myOwnedVars = SimpleIdentitySet.empty
111+
this.myRigidVars = SimpleIdentitySet.empty
102112
this.isCommitted = false
103113
this
104114

105115
/** A fresh typer state with the same constraint as this one. */
106116
def fresh(reporter: Reporter = StoreReporter(this.reporter, fromTyperState = true),
107117
committable: Boolean = this.isCommittable): TyperState =
108118
util.Stats.record("TyperState.fresh")
109-
TyperState().init(this, this.constraint)
119+
val ts = TyperState().init(this, this.constraint)
110120
.setReporter(reporter)
111121
.setCommittable(committable)
122+
ts.rigidVars = this.rigidVars
123+
ts
112124

113125
/** The uninstantiated variables */
114126
def uninstVars: collection.Seq[TypeVar] = constraint.uninstVars
@@ -161,6 +173,7 @@ class TyperState() {
161173
constr.println(i"committing $this to $targetState, fromConstr = $constraint, toConstr = ${targetState.constraint}")
162174
if targetState.constraint eq previousConstraint then
163175
targetState.constraint = constraint
176+
targetState.rigidVars = rigidVars
164177
if !ownedVars.isEmpty then ownedVars.foreach(targetState.includeVar)
165178
else
166179
targetState.mergeConstraintWith(this)
@@ -213,6 +226,7 @@ class TyperState() {
213226
val otherLos = other.lower(p)
214227
val otherHis = other.upper(p)
215228
val otherEntry = other.entry(p)
229+
if that.rigidVars.contains(tv) then this.myRigidVars += tv
216230
( (otherLos eq constraint.lower(p)) || otherLos.forall(_ <:< p)) &&
217231
( (otherHis eq constraint.upper(p)) || otherHis.forall(p <:< _)) &&
218232
((otherEntry eq constraint.entry(p)) || otherEntry.match

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,14 +4536,6 @@ object Types {
45364536
private[core] var owningState: WeakReference[TyperState] | Null =
45374537
if (creatorState == null) null else new WeakReference(creatorState)
45384538

4539-
private var myWidenUnions = true
4540-
4541-
/** If true, widen unions in lower bound before instantiating this variable to it.
4542-
* If false, convert unions in lower bound to hard unions instead
4543-
*/
4544-
private [core] def widenUnions = myWidenUnions
4545-
private[core] def widenUnions_=(x: Boolean): Unit = myWidenUnions = x
4546-
45474539
/** The instance type of this variable, or NoType if the variable is currently
45484540
* uninstantiated
45494541
*/
@@ -4583,6 +4575,9 @@ object Types {
45834575
else
45844576
instantiateWith(tp)
45854577

4578+
def widenUnions(using Context) =
4579+
!ctx.typerState.rigidVars.contains(this)
4580+
45864581
/** For uninstantiated type variables: the entry in the constraint (either bounds or
45874582
* provisional instance value)
45884583
*/

0 commit comments

Comments
 (0)