[ty] Refactor constraint traversal and cache satisfiability checks (#29492)
This PR extracts some refactoring changes out of #29027 so they can be
reviewed separately. This should be entirely behavioral neutral.
The changes:
- There is now a clear separation between "atomic" constraints and
non-atomic constraints. There aren't actually any non-atomic constraints
yet, but #29027 will add existential nodes as a non-atomic constraint.
The defining characteristic is that an atomic constraint is one that is
an actual assignment to a typevar; it is what `PathAssignments` builds
up as it walks a BDD, and is what can live as an antecedent or
consequent in a `SequentMap`.
- We've extracted the logic for persisting a `ConstraintSet` into an
`OwnedConstraintSet`, moving it into a standalone file and structuring
it better via a helper type and some finer grained methods.
- Removed some code sharing in `SolutionWalker` that was actually
leading to more complex code. `visit_node` and
`node_is_satisfiable_on_path` no longer use a shared helper, since the
two uses had many differences, which required overridable hook points.
The shared part was much smaller, so it's simpler to just copy/paste
that part.
- That makes it easier to add caching of `node_is_satisfiable_on_path`,
similar to the caching we already had for `visit_node`.