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:
File diff suppressed because one or more lines are too long
@@ -1,20 +1,16 @@
|
||||
; Iter 15g — fifth consumer demo. First demo to import four stdlib
|
||||
; modules (std_list, std_either, std_pair, std_either_list); first to
|
||||
; thread a List<Either<Int, Int>> through three combinators that
|
||||
; Iter 15g (refactored in 15g-aux) — fifth consumer demo. Imports four
|
||||
; stdlib modules (std_list, std_either, std_pair, std_either_list);
|
||||
; threads a List<Either<Int, Int>> through three combinators that
|
||||
; together exercise every monomorphisation site introduced by 15g.
|
||||
;
|
||||
; The list is constructed via the monomorphic helpers `mkleft` and
|
||||
; `mkright` rather than bare `(term-ctor std_either.Either Left ...)` /
|
||||
; `(term-ctor std_either.Either Right ...)`. This sidesteps a codegen
|
||||
; bug that 15g surfaced: when an inline list literal mixes
|
||||
; `Either Left n` (pins e, leaves a as `$u`) and `Either Right n` (pins
|
||||
; a, leaves e as `$u`), the synth-time unification of the outer
|
||||
; `List<a>`'s parameter against the `$u`-bearing element types fails
|
||||
; on the param side because `unify_for_subst` only accepts arg-side
|
||||
; `$u` wildcards. The helpers fully pin both type vars at the call
|
||||
; site, so each list element arrives with concrete `Either<Int, Int>`
|
||||
; and the bug is dodged. Logged as known-debt under 15g; the fix is
|
||||
; a one-line symmetric extension of the `$u` early-return.
|
||||
; The list is constructed inline by mixing `(term-ctor std_either.Either
|
||||
; Left ...)` and `(... Right ...)`. Iter 15g surfaced a `unify_for_subst`
|
||||
; asymmetry that would have rejected this construction at synth time;
|
||||
; 15g-aux fixed it by accepting `$u` synth-wildcards on either side of
|
||||
; the param/arg unification (see ailang-codegen/src/lib.rs's
|
||||
; `unify_for_subst`). This demo is the regression fixture: if the
|
||||
; symmetric early-return is reverted, the inline form below errors out
|
||||
; before reaching codegen.
|
||||
|
||||
(module std_either_list_demo
|
||||
|
||||
@@ -23,24 +19,12 @@
|
||||
(import std_pair)
|
||||
(import std_either_list)
|
||||
|
||||
(fn mkleft
|
||||
(doc "Monomorphic Left-injector at Either<Int, Int>. Pins both type vars at the call site so the codegen synth doesn't leave a `$u` wildcard on the second var.")
|
||||
(type (fn-type (params (con Int)) (ret (con std_either.Either (con Int) (con Int)))))
|
||||
(params x)
|
||||
(body (term-ctor std_either.Either Left x)))
|
||||
|
||||
(fn mkright
|
||||
(doc "Monomorphic Right-injector at Either<Int, Int>. Symmetric to mkleft.")
|
||||
(type (fn-type (params (con Int)) (ret (con std_either.Either (con Int) (con Int)))))
|
||||
(params x)
|
||||
(body (term-ctor std_either.Either Right x)))
|
||||
|
||||
(fn main
|
||||
(doc "Drive lefts, rights, and partition_eithers on the same five-element List<Either<Int, Int>> (Left 1, Right 10, Left 2, Right 20, Right 30). Expected output (one per line): 2, 3, 2, 3.")
|
||||
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
||||
(params)
|
||||
(body
|
||||
(seq (do io/print_int (app std_list.length (app std_either_list.lefts (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil)))))))))
|
||||
(seq (do io/print_int (app std_list.length (app std_either_list.rights (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil)))))))))
|
||||
(seq (do io/print_int (app std_list.length (app std_pair.fst (app std_either_list.partition_eithers (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil))))))))))
|
||||
(do io/print_int (app std_list.length (app std_pair.snd (app std_either_list.partition_eithers (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil))))))))))))))))
|
||||
(seq (do io/print_int (app std_list.length (app std_either_list.lefts (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil)))))))))
|
||||
(seq (do io/print_int (app std_list.length (app std_either_list.rights (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil)))))))))
|
||||
(seq (do io/print_int (app std_list.length (app std_pair.fst (app std_either_list.partition_eithers (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil))))))))))
|
||||
(do io/print_int (app std_list.length (app std_pair.snd (app std_either_list.partition_eithers (term-ctor std_list.List Cons (term-ctor std_either.Either Left 1) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 10) (term-ctor std_list.List Cons (term-ctor std_either.Either Left 2) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 20) (term-ctor std_list.List Cons (term-ctor std_either.Either Right 30) (term-ctor std_list.List Nil))))))))))))))))
|
||||
|
||||
Reference in New Issue
Block a user