Skip to content

Commit

Permalink
Added option for renaming a storage varialble path. (#6758)
Browse files Browse the repository at this point in the history
  • Loading branch information
orizi authored Nov 28, 2024
1 parent a55979d commit f0a8e0e
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 34 deletions.
2 changes: 2 additions & 0 deletions crates/cairo-lang-starknet/cairo_level_tests/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ mod collections_test;
mod component_usage_test;
#[cfg(test)]
mod flat_storage_test;
#[cfg(test)]
mod renamed_storage_test;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use core::starknet::storage::{StoragePointerWriteAccess, StoragePointerReadAccess};

#[starknet::storage_node]
struct A {
pub a: felt252,
}

#[starknet::storage_node]
struct B {
#[rename("a")]
pub b: felt252,
}

#[starknet::storage_node]
struct AB {
#[flat]
pub a: A,
#[allow(starknet::colliding_storage_paths)]
#[flat]
pub b: B,
}

#[starknet::contract]
mod contract {
#[storage]
pub struct Storage {
pub a: super::A,
#[allow(starknet::colliding_storage_paths)]
#[rename("a")]
pub b: super::B,
pub ab: super::AB,
}
}

#[test]
fn rename_test() {
let mut state = contract::contract_state_for_testing();
state.a.a.write(1);
assert_eq!(state.b.b.read(), 1);
state.b.b.write(2);
assert_eq!(state.a.a.read(), 2);
assert_eq!(state.ab.a.a.read(), 0);
state.ab.a.a.write(3);
assert_eq!(state.ab.b.b.read(), 3);
state.ab.b.b.write(4);
assert_eq!(state.ab.a.a.read(), 4);
}
19 changes: 9 additions & 10 deletions crates/cairo-lang-starknet/src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ use smol_str::SmolStr;
use crate::abi::{ABIError, AbiBuilder, BuilderConfig};
use crate::contract::module_contract;
use crate::plugin::consts::{
COMPONENT_ATTR, CONTRACT_ATTR, EMBEDDABLE_ATTR, FLAT_ATTR, STORAGE_ATTR, STORAGE_NODE_ATTR,
STORAGE_STRUCT_NAME, STORE_TRAIT, SUBSTORAGE_ATTR,
COMPONENT_ATTR, CONTRACT_ATTR, EMBEDDABLE_ATTR, STORAGE_ATTR, STORAGE_NODE_ATTR,
STORAGE_STRUCT_NAME, STORE_TRAIT,
};
use crate::plugin::storage_interfaces::{StorageMemberKind, get_member_storage_config};
use crate::plugin::utils::has_derive;

const ALLOW_NO_DEFAULT_VARIANT_ATTR: &str = "starknet::store_no_default_variant";
Expand Down Expand Up @@ -218,14 +219,12 @@ fn member_analyze(
diagnostics: &mut Vec<PluginDiagnostic>,
) {
user_data_path.push(member_name.clone());
if !(member.id.stable_ptr(db.upcast()).lookup(db.upcast()).has_attr(db.upcast(), FLAT_ATTR)
|| member
.id
.stable_ptr(db.upcast())
.lookup(db.upcast())
.has_attr(db.upcast(), SUBSTORAGE_ATTR))
{
paths_data.handle(member_name, user_data_path.clone(), pointer_to_code, diagnostics);
let member_ast = member.id.stable_ptr(db.upcast()).lookup(db.upcast());
// Ignoring diagnostics as these would have been reported previously.
let config = get_member_storage_config(db.upcast(), &member_ast, &mut vec![]);
if config.kind == StorageMemberKind::Basic {
let name = config.rename.map(Into::into).unwrap_or(member_name);
paths_data.handle(name, user_data_path.clone(), pointer_to_code, diagnostics);
user_data_path.pop();
return;
}
Expand Down
1 change: 1 addition & 0 deletions crates/cairo-lang-starknet/src/plugin/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub const EMBEDDABLE_AS_ATTR: &str = "embeddable_as";
pub const COMPONENT_INLINE_MACRO: &str = "component";
pub const HAS_COMPONENT_TRAIT: &str = "HasComponent";
pub const SUBSTORAGE_ATTR: &str = "substorage";
pub const RENAME_ATTR: &str = "rename";
pub const NESTED_ATTR: &str = "nested";
pub const FLAT_ATTR: &str = "flat";
pub const KEY_ATTR: &str = "key";
Expand Down
8 changes: 6 additions & 2 deletions crates/cairo-lang-starknet/src/plugin/derive/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use indent::indent_by;
use indoc::formatdoc;

use crate::plugin::consts::STORE_TRAIT;
use crate::plugin::storage_interfaces::handle_storage_interface_struct;
use crate::plugin::storage_interfaces::{
handle_storage_interface_struct, struct_members_storage_configs,
};

/// Returns the rewrite node for the `#[derive(starknet::Store)]` attribute.
pub fn handle_store_derive(
Expand All @@ -22,7 +24,9 @@ pub fn handle_store_derive(
// a sub-pointers implementation.
let store_trait_code = handle_struct_store(db, struct_ast)?;
let sub_pointers_code = if !struct_ast.members(db).elements(db).is_empty() {
handle_storage_interface_struct(db, struct_ast, metadata).into_rewrite_node()
let configs = struct_members_storage_configs(db, struct_ast, diagnostics);
handle_storage_interface_struct(db, struct_ast, &configs, metadata)
.into_rewrite_node()
} else {
RewriteNode::Text("".to_string())
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,11 @@ impl StorageStorageBaseMutDrop of core::traits::Drop::<StorageStorageBaseMut>;
impl StorageStorageBaseMutCopy of core::traits::Copy::<StorageStorageBaseMut>;

//! > expected_diagnostics
error: Plugin diagnostic: Only #[substorage(v0)] is supported.
--> lib.cairo:19:9
#[substorage]
^***********^

error: Plugin diagnostic: `substorage` attribute is only allowed for members of type [some_path::]Storage`
--> lib.cairo:14:9
#[substorage(v0)]
Expand Down
23 changes: 16 additions & 7 deletions crates/cairo-lang-starknet/src/plugin/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::helpers::QueryAttrs;
use cairo_lang_syntax::node::{Terminal, TypedSyntaxNode, ast};
use indoc::formatdoc;
use itertools::zip_eq;

use super::starknet_module::generation_data::StarknetModuleCommonGenerationData;
use super::starknet_module::{StarknetModuleKind, backwards_compatible_storage};
use super::storage_interfaces::handle_storage_interface_struct;
use super::storage_interfaces::{
StorageMemberConfig, StorageMemberKind, handle_storage_interface_struct,
struct_members_storage_configs,
};
use super::{CONCRETE_COMPONENT_STATE_NAME, CONTRACT_STATE_NAME, FLAT_ATTR, STORAGE_STRUCT_NAME};
use crate::plugin::SUBSTORAGE_ATTR;

Expand All @@ -31,8 +35,9 @@ pub fn handle_storage_struct(
let mut substorage_members_struct_code = vec![];
let mut substorage_members_init_code = vec![];
let mut storage_struct_members = vec![];
for member in struct_ast.members(db).elements(db) {
if member.has_attr(db, SUBSTORAGE_ATTR) {
let configs = struct_members_storage_configs(db, &struct_ast, diagnostics);
for (member, config) in zip_eq(struct_ast.members(db).elements(db), &configs) {
if config.kind == StorageMemberKind::SubStorage {
if let Some((struct_code, init_code)) =
get_substorage_member_code(db, &member, metadata)
{
Expand All @@ -49,7 +54,7 @@ pub fn handle_storage_struct(
}
}
let SimpleMemberGeneratedCode { struct_code, struct_code_mut, init_code, storage_member } =
get_simple_member_code(db, &member, metadata);
get_simple_member_code(db, &member, config, metadata);
members_struct_code.push(struct_code);
members_struct_code_mut.push(struct_code_mut);
members_init_code.push(init_code);
Expand All @@ -70,7 +75,7 @@ pub fn handle_storage_struct(
"".to_string()
};
let storage_base_code =
handle_storage_interface_struct(db, &struct_ast, metadata).into_rewrite_node();
handle_storage_interface_struct(db, &struct_ast, &configs, metadata).into_rewrite_node();
data.state_struct_code = RewriteNode::interpolate_patched(
&formatdoc!(
"
Expand Down Expand Up @@ -211,10 +216,11 @@ struct SimpleMemberGeneratedCode {
fn get_simple_member_code(
db: &dyn SyntaxGroup,
member: &ast::Member,
config: &StorageMemberConfig,
metadata: &MacroPluginMetadata<'_>,
) -> SimpleMemberGeneratedCode {
let member_wrapper_type = RewriteNode::text(
if member.has_attr(db, SUBSTORAGE_ATTR) || member.has_attr(db, FLAT_ATTR) {
if matches!(config.kind, StorageMemberKind::SubStorage | StorageMemberKind::Flat) {
"FlattenedStorage"
} else {
"StorageBase"
Expand All @@ -226,11 +232,14 @@ fn get_simple_member_code(
RewriteNode::from_ast(&member.visibility(db))
};
let member_name = RewriteNode::from_ast_trimmed(&member.name(db));
let member_selector_name =
config.rename.as_deref().map_or_else(|| member_name.clone(), RewriteNode::text);
let patches = [
("attributes".to_string(), RewriteNode::from_ast(&member.attributes(db))),
("member_visibility".to_string(), member_visibility.clone()),
("member_wrapper_type".to_string(), member_wrapper_type.clone()),
("member_name".to_string(), member_name),
("member_selector_name".to_string(), member_selector_name),
("member_type".to_string(), RewriteNode::from_ast_trimmed(&member.type_clause(db).ty(db))),
]
.into();
Expand All @@ -256,7 +265,7 @@ fn get_simple_member_code(
} else {
RewriteNode::interpolate_patched(
"\n $member_name$: starknet::storage::StorageBase{ address: \
selector!(\"$member_name$\") },",
selector!(\"$member_selector_name$\") },",
&patches,
)
}
Expand Down
Loading

0 comments on commit f0a8e0e

Please sign in to comment.