A "late specialization" of a type is an ability specialization that
is not visible or needed until after type-specialization; i.e. during
monomorphization.
The `Inspect.toInspector` ability is special-cased for opaques that do
not claim or explicitly implement `Inspect`. In such cases, they are
treated as structural types, and given the immediate specialization of
`Inpect.inspectOpaque`.
However, prior to this commit, that special-casing would only be applied
during early specialiation (i.e. specializations visible during
generalized type inference). This commit applies the special case to
late specialization as well - the specialization decision for an opaque
type is always the specialization of the opaque type in the late case,
but now, when we go to look up the ambient lambda set of the
specialization, if it does not exist and corresponds to
`Inspect.toInspector`, we fall back to the immediate.
One concern I have here is that in a case like
```
Op := {}
x =
dbg (@Op {})
```
the specialization of `Inspect.toInspector` for `Op` should be known
early. Indeed, the program
```
Op := {}
x =
Inspect.toInspector (@Op {}) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr
```
Compiles fine without this change. This makes me suspect there is an
issue with the implementation of `dbg`'s desugaring. If possible, this
should be addressed sooner rather than later.
Closes#6127
During the unspecialized lambda set compaction procedure, we might end
up trying to merge too many disjoint variables during unspecialized
lambda unification. Avoid doing so, by checking if we're in the
compaction procedure.
Despite our best efforts, sometimes we still can't specialize lambda
sets on the fly, if a specialization lambda set's specialization type
isn't yet well-known! This commit adds an `AwaitingSpecializations`
data structure to keep track of the lambda sets blocked for
specialization behind a specialization's full resolution in the module.
After the specialization is resolved, its blocked lambda sets can be
eagerly compacted.