feat(function-calls): FC-a — records cross the fn boundary by value (plan slice 5, first half) #65
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/065-feat-function-calls-fc-a-records-cross-the-fn"
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?
feat(function-calls): FC-a — records cross the fn boundary by value (plan slice 5, first half)
Along the way:
Touches 122 files:
Alloc.ck,handoff.md,plan_values_02.md,slice_alloc.md,src/rust/crates/ck_codegen/src/call.rs,src/rust/crates/ck_codegen/src/indirect.rsand 116 more.Split. The decision in
nm_allis a pure function now, with its own tests insrc/rust/crates/ck_driver/tests/record_totality_run.rs.Named them all. A new variant is a compile error in
src/rust/crates/ck_types/src/lift.rsnow, which is where we want to find out.I do not want to merge while the error path in
src/rust/crates/ck_driver/tests/record_totality_run.rsis silent. The rest is fine.@ -0,0 +122,4 @@}/// `nm <binary>` output (all symbols; scanned for forbidden libc/`ck_rt` names).fn nm_all(binary: &Path) -> String {nm_allreads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?@ -189,0 +216,4 @@let id = match head {"String" => interner.string_id()?,"EmptyString" => interner.empty_string_id()?,_ => return None,The catch-all arm means a variant added later compiles and lands here without a word. Can the match on
_name every variant so the compiler tells us?, at src/rust/crates/ck_types/src/lift.rs:219.Updated. The point about
src/rust/crates/ck_driver/tests/record_totality_run.rsturned out to be a real bug, so thank you.Looked through
src/rust/crates/ck_driver/tests/record_totality_run.rsas well. Fine by me.Both answered, and
src/rust/crates/ck_driver/tests/record_totality_run.rsreads right now. Merging.ADD (one generic law, TypeId-keyed, zero name arms): recursive Ty::Nominal -> RecordLayout resolver (compile/record_abi.rs) snapshotted as RecordLayouts and threaded like LeafReprs; ValueRepr::Record(Arc<RecordLayout>); abi_types total over both snapshots; caller flatten (emit_call_arg) / callee repack (bind_params fresh frame) / symmetric multi-word returns (ReturnMode::ValueWords, emit_user_call_value repack); record_seed.rs pre-registers record-typed locals. record_plan now delegates to the one resolver (narrow Int/String-only copy deleted). KILL (grep-proven): abi_types Nominal|Unknown => vec![pointer] blanket + other => Err("...S1/FS4 frame...") arm + both defensive frame comments; user_fns.rs multi-word-return refusal + is_scalar_return (whole dead subtree). Gates: unit record_crosses_as_its_flattened_ordered_word_sequence (flat + nested); corpus record_fn_cross (swap round-trip, exit 42, freestanding, in-container); arch-test R5 (no type-name string literal in the ABI path), red-proven twice (sub-agent + orchestrator, independently); LoC caps HELD (ck_codegen 594/72, ck_lower 552/71 — not raised). fmt 0 / clippy 0 / workspace exit 0 (147 test binaries), verified by the orchestrator. Net: 40 files, +1044/-272 (production ~+679/-272 — additive by design per the revised runbook: the word-list machinery did not exist; the 2026-07-16 runbook revision records the measured-false original premise). Owned debt (recorded): nested-record CROSSING is an honest hard error today (codegen: unsupported Floor IR form) because construction keeps a nested record as one frame-pointer word while the ABI flattens fully — closes when construction inlines nested records; owner: function-calls follow-up. union_copy_run untouched and green; union paths (lower_union_return, copy_union_frame) stay alive for FC-b, next commit.KILL (grep-proven, 0 production hits): the Ty::String / Ty::EmptyString variants (ck_types/src/ty.rs) and builtin_ty's variant-fabricating rows. String is now ordinary Ty::Nominal{String,[Value N]}; EmptyString Ty::Nominal{EmptyString,[]}. Recognition everywhere is by well-known TypeId (Interner::string_id/empty_string_id, registered once at resolve from the DECLARED corpus name — the sanctioned binding that dies with the literals slice), threaded through ck_lower/ck_codegen like FC-a's RecordLayouts. ValueRepr::Str survives as the two-word handle shape. No name-string probe in any ABI/lowering path (arch-test V3 enforces). ADD: live corpus tests/corpus/stdlib/Types.ck grown to the base roster — newtype String<size: Size> = (| position: usize, len: usize |) (V3c rep), the LOCKED same-name alias type String = String<64> (V3b arity law), record EmptyString {}, List/Map/Set; composes trimmed (owned divergence, traits slice). Global well-known resolution (well_known_value_type) so every module agrees on one String TypeId. The pS1b coercion turbofish wired for string literals via the existing generic value_turbofish path: "world"::<String> / ::<String<64>>, fit-gated by exact byte measure (§1.4), ""::<String<N>> per §2a, E0715/E0739. "hello" -> String<8> by the 2^k bucket; "" -> EmptyString. Arch-test V3 (plan_parameters §8.6): a parameterized stdlib value type reaching machine code through a type-name literal in the ABI decision path is a build failure — error-level, red-proven twice (sub-agent + orchestrator independently, Edit-reversal probes). Architecture suite 14/14. Corpus/goldens: ~20 call sites coerced ::<String> to meet the strict String<64> boundary (§1a: the fn boundary never coerces — the law's own accepted verbosity); cktest goldens re-specified from real output; untrapped ratchet back at exactly 112 (cap unchanged); greeter .meta regenerated (291 bytes, only the 20-byte span shifts). Owned debt (comments in place): (1) transitional +-as-concat result = String<64> — operators/traits slice; (2) Panic::raise hint accepts any String<N> — traits slice; (3) §1b letter-form coercion (x::Name<...>) unimplemented language-wide, corpus spelled ::<T> meanwhile — ESCALATED to owner (doc-vs-code conflict, likely entangled with path syntax); (4) stale doc-comment references to the deleted variants (narrow.rs, mock.rs) — Haiku doc sweep. Debt #17 not absorbed. Gates (orchestrator-run): fmt 0 / clippy -D warnings 0 / cargo test --workspace exit 0 (147 test binaries; soft-assert stdout noise only). Net: 89 files +1039/-295 (production +818/-204 — honest report: the id-registry + threading is the price of String-as-nominal, FC-a precedent). The values slice (V1..V4) and the function-calls slice are now COMPLETE.