feat(sum): named record as a sum-variant payload (M4) - #156
Merged
Conversation
A sum variant may now carry a previously-declared record type as its payload (e.g. `Method = Get / Post(Body)`), not only a built-in scalar. The checker resolves the named payload to its full record type at the declaration, so a match arm binds it at that type and reads its fields and calls its methods. Codegen registers the bound payload as a record (by pointer, the record ABI, consistent with the uniform slot layout). The "consistent payload type per position" invariant is preserved; the named type must be a record (nesting another sum is rejected) and must be declared above the sum (no hoisting). Ships an example, run + type-error tests, and LANGUAGE.md updates. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Extract `track_named_record_binding` and reuse it from the match-arm payload binding and the `=`-binding site (removes duplication). - Checker: decide a named payload's acceptability by whether the name is a registered record (env lookup) rather than by field count, so the reject path is about registration/kind, not an emptiness proxy. - Debug info: a record-payload sum slot is a pointer (the record ABI), so emit its DWARF slot as a pointer instead of the record struct by value. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A sum-type variant can now carry a previously-declared named record as its payload — e.g.
Method = Get / Post(Body)whereBodyis a record. This is the confirmed M4 "authoritative composite types" gap and unblocks the HTTP client'sMethod/Request/Response(#143).Scope is part (A) only (named record as a sum payload). Part (B) — a named composite as a record field — is intentionally deferred.
Step-0 state (before this change)
Boxed = Box(Point)(single-variant) never parsed as a sum: a single-variantName(Payload)is parsed as an expression, so it failed with "Undefined variable". Multi-variant sums are the real path (and matchMethod).Boxed = Box(Point) / Empty) failed type-checking at the declaration:error: Type mismatch: expected Num, got Named { name: "Point", fields: [] }. The checker rejected any non-scalar payload up front, and the parsed named payload carried empty fields.p.fielderrored "Field access not fully implemented").What changed
decls.rs): a sum declaration now resolves each variant payload. Built-in scalars (Num/Text/Bool/$) pass through; a named type must resolve to an already-declared record (its fields carried through). Arrays are rejected by the parser; a nested sum, an unknown name, and heterogeneous concrete types per position are rejected by the checker. The per-position consistency check runs over the resolved variants.matching.rs): when a match binds a record-typed payload, it is registered like any record local (record_types+var_named_types), so field reads and method calls on the binding resolve. The payload rides in the tagged-union slot by pointer (the record ABI), consistent with the uniform layout — no new boxing path.Preserved invariants
Num/Text/Bool/$/array payloads and theResultboxing path are unchanged.Ships with
examples/nested_composites.ql— aMethod = Get / Post(Body)sum: construct, match, read aTextfield, call a method; self-asserting, exits 0 (JIT + AOT).tests/run_test.rs.docs/LANGUAGE.mdsum-type section, feature matrix, and Known limitations updated.Gate
cargo fmt --check,cargo clippy --all-targets -- -D warnings, and the fullcargo testsuite underRUSTFLAGS=-D warningsall pass.PARKED — do not merge without explicit approval.
🤖 Generated with Claude Code