fix(starknet): handle empty enum in Store derive - #10069
Conversation
PR SummaryLow Risk Overview Empty enums ( Non-empty enums: match arms for read/write now carry their own trailing comma, and arms are joined with Plugin snapshots ( Reviewed by Cursor Bugbot for commit c879cdc. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8df03ffe6f
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
8df03ff to
1c09023
Compare
orizi
left a comment
There was a problem hiding this comment.
@orizi resolved 1 discussion.
Reviewable status: 0 of 3 files reviewed, all discussions resolved (waiting on eytan-starkware and TomerStarkware).
`#[derive(starknet::Store)]` on a zero-variant enum generated invalid code: the per-variant `match` arms collapsed to a stray leading `,`, and `size()` emitted a dangling `1_u8 + ` with no right operand. Both failed to parse. Carry the arm-terminating comma per arm (so an empty variant list yields no comma at all), and fall back to `0` for the accumulated max-size when there are no variants, mirroring the struct handler. Cover the empty-enum case in the user_defined_types expansion test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1c09023 to
c879cdc
Compare
|
The empty-enum handling can be a lot smaller. For a variant-less enum the existing template only breaks in two spots, and the comma fix already covers one of them:
With just those, the existing template generates valid code for empty enums: fn read(...) { let idx = Store::<felt252>::read(...)?; match idx { 0 | _ => Err(...) } }
fn write(..., value) { match value {}; Ok(()) } // uninhabited → exhaustive
fn size() -> u8 { 1_u8 + 0 }so the separate ~35-line impl isn't needed. Net is +16/−10 in Minor: this reuses the normal If we'd rather not pretend an uninhabited type is storable, the even-smaller option is to reject it outright with a diagnostic at the top of |
orizi
left a comment
There was a problem hiding this comment.
this generates unreachable code - handling to create trivial code is more sensible.
@orizi made 1 comment.
Reviewable status: 0 of 3 files reviewed, all discussions resolved (waiting on eytan-starkware and TomerStarkware).
eytan-starkware
left a comment
There was a problem hiding this comment.
@eytan-starkware reviewed 3 files and all commit messages, and made 1 comment.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on TomerStarkware).

Summary
Fixes malformed Cairo code generated by the
#[derive(starknet::Store)]macro for enums. Match arm strings were being joined with,\nat the join site while also having commas appended individually to each arm, resulting in double commas. The fix moves the trailing comma into each arm's format string and joins with\nonly. Additionally, adds support for empty enums (enum Foo {}): thesize()method previously emitted a dangling+operator when no variants were present; it now falls back to0in that case, matching the struct handler's behavior.Type of change
Please check one:
Why is this change needed?
The
Storederive macro for enums was joining match arms with,\nat thejoincall while each arm string already lacked a trailing comma, causing the last arm to be missing its comma. Separately, when an enum had zero variants,match_sizeremained empty and was interpolated directly into1_u8 +insize(), producing invalid Cairo syntax with a dangling+.What was the behavior or documentation before?
writeandwrite_at_offsetmatch arms were missing trailing commas on the last arm.starknet::Storeon an empty enum caused a compiler error due to1_u8 +with nothing following the operator in the generatedsize()implementation.What is the behavior or documentation after?
\nalone, producing well-formed Cairo match expressions.starknet::Storewithout a syntax error;size()emits1_u8 + 0instead of1_u8 +.Related issue or discussion (if any)
N/A
Additional context
Test data snapshots for
new_storage_interfaceanduser_defined_typeshave been updated to reflect the corrected output, including a newEmptyEnumtest case and its expected generatedStoreimplementation and diagnostics.