fix(semantic): reject a + expansion repetition over zero groups - #10315
Conversation
9fd42a9 to
b559512
Compare
94fdd8f to
11ce2dc
Compare
b559512 to
71fa44b
Compare
f874dc3 to
4226edc
Compare
71fa44b to
61861f5
Compare
PR SummaryLow Risk Overview The expander returns Inline macro diagnostic tests cover reject/accept for Reviewed by Cursor Bugbot for commit 3e84e0c. Bugbot is set up for automated code reviews on this repo. Configure here. |
4226edc to
846bfe2
Compare
61861f5 to
581b678
Compare
846bfe2 to
f1c1c1a
Compare
581b678 to
92c87f9
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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.
f1c1c1a to
5886c8d
Compare
orizi
left a comment
There was a problem hiding this comment.
@orizi+AGNT made 1 comment.
Reviewable status: 0 of 3 files reviewed, all discussions resolved (waiting on eytan-starkware and TomerStarkware).
92c87f9 to
edf9f91
Compare
b8fbc5e to
fe293f7
Compare
edf9f91 to
5284225
Compare
eytan-starkware
left a comment
There was a problem hiding this comment.
@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>
5284225 to
6067cf6
Compare
fe293f7 to
3e84e0c
Compare
eytan-starkware
left a comment
There was a problem hiding this comment.
@eytan-starkware+AGNT resolved 1 discussion.
Reviewable status: 0 of 3 files reviewed, 5 unresolved discussions (waiting on orizi and TomerStarkware).


A
$( ... )+block in a macro expansion promises at least onerepetition, 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