In salvage(), there is a point where we're done solving, but we haven't
yet torn down ConstraintSystem::solverState, so the trail is still
active.
It was possible to cause a change to be recorded, because of the
path compression we do in TypeVariableType::getRepresentative().
We have a similar situation where we don't want to do path compression
when we're looking up a type variable's representative in the middle
of undo(). Generalize the existing UndoActive flag to Closed, and set
it after solving in salvage() as well.
While we're here, clean up an existing place where we would check
isUndoActive() to not do that anymore, so now getRepresentative() is
the only place that checks the state of the trail.
A better cleanup would be to try to refactor or eliminate SolverState
entirely, but this fix is pretty clean.
Note that the test cases are somewhat random because the exact scenario
is hard to trigger; you need to set up an invalid expression where the
type variables are set up in just the right way so that path compression
kicks in.
- Fixes rdar://152143989.
- Fixes https://github.com/swiftlang/swift/issues/81801.
- Fixes https://github.com/swiftlang/swift/issues/84884.
Instead of "catch call" `InferredBindings` that calls `retract` on
`undo`, let's track each mutation of the potential bindings with a
dedicated trail node and undo each individually. This change reduced
the amount of work that `undo` has to make on every scope rollback
and would help helpful for transitive binding inference as well.
Instead of using a flag in `addBinding`, let's record what type variable
does the binding belong to in `PotentialBinding` itself. This is going
to help remove bindings introduced transitively when the inference is
done lazily.
- Track environments for `PackExpansionExpr` directly
instead of using a locator.
- Split up the querying and creation of the environment
such that the mismatch logic can be done directly in
CSSimplify instead of duplicating it.
- Just store the environment directly instead of
the shape and UUID.
Resolve a couple of FIXMEs by using `dumpAnchor` to
dump a couple of ASTNodes. This uses the same
compact representation as used in ConstraintLocator
dumping.
Instead of making an undo() do an infer(), let's record fine-grained
changes about what was retracted, and directly re-insert the same
elements into the data structures.
`dumpActiveScopeChanges` is used as part of `-debug-constraints`
and could be overwhelming if there are a lot of changes in the scope
because it prints every change including binding inference from
every applicable constraint.
These changes make `dumpActiveScopeChanges` more of summary of
what happened with type variables and constraints so far which
is much easier to navigate while debugging.