Skip to content

fix: patterns inside a constructor pattern; 3 review findings on #434; doc comments - #435

Merged
hyperpolymath merged 3 commits into
mainfrom
claude/e2e-language-pass-ow72tj
Nov 10, 2026
Merged

hyperpolymath merged 3 commits into
mainfrom
claude/e2e-language-pass-ow72tj

Conversation

@hyperpolymath

@hyperpolymath hyperpolymath commented Nov 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

3 commits.

  1. A match with no guard no longer takes a pattern inside a constructor pattern as a wildcard.
  2. 3 review findings on feat(parser): unimplemented syntax is refused by name (E7 gate) #434, which merged before they arrived. 2 of them are regressions of feat(parser): unimplemented syntax is refused by name (E7 gate) #434.
  3. Doc comments for the declarations that the Docstring Coverage check listed. No behaviour changes.

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.

Program Before Now
Some(0) => 1 | Some(n) => 2 | None => 3 on Some(0) 2 1
Some(0) => 1 | None => 3 on Some(5) 1 refused: the match does not cover Some(5)
W(Some(x)) => 1 | W(None) => 0 on W(Some(9)) 0 refused by name

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. 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 is now NestedConstructorPattern (it was GuardWithNestedConstructor).
  • A match with no such pattern and no guard lowers as before.

2. Review findings on #434

  • Expression entry points. parse and parse_surface_expr did not refuse unimplemented syntax, and the core parser read 1 ++ 2 as 1. Each entry point of the 2 parsers now runs refuse_unimplemented on the parse tree.
  • Interpreter scope (regression of feat(parser): unimplemented syntax is refused by name (E7 gate) #434). A top-level function took the local names of its caller. With let g = 0 in f(1), the g() in the body of f found the g of the caller: "Not a function". A top-level function value now starts from an empty environment.
  • Capability annotation. The rule 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.

Part 1 of spec/ephapax-v2-grammar.ebnf is 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:

  • library code of the CLI, driver, interpreter, LSP, REPL, syntax, typing and wasm crates;
  • the grammar conformance test;
  • the helpers of 4 test files (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 --check and cargo 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).
  • New tests: a_pattern_inside_a_constructor_pattern_is_not_a_wildcard, an_expression_with_unimplemented_syntax_is_refused_by_name, and one more program in the_interpreter_calls_and_borrows_as_wasm_does.

🤖 Generated with Claude Code

https://claude.ai/code/session_0136P7ZmKrYLDC4WHi2yt11u

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
@coderabbitai

coderabbitai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Explain Change →

Caution

Review failed

The pull request is closed.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Share

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
@hyperpolymath hyperpolymath changed the title fix(desugar): a pattern inside a constructor pattern is not a wildcard fix: patterns inside a constructor pattern; 3 review findings on #434 Nov 10, 2026
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
@hyperpolymath hyperpolymath changed the title fix: patterns inside a constructor pattern; 3 review findings on #434 fix: patterns inside a constructor pattern; 3 review findings on #434; doc comments Nov 10, 2026
@sonarqubecloud

Copy link
Copy Markdown

@hyperpolymath
hyperpolymath marked this pull request as ready for review November 10, 2026 18:41
@hyperpolymath
hyperpolymath merged commit 26d08fc into main Nov 10, 2026
47 checks passed
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ❌ Failed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-10T18:44:33.133529Z 6678a3e Draft marked ready
🔒 Security Review ❌ Failed 2026-11-10T18:41:59.883621Z
We couldn’t complete this review. Comment @codex security review to try again.
6678a3e Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@hyperpolymath
hyperpolymath deleted the claude/e2e-language-pass-ow72tj branch November 10, 2026 18:42
@chatgpt-codex-connector

Copy link
Copy Markdown

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants