fix(semantic): add salsa cycle recovery to the item generic-params queries - #10272
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
PR SummaryMedium Risk Overview Shared handlers in Module type alias cycle handling now short-circuits with Golden tests cover the macro → enum variant → generic item with trait bound pattern across the affected item kinds. Reviewed by Cursor Bugbot for commit 7a5f5b7. Bugbot is set up for automated code reviews on this repo. Configure here. |
eytan-starkware
left a comment
There was a problem hiding this comment.
@eytan-starkware reviewed 16 files and all commit messages, and made 2 comments.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on orizi and TomerStarkware).
crates/cairo-lang-semantic/src/items/generics.rs line 295 at r1 (raw file):
/// silently drop them. /// /// Convergence is bounded and observed: the fixpoint settles within three iterations on the
Why 3 iterations?
I believe this comment can be less prose and more concise if it had some structure x -> y -> z
|
Re: Why 3: iteration i recomputes the cycle head with the re-entrant read seeing iteration i-1's provisional value, and the computed result only depends on whether that read saw the initial Restructured the whole doc comment into arrow chains (both the cycle path and the convergence argument) and pushed it to Generated by Claude Code |
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 9db7950. Configure here.
9db7950 to
9e773a7
Compare
eytan-starkware
left a comment
There was a problem hiding this comment.
@eytan-starkware reviewed 1 file and all commit messages, made 1 comment, and resolved 1 discussion.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on orizi and TomerStarkware).
…eries Follow-up to #10268, which fixed enum_definition_data. Seven sibling queries had the same gap and each panicked with its own cycle head: struct_generic_params_data, enum_generic_params_data, free_function_generic_params_data, extern_function_declaration_generic_params_data, impl_def_generic_params_data, module_type_alias_generic_params_data, priv_trait_function_generic_params_data The trigger needs no malformed input, contrary to how the original was described. `E::A!(());` is well-formed item-level macro syntax whose path names <enum>::<variant>; combined with any generic item carrying a trait bound, the macro-call expansion resolves the enum, the enum resolves a variant type, and that re-enters whichever generic-params query is already on the stack. The re-entered query need not be reachable from priv_macro_call_data at all - it only has to be on the stack. One generic handler pair in generics.rs serves all seven, with salsa inferring the key type, rather than fourteen near-identical functions. Use the fixpoint shape - cycle_fn returns the computed value, not the provisional. Measured on these goldens, the provisional shape is worse than just losing information: five of seven change, it drops E2028 and (for extern fns) E2165, and for struct/enum it invents a spurious E2006 "Unknown type". Convergence measured per key via Cycle::iteration(): at most 3 iterations, against MAX_ITERATIONS 200. Also guard module_type_alias_semantic_data_cycle. It recovers by re-calling module_type_alias_semantic_data(id, true), but that body reads module_type_alias_generic_params_data before branching on in_cycle, so once that query recovers, the handler re-enters itself and stack-overflows. Without the guard this change trades an ICE for a worse one. The guard is inert for genuine alias cycles - it fires only on re-entry of the in_cycle key. The guard leaves module_type_alias_semantic_data(id, false) as Err in this scenario, which module_type_alias_semantic_diagnostics mapped to no diagnostics, dropping the alias's own E2028 (caught by Cursor Bugbot). Its Err path now falls back to the generic-params diagnostics, which no other query surfaces; the type_alias golden now shows E2028 like the sibling item kinds. impl_alias_semantic_data has the same unsafe shape and is latent only because impl_alias_generic_params_data still lacks recovery; adding it there later must guard that handler too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E43saQzYdQ7UC9UyyGx5Sr
9e773a7 to
7a5f5b7
Compare
TomerStarkware
left a comment
There was a problem hiding this comment.
@TomerStarkware reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on eytan-starkware).
orizi
left a comment
There was a problem hiding this comment.
@orizi resolved 1 discussion.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on orizi).


Summary
Adds
cycle_fnandcycle_initialhandlers to all*_generic_params_datasalsa queries (enum,struct,free_function,extern_function,impl_def,module_type_alias,trait_function). The shared handlers (generic_params_data_cycle,generic_params_data_initial) are defined ingenerics.rsand return the freshly computed value on cycle recovery rather than freezing at the initial provisional value, allowing salsa to fixpoint-iterate to the correct result. Also fixesmodule_type_alias_semantic_data_cycleto short-circuit withskip_diagnostic()whenin_cycleis true, preventing infinite re-entry.Type of change
Please check one:
Why is this change needed?
When an item-level macro call uses a path that names an enum variant (e.g.
E::A!(());), the compiler resolves the path throughmacro_call_module_id/priv_macro_call_data, which reads the enum's variants, which resolves the variant's type. If that type references a generic item with a trait bound (e.g.W<felt252>whereW<T, +Drop<T>>), resolving it re-enters the*_generic_params_dataquery for that item while it is still on the stack. Without cycle handlers, salsa would panic with an ICE (internal compiler error) instead of recovering gracefully.What was the behavior or documentation before?
The compiler would ICE (panic) when encountering item-level macro calls whose path resolved through an enum variant whose type referenced a generic item with a trait bound, because the resulting query cycle had no registered handler.
What is the behavior or documentation after?
The compiler recovers from the cycle, emits a
E2028: Cycle detected while resolving generic paramdiagnostic (andE2156: Inline macro not foundfor the unresolvable macro), and continues without panicking. Golden test files are added forenum,struct,free_function,extern_function,impl_def,trait, andtype_aliasto cover each affected query.Related issue or discussion (if any)
Additional context
Convergence is bounded: the fixpoint settles within three iterations on the cycle-triggering inputs covered by the golden tests, well within salsa's
MAX_ITERATIONSceiling of 200.