Skip to content

Commit 3efcebe

Browse files
committed
Refine snapshot logic to take spurious nulls in weak references into account
1 parent d5eb457 commit 3efcebe

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,19 @@ object TyperState {
2323
.setReporter(new ConsoleReporter())
2424
.setCommittable(true)
2525

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

2828
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)
3033

3134
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)
3439
ts.ownedVars = tvs
3540
ts.constraint = c
3641
}
@@ -74,7 +79,11 @@ class TyperState() {
7479

7580
private var isCommitted: Boolean = _
7681

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+
*/
7887
private var myOwnedVars: TypeVars = _
7988
def ownedVars: TypeVars = myOwnedVars
8089
def ownedVars_=(vs: TypeVars): Unit = myOwnedVars = vs
@@ -187,7 +196,7 @@ class TyperState() {
187196
Stats.record("typerState.gc")
188197
val toCollect = new mutable.ListBuffer[TypeLambda]
189198
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
191200
val inst = constraint.instType(tvar)
192201
if inst.exists then
193202
tvar.setInst(inst)

0 commit comments

Comments
 (0)