Add nested literal, constructor and list patterns - #1434
Merged
Merged
Conversation
Constructor fields and list or tuple elements are now patterns at any
depth: Option.Some(0), Result.Ok("x"), Shape.Rect(0, h),
Option.Some(Option.None), and list patterns [a], [a, b], [a, b, ..rest],
[..all] with pattern elements such as [0, ..rest] or
[Option.Some(x), ..rest].
The checker reads the patterns as written: exhaustiveness counts list
patterns by length and never lets a literal cover its constructor,
literal and list patterns are type-checked against their position, and
pattern errors point at the arm. The front door then compiles each such
match into nested flat matches (src/ir/nested_patterns.rs) and checks
the lowered program again, so the VM, Rust, wasm-gc, wasip2, the Lean
export and the certificate model all read ordinary matches. An arm the
compiled tree never reaches is reported as unreachable. Nested patterns
inside a yield function are refused for now.
aver format prints match patterns in canonical spelling, changing only
whitespace.
Also fix the escape pass: a one-parameter body holding a match that
binds a name is no longer spliced into its caller, where the binder's
slot did not exist (VM index panic, wasm-gc validation failure, or a
clobbered caller local).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
jasisz
added a commit
that referenced
this pull request
Sep 25, 2026
Brings in nested literal and list patterns (#1434), Run.fail (#1430), #1428, #1429 and #1432. A module with no process of its own used to go down one of two exclusive branches of the front pipeline: compile its nested patterns, or carry its waits keyed by a type other than Int. A dependency can need both, so the branch now does both in order: check the module as written, so errors name the patterns the user wrote; compile the nested patterns and check again; carry the waits with the key types read off that check of the lowered module; and check what the carrying wrote once more. The entry already did both: the yield lowering carries its waits over the module as written, and the nested patterns are compiled after it. Nested patterns inside a yield function are still refused. Co-Authored-By: Claude Opus 5.5 (1M context) <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.
Syntax
Option.Some(0),Result.Ok("x"),Shape.Rect(0, h),Option.Some(true),Option.Some(Option.None),Option.Some((0, _)). Literal kinds are the ones a top-level arm takes: Int, String, Float, Bool.[],[a],[a, b](exact length),[a, b, ..rest](at least two),[..all], with pattern elements ([0, ..rest],[Option.Some(x), ..rest])...restis last and is a binder or_.[h, ..t]keeps its old flat form.How it works
Pattern::ConstructorNested(name, Vec<Pattern>)andPattern::List { items, rest }. A constructor whose fields are all binders staysPattern::Constructor, so existing programs are unchanged.missing pattern Option.Some(_),Option.Some(false)and[_, _, _, .._]. Literal patterns are checked against their position's type, and a list pattern against a non-list is an error. Pattern errors now point at the arm line.src/ir/nested_patterns.rs: in the front door, after the program is checked as written, each match with a nested form is compiled into nested flat matches with a clause-matrix compilation. Arms keep first-match order. A switch has no_default when its constructors cover the type, using the variant families the checker records. Binders keep user names where that cannot capture anything; otherwise they get fresh__patNnames. A computed subject is evaluated once. The lowered program is then checked again. An arm that no leaf of the compiled tree reaches is reported as unreachable, which catches arms covered only by several earlier arms together. Dependencies go through the same step inlower_loaded_yield_modules.yieldfunction are refused with an error for now.aver formathas a new rule,bad-match-pattern, that prints arm patterns in canonical spelling. It only rewrites when the change is whitespace. It fires on nothing in examples/, stdlib/, self_hosted/, projects/ or tests/fixtures/.src/ir/escape.rs: a one-parameter body that contains a bindingmatchwas spliced into its caller together with a slot the caller does not have. On main this already breaks a hand-writtenmatch h | Holder.Full(inner) -> match inner | Option.Some(x) -> x ...called with a literal constructor: the VM panics with index out of bounds and wasm-gc fails validation. Nested patterns produce exactly this shape. Such bodies now stay calls.Self-host
Not updated. Self-host parity only runs examples/core/{hello,calculator,shapes}, and none of them use the new syntax.
aver run --self-hoston a program that uses it fails with a parse error in the self-hosted parser; it does not run wrong code.tools/regenerate_self_host.py --checkstill reports that the checked-in output is fresh.Tests
..restplacement and binder rules, unparse round trip.src/ir/nested_patterns/tests.rs: lowering shape, no redundant defaults, dead-arm detection, the subject evaluated once.aver verifyand CLI diagnostics.Option.Some(0)and[0, ..rest]build in Lean with 0 sorries (3 universal).