R2c-fe fix: list-in-let irrefutable iff pure [..rest] (soundness) #46
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/046-r2c-fe-fix-list-in-let-irrefutable-iff-pure-re"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
R2c-fe fix: list-in-let irrefutable iff pure [..rest] (soundness)
Along the way:
Touches 45 files:
current-state.md,docs/impl/runtime-testing/README.md,docs/impl/runtime-testing/T7-fuzz-validator.md,docs/impl/runtime-testing/T9-bounded-arena-stress-reconcile.md,docs/impl/runtime/README.md,docs/impl/type-system/TY7-exhaustive-match-and-narrowing.mdand 39 more.Split. The decision in
newis a pure function now, with its own tests insrc/rust/crates/ck_driver/tests/match_guard_run.rs.Happy with this. I ran the suite against the branch and it is green,
src/rust/crates/ck_driver/tests/match_guard_run.rsincluded.@ -0,0 +146,4 @@}impl Teardown {fn new(name: &str) -> Self {newreads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?Completes R2c: an irrefutable destructuring `let` now RUNS. Floor IR StmtKind::Let carries a lowered LetBinding = Simple(Option<LocalId>) | Record(Vec<FieldBind{field_name,local}>) | RestList(LocalId) — the HIR Pattern is reduced to exactly what codegen reads, never carried whole. codegen::binding emit_let_record projects each field of an inline-record RHS (P2.2 base pointer + plan_fields) into its bound local via the new reusable record::project_field helper (R2d reuses it for variant-payload destructure); emit_let_rest aliases the whole list handle for a pure [..rest]. Field-name matching: the HIR record pattern drops field names, so the driver threads the resolver's per-LocalId binder names into lower_body_with; a pun `{x, y}` binds by name (order-independent, matched in the field plan), a rename `{x: a}` / nested / non-inline-RHS falls to Simple(None) => Unsupported (never a guessed offset). No front-end change. Records-only + [..rest]; nested / list-elem / param-record RHS stay real Unsupported. Gates: fmt/clippy(-D warnings)/build/test --workspace all exit 0; codegen.rs at 809/809 (not over). Gates: tests/corpus/let_destructure (let Point{x,y} = Point{x:20,y:22}; x+y -> exit 42) + let_destructure_wide (offset past a wide field -> 42), both freestanding in RUNTIME_TESTED; 4 ck_lower lowering tests (incl. [..rest] + the rename->Unsupported guard). [..rest] runtime fixture deferred (freestanding list-alloc), gated at lowering.Records the "ultimate integration test" as a first-class blocked T-slice: build an actor around its declared bounds, drive a saturating workload, and gate that the compiler's static arena reservation is a true and tight upper bound on what the running actor does. Three properties, each a distinct gate: 1. soundness — no OOM within bounds (measured ArenaHighWater <= calculated) 2. tightness — no wasted headroom under saturation (measured ~= calculated per region; the "underflow" half — a rec<N> never observed at depth N is a bound set too loose) 3. enforcement — over-bound fires the designed Panic::raise (StackOverflow / OOM-by-design), never memory unsafety Today arena sizing is only tested against itself (77 static arena_size unit tests; arena_reclaim_run / mem_report_run explicitly do NOT gate calculated >= measured, stdlib.md §9.4/9.5). T9 turns that documented-but- ungated invariant into a machine-verified gate. Load-bearing design note captured before R2: the workload is the hard part (must saturate, and saturation must be verified off the stream), not the assertion. Blocked on R2 (typed bounded allocation — no runnable corpus actor sizes finite-nonzero until then) + T5 (memory inspection). Interim floor buildable now: gate measured <= calculated on every is_bounded() actor. Registers T9 in the README slice cascade + corpus targets; updates T7's stale "fifth generator not yet a slice" cross-reference. Link checker green.Draw a hard scope divider and remove the contradiction between the two docs: lowering.md — owns lowering, the Floor IR, and codegen (how high-level CkLang desugars to primitives, the ck_lower/ck_codegen crate split, closure conversion). Payload-variant lowering (the old "R2e") now lives here as LC5. stdlib.md — owns the lego blocks (syscall table + CkLang stdlib units, and when each is promoted). It no longer specifies HOW any construct lowers. Bakes in the review's four holes: #1 stdlib.md §9.6 no longer instructs a codegen arm for R2e; it defers to lowering.md LC5 and refocuses on the FS floor units + syscall additions, with a table mapping each lego-block dep to its LC slice. #2 typed Floor IR on the run path is now the explicit LC1 PRECONDITION — every run/test/actor site lowers with TypeckResults::default() today, so a desugaring would re-fake layout via CST-span re-reading; LC1 threads real types and retires the driver sideways-maps for real. #3 adds LC6 monomorphization (generics) and flags data-constructor typing (E0704) as a front-end prereq of LC5 — neither was in scope before. #4 makes the "bottom is CkLang only where LC ∧ FS8 meet at Arena::alloc" caveat explicit (Alloc = interim ck_rt_alloc until FS8). Cascade renumbered LC0–LC9.