@@ -23,21 +23,22 @@ object TyperState {
23
23
.setReporter(new ConsoleReporter ())
24
24
.setCommittable(true )
25
25
26
- opaque type Snapshot = (Constraint , TypeVars , TypeVars )
26
+ opaque type Snapshot = (Constraint , TypeVars , TypeVars , TypeVars )
27
27
28
28
extension (ts : TyperState )
29
29
def snapshot ()(using Context ): Snapshot =
30
30
var previouslyInstantiated : TypeVars = SimpleIdentitySet .empty
31
31
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 )
33
33
34
34
def resetTo (state : Snapshot )(using Context ): Unit =
35
- val (c, tvs, previouslyInstantiated) = state
35
+ val (c, tvs, previouslyInstantiated, rvars ) = state
36
36
for tv <- tvs do
37
37
if tv.inst.exists && ! previouslyInstantiated.contains(tv) then
38
38
tv.resetInst(ts)
39
39
ts.ownedVars = tvs
40
40
ts.constraint = c
41
+ ts.rigidVars = rvars
41
42
}
42
43
43
44
class TyperState () {
@@ -89,6 +90,14 @@ class TyperState() {
89
90
def ownedVars : TypeVars = myOwnedVars
90
91
def ownedVars_= (vs : TypeVars ): Unit = myOwnedVars = vs
91
92
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
+
92
101
/** Initializes all fields except reporter, isCommittable, which need to be
93
102
* set separately.
94
103
*/
@@ -99,16 +108,19 @@ class TyperState() {
99
108
this .myConstraint = constraint
100
109
this .previousConstraint = constraint
101
110
this .myOwnedVars = SimpleIdentitySet .empty
111
+ this .myRigidVars = SimpleIdentitySet .empty
102
112
this .isCommitted = false
103
113
this
104
114
105
115
/** A fresh typer state with the same constraint as this one. */
106
116
def fresh (reporter : Reporter = StoreReporter (this .reporter, fromTyperState = true ),
107
117
committable : Boolean = this .isCommittable): TyperState =
108
118
util.Stats .record(" TyperState.fresh" )
109
- TyperState ().init(this , this .constraint)
119
+ val ts = TyperState ().init(this , this .constraint)
110
120
.setReporter(reporter)
111
121
.setCommittable(committable)
122
+ ts.rigidVars = this .rigidVars
123
+ ts
112
124
113
125
/** The uninstantiated variables */
114
126
def uninstVars : collection.Seq [TypeVar ] = constraint.uninstVars
@@ -161,6 +173,7 @@ class TyperState() {
161
173
constr.println(i " committing $this to $targetState, fromConstr = $constraint, toConstr = ${targetState.constraint}" )
162
174
if targetState.constraint eq previousConstraint then
163
175
targetState.constraint = constraint
176
+ targetState.rigidVars = rigidVars
164
177
if ! ownedVars.isEmpty then ownedVars.foreach(targetState.includeVar)
165
178
else
166
179
targetState.mergeConstraintWith(this )
@@ -213,6 +226,7 @@ class TyperState() {
213
226
val otherLos = other.lower(p)
214
227
val otherHis = other.upper(p)
215
228
val otherEntry = other.entry(p)
229
+ if that.rigidVars.contains(tv) then this .myRigidVars += tv
216
230
( (otherLos eq constraint.lower(p)) || otherLos.forall(_ <:< p)) &&
217
231
( (otherHis eq constraint.upper(p)) || otherHis.forall(p <:< _)) &&
218
232
((otherEntry eq constraint.entry(p)) || otherEntry.match
0 commit comments