Skip to content

fix(semantic): reject a + expansion repetition over zero groups - #10315

Open
orizi wants to merge 1 commit into
graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensivefrom
graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group
Open

fix(semantic): reject a + expansion repetition over zero groups#10315
orizi wants to merge 1 commit into
graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensivefrom
graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group

Conversation

@orizi

@orizi orizi commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

A $( ... )+ block in a macro expansion promises at least one
repetition, but a call matching zero groups silently expanded it to
nothing. Report the new E2210 instead, as rustc does ("this must repeat
at least once"). * and ? blocks over zero groups stay valid.

Co-Authored-By: Claude Fable 5 noreply@anthropic.com

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

orizi commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from 9fd42a9 to b559512 Compare August 4, 2026 08:41
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group branch from 94fdd8f to 11ce2dc Compare August 4, 2026 08:41
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from b559512 to 71fa44b Compare August 4, 2026 08:56
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group branch 2 times, most recently from f874dc3 to 4226edc Compare August 5, 2026 10:54
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from 71fa44b to 61861f5 Compare August 5, 2026 10:54
@orizi
orizi marked this pull request as ready for review August 5, 2026 11:10
@cursor

cursor Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Localized macro expansion validation and diagnostics; behavior change only for invalid + expansions at zero groups.

Overview
Macro expansion now errors when a $(...)+ block in a rule’s expansion would run zero times. Previously that case expanded to nothing, breaking the “at least once” meaning of + (aligned with rustc).

The expander returns MacroExpansionFailure::EmptyPlusRepetition, surfaced as E2210 with a message on the expansion repetition. Other MacroExpansionFailed cases stay on E2202. * and ? expansion repetitions over zero groups are unchanged.

Inline macro diagnostic tests cover reject/accept for +, *, and ?.

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

@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group branch from 4226edc to 846bfe2 Compare August 5, 2026 15:15
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from 61861f5 to 581b678 Compare August 5, 2026 15:15
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group branch from 846bfe2 to f1c1c1a Compare August 6, 2026 11:33
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from 581b678 to 92c87f9 Compare August 6, 2026 11:33

@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

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f1c1c1a. Configure here.

Comment thread crates/cairo-lang-semantic/src/items/macro_declaration.rs
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group branch from f1c1c1a to 5886c8d Compare August 6, 2026 11:39

@orizi orizi left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@orizi+AGNT made 1 comment.
Reviewable status: 0 of 3 files reviewed, all discussions resolved (waiting on eytan-starkware and TomerStarkware).

Comment thread crates/cairo-lang-semantic/src/items/macro_declaration.rs
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from 92c87f9 to edf9f91 Compare August 12, 2026 20:54
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group branch 2 times, most recently from b8fbc5e to fe293f7 Compare August 16, 2026 10:04
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from edf9f91 to 5284225 Compare August 16, 2026 10:04

@eytan-starkware eytan-starkware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@eytan-starkware+AGNT made 7 comments.
Reviewable status: 0 of 3 files reviewed, 6 unresolved discussions (waiting on eytan-starkware, orizi, and TomerStarkware).


a discussion (no related file):
Note: the comments below are from an automatic orizi-review run (Claude agents reviewing in Ori's style, findings adversarially verified before posting). Treat with the usual bot skepticism.


crates/cairo-lang-semantic/src/items/macro_declaration.rs line 1081 at r4 (raw file):

/// sites). They are kept as a backstop, so that a rule a future matcher or checker change lets
/// through fails with a diagnostic instead of expanding to something arbitrary.
/// [`MacroExpansionFailure::EmptyPlusRepetition`] is reachable by design: the number of groups is

"reachable by design" is exactly why it doesn't belong in this enum. MacroExpansionFailure is documented as the defensive backstop for things no program reaches; putting the one user-facing failure in it is what forces this doc caveat and the nested match in error_code. give it its own SemanticDiagnosticKind and have MacroExpansionError::report map to it - then this paragraph and the _ => arm both go away.


crates/cairo-lang-semantic/src/items/macro_declaration.rs line 1095 at r4 (raw file):

    /// A `$( ... )+` block in the expansion expands over zero groups, violating the at-least-once
    /// promise of its `+` operator.
    EmptyPlusRepetition,

name it after the operator, not the token - MacroRepetitionSeparatorWithZeroOrOne next door already does. EmptyOneOrMoreRepetition.


crates/cairo-lang-semantic/src/items/macro_declaration.rs line 1278 at r4 (raw file):

        let db = self.db;
        let group_count = self.group_count(repetition)?;
        if group_count == 0

the ? half of this is still silently wrong. ? promises at most once, and nothing here caps the loop - ($($x:ident),*) => { $($x + )? 0 } on m!(a, b) expands to a + b + 0 with no diagnostic (verified against expand_inline_macros). and a ? block can't carry a separator, so the extra groups are emitted glued. if the operator's promise is enforced, enforce both ends here:

        let group_count = self.group_count(repetition)?;
        let valid = match repetition.operator(db) {
            ast::MacroRepetitionOperator::OneOrMore(_) => group_count >= 1,
            ast::MacroRepetitionOperator::ZeroOrOne(_) => group_count <= 1,
            _ => true,
        };
        if !valid {

or say why ? is deliberately left alone.


crates/cairo-lang-semantic/src/items/macro_declaration.rs line 1284 at r4 (raw file):

            // at least one repetition, and only the matched call determines the group count.
            return Err(MacroExpansionError {
                stable_ptr: repetition.stable_ptr(db).untyped(),

this is the first MacroExpansionFailure a user can actually hit, and it reports on the declaration only. a call to a macro declared in another file puts the error in that file, with nothing at the call and no hint which call triggered it - rustc points at the definition too, but adds in this macro invocation. both callers (compute.rs:836, macro_call.rs:165) have the call syntax; worth carrying it into the report.


crates/cairo-lang-semantic/src/expr/test_data/inline_macros line 4105 at r4 (raw file):

error[E2210]: This macro expansion block must repeat at least once, but the call matched zero repetitions.
 --> lib.cairo:2:26
    ($($x:ident),*) => { $($x + )+ 0 };

expansion_test_data/inline_macros:363 still pins "The operator of an expansion repetition is ignored" as the rule. it isn't, as of this PR. update that comment (and its test name) while the + case is being carved out, otherwise the two files document opposite invariants.


crates/cairo-lang-semantic/src/diagnostic.rs line 1568 at r4 (raw file):

            SemanticDiagnosticKind::MacroExpansionFailed(failure) => match failure {
                MacroExpansionFailure::EmptyPlusRepetition => error_code!(E2210),
                _ => error_code!(E2202),

_ hands E2202 to whatever variant gets added next, silently. also this is the only arm in the whole error_code match that looks inside a kind - everywhere else is one code per kind. at minimum list them:

                MacroExpansionFailure::MissingRepetitionDriver
                | MacroExpansionFailure::ConflictingRepetitionDrivers
                | MacroExpansionFailure::MissingCapture(_) => error_code!(E2202),

A `$( ... )+` block in a macro expansion promises at least one
repetition, but a call matching zero groups silently expanded it to
nothing. Report the new E2210 instead, as rustc does ("this must repeat
at least once"). `*` and `?` blocks over zero groups stay valid.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/doc-expansion-error-defensive branch from 5284225 to 6067cf6 Compare August 16, 2026 11:37
@orizi
orizi force-pushed the graph-plan/2026-08-03-macro-fixes/expansion-plus-requires-group branch from fe293f7 to 3e84e0c Compare August 16, 2026 11:37

@eytan-starkware eytan-starkware left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@eytan-starkware+AGNT resolved 1 discussion.
Reviewable status: 0 of 3 files reviewed, 5 unresolved discussions (waiting on orizi and TomerStarkware).

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