@@ -23,14 +23,19 @@ object TyperState {
23
23
.setReporter(new ConsoleReporter ())
24
24
.setCommittable(true )
25
25
26
- opaque type Snapshot = (Constraint , TypeVars )
26
+ opaque type Snapshot = (Constraint , TypeVars , TypeVars )
27
27
28
28
extension (ts : TyperState )
29
- def snapshot (): Snapshot = (ts.constraint, ts.ownedVars)
29
+ def snapshot ()(using Context ): Snapshot =
30
+ var previouslyInstantiated : TypeVars = SimpleIdentitySet .empty
31
+ for tv <- ts.ownedVars do if tv.inst.exists then previouslyInstantiated += tv
32
+ (ts.constraint, ts.ownedVars, previouslyInstantiated)
30
33
31
34
def resetTo (state : Snapshot )(using Context ): Unit =
32
- val (c, tvs) = state
33
- for tv <- tvs do if tv.isInstantiated then tv.resetInst(ts)
35
+ val (c, tvs, previouslyInstantiated) = state
36
+ for tv <- tvs do
37
+ if tv.inst.exists && ! previouslyInstantiated.contains(tv) then
38
+ tv.resetInst(ts)
34
39
ts.ownedVars = tvs
35
40
ts.constraint = c
36
41
}
@@ -74,7 +79,11 @@ class TyperState() {
74
79
75
80
private var isCommitted : Boolean = _
76
81
77
- /** The set of uninstantiated type variables which have this state as their owning state */
82
+ /** The set of uninstantiated type variables which have this state as their owning state
83
+ * NOTE: It could be that a variable in `ownedVars` is already instantiated. This is because
84
+ * the link between ownedVars and variable instantiation in TypeVar#setInst is made up
85
+ * from a weak reference and weak references can have spurious nulls.
86
+ */
78
87
private var myOwnedVars : TypeVars = _
79
88
def ownedVars : TypeVars = myOwnedVars
80
89
def ownedVars_= (vs : TypeVars ): Unit = myOwnedVars = vs
@@ -187,7 +196,7 @@ class TyperState() {
187
196
Stats .record(" typerState.gc" )
188
197
val toCollect = new mutable.ListBuffer [TypeLambda ]
189
198
for tvar <- ownedVars do
190
- if ! tvar.inst.exists then
199
+ if ! tvar.inst.exists then // See comment of `ownedVars` for why this test is necessary
191
200
val inst = constraint.instType(tvar)
192
201
if inst.exists then
193
202
tvar.setInst(inst)
0 commit comments