feat(traits T-2): Prelude.ck + Types.ck traits tier live; PRIMITIVE_TRAITS DELETED #69

Manually merged
mdoorn merged 6 commits from feat/069-feat-traits-t-2-prelude-ck-types-ck-traits-tie into master 2026-03-27 08:30:00 +01:00
Owner

feat(traits T-2): Prelude.ck + Types.ck traits tier live; PRIMITIVE_TRAITS DELETED

Along the way:

  • feat(traits): 'not' contextual in name position (owner ruling 2026-07-18); Not roster lands — debt #31 CLOSED
  • feat(traits T-3): Ty::NamedTuple built (ruling 4); seal E0745; tuple field honesty; parameter-as-value-field — debts #11/#13/#23 CLOSED
  • corpus: primes_actor_garage_bitwise — the bits=1 drag-race sibling (owner-authored)
  • test(corpus): register primes_actor_garage_bitwise in RUNTIME_TESTED
  • feat(tuples S7): tuple values lower by the record positional-frame law; TupleUnsupported DELETED; NamedTuple seam reconciled

Touches 45 files: slice_traits.md, src/rust/crates/ck_codegen/src/lib.rs, src/rust/crates/ck_codegen/src/record_value.rs, src/rust/crates/ck_codegen/src/user_fn.rs, src/rust/crates/ck_codegen/src/value.rs, src/rust/crates/ck_driver/src/compile/mono.rs and 39 more.

feat(traits T-2): Prelude.ck + Types.ck traits tier live; PRIMITIVE_TRAITS DELETED Along the way: - feat(traits): 'not' contextual in name position (owner ruling 2026-07-18); Not roster lands — debt #31 CLOSED - feat(traits T-3): Ty::NamedTuple built (ruling 4); seal E0745; tuple field honesty; parameter-as-value-field — debts #11/#13/#23 CLOSED - corpus: primes_actor_garage_bitwise — the bits=1 drag-race sibling (owner-authored) - test(corpus): register primes_actor_garage_bitwise in RUNTIME_TESTED - feat(tuples S7): tuple values lower by the record positional-frame law; TupleUnsupported DELETED; NamedTuple seam reconciled Touches 45 files: `slice_traits.md`, `src/rust/crates/ck_codegen/src/lib.rs`, `src/rust/crates/ck_codegen/src/record_value.rs`, `src/rust/crates/ck_codegen/src/user_fn.rs`, `src/rust/crates/ck_codegen/src/value.rs`, `src/rust/crates/ck_driver/src/compile/mono.rs` and 39 more.
mdoorn requested changes 2026-03-26 09:52:06 +01:00
Dismissed
mdoorn left a comment

Two things inline. The one in src/rust/crates/ck_parser/src/tests/impl_decl.rs is the one I care about.

Two things inline. The one in `src/rust/crates/ck_parser/src/tests/impl_decl.rs` is the one I care about.
@ -0,0 +44,4 @@
/// well-formed `cklang;<passes>;<seconds>;1;…bits=1` line with a positive
/// score and ≥ 5.0 s elapsed, freestanding.
#[test]
fn actor_races_five_seconds_bit_packed_and_reports_a_wellformed_drag_race_line() {
Owner

actor_races_five_seconds_bit_packed_and_reports_a_wellformed_drag_race_line reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?

`actor_races_five_seconds_bit_packed_and_reports_a_wellformed_drag_race_line` reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?
@ -151,0 +162,4 @@
out.diagnostics
);
let i = find_first(&out.tree, SyntaxKind::ImplDecl).expect("ImplDecl");
let f = find_first(i, SyntaxKind::FnDecl).expect("FnDecl");
Owner

The expect message on f is the only thing a user sees if this fires. Does it say what they should do, or only what we assumed?, at src/rust/crates/ck_parser/src/tests/impl_decl.rs:165.

The expect message on `f` is the only thing a user sees if this fires. Does it say what they should do, or only what we assumed?, at src/rust/crates/ck_parser/src/tests/impl_decl.rs:165.
@ -378,0 +410,4 @@
// arena: Arena |)` returning `(| h, a |)` must stay legal.
let handle = nominal(200, vec![]);
let arena = nominal(201, vec![]);
let positional = Ty::tuple(vec![handle.clone(), arena.clone()]);
Owner

positional is cloned on what looks like a hot path. Is the ownership forced here, or can this borrow?

`positional` is cloned on what looks like a hot path. Is the ownership forced here, or can this borrow?
Author
Owner

It said what I assumed. Reworded in src/rust/crates/ck_parser/src/tests/impl_decl.rs so it names the input that broke it, which is what the bug report will need.

It said what I assumed. Reworded in `src/rust/crates/ck_parser/src/tests/impl_decl.rs` so it names the input that broke it, which is what the bug report will need.
Author
Owner

Split. The decision in actor_races_five_seconds_bit_packed_and_reports_a_wellformed_drag_race_line is a pure function now, with its own tests in src/rust/crates/ck_driver/tests/primes_actor_garage_bitwise_run.rs.

Split. The decision in `actor_races_five_seconds_bit_packed_and_reports_a_wellformed_drag_race_line` is a pure function now, with its own tests in `src/rust/crates/ck_driver/tests/primes_actor_garage_bitwise_run.rs`.
Author
Owner

It can borrow. The clone of positional was left over from before the lifetime was threaded through src/rust/crates/ck_types/tests/assignable.rs, and it is gone.

It can borrow. The clone of `positional` was left over from before the lifetime was threaded through `src/rust/crates/ck_types/tests/assignable.rs`, and it is gone.
mdoorn approved these changes 2026-03-27 08:25:00 +01:00
mdoorn left a comment

Good. The second pass on src/rust/crates/ck_parser/src/tests/impl_decl.rs is what I hoped for.

Good. The second pass on `src/rust/crates/ck_parser/src/tests/impl_decl.rs` is what I hoped for.
tvidal approved these changes 2026-03-27 08:25:00 +01:00
tvidal left a comment

Second read on src/rust/crates/ck_parser/src/tests/impl_decl.rs. Nothing to add.

Second read on `src/rust/crates/ck_parser/src/tests/impl_decl.rs`. Nothing to add.
Author
Owner

Pushed a fix for both. The second pass on src/rust/crates/ck_parser/src/tests/impl_decl.rs is much smaller than the first.

Pushed a fix for both. The second pass on `src/rust/crates/ck_parser/src/tests/impl_decl.rs` is much smaller than the first.
KILL (debt #4): the PRIMITIVE_TRAITS const and decide's leaf/string fallback
arm are deleted from coherence.rs — including the interner.resolve(...)
trait-name probe that arm carried. decide for a scalar leaf is now an
ordinary coherence-table probe, no leaf special case. DERIVABLE_TRAITS kept
(auto-derive is a separate concern). Unit test re-specified:
decide_primitive_probes_the_table_like_any_nominal. Consumers measured:
fields.rs auto-derive + predicate_check both satisfied by Prelude's real
Equals rows; the old Hash grant was unreachable-dead (no trait Hash exists
anywhere in the corpus).

ADD: tests/corpus/stdlib/Prelude.ck (mod Prelude): 18 trait declarations,
136 primitive impls with real one-line Floor::* bodies (typechecked and
lowered via T-1b). Omitted, owner-gated: Not trait+impl (debt #31 keyword
collision), heterogeneous delegating impls (debt #33 turbofish surface);
Concat/Pow/Convert/Show land as declarations only — no invented bodies.
Types.ck extends to the traits tier: Sized, Collection composes Sized,
composes clauses on String/List/Map/Set, data Option<T>, the Error tier.
World-types + Literal impls stay in slice 8. Debt #14 silence preserved.

Arch rule R7 (r7_deleted_primitive_trait_table_stays_dead, new
architecture/traits.rs): no name-keyed primitive-trait symbol in any crate's
src/ — error-level, red-proven by the orchestrator first-hand.

Fixture churn (honest): cons_positional now traps the real E0731 (Option is
a genuine 2-variant union); the two auto-derive fixtures state impl
Equals<Int> locally — the same law Prelude supplies globally, made explicit.

Gates (orchestrator-run): fmt 0 · clippy -D warnings 0 · 147/147 cargo
summaries ok · arch 15/15 (14 + R7) · stdlib_type_clean green non-vacuously
· ratchet 98 unchanged.

Net Rust delta: src/ -19 LoC (coherence.rs 38+/57-); gate layer +67 (R7 rule
+ harness registration). The primitive-trait knowledge now lives in
Prelude.ck, not Rust.
The ruling: 'not' is an ordinary identifier in a NAME slot (fn-decl name in
module/impl/trait, method selector after '.'); everywhere else it stays the
hard keyword. ONE generic mechanism (ck_parser/src/name_slot.rs, R3-cap
respected by extraction): expect_name accepts Ident or any
is_contextual_name_kw token and re-tags it Ident in the CST — the contextual
set is named in exactly one place; no per-callsite probe, no Not-specific
arm. Wired at the three name-acceptance points (fn_decl, trait_decl,
postfix member selector).

Prelude.ck: trait Not<T> + impl Not<Bool> (= Floor::ieq(a, false), the
authored soll body over an existing leaf) — the T-2 omission is closed;
header divergence note removed.

Coverage: 4 parser unit tests — fn not in impl, fn not in trait decl,
x.not() selector, and the negative ('not x' stays UnaryExpr/keyword).

Gates (orchestrator-run): fmt 0 · clippy -D warnings 0 · 147/147 cargo
summaries ok · arch 15/15 · stdlib_type_clean green (full Prelude incl. Not
resolves + typechecks) · ratchet 98 unchanged.

Net Rust delta: +80 src LoC (the one generic name-slot mechanism) + 97 test
LoC; the Not knowledge itself lives in Prelude.ck.
S1 Ty::NamedTuple carrying (Symbol, Ty) pairs — the 'labels are cosmetic'
doc was WRONG per ruling 4 and is rewritten; absorbing-Unknown constructor;
arms in render/instantiate/arena_size/check_util/mono (the scout's exact
set — compiler surfaced zero more). S2 lift: >=1 label => NamedTuple via
tuple_labeled_components; mixed labels lift with an empty-symbol slot
(unaddressable; documented, tested; no invented diagnostic). The newtype-rep
path is genuinely separate and untouched. S3 assignability: one
tuple_component_tys helper — Tuple<->NamedTuple positional, label-agnostic;
the Alloc-shaped tripwire (positional literal into named return slot) is a
test. S4 honesty (debts #13-adjacent/#23/P17): Ty::Tuple name-access =>
Missing/E0718; NamedTuple => label lookup. S5 the seal (debt #13): E0745 on
any NamedTuple impl-head type-arg — a TYPE-KIND match
(matches!(Ty::NamedTuple)), never a CST label probe; extracted
seal_named_tuple_heads. S6 s.size (debt #11): Nominal args no longer
discarded; generic Ty::Value{name,ty} scan matches ANY parameter — no name
probe; the composed-Sized merge question stays unruled AND unreachable (no
merge logic added).

R4/R3 held by extraction (write_tuple, seal_named_tuple_heads +
bind_impl_method_bodies, E0745 homed in diag/values.rs) — caps never raised.

Gates (orchestrator-run): fmt 0 · clippy -D warnings 0 · 148/148 cargo
summaries ok · arch 15/15 · stdlib_type_clean green (Alloc.ck typechecks) ·
ratchet 98 exact.

Net Rust delta: ~+190 src LoC (the NamedTuple type law + honesty arms) +
~110 test LoC. Fail-softs killed: the tuple Opaque pass-through, the silent
sealed-impl no-op, the discarded Nominal args.
Bit-packed prime sieve drag race: flag storage is one BIT per odd candidate
(62,500 bytes) addressed via the floor's band/bor/ishl/sshr leaves — no
operator sugar (bitwise glyphs arrive with the operators slice). Same
verified 5 s race protocol as primes_actor_garage; emits one
cklang;<passes>;<seconds>;1;algorithm=base,faithful=yes,bits=1 line;
freestanding, exit 0. Registered in RUNTIME_TESTED.

Verified in-suite by the orchestrator across the T-3 gate runs (148/148).
The bits=1 sibling's registry entry (the app + run-gate landed in 6c54051):
disk-derived coverage gate requires every clean runnable corpus app listed.
One law, two spellings: a tuple literal lowers to the SAME transitional
Record node a headed record literal lowers to (positional FieldInits,
Symbol(0) placeholder names — the union_frame convention); classification
adds ty_repr arms Ty::Tuple/Ty::NamedTuple -> plan_tuple (the positional
spelling of plan_record_fields, components resolved by recursing ty_repr
itself). The ABI crossing reuses FC-a wholesale: abi_types recurses over
components (both spellings), abi_layout_at bridges structural tuples (no
TypeId row) through value_repr_of_ty; record_abi::field_repr classifies a
tuple field by the same law. No new ValueRepr case, no by-name arm, no
intrinsic.

KILL: LowerError::TupleUnsupported (variant + Display arm + helper) —
grep-proven gone; tuple literals no longer error.

Seam reconciliation (orchestrator, at merge with T-3's Ty::NamedTuple): S7
was authored pre-T-3, when labeled types still lifted positionally. Post-
merge, labeled tuple types lift to Ty::NamedTuple and were falling through
abi_types' one-pointer fallback and ty_repr's None — an accidentally-
coherent wrong ABI (probe-proven exercised: the stone's labeled types hit
the NamedTuple arm 5x). Both spellings now delegate to the one positional
law; the false 'both lift to one Ty::Tuple' comments corrected.

Stone: tests/corpus/tuple_fn_cross — fn pair -> (| x: Int, y: Int |) built
from a positional literal crosses the fn boundary by word-list BOTH ways
(callee returns two words, caller unpacks, re-flattens for sink), compile+
link+run freestanding, exit 42 (honestly sourced from the scalar out;
component projection is T-3's typecheck + a later lowering read). Doc
correction: slice_traits.md's 'tuple lowering half is ready' claim replaced
with the measured truth.

Gates (orchestrator-run on the MERGED tree): fmt 0 · clippy -D warnings 0 ·
149/149 cargo summaries ok · arch 15/15 (lower_expr R4 cap held by
extraction) · stdlib_type_clean green · ratchet 98.

Net Rust delta: ~+150 src LoC (the tuple arm riding the record law; error
path -26). Alloc.ck's named-tuple return now LOWERS (dispatch still has its
own dependencies).
mdoorn manually merged commit a5b7657855 into master 2026-03-27 08:30:00 +01:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
northgale/cklang-bootstrap!69
No description provided.