diff --git a/corelib/src/starknet/storage/vec.cairo b/corelib/src/starknet/storage/vec.cairo index becb2b41586..3230c4c2591 100644 --- a/corelib/src/starknet/storage/vec.cairo +++ b/corelib/src/starknet/storage/vec.cairo @@ -450,7 +450,7 @@ impl MutableVecImpl of MutableVecTrait>>> { fn push<+Drop, +starknet::Store>( self: StoragePath>>, value: Self::ElementType, ) { - self.append().write(value); + self.allocate().write(value); } fn pop<+Drop, +starknet::Store>( diff --git a/crates/cairo-lang-semantic/src/db.rs b/crates/cairo-lang-semantic/src/db.rs index 99d48244ab2..25510634585 100644 --- a/crates/cairo-lang-semantic/src/db.rs +++ b/crates/cairo-lang-semantic/src/db.rs @@ -34,7 +34,7 @@ use crate::items::imp::{ use crate::items::module::{ModuleItemInfo, ModuleSemanticData}; use crate::items::trt::{ ConcreteTraitGenericFunctionId, ConcreteTraitId, TraitItemConstantData, TraitItemImplData, - TraitItemTypeData, + TraitItemInfo, TraitItemTypeData, }; use crate::items::us::{ImportedModules, SemanticUseEx}; use crate::items::visibility::Visibility; @@ -466,6 +466,13 @@ pub trait SemanticGroup: /// Returns the item of the trait, by the given `name`, if exists. #[salsa::invoke(items::trt::trait_item_by_name)] fn trait_item_by_name(&self, trait_id: TraitId, name: SmolStr) -> Maybe>; + /// Returns the metadata for a trait item, by the given `name`, if exists. + #[salsa::invoke(items::trt::trait_item_info_by_name)] + fn trait_item_info_by_name( + &self, + trait_id: TraitId, + name: SmolStr, + ) -> Maybe>; /// Returns all the items used within the trait. #[salsa::invoke(items::trt::trait_all_used_items)] fn trait_all_used_items(&self, trait_id: TraitId) -> Maybe>>; diff --git a/crates/cairo-lang-semantic/src/diagnostic_test_data/tests b/crates/cairo-lang-semantic/src/diagnostic_test_data/tests index 10f5515debd..87e59b12f55 100644 --- a/crates/cairo-lang-semantic/src/diagnostic_test_data/tests +++ b/crates/cairo-lang-semantic/src/diagnostic_test_data/tests @@ -1267,3 +1267,69 @@ error: Global `use` item is not supported in `V2023_01` edition. --> lib.cairo:4:8 use a::*; ^ + +//! > ========================================================================== + +//! > Test usage of deprecated trait function (via function path). + +//! > test_runner_name +test_expr_diagnostics(expect_diagnostics: warnings_only) + +//! > expr_code +{ + let x = Struct {}; + MyTrait::deprecated_method(@x); +} + +//! > module_code +pub struct Struct {} + +pub trait MyTrait { + #[deprecated(feature: "deprecated", note: "This method is deprecated", since: "1.0.0")] + fn deprecated_method(self: @Struct); +} + +impl MyTraitImpl of MyTrait { + fn deprecated_method(self: @Struct) {} +} + +//! > function_body + +//! > expected_diagnostics +warning: Usage of deprecated feature `"deprecated"` with no `#[feature("deprecated")]` attribute. Note: "This method is deprecated" + --> lib.cairo:14:12 + MyTrait::deprecated_method(@x); + ^^^^^^^^^^^^^^^^^ + +//! > ========================================================================== + +//! > Test usage of deprecated trait function (via method). + +//! > test_runner_name +test_expr_diagnostics(expect_diagnostics: warnings_only) + +//! > expr_code +{ + let x = Struct {}; + x.deprecated_method(); +} + +//! > module_code +pub struct Struct {} + +pub trait MyTrait { + #[deprecated(feature: "deprecated", note: "This method is deprecated", since: "1.0.0")] + fn deprecated_method(self: @Struct); +} + +impl MyTraitImpl of MyTrait { + fn deprecated_method(self: @Struct) {} +} + +//! > function_body + +//! > expected_diagnostics +warning: Usage of deprecated feature `"deprecated"` with no `#[feature("deprecated")]` attribute. Note: "This method is deprecated" + --> lib.cairo:14:5 + x.deprecated_method(); + ^^^^^^^^^^^^^^^^^ diff --git a/crates/cairo-lang-semantic/src/expr/compute.rs b/crates/cairo-lang-semantic/src/expr/compute.rs index 35bb6dda1c6..60baa6226e2 100644 --- a/crates/cairo-lang-semantic/src/expr/compute.rs +++ b/crates/cairo-lang-semantic/src/expr/compute.rs @@ -2945,7 +2945,7 @@ fn method_call_expr( compute_method_function_call_data( ctx, candidate_traits.keys().copied().collect_vec().as_slice(), - func_name, + func_name.clone(), lexpr, path.stable_ptr().untyped(), generic_args_syntax, @@ -2968,8 +2968,17 @@ fn method_call_expr( Some(AmbiguousTrait { trait_function_id0, trait_function_id1 }) }, )?; - ctx.resolver.data.used_items.insert(candidate_traits[&actual_trait_id]); + if let Ok(trait_definition_data) = ctx.db.priv_trait_definition_data(actual_trait_id) { + if let Some(trait_item_info) = trait_definition_data.get_trait_item_info(&func_name) { + ctx.resolver.validate_feature_constraints( + ctx.diagnostics, + &segment.identifier_ast(db.upcast()), + &trait_item_info, + ); + } + } + ctx.resolver.data.used_items.insert(candidate_traits[&actual_trait_id]); ctx.resolver.data.resolved_items.mark_concrete( ctx.db, &segment, diff --git a/crates/cairo-lang-semantic/src/items/feature_kind.rs b/crates/cairo-lang-semantic/src/items/feature_kind.rs index 1ee2dd5e10e..047349e534d 100644 --- a/crates/cairo-lang-semantic/src/items/feature_kind.rs +++ b/crates/cairo-lang-semantic/src/items/feature_kind.rs @@ -71,6 +71,12 @@ impl FeatureKind { } } +/// A trait for retrieving the `FeatureKind` of an item. +pub trait HasFeatureKind { + /// Returns the `FeatureKind` associated with the implementing struct. + fn feature_kind(&self) -> &FeatureKind; +} + /// Diagnostics for feature markers. #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum FeatureMarkerDiagnostic { diff --git a/crates/cairo-lang-semantic/src/items/module.rs b/crates/cairo-lang-semantic/src/items/module.rs index cbebaefe8ce..90a902e30ad 100644 --- a/crates/cairo-lang-semantic/src/items/module.rs +++ b/crates/cairo-lang-semantic/src/items/module.rs @@ -19,6 +19,7 @@ use super::visibility::{Visibility, peek_visible_in}; use crate::SemanticDiagnostic; use crate::db::{SemanticGroup, get_resolver_data_options}; use crate::diagnostic::{SemanticDiagnosticKind, SemanticDiagnosticsBuilder}; +use crate::items::feature_kind::HasFeatureKind; use crate::resolve::ResolvedGenericItem; /// Information per item in a module. @@ -284,3 +285,9 @@ fn specific_module_usable_trait_ids( } Ok(module_traits) } + +impl HasFeatureKind for ModuleItemInfo { + fn feature_kind(&self) -> &FeatureKind { + &self.feature_kind + } +} diff --git a/crates/cairo-lang-semantic/src/items/trt.rs b/crates/cairo-lang-semantic/src/items/trt.rs index 04564754b13..7e37f641b00 100644 --- a/crates/cairo-lang-semantic/src/items/trt.rs +++ b/crates/cairo-lang-semantic/src/items/trt.rs @@ -20,6 +20,7 @@ use cairo_lang_utils::{Intern, LookupIntern, define_short_id}; use smol_str::SmolStr; use super::TraitOrImplContext; +use super::feature_kind::FeatureKind; use super::function_with_body::{FunctionBodyData, get_implicit_precedence, get_inline_config}; use super::functions::{ FunctionDeclarationData, GenericFunctionId, ImplGenericFunctionId, ImplicitPrecedence, @@ -36,6 +37,7 @@ use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosti use crate::expr::compute::{ComputationContext, ContextFunction, Environment, compute_root_expr}; use crate::expr::inference::InferenceId; use crate::expr::inference::canonic::ResultNoErrEx; +use crate::items::feature_kind::HasFeatureKind; use crate::resolve::{ResolvedConcreteItem, Resolver, ResolverData}; use crate::substitution::{GenericSubstitution, SemanticRewriter}; use crate::types::resolve_type; @@ -477,7 +479,29 @@ pub struct TraitDefinitionData { item_impl_asts: OrderedHashMap, /// Mapping of item names to their IDs. All the IDs should appear in one of the AST maps above. - item_id_by_name: Arc>, + item_id_by_name: Arc>, +} + +impl TraitDefinitionData { + /// Retrieves trait item information by its name. + pub fn get_trait_item_info(&self, item_name: &SmolStr) -> Option { + self.item_id_by_name.get(item_name).cloned() + } +} +/// Stores metadata for a trait item, including its ID and feature kind. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TraitItemInfo { + /// The unique identifier of the trait item. + pub id: TraitItemId, + /// The feature kind associated with this trait item. + pub feature_kind: FeatureKind, +} + +impl HasFeatureKind for TraitItemInfo { + /// Returns the feature kind of this trait item. + fn feature_kind(&self) -> &FeatureKind { + &self.feature_kind + } } // --- Selectors --- @@ -520,7 +544,7 @@ pub fn trait_required_item_names( ) -> Maybe> { let mut required_items = OrderedHashSet::<_>::default(); for (item_name, item_id) in db.priv_trait_definition_data(trait_id)?.item_id_by_name.iter() { - if match item_id { + if match item_id.id { TraitItemId::Function(id) => { let body = id.stable_ptr(db.upcast()).lookup(db.upcast()).body(db.upcast()); matches!(body, ast::MaybeTraitFunctionBody::None(_)) @@ -540,7 +564,17 @@ pub fn trait_item_by_name( trait_id: TraitId, name: SmolStr, ) -> Maybe> { - Ok(db.priv_trait_definition_data(trait_id)?.item_id_by_name.get(&name).cloned()) + Ok(db.priv_trait_definition_data(trait_id)?.item_id_by_name.get(&name).map(|info| info.id)) +} + +/// Query implementation of [crate::db::SemanticGroup::trait_item_info_by_name]. +pub fn trait_item_info_by_name( + db: &dyn SemanticGroup, + trait_id: TraitId, + name: SmolStr, +) -> Maybe> { + let trait_definition_data = db.priv_trait_definition_data(trait_id)?; + Ok(trait_definition_data.get_trait_item_info(&name)) } /// Query implementation of [SemanticGroup::trait_all_used_items]. @@ -551,7 +585,7 @@ pub fn trait_all_used_items( let mut all_used_items = db.trait_resolver_data(trait_id)?.used_items.clone(); let data = db.priv_trait_definition_data(trait_id)?; for item in data.item_id_by_name.values() { - for resolver_data in get_resolver_data_options(LookupItemId::TraitItem(*item), db) { + for resolver_data in get_resolver_data_options(LookupItemId::TraitItem(item.id), db) { all_used_items.extend(resolver_data.used_items.iter().cloned()); } } @@ -679,7 +713,7 @@ pub fn priv_trait_definition_data( let mut item_type_asts = OrderedHashMap::default(); let mut item_constant_asts = OrderedHashMap::default(); let mut item_impl_asts = OrderedHashMap::default(); - let mut item_id_by_name = OrderedHashMap::default(); + let mut item_id_by_name: OrderedHashMap = OrderedHashMap::default(); if let ast::MaybeTraitBody::Some(body) = trait_ast.body(syntax_db) { for item in body.items(syntax_db).elements(syntax_db) { @@ -689,8 +723,14 @@ pub fn priv_trait_definition_data( TraitFunctionLongId(module_file_id, func.stable_ptr()).intern(db); let name_node = func.declaration(syntax_db).name(syntax_db); let name = name_node.text(syntax_db); + let attributes = func.attributes(syntax_db); + let feature_kind = + FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes); if item_id_by_name - .insert(name.clone(), TraitItemId::Function(trait_func_id)) + .insert(name.clone(), TraitItemInfo { + id: TraitItemId::Function(trait_func_id), + feature_kind, + }) .is_some() { diagnostics.report( @@ -704,8 +744,14 @@ pub fn priv_trait_definition_data( let trait_type_id = TraitTypeLongId(module_file_id, ty.stable_ptr()).intern(db); let name_node = ty.name(syntax_db); let name = name_node.text(syntax_db); + let attributes = ty.attributes(syntax_db); + let feature_kind = + FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes); if item_id_by_name - .insert(name.clone(), TraitItemId::Type(trait_type_id)) + .insert(name.clone(), TraitItemInfo { + id: TraitItemId::Type(trait_type_id), + feature_kind, + }) .is_some() { diagnostics.report( @@ -721,8 +767,14 @@ pub fn priv_trait_definition_data( let name_node = constant.name(syntax_db); let name = name_node.text(syntax_db); + let attributes = constant.attributes(syntax_db); + let feature_kind = + FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes); if item_id_by_name - .insert(name.clone(), TraitItemId::Constant(trait_constant)) + .insert(name.clone(), TraitItemInfo { + id: TraitItemId::Constant(trait_constant), + feature_kind, + }) .is_some() { diagnostics.report( @@ -737,7 +789,15 @@ pub fn priv_trait_definition_data( let name_node = imp.name(syntax_db); let name = name_node.text(syntax_db); - if item_id_by_name.insert(name.clone(), TraitItemId::Impl(trait_impl)).is_some() + let attributes = imp.attributes(syntax_db); + let feature_kind = + FeatureKind::from_ast(db.upcast(), &mut diagnostics, &attributes); + if item_id_by_name + .insert(name.clone(), TraitItemInfo { + id: TraitItemId::Impl(trait_impl), + feature_kind, + }) + .is_some() { diagnostics.report( &name_node, @@ -757,7 +817,7 @@ pub fn priv_trait_definition_data( item_type_asts, item_constant_asts, item_impl_asts, - item_id_by_name: item_id_by_name.into(), + item_id_by_name: Arc::new(item_id_by_name), }) } diff --git a/crates/cairo-lang-semantic/src/resolve/mod.rs b/crates/cairo-lang-semantic/src/resolve/mod.rs index 3dc6cc7bb46..96710e0f661 100644 --- a/crates/cairo-lang-semantic/src/resolve/mod.rs +++ b/crates/cairo-lang-semantic/src/resolve/mod.rs @@ -41,7 +41,9 @@ use crate::expr::inference::infers::InferenceEmbeddings; use crate::expr::inference::{Inference, InferenceData, InferenceId}; use crate::items::constant::{ConstValue, ImplConstantId, resolve_const_expr_and_evaluate}; use crate::items::enm::SemanticEnumEx; -use crate::items::feature_kind::{FeatureConfig, FeatureKind, extract_feature_config}; +use crate::items::feature_kind::{ + FeatureConfig, FeatureKind, HasFeatureKind, extract_feature_config, +}; use crate::items::functions::{GenericFunctionId, ImplGenericFunctionId}; use crate::items::generics::generic_params_to_args; use crate::items::imp::{ @@ -423,7 +425,7 @@ impl<'db> Resolver<'db> { ) -> Maybe { let generic_args_syntax = segment.generic_args(self.db.upcast()); let segment_stable_ptr = segment.stable_ptr().untyped(); - self.validate_item_usability(diagnostics, module_id, identifier, &inner_item_info); + self.validate_module_item_usability(diagnostics, module_id, identifier, &inner_item_info); self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id)); let inner_generic_item = ResolvedGenericItem::from_module_item(self.db, inner_item_info.item_id)?; @@ -842,11 +844,18 @@ impl<'db> Resolver<'db> { } ResolvedConcreteItem::SelfTrait(concrete_trait_id) => { let impl_id = ImplLongId::SelfImpl(*concrete_trait_id).intern(self.db); - let Some(trait_item_id) = - self.db.trait_item_by_name(concrete_trait_id.trait_id(self.db), ident)? + let Some(trait_item_id) = self + .db + .trait_item_by_name(concrete_trait_id.trait_id(self.db), ident.clone())? else { return Err(diagnostics.report(identifier, InvalidPath)); }; + if let Ok(Some(trait_item_info)) = self + .db + .trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident.clone()) + { + self.validate_feature_constraints(diagnostics, identifier, &trait_item_info); + } self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id)); Ok(match trait_item_id { TraitItemId::Function(trait_function_id) => { @@ -879,11 +888,19 @@ impl<'db> Resolver<'db> { }) } ResolvedConcreteItem::Trait(concrete_trait_id) => { - let Some(trait_item_id) = - self.db.trait_item_by_name(concrete_trait_id.trait_id(self.db), ident)? + let Some(trait_item_id) = self + .db + .trait_item_by_name(concrete_trait_id.trait_id(self.db), ident.clone())? else { return Err(diagnostics.report(identifier, InvalidPath)); }; + + if let Ok(Some(trait_item_info)) = self + .db + .trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident.clone()) + { + self.validate_feature_constraints(diagnostics, identifier, &trait_item_info); + } self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id)); match trait_item_id { @@ -976,9 +993,16 @@ impl<'db> Resolver<'db> { ResolvedConcreteItem::Impl(impl_id) => { let concrete_trait_id = self.db.impl_concrete_trait(*impl_id)?; let trait_id = concrete_trait_id.trait_id(self.db); - let Some(trait_item_id) = self.db.trait_item_by_name(trait_id, ident)? else { + let Some(trait_item_id) = self.db.trait_item_by_name(trait_id, ident.clone())? + else { return Err(diagnostics.report(identifier, InvalidPath)); }; + if let Ok(Some(trait_item_info)) = self + .db + .trait_item_info_by_name(concrete_trait_id.trait_id(self.db), ident.clone()) + { + self.validate_feature_constraints(diagnostics, identifier, &trait_item_info); + } self.data.used_items.insert(LookupItemId::TraitItem(trait_item_id)); match trait_item_id { @@ -1220,7 +1244,12 @@ impl<'db> Resolver<'db> { item_type, )?; - self.validate_item_usability(diagnostics, *module_id, identifier, &inner_item_info); + self.validate_module_item_usability( + diagnostics, + *module_id, + identifier, + &inner_item_info, + ); self.data.used_items.insert(LookupItemId::ModuleItem(inner_item_info.item_id)); ResolvedGenericItem::from_module_item(self.db, inner_item_info.item_id) } @@ -1709,19 +1738,17 @@ impl<'db> Resolver<'db> { || self.settings.edition.ignore_visibility() && module_crate == self.db.core_crate() } - /// Validates that an item is usable from the current module or adds a diagnostic. - /// This includes visibility checks and feature checks. - fn validate_item_usability( + /// Validates whether a given item is allowed based on its feature kind. + /// This function checks if the item's feature kind is allowed in the current + /// configuration. If the item uses an unstable, deprecated, or internal feature + /// that is not permitted, a corresponding diagnostic error is reported. + pub fn validate_feature_constraints( &self, diagnostics: &mut SemanticDiagnostics, - containing_module_id: ModuleId, identifier: &ast::TerminalIdentifier, - item_info: &ModuleItemInfo, + item_info: &T, ) { - if !self.is_item_visible(containing_module_id, item_info, self.module_file_id.0) { - diagnostics.report(identifier, ItemNotVisible(item_info.item_id, vec![])); - } - match &item_info.feature_kind { + match &item_info.feature_kind() { FeatureKind::Unstable { feature, note } if !self.data.feature_config.allowed_features.contains(feature) => { @@ -1751,6 +1778,22 @@ impl<'db> Resolver<'db> { } } + /// Validates that an item is usable from the current module or adds a diagnostic. + /// This includes visibility checks and feature checks. + fn validate_module_item_usability( + &self, + diagnostics: &mut SemanticDiagnostics, + containing_module_id: ModuleId, + identifier: &ast::TerminalIdentifier, + item_info: &ModuleItemInfo, + ) { + if !self.is_item_visible(containing_module_id, item_info, self.module_file_id.0) { + diagnostics.report(identifier, ItemNotVisible(item_info.item_id, vec![])); + } + + self.validate_feature_constraints(diagnostics, identifier, item_info); + } + /// Checks if an item is visible from the current module. fn is_item_visible( &self, diff --git a/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo b/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo index 566eee76cb8..d3c8c49c3e2 100644 --- a/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo +++ b/crates/cairo-lang-starknet/cairo_level_tests/collections_test.cairo @@ -27,7 +27,7 @@ mod contract_with_vec { fn test_simple_member_write_to_map() { let mut map_contract_state = contract_with_map::contract_state_for_testing(); let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); - let vec_entry = vec_contract_state.simple.append(); + let vec_entry = vec_contract_state.simple.allocate(); map_contract_state.simple.entry(0).write(1); assert_eq!(vec_entry.read(), 1); } @@ -36,7 +36,7 @@ fn test_simple_member_write_to_map() { fn test_vec_iter() { let mut mut_state = contract_with_vec::contract_state_for_testing(); for i in 0..9_usize { - mut_state.simple.append().write(i); + mut_state.simple.push(i); } let state = @contract_with_vec::contract_state_for_testing(); @@ -59,7 +59,7 @@ fn test_vec_iter() { fn test_mut_vec_iter() { let mut mut_state = contract_with_vec::contract_state_for_testing(); for i in 0..9_usize { - mut_state.simple.append().write(i); + mut_state.simple.push(i); } let mut i = 0; @@ -81,7 +81,7 @@ fn test_mut_vec_iter() { fn test_simple_member_write_to_vec() { let mut map_contract_state = contract_with_map::contract_state_for_testing(); let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); - vec_contract_state.simple.append().write(1); + vec_contract_state.simple.push(1); assert_eq!(map_contract_state.simple.entry(0).read(), 1); } @@ -89,7 +89,7 @@ fn test_simple_member_write_to_vec() { fn test_nested_member_write_to_map() { let mut map_contract_state = contract_with_map::contract_state_for_testing(); let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); - let vec_entry = vec_contract_state.nested.append().append(); + let vec_entry = vec_contract_state.nested.allocate().allocate(); map_contract_state.nested.entry(0).entry(0).write(1); assert_eq!(vec_entry.read(), 1); } @@ -98,7 +98,7 @@ fn test_nested_member_write_to_map() { fn test_nested_member_write_to_vec() { let mut map_contract_state = contract_with_map::contract_state_for_testing(); let mut vec_contract_state = contract_with_vec::contract_state_for_testing(); - vec_contract_state.nested.append().append().write(1); + vec_contract_state.nested.allocate().push(1); assert_eq!(map_contract_state.nested.entry(0).entry(0).read(), 1); } @@ -117,9 +117,9 @@ fn test_simple_member_push_to_vec() { #[test] fn test_simple_member_pop_from_vec() { let mut state = contract_with_vec::contract_state_for_testing(); - state.simple.append().write(10); - state.simple.append().write(20); - state.simple.append().write(30); + state.simple.push(10); + state.simple.push(20); + state.simple.push(30); assert_eq!(state.simple.pop(), Some(30)); assert_eq!(state.simple.pop(), Some(20)); assert_eq!(state.simple.pop(), Some(10)); diff --git a/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo b/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo index c2fa5331402..7f8f7f4a33a 100644 --- a/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo +++ b/crates/cairo-lang-starknet/cairo_level_tests/storage_access.cairo @@ -203,9 +203,9 @@ fn test_read_write_non_zero() { #[test] fn test_storage_array() { let mut state = test_contract::contract_state_for_testing(); - state.vecs.vec.append().write(1_u32); - state.vecs.vec.append().write(2_u32); - state.vecs.vec.append().write(3_u32); + state.vecs.vec.push(1_u32); + state.vecs.vec.push(2_u32); + state.vecs.vec.push(3_u32); assert_eq!(state.vecs.vec.len(), 3); assert_eq!(state.vecs.vec[0].read(), 1); assert_eq!(state.vecs.vec[1].read(), 2); @@ -219,13 +219,13 @@ fn test_storage_array() { #[test] fn test_storage_vec_of_vecs() { let mut state = test_contract::contract_state_for_testing(); - state.vecs.vec_of_vecs.append(); - state.vecs.vec_of_vecs[0].append().write(1); - state.vecs.vec_of_vecs[0].append().write(2); - state.vecs.vec_of_vecs[0].append().write(3); - state.vecs.vec_of_vecs.append(); - state.vecs.vec_of_vecs[1].append().write(4); - state.vecs.vec_of_vecs[1].append().write(5); + state.vecs.vec_of_vecs.allocate(); + state.vecs.vec_of_vecs[0].push(1); + state.vecs.vec_of_vecs[0].push(2); + state.vecs.vec_of_vecs[0].push(3); + state.vecs.vec_of_vecs.allocate(); + state.vecs.vec_of_vecs[1].push(4); + state.vecs.vec_of_vecs[1].push(5); assert_eq!(state.vecs.vec_of_vecs.len(), 2); assert_eq!(state.vecs.vec_of_vecs[0].len(), 3); assert_eq!(state.vecs.vec_of_vecs[0][0].read(), 1); diff --git a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface index 6572bcaffe3..08089d26718 100644 --- a/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface +++ b/crates/cairo-lang-starknet/src/plugin/plugin_test_data/contracts/new_storage_interface @@ -3091,6 +3091,11 @@ warning: Plugin diagnostic: Enum with `#[derive(starknet::Store)] has no default | } |_^ +warning: Usage of deprecated feature `"starknet-storage-deprecation"` with no `#[feature("starknet-storage-deprecation")]` attribute. Note: "Use `core::starknet::storage::MutableVecTrait::allocate` instead" + --> lib.cairo:132:22 + self.arr.append().write(value); + ^^^^^^ + warning: Usage of deprecated feature `"deprecated_legacy_map"` with no `#[feature("deprecated_legacy_map")]` attribute. Note: "Use `starknet::storage::Map` instead." --> lib.cairo:75:28 legacy_map_balace: LegacyMap,