Files
AILang/examples/std_either_list.ail
T
Brummel 2769e50a35 fix(examples): destructure partition_eithers result once (#57, 0064 iter 4)
Final iteration of spec 0064 (the #55-cutover hardening, #57). Closes
class 4, the one genuine corpus bug among the four (not a false
positive): std_either_list.partition_eithers projected both
(app Pair.fst rest) and (app Pair.snd rest) from one owned `rest`.
Pair.fst/snd are own-param projections that move a field out, so each
consumes `rest` -> a genuine double-consume that universal linearity
activation (#55) would correctly reject. The fix is a body rewrite
(destructure `rest` once via (match rest (case (pat-ctor MkPair ls rs)
…)) then dispatch on the head), NOT a check change -- the check is
right.

Latent until activation: partition_eithers' param is a bare (Implicit)
slot today, so the check is skipped on it -- no RED->GREEN flip on the
real fixture. The rewrite is a pre-emptive corpus fix. Its correctness
rests on the unchanged 2 3 2 3 E2E output (std_either_list_demo, a
semantically-identical partition) and on the new c4_double_consume
must-stay-RED fixture, which -- with explicit modes, so the check is
active today -- demonstrates the double-projection shape IS rejected.

- examples/std_either_list.ail: partition_eithers Cons arm rewritten;
  doc updated (destructure-once, no longer "projections").
- examples/c4_double_consume.ail: must-stay-RED pin (the rejected
  shape), folded into a generalised
  harden_ownership_heap_double_consume_still_errors loop over
  {real_consume, c4_double_consume}.
- examples/c4_rewrite.ail: stays-clean pin (the accepted
  destructure-once shape), added to
  harden_ownership_false_positives_are_clean.

No hash-pin on std_either_list (verified); the e2e 2 3 2 3 output pin
is the content pin and is preserved. No check/schema/codegen change.
Verified: std_either_list checks clean; demo 2 3 2 3; both harden
assertions green; cargo test --workspace green; bench/check.py 34/34,
compile_check.py 24/24 stable.

This is the last of the four #57 hardening classes. Spec 0064 is now
code-complete: classes 1 (local fn-param modes), 2 (let-alias redirect),
3 (value-typed let-binder), and 4 (this) all shipped. The cycle is ready
for audit; the #55 cutover precondition is met.

refs #57
2026-06-01 18:22:59 +02:00

74 lines
2.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
; Iter 15g — fifth stdlib module: first 3-way cross-module fn set.
; Imports std_list, std_either, std_pair simultaneously. All three
; combinators dispatch over List<Either<e, a>>; partition_eithers
; additionally returns Pair<List<e>, List<a>>. Stresses
; monomorphisation across List × Either × Pair, cross-module ctor
; resolution at qualified term-ctor sites, and the 16a desugar
; layer at depth-2 nested Ctor patterns (in `lefts` / `rights`).
(module std_either_list
(import std_list)
(import std_either)
(import std_pair)
(fn lefts
(doc "Project the Left payloads of a list of Eithers into a List<e>. Order-preserving. Uses the 16a nested-Ctor pattern to inline the inner Either dispatch within each Cons arm; the trailing wildcard arm seals the desugar's fall-through chain into a List<e> rather than the synthetic Unit fallback.")
(type
(forall (vars e a)
(fn-type
(params (con List (con Either e a)))
(ret (con List e)))))
(params xs)
(body
(match xs
(case (pat-ctor Cons (pat-ctor Left l) t)
(term-ctor List Cons l (app lefts t)))
(case (pat-ctor Cons (pat-ctor Right _) t)
(app lefts t))
(case _ (term-ctor List Nil)))))
(fn rights
(doc "Project the Right payloads of a list of Eithers into a List<a>. Symmetric to lefts; same nested-Ctor + wildcard-tail pattern shape.")
(type
(forall (vars e a)
(fn-type
(params (con List (con Either e a)))
(ret (con List a)))))
(params xs)
(body
(match xs
(case (pat-ctor Cons (pat-ctor Left _) t)
(app rights t))
(case (pat-ctor Cons (pat-ctor Right r) t)
(term-ctor List Cons r (app rights t)))
(case _ (term-ctor List Nil)))))
(fn partition_eithers
(doc "Partition a list of Eithers into a Pair<List<e>, List<a>>: lefts on the left, rights on the right. Single pass via direct recursion; the recursive result is destructured once and the head dispatches into the matching side.")
(type
(forall (vars e a)
(fn-type
(params (con List (con Either e a)))
(ret (con Pair (con List e) (con List a))))))
(params xs)
(body
(match xs
(case (pat-ctor Nil)
(term-ctor Pair MkPair
(term-ctor List Nil)
(term-ctor List Nil)))
(case (pat-ctor Cons h t)
(let rest (app partition_eithers t)
(match rest
(case (pat-ctor MkPair ls rs)
(match h
(case (pat-ctor Left l)
(term-ctor Pair MkPair
(term-ctor List Cons l ls)
rs))
(case (pat-ctor Right r)
(term-ctor Pair MkPair
ls
(term-ctor List Cons r rs))))))))))))