Skip to content

feat(lowering): lower match arm guards - #10432

Open
SahilRajputdotexe wants to merge 3 commits into
starkware-libs:mainfrom
SahilRajputdotexe:feat/match-guard-lowering
Open

SahilRajputdotexe wants to merge 3 commits into
starkware-libs:mainfrom
SahilRajputdotexe:feat/match-guard-lowering

Conversation

@SahilRajputdotexe

Copy link
Copy Markdown

Summary

Stacked on #10431, only the last commit is new.

Lowers guarded arms in the flow control graph. create_guarded_arms_node tries the candidate arms in order: bind the pattern variables, evaluate the guard, take the arm if it holds, otherwise move on. Arms after an unguarded one are unreachable, and if every candidate is guarded the match is non-exhaustive.

A guard can replace the lowered variable of a pattern variable, for example x.len() snapshots x. A new RefreshVar node reads the current value after a failed guard, so the next arm binds the up to date variable instead of the consumed one. The Unsupported report from the previous PR is removed.

Tests: lowering golden cases, a runtime test in tests/bug_samples, and a docs section on match guards.


Type of change

  • New feature

Why is this change needed?

This completes match guards, which #10430 and #10431 only parse and check.


What was the behavior or documentation before?

Lowering reported Unsupported on any guard.


What is the behavior or documentation after?

Guards compile and run.


Related issue or discussion (if any)

None.


Additional context

Binding the whole non Copy scrutinee in a later arm fails with "Variable was previously moved", guard or not. match a { None => 0, o => take_opt(o) } on an Option<Array<felt252>> fails on the base branch, because the enum match consumes it, and so does a refutable tuple pattern like Some((arr, 0)) before o. So Some(x) if x.len() > 1 => 2, o => take_opt(o) fails the same way. I left that alone. Binding the payload in a later arm (Some(y) => take(y)) works and is tested.

@cursor

cursor Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

PR Summary

High Risk
Changes core match lowering and move/snapshot semantics across the compiler pipeline; incorrect guard refresh or candidate ordering could cause subtle runtime bugs.

Overview
Match arm guards (pattern if bool_expr => ...) are now lowered end-to-end instead of reporting unsupported.

Lowering builds guarded match control flow via create_guarded_arms_node: candidate arms are tried in order (bind pattern, evaluate guard, branch). Arms after the first unguarded match are unreachable; all-guarded matches can be non-exhaustive. A new RefreshVar graph node restores pattern bindings after a failed guard when the guard may have changed lowered state (e.g. snapshots from x.len()), so later arms see up-to-date variables.

Semantics already carry MatchArm.guard; this PR wires E2204 when a guard moves or mutates a pattern binding (non-Copy use without snapshot is rejected). Const match evaluation respects guards (false guard falls through). Formatter adds a match_guard golden test; reference docs describe guard behavior and exhaustiveness.

Extensive parser/lowering/semantic/runtime tests cover fall-through, or-patterns, nested enums, and outer-variable side effects in guards.

Reviewed by Cursor Bugbot for commit 96c59f8. Bugbot is set up for automated code reviews on this repo. Configure here.

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

@SahilRajputdotexe
SahilRajputdotexe force-pushed the feat/match-guard-lowering branch from f87424a to 586b4dd Compare October 1, 2026 15:12

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 586b4dd. Configure here.

Comment thread crates/cairo-lang-lowering/src/lower/flow_control/create_graph.rs
@SahilRajputdotexe
SahilRajputdotexe force-pushed the feat/match-guard-lowering branch from 586b4dd to 96c59f8 Compare October 2, 2026 06:06

@orizi orizi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi made 1 comment.
Reviewable status: 0 of 34 files reviewed, 1 unresolved discussion (waiting on SahilRajputdotexe).


-- commits line 6 at r2:
base PR over actual base PR instead of main.

This branch has not been deployed

No deployments
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