types(TY4): transitive trait-fields + data auto-derive (the TY4c sliver) #28

Manually merged
hkowalski merged 4 commits from feat/028-types-ty4-transitive-trait-fields-data-auto-de into master 2026-02-04 12:39:04 +01:00
Owner

types(TY4): transitive trait-fields + data auto-derive (the TY4c sliver)

Along the way:

  • corpus: split per-app diagnostics into per-app trap.md files
  • types(TY6): empty-list check-only form at the manifest let slot
  • chore: gitignore per-user .mcp.json

Touches 27 files: .gitignore, corpus_diagnostics.md, docs/impl/type-system/TY4-constraints-and-coherence.md, src/rust/crates/ck_driver/tests/corpus.rs, src/rust/crates/ck_hir/src/fields.rs, src/rust/crates/ck_hir/src/lib.rs and 21 more.

types(TY4): transitive trait-fields + data auto-derive (the TY4c sliver) Along the way: - corpus: split per-app diagnostics into per-app trap.md files - types(TY6): empty-list check-only form at the manifest let slot - chore: gitignore per-user .mcp.json Touches 27 files: `.gitignore`, `corpus_diagnostics.md`, `docs/impl/type-system/TY4-constraints-and-coherence.md`, `src/rust/crates/ck_driver/tests/corpus.rs`, `src/rust/crates/ck_hir/src/fields.rs`, `src/rust/crates/ck_hir/src/lib.rs` and 21 more.
hkowalski approved these changes 2026-02-04 08:00:00 +01:00
hkowalski left a comment

A clear improvement. The change in src/rust/crates/ck_driver/tests/corpus.rs is the part I would have argued for.

A clear improvement. The change in `src/rust/crates/ck_driver/tests/corpus.rs` is the part I would have argued for.
@ -699,0 +680,4 @@
fn runtime_coverage_is_exhaustive() {
let apps = corpus_apps();
let tested: BTreeSet<&str> = RUNTIME_TESTED.iter().copied().collect();
let mut failures = Vec::new();
Owner

failures allocates a fresh buffer per call. If this runs per frame or per token, can the buffer be reused?

`failures` allocates a fresh buffer per call. If this runs per frame or per token, can the buffer be reused?
@ -14,0 +41,4 @@
/// traits). Empty when the trait composes nothing. Same shared `composes`
/// projection a `record` / `data` head reads; N1 records these names (not
/// `TraitId`s) and `TY4c` resolves them against module scope.
pub fn composed_traits(&self) -> impl Iterator<Item = NameToken> + 'a {
Owner

composed_traits is public. Does anything outside the crate call it, or is it pub because that was easier? Every public item is a promise.

`composed_traits` is public. Does anything outside the crate call it, or is it pub because that was easier? Every public item is a promise.
@ -258,0 +256,4 @@
/// Subtrees whose own span does not contain `target` are pruned. Shared with
/// the body walker's [`let`-annotation reader](crate::check) (TY6), which
/// finds a `LetStmt` CST node by its lowered `Stmt.span`.
pub(crate) fn find_node_with_span(
Owner

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

`find_node_with_span` reads, decides and writes in one function. The deciding part is the piece I would want to test on its own. Worth splitting?
mdoorn approved these changes 2026-02-04 08:45:20 +01:00
mdoorn left a comment

Second read on src/rust/crates/ck_driver/tests/corpus.rs. Nothing to add.

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

It runs per token. The buffer behind failures lives on the struct in src/rust/crates/ck_driver/tests/corpus.rs now and is cleared rather than reallocated.

It runs per token. The buffer behind `failures` lives on the struct in `src/rust/crates/ck_driver/tests/corpus.rs` now and is cleared rather than reallocated.
Author
Owner

Nothing outside calls composed_traits. It is pub(crate) in src/rust/crates/ck_syntax/src/ast/members.rs now.

Nothing outside calls `composed_traits`. It is pub(crate) in `src/rust/crates/ck_syntax/src/ast/members.rs` now.
Author
Owner

Split. The decision in find_node_with_span is a pure function now, with its own tests in src/rust/crates/ck_types/src/value_turbofish.rs.

Split. The decision in `find_node_with_span` is a pure function now, with its own tests in `src/rust/crates/ck_types/src/value_turbofish.rs`.
Close the two gaps the minimal TY4c goldens did not exercise:

- Transitive trait-field contribution: a `trait` may itself `composes`
  other field-bearing traits, and those fields flow to every type that
  composes it (`record User composes Entity`, `trait Entity composes
  Identified` -> `u.id`). N1 records a trait's own composes head names
  (Interner::trait_composed_traits); field_access::trait_contributed_field
  is the one cycle-guarded recursive walk that both the read surface
  (concrete + `where E is Error` bound Var receiver) and the E0727
  collision check call.

- data auto-derive (tag-then-payload): `data .. composes Equals`/`Hash`
  registers a derived coherence row for the parent type (duplicate user
  impl -> E0709) and fires E0711 when a variant payload slot (named or
  positional) is not itself derivable. Payload types are lifted from the
  CST at check-time; emit_if_underivable phrases the same E0711 for a
  record field and a data payload.

New goldens (multi-page, trap-covered): transitive_trait_fields.cktest,
data_auto_derive.cktest. Doc: TY4 "What landed after TY4c".
Move the declared compiler-gap traps out of the monolithic
corpus_diagnostics.md into one `tests/corpus/<app>/trap.md` per app
(calc, counter, route, todo, types), each `### <File>` heading carrying a
`​```trap` block in the `.cktest` `# trap` grammar. Refactor
ck_driver/tests/corpus.rs to read and reconcile them strict-exhaustive
both ways, keeping corpus_inspect under the R4 fn-length cap.
Wires the `let`-annotation read (the prior `let_annotation` stub returned
None, so `let xs: List<…> = []` synthesized the empty literal and spuriously
fired E0713). The annotation is now the manifest slot the check-only empty
list needs: `[]` types *against* it instead of synthesizing. A bare
`let xs = []` still fires E0713.

The annotation lift reuses `lift_required_type_ref`, so a `let` annotation
resolves identically to a parameter/return type. Block + `let` walking moves
to a new `check_block.rs` (mirroring `check_lit.rs`) so `check.rs` stays under
the R3 file-LoC cap rather than raising it.

Lands the two remaining TY6 goldens: empty_list_inferred (annotated slot, no
diagnostic) and empty_list_unannotated (E0713, trapped).
Local MCP server config (credentials / endpoints), never repo content.
hkowalski manually merged commit 6c1d4e8906 into master 2026-02-04 12:39:04 +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!28
No description provided.