Sometimes, we might need to fixpoint-fix a unification like
[ Bar [ Bar <a>, Foo ], Foo ] as <a> 🛠️ [ Bar <b>, Foo ] as <b>
where we hit a comparison between <a> and <b>. In this case, follow each
recursion point independently and see if we can find the chain to the needle
we were searching for.
Closes#5476
At times we can have alias arguments that are recursive in their
position, but whose recursiveness is not immediately visible in the real
var.
Closes#5330
While unifying two unions, we may turn one of them into a recursive
union. If we don't recognize the recursiveness before merging, we'll
have lost the recursive value of the union.
There are times that multiple concrete types may appear in
unspecialized lambda sets that are being unified. The primary case is
during monomorphization, when unspecialized lambda sets join at the same
time that concrete types get instantiated. Since lambda set
specialization and compaction happens only after unifications are
complete, unifications that monomorphize can induce the above-described
situation.
In these cases,
- unspecialized lambda sets that are due to equivalent type variables
can be compacted, since they are in fact the same specialization.
- unspecialized lambda sets that are due to different type variables
cannot be compacted, even if their types unify, since they may point
to different specializations. For example, consider the unspecialized
lambda set `[[] + [A]:toEncoder:1 + [B]:toEncoder:1]` - this set wants
two encoders, one for `[A]` and one for `[B]`, which is materially
different from the set `[[] + [A, B]:toEncoder:1]`.
When we unify variables in mono, we must invalidate the sections of the
layout cache reached by those variables. Previously we did this by
recording changed variables as those that were `merge`d. However this is
not enough; we must also record all the parent types they came from. The
reason is we may have something like
```
Alias (Foo, a) ~ Alias (Bar, U8)
```
where we will merge `a = U8` but we do not merge the aliases.
Closes#4919