Schemes leave closed
A Scheme leaves the unifier that minted it only if it is closed — every
variable in its body is either ground or bound by the quantifier (or is a
cyclic-binding root, which the ∀-prefix carries as a μ-equation). A scheme that
still mentions a residual variable — one free in the minting unifier — must
not cross out of that unifier’s lifetime.
This is hard, not stylistic, because quantification is nominal-by-listing
over unifier root ids (type-inference): the
quantifier is a Vec of u32-tagged variable ids, and a free id is meaningful
only relative to the union-find that minted it. A turn’s unifier dies with the
turn and the next turn’s ids restart at zero. An open scheme imported into a
fresh unifier therefore silently aliases that unifier’s variables — type
corruption that no check catches, not an error that surfaces.
Closure is enforced where schemes are minted for exit, by generalising against
the empty TyEnv: with no environment to subtract, generalize quantifies
every residual variable and resolves the body against the final unifier
(core/src/typecheck/generalize.rs). Two sites mint:
- the top-level
Bind-node annotation, where each statement’s scheme rides the IR into the evaluator (typecheck::annotate); - the alias arm stored on the persistent handler frame at install
(
typecheck::alias_arm_scheme).
Every other carrier only transports what those two closed: the build-time
prelude bake harvests the schemes off the annotated prelude’s Bind nodes
(typecheck::bake_prelude), and the serial scope tables carry the installed
(value, scheme) pairs across the pipeline-stage helper wire
(serial::SerialBinding).
One consequence: α-equivalence is not quotiented. Scheme’s PartialEq is
derived, hence structural on the listed ids, so two schemes minted by different
unifier runs compare unequal even when they denote the same ∀-type. Scheme
comparisons must stay within one unifier run, or go through fmt_scheme
(core/src/typecheck/fmt.rs), which renames the prefix to canonical Greek
letters before comparing.
See session-scheme-continuity for the decision this rule serves, and type-inference for how the prefix is represented.