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 SummaryMedium Risk Overview
Tests are updated so a Reviewed by Cursor Bugbot for commit 26c8e7b. Bugbot is set up for automated code reviews on this repo. Configure here. |
4226edc to
846bfe2
Compare
460d19f to
2d6c678
Compare
5545a66 to
c19648b
Compare
c6ccdef to
a454a87
Compare
c19648b to
0fa0009
Compare
a454a87 to
d5a0d2d
Compare
0fa0009 to
175bdc0
Compare
d5a0d2d to
d621f68
Compare
175bdc0 to
d9fcfe4
Compare
d621f68 to
8b23a11
Compare
d9fcfe4 to
bc5a48e
Compare
orizi
left a comment
There was a problem hiding this comment.
@orizi+AGNT made 5 comments and resolved 5 discussions.
Reviewable status: 0 of 6 files reviewed, all discussions resolved (waiting on TomerStarkware).
crates/cairo-lang-semantic/src/diagnostic.rs line 1568 at r4 (raw file):
Previously, eytan-starkware+AGNT (Agent AGNT for eytan-starkware) wrote…
_hands E2202 to whatever variant gets added next, silently. also this is the only arm in the wholeerror_codematch 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),
Gone with the redesign - MacroExpansionFailed(_) is one code again and the new kind carries its own.
crates/cairo-lang-semantic/src/expr/test_data/inline_macros line 4105 at r4 (raw file):
Previously, eytan-starkware+AGNT (Agent AGNT for eytan-starkware) wrote…
expansion_test_data/inline_macros:363still 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.
Updated - the golden is now "Test an expansion repetition whose operator differs from the pattern's, within its count." and its comment states the enforced promise and the rustc decl-time divergence.
crates/cairo-lang-semantic/src/items/macro_declaration.rs line 1081 at r4 (raw file):
Previously, eytan-starkware+AGNT (Agent AGNT for eytan-starkware) wrote…
"reachable by design" is exactly why it doesn't belong in this enum.
MacroExpansionFailureis 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 inerror_code. give it its ownSemanticDiagnosticKindand haveMacroExpansionError::reportmap to it - then this paragraph and the_ =>arm both go away.
Done - the variant left MacroExpansionFailure entirely. The reachable failure is its own SemanticDiagnosticKind::MacroExpansionRepetitionCountMismatch (covering both ends of the operator's promise), constructed as its own MacroExpansionError variant and mapped by report; the caveat paragraph and the nested error_code match are both gone.
crates/cairo-lang-semantic/src/items/macro_declaration.rs line 1278 at r4 (raw file):
Previously, eytan-starkware+AGNT (Agent AGNT for eytan-starkware) wrote…
the
?half of this is still silently wrong.?promises at most once, and nothing here caps the loop -($($x:ident),*) => { $($x + )? 0 }onm!(a, b)expands toa + b + 0with no diagnostic (verified againstexpand_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.
Enforced on both ends as suggested - + requires at least one group, ? allows at most one - and the mixed-operator golden now pins all three counts, with mixed_op!(1, 2) rejected at the call.
crates/cairo-lang-semantic/src/items/macro_declaration.rs line 1284 at r4 (raw file):
Previously, eytan-starkware+AGNT (Agent AGNT for eytan-starkware) wrote…
this is the first
MacroExpansionFailurea 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 addsin this macro invocation. both callers (compute.rs:836,macro_call.rs:165) have the call syntax; worth carrying it into the report.
Done - report now takes the call's stable pointer from both callers and anchors the count-mismatch diagnostic on the call that determined the group count (Cairo diagnostics are single-span, so the call site wins over the declaration; the message names the block's operator instead). The defensive failures stay on the expansion node.
bc5a48e to
6c36c5a
Compare
8b23a11 to
fb44fb8
Compare
6c36c5a to
629b2a8
Compare
fb44fb8 to
083c15c
Compare
629b2a8 to
8eefe56
Compare
0d8844c to
ca492eb
Compare
8eefe56 to
1f73148
Compare
ca492eb to
77b3591
Compare
b15aded to
d595d86
Compare
2bc894b to
8b3f58b
Compare
8b3f58b to
ce3f35c
Compare
d595d86 to
a991f8b
Compare
…their operator's promise A `$( ... )+` block in a macro expansion promises at least one repetition, but a call matching zero groups silently expanded it to nothing; a `$( ... )?` block promises at most one, but a call matching more silently expanded it once per group. Both ends now report the new E2210 at the call that determined the count. `*` blocks and zero-group `?` blocks stay valid, and an expansion operator still does not have to match its driver's. rustc reports "this must repeat at least once" on the `+` end; the `?` end is Cairo's own - rustc only lints the operator mismatch (allow-by-default `meta_variable_misuse`) and silently expands its `?` block once per group. The `?` change reverses behavior a golden previously pinned as valid: the mixed-operator test now pins all three counts, the two-group call rejected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ce3f35c to
ea8bb08
Compare
a991f8b to
26c8e7b
Compare

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