Iter 15g-aux — symmetric $u early-return in unify_for_subst
Fix the codegen asymmetry that 15g surfaced. unify_for_subst had an arg-side-only early-return for $u-prefixed synth wildcards. The function's prev-binding recursion can swap a $u from arg into param position when re-unifying a previously-bound type against a fresh arg. Reduced repro: `length [Left 1, Right 10]` — `a` first binds to `Either<Int, $u>`, then the recursive unification against `Either<$u, Int>` lands $u in param-pos[1] and falls through to the catch-all error. Fix is three lines: add a symmetric $u early-return for param side. $u is a synth-only wildcard regardless of which side it ends up on after the prev-binding swap. Doc comment expanded to record the origin and justification. std_either_list_demo refactored: mkleft/mkright workaround helpers removed; the list is now constructed inline by mixing (term-ctor std_either.Either Left 1) and (... Right 10) directly. Same expected output (2, 3, 2, 3); the demo doubles as the 15g-aux regression fixture. Tests: 94/94, unchanged. The fix expanded what compiles without changing observable behaviour for any prior fixture.
This commit is contained in:
@@ -2991,3 +2991,54 @@ under `ailang-codegen/src/lib.rs`.
|
||||
acceptance — small, one-line in `unify_for_subst`); 16b (local
|
||||
recursive `let`); 16c (Lit-in-Ctor patterns); 17a (per-fn arena,
|
||||
gated on user discussion).
|
||||
|
||||
---
|
||||
|
||||
## Iter 15g-aux — symmetric `$u` early-return in `unify_for_subst`
|
||||
|
||||
**Goal.** Fix the codegen asymmetry that 15g surfaced: inline list
|
||||
literals mixing `Left n` and `Right n` ctor calls of the same
|
||||
`Either<e, a>` errored at synth time even though both elements have
|
||||
fully-determined concrete-after-pinning types.
|
||||
|
||||
**Diagnosis.** `unify_for_subst` (`crates/ailang-codegen/src/lib.rs`)
|
||||
had an arg-side-only early-return for `$u`-prefixed synth wildcards.
|
||||
The function has a prev-binding recursion path that re-invokes
|
||||
itself with the previously-bound type as the new param and the
|
||||
fresh arg, which can swap a `$u` from arg position into param
|
||||
position. Concretely, `length [Left 1, Right 10]` synths the list
|
||||
elements as `Either<Int, $u>` and `Either<$u, Int>`. The first
|
||||
element pins `a = Either<Int, $u>` for `Cons`'s parameter `a`. The
|
||||
second element triggers a recursive unification of the previously-
|
||||
bound `Either<Int, $u>` against `Either<$u, Int>`, walking
|
||||
pairwise: `Int` vs `$u` (arg-side `$u`, ok) and `$u` vs `Int`
|
||||
(param-side `$u`, **falls through** to the catch-all error).
|
||||
|
||||
**Fix.** Three lines in `unify_for_subst`: add a symmetric early-
|
||||
return for param-side `$u`. Doc comment expanded to record the
|
||||
asymmetry's origin and the symmetric extension's justification
|
||||
(`$u` is a synth-only wildcard regardless of which side it ends
|
||||
up on after the prev-binding swap).
|
||||
|
||||
**Demo refactor.** `examples/std_either_list_demo.ailx` no longer
|
||||
uses the `mkleft`/`mkright` monomorphic helpers introduced as the
|
||||
15g workaround. The list is now constructed inline by mixing
|
||||
`(term-ctor std_either.Either Left 1)` and `(term-ctor
|
||||
std_either.Either Right 10)` directly. Same expected output
|
||||
(2, 3, 2, 3); the demo doubles as the 15g-aux regression fixture.
|
||||
|
||||
**Tests: 94/94, unchanged.** The fix expanded what compiles, did
|
||||
not change observable behaviour for any prior fixture.
|
||||
|
||||
**Cumulative state, post-15g-aux.**
|
||||
|
||||
- Stdlib unchanged (5 modules, 27 combinators).
|
||||
- One latent codegen bug retired. The bug count in the dogfood
|
||||
audit since 14a stays at 4 surfaced + fixed (this is a fresh
|
||||
surface from 15g, so 5 surfaced / 5 fixed).
|
||||
- The std_either_list_demo workaround is gone, leaving the inline
|
||||
cross-module mixed-ctor list as the canonical idiom.
|
||||
|
||||
**Queue update.** 15g-aux done. Unchanged: 16b (local recursive
|
||||
let), 16c (Lit-in-Ctor patterns), 17a (per-fn arena, gated on
|
||||
user discussion of memory management).
|
||||
|
||||
Reference in New Issue
Block a user