Repository navigation
fix: patterns inside a constructor pattern; 3 review findings on #434; doc comments - #435
Conversation
In a match with no guard, the desugarer took a literal or a constructor inside a constructor pattern as a wildcard, and it kept only the last arm of each constructor. So `Some(0) => 1 | Some(n) => 2` gave 2 for `Some(0)`, and `Some(0) => 1 | None => 3` took each `Some`. A match where an arm has a literal or a constructor inside a constructor pattern now takes the ordered path of a match with a guard (#431): each arm of a constructor, in source order, in one core `match` on the payload. - A literal inside a constructor pattern is honoured, and the type checker finds a match that does not cover the payload. - A constructor inside a constructor pattern (`W(Some(x))`) has no lowering yet. It is refused by name. The error has the new name `NestedConstructorPattern` (it was `GuardWithNestedConstructor`), because it is not only for a match with a guard. - A match with no such pattern and no guard lowers as before. Tests: 2 programs on both engines and 2 refused programs. 619 all-target. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0136P7ZmKrYLDC4WHi2yt11u
|
Caution Review failedThe pull request is closed.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Each finding is checked against the code. - The 2 entry points for one expression (`parse`, `parse_surface_expr`) did not refuse unimplemented syntax. The core parser read `1 ++ 2` as `1`, because the code that builds an expression does not know the rule for `++`. Each entry point of the 2 parsers now runs `refuse_unimplemented` on the parse tree. - The interpreter gave a top-level function the local names of its caller. Since #434 a local name shadows a function, so in `let g = 0 in f(1)` the `g()` in the body of `f` found the `g` of the caller: "Not a function"; wasm gave the right result. A top-level function value now starts from an empty environment: its body sees its parameters and the top-level functions. - The rule for `capability_annotation` was on declaration annotations. The design has it at the FFI call: `__ffi@capabilities(io)("f")`. The rule is now in `ffi_expr`, and the fixture has the design form. `@capabilities(io)` on a declaration is `annotation_args`, as each annotation with arguments is. Part 1 of spec/ephapax-v2-grammar.ebnf is written again from the grammar. Tests: one new test for the expression entry points, one more program in the interpreter test. 620 all-target. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0136P7ZmKrYLDC4WHi2yt11u
The CodeRabbit check Docstring Coverage listed declarations with no doc comment. Each one now has a doc comment of 1 or 2 lines: library code of the CLI, driver, interpreter, LSP, REPL, syntax, typing and wasm crates, the grammar conformance test, and the helpers of 4 test files. No behaviour changes: 623 tests pass, the all-target count stays 620. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0136P7ZmKrYLDC4WHi2yt11u
|
Codex Review Summary: ❌ FailedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins. |



Summary
3 commits.
1. A pattern inside a constructor pattern is not a wildcard
In a match with no guard, the desugarer took a literal or a constructor inside a constructor pattern as a wildcard, and it kept only the last arm of each constructor. Programs gave wrong results with no error.
Some(0) => 1 | Some(n) => 2 | None => 3onSome(0)Some(0) => 1 | None => 3onSome(5)Some(5)W(Some(x)) => 1 | W(None) => 0onW(Some(9))A match where an arm has a literal or a constructor inside a constructor pattern now takes the ordered path of a match with a guard (#431): each arm of a constructor, in source order, in one core
matchon the payload.W(Some(x))) has no lowering yet. It is refused by name. The error is nowNestedConstructorPattern(it wasGuardWithNestedConstructor).2. Review findings on #434
parseandparse_surface_exprdid not refuse unimplemented syntax, and the core parser read1 ++ 2as1. Each entry point of the 2 parsers now runsrefuse_unimplementedon the parse tree.let g = 0 in f(1), theg()in the body offfound thegof the caller: "Not a function". A top-level function value now starts from an empty environment.__ffi@capabilities(io)("f"). The rule is now inffi_expr, and the fixture has the design form.Part 1 of
spec/ephapax-v2-grammar.ebnfis written again from the grammar.3. Doc comments
The CodeRabbit check Docstring Coverage listed declarations with no doc comment. Each one now has a doc comment of 1 or 2 lines:
driver_agreement.rs,generics.rs,run_wasm.rs,typed_codegen_matrix.rs).The commit adds 61 lines of comment in 17 files and changes no code.
Verification
cargo test --workspace: 623 passed, 0 failed. No program of the corpus changed.cargo fmt --all --checkandcargo clippy --workspace --all-targets: clean.scripts/status-gate.sh: 620 all-target tests.scripts/probe-battery.sh: 51 SAME, 7 SKIP (the SKIP rows need the wasmtime CLI).a_pattern_inside_a_constructor_pattern_is_not_a_wildcard,an_expression_with_unimplemented_syntax_is_refused_by_name, and one more program inthe_interpreter_calls_and_borrows_as_wasm_does.🤖 Generated with Claude Code
https://claude.ai/code/session_0136P7ZmKrYLDC4WHi2yt11u