Sitelet https://github.com/starkware-libs/cairo/pull/10137
Skip to content

bug fix(starknet): Fully-qualify prelude types in contract codegen. - #10137

Merged
orizi merged 1 commit into
mainfrom
orizi/06-21-bug_fix_starknet_fully-qualify_prelude_types_in_contract_codegen
Jun 22, 2026
Merged

orizi merged 1 commit into
mainfrom
orizi/06-21-bug_fix_starknet_fully-qualify_prelude_types_in_contract_codegen

Conversation

@orizi

@orizi orizi commented Jun 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The #[starknet::contract] plugin now fully-qualifies the prelude types it
emits in generated code (core::array::Array, core::array::Span,
core::option::Option, plus Option::Some/Option::None and
core::array::ArrayTrait::new) instead of relying on the bare prelude names.

Touched codegen sites:

  • derive/event.rs — struct & enum Event impls (append_keys_and_data /
    deserialize) and the flat/nested variant deserialization.
  • entry_point.rs — entry-point wrapper signature (Span) and ArrayTrait::new.
  • dispatcher.rs — forward-method wrapper signature (Span).

Adds a regression test (shadowed_prelude_types) covering a contract that
defines Array, Span, and Option user types, and regenerates the affected
plugin_test_data golden files.


Type of change

  • Bug fix (fixes incorrect behavior)

Why is this change needed?

Cairo has a single flat namespace, so a user type defined inside a contract
module that shares a name with a prelude type shadows that prelude name. Because
the generated code referenced the bare names (e.g. Array<felt252>), a user
struct Array {} (0 generic params) made the generated Array<felt252> resolve
to the user struct, producing:

error[E2163]: Expected 0 generic arguments, found 1

This happened even for a storage-only contract with no entry points — the
auto-derived empty Event impl alone references the bare prelude types. The
diagnostic gave no hint that the user's type name was the cause.

Fixes #10128.


What was the behavior before?

#[starknet::contract]
mod c {
    #[storage]
    struct Storage {}
    struct Array {}
}

failed to compile with error[E2163]: Expected 0 generic arguments, found 1
(same for Option and Span).


What is the behavior after?

The contract compiles. Generated code fully-qualifies every prelude type it
references, so a same-module user type sharing the name can no longer shadow it.


Additional context

Removing the bare reference also surfaced a now-redundant
use core::array::ArrayTrait; in cairo_level_tests/l2_to_l1_messages.cairo
(it was only being consumed by the previously-bare generated ArrayTrait::new()),
which has been dropped.

This is scoped to the prelude-type axis named in the issue and is distinct
from parameter-name collisions (e.g. __calldata__, component,
serialized, value).

@reviewable-StarkWare

Copy link
Copy Markdown

This change is Reviewable

orizi commented Jun 21, 2026

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

The contract plugin emitted bare prelude type names (Array, Span, Option)
in generated code. A user type sharing one of those names inside the
contract module shadows the prelude, breaking compilation (E2163). Qualify
every emission to core::array::Array, core::array::Span, core::option::Option
(and Option::Some/None, ArrayTrait::new), matching the existing convention.

Fixes #10128.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@orizi
orizi force-pushed the orizi/06-21-bug_fix_starknet_fully-qualify_prelude_types_in_contract_codegen branch from 10729a1 to 2af8f3e Compare June 21, 2026 10:19
@orizi
orizi marked this pull request as ready for review June 21, 2026 10:40
@cursor

cursor Bot commented Jun 21, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches all Starknet contract expansion paths; semantics should match when prelude names are not shadowed, but any mistake in qualified paths would break every contract compile.

Overview
Starknet contract plugin output no longer uses bare prelude names (Array, Span, Option, ArrayTrait::new, Option::Some/None) in generated code. Those references are emitted as core::array::* and core::option::Option so user-defined types with the same names inside a contract module cannot shadow the prelude and break expansion (e.g. Expected 0 generic arguments, found 1).

Codegen templates in derive/event.rs (Event derive), entry_point.rs (entry-point wrappers), and dispatcher.rs (forward-impl wrappers) are updated accordingly; plugin_test_data goldens are refreshed and a shadowed_prelude_types regression test is wired in. The level test l2_to_l1_messages.cairo drops a redundant ArrayTrait import that was only needed for the old bare generated call.

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

@TomerStarkware TomerStarkware left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

:lgtm:

@TomerStarkware reviewed 35 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on eytan-starkware).

@orizi
orizi added this pull request to the merge queue Jun 22, 2026
Merged via the queue into main with commit 5fa8c31 Jun 22, 2026
55 checks passed
@orizi
orizi deleted the orizi/06-21-bug_fix_starknet_fully-qualify_prelude_types_in_contract_codegen branch June 23, 2026 07:45
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.

bug: Contract codegen bare prelude type names break compile

3 participants