Skip to content

Commit d387e8f

Browse files
committed
Properly re-own type variables when merging constraints
The documentation for myOwnedVars used to say that it could contain already instantiated variables because "weak references can have spurious nulls" but I think that's incorrect: the documentation of WeakReference makes no mention of spurious nulls, the object it references should only be replaced by null if it cannot be reached through a non-weak reference. Instead I believe the issue was that `mergeConstraintWith` did not set the `owningState` of type variables that it now owns.
1 parent 8f3fdf5 commit d387e8f

File tree

1 file changed

+12
-11
lines changed

1 file changed

+12
-11
lines changed

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ class TyperState() {
7979

8080
private var isCommitted: Boolean = _
8181

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.
82+
/** The set of uninstantiated type variables which have this state as their owning state.
83+
*
84+
* Invariant:
85+
* `tstate.ownedVars.contains(tvar)` iff `tvar.owningState.get eq tstate`
8686
*/
8787
private var myOwnedVars: TypeVars = _
8888
def ownedVars: TypeVars = myOwnedVars
@@ -176,7 +176,7 @@ class TyperState() {
176176
that.ensureNotConflicting(constraint)
177177
constraint = constraint & (that.constraint, otherHasErrors = that.reporter.errorsReported)
178178
for tvar <- constraint.uninstVars do
179-
if !isOwnedAnywhere(this, tvar) then ownedVars += tvar
179+
if !isOwnedAnywhere(this, tvar) then includeVar(tvar)
180180
for tl <- constraint.domainLambdas do
181181
if constraint.isRemovable(tl) then constraint = constraint.remove(tl)
182182

@@ -196,12 +196,13 @@ class TyperState() {
196196
Stats.record("typerState.gc")
197197
val toCollect = new mutable.ListBuffer[TypeLambda]
198198
for tvar <- ownedVars do
199-
if !tvar.inst.exists then // See comment of `ownedVars` for why this test is necessary
200-
val inst = constraint.instType(tvar)
201-
if inst.exists then
202-
tvar.setInst(inst)
203-
val tl = tvar.origin.binder
204-
if constraint.isRemovable(tl) then toCollect += tl
199+
assert(tvar.owningState.get eq this, s"Inconsistent state in $this: it owns $tvar whose owningState is ${tvar.owningState.get}")
200+
assert(!tvar.inst.exists, s"Inconsistent state in $this: it owns $tvar which is already instantiated")
201+
val inst = constraint.instType(tvar)
202+
if inst.exists then
203+
tvar.setInst(inst)
204+
val tl = tvar.origin.binder
205+
if constraint.isRemovable(tl) then toCollect += tl
205206
for tl <- toCollect do
206207
constraint = constraint.remove(tl)
207208

0 commit comments

Comments
 (0)