From 2ea562037f87cd94fae26ce21656d34d367b0c05 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 24 May 2024 09:35:49 +0100 Subject: [PATCH 01/14] Changes storage keys to use names instead of indices. With this change storage keys will have a hash based on: `sha256("storage::::")` or a given key. A key can be provide by using the `in` keyword in a storage field as such: ``` storage { a in 0x02dac99c283f16bc91b74f6942db7f012699a2ad51272b15207b9cc14a70dbae: u64 } ``` StorageKey.field_id is now based on: `sha256("storage::::..")` Nested storage field such as the following are not yet supported and will be added in a later pull request. ``` storage { a { b:u64 } } ``` --- sway-ast/src/item/item_storage.rs | 2 + sway-core/src/ir_generation/function.rs | 40 +++++++---- sway-core/src/ir_generation/storage.rs | 66 ++++++++++++------- .../language/parsed/declaration/storage.rs | 3 +- .../src/language/ty/declaration/storage.rs | 47 +++++++------ .../src/language/ty/expression/storage.rs | 25 ++++--- .../ast_node/declaration/declaration.rs | 2 + .../ast_node/declaration/storage.rs | 17 ++--- .../to_parsed_lang/convert_parse_tree.rs | 13 ++++ sway-error/src/parser_error.rs | 2 + sway-parse/src/item/item_storage.rs | 15 ++++- sway-types/src/lib.rs | 2 - sway-types/src/state.rs | 30 --------- sway-utils/src/constants.rs | 4 +- 14 files changed, 163 insertions(+), 105 deletions(-) delete mode 100644 sway-types/src/state.rs diff --git a/sway-ast/src/item/item_storage.rs b/sway-ast/src/item/item_storage.rs index ea923faee73..a526ad0e1fc 100644 --- a/sway-ast/src/item/item_storage.rs +++ b/sway-ast/src/item/item_storage.rs @@ -15,6 +15,8 @@ impl Spanned for ItemStorage { #[derive(Clone, Debug, Serialize)] pub struct StorageField { pub name: Ident, + pub in_token: Option, + pub key: Option, pub colon_token: ColonToken, pub ty: Ty, pub eq_token: EqToken, diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs index e433f9ee6e5..289345c8f26 100644 --- a/sway-core/src/ir_generation/function.rs +++ b/sway-core/src/ir_generation/function.rs @@ -2,7 +2,7 @@ use super::{ compile::compile_function, convert::*, lexical_map::LexicalMap, - storage::{add_to_b256, get_storage_key}, + storage::{add_to_b256, get_storage_field_id, get_storage_key}, types::*, }; use crate::{ @@ -28,7 +28,6 @@ use sway_types::{ ident::Ident, integer_bits::IntegerBits, span::{Span, Spanned}, - state::StateIndex, u256::U256, Named, }; @@ -589,8 +588,14 @@ impl<'eng> FnCompiler<'eng> { } ty::TyExpressionVariant::StorageAccess(access) => { let span_md_idx = md_mgr.span_to_md(context, &access.span()); - let ns = access.namespace.as_ref().map(|ns| ns.as_str()); - self.compile_storage_access(context, ns, &access.ix, &access.fields, span_md_idx) + self.compile_storage_access( + context, + access.storage_field_names.clone(), + access.struct_field_names.clone(), + access.key.clone(), + &access.fields, + span_md_idx, + ) } ty::TyExpressionVariant::IntrinsicFunction(kind) => { self.compile_intrinsic_function(context, md_mgr, kind, ast_expr.span.clone()) @@ -3726,8 +3731,9 @@ impl<'eng> FnCompiler<'eng> { fn compile_storage_access( &mut self, context: &mut Context, - ns: Option<&str>, - ix: &StateIndex, + storage_field_names: Vec, + struct_field_names: Vec, + key: Option, fields: &[ty::TyStorageAccessDescriptor], span_md_idx: Option, ) -> Result { @@ -3752,7 +3758,15 @@ impl<'eng> FnCompiler<'eng> { // Do the actual work. This is a recursive function because we want to drill down // to load each primitive type in the storage field in its own storage slot. - self.compile_storage_read(context, ns, ix, &field_idcs, &base_type, span_md_idx) + self.compile_storage_read( + context, + storage_field_names, + struct_field_names, + key, + &field_idcs, + &base_type, + span_md_idx, + ) } #[allow(clippy::too_many_arguments)] @@ -3857,8 +3871,9 @@ impl<'eng> FnCompiler<'eng> { fn compile_storage_read( &mut self, context: &mut Context, - ns: Option<&str>, - ix: &StateIndex, + storage_field_names: Vec, + struct_field_names: Vec, + key: Option, indices: &[u64], base_type: &Type, span_md_idx: Option, @@ -3895,7 +3910,10 @@ impl<'eng> FnCompiler<'eng> { // plus the offset, in number of slots, computed above. The offset within this // particular slot is the remaining offset, in words. ( - add_to_b256(get_storage_key::(ns, ix, &[]), offset_in_slots), + add_to_b256( + get_storage_key(storage_field_names.clone(), key.clone()), + offset_in_slots, + ), offset_remaining, ) }; @@ -3950,7 +3968,7 @@ impl<'eng> FnCompiler<'eng> { .add_metadatum(context, span_md_idx); // Store the field identifier as the third field in the `StorageKey` struct - let unique_field_id = get_storage_key(ns, ix, indices); // use the indices to get a field id that is unique even for zero-sized values that live in the same slot + let unique_field_id = get_storage_field_id(storage_field_names, struct_field_names); // use the struct_field_names to get a field id that is unique even for zero-sized values that live in the same slot let field_id = convert_literal_to_value(context, &Literal::B256(unique_field_id.into())) .add_metadatum(context, span_md_idx); let gep_2_val = diff --git a/sway-core/src/ir_generation/storage.rs b/sway-core/src/ir_generation/storage.rs index 2f0bda0ee38..89f7088f277 100644 --- a/sway-core/src/ir_generation/storage.rs +++ b/sway-core/src/ir_generation/storage.rs @@ -8,7 +8,7 @@ use sway_ir::{ context::Context, irtype::Type, }; -use sway_types::state::StateIndex; +use sway_types::u256::U256; /// Determines how values that are less then a word in length /// has to be padded to word boundary when in structs or enums. @@ -19,20 +19,43 @@ enum InByte8Padding { Left, } -/// Hands out storage keys using a state index and a list of subfield indices. -/// Basically returns sha256("storage____..") -/// or sha256("storage_____..") -pub(super) fn get_storage_key(namespace: Option<&str>, ix: &StateIndex, indices: &[T]) -> Bytes32 -where - T: std::fmt::Display, -{ +/// Hands out storage keys using storage field names or an existing key. +/// Basically returns sha256("storage::::") +/// or key if defined. +pub(super) fn get_storage_key(storage_field_names: Vec, key: Option) -> Bytes32 { + if let Some(key) = key { + return key.to_be_bytes().into(); + } let data = format!( "{}{}{}", - sway_utils::constants::STORAGE_DOMAIN_SEPARATOR, - namespace.map(|ns| format!("{ns}_")).unwrap_or("".into()), - ix.to_usize(), + sway_utils::constants::STORAGE_DOMAIN, + sway_utils::constants::STORAGE_FIELD_SEPARATOR, + storage_field_names.join(sway_utils::constants::STORAGE_FIELD_SEPARATOR), + ); + Hasher::hash(data) +} + +/// Hands out unique storage field ids using storage field names and struct field names. +/// Basically returns sha256("storage::::..") +pub(super) fn get_storage_field_id( + storage_field_names: Vec, + struct_field_names: Vec, +) -> Bytes32 { + let data = format!( + "{}{}{}{}", + sway_utils::constants::STORAGE_DOMAIN, + sway_utils::constants::STORAGE_FIELD_SEPARATOR, + storage_field_names.join(sway_utils::constants::STORAGE_FIELD_SEPARATOR), + if struct_field_names.is_empty() { + "".to_string() + } else { + format!( + "{}{}", + sway_utils::constants::STRUCT_FIELD_SEPARATOR, + struct_field_names.join(sway_utils::constants::STRUCT_FIELD_SEPARATOR), + ) + } ); - let data = indices.iter().fold(data, |acc, i| format!("{acc}_{i}")); Hasher::hash(data) } @@ -64,22 +87,21 @@ pub(super) fn add_to_b256(x: Bytes32, y: u64) -> Bytes32 { pub fn serialize_to_storage_slots( constant: &Constant, context: &Context, - ix: &StateIndex, - ns: Option<&str>, + storage_field_names: Vec, + key: Option, ty: &Type, - indices: &[usize], ) -> Vec { match &constant.value { ConstantValue::Undef => vec![], // If not being a part of an aggregate, single byte values like `bool`, `u8`, and unit // are stored as a byte at the beginning of the storage slot. ConstantValue::Unit if ty.is_unit(context) => vec![StorageSlot::new( - get_storage_key(ns, ix, indices), + get_storage_key(storage_field_names, key), Bytes32::new([0; 32]), )], ConstantValue::Bool(b) if ty.is_bool(context) => { vec![StorageSlot::new( - get_storage_key(ns, ix, indices), + get_storage_key(storage_field_names, key), Bytes32::new([ if *b { 1 } else { 0 }, 0, @@ -118,7 +140,7 @@ pub fn serialize_to_storage_slots( } ConstantValue::Uint(b) if ty.is_uint8(context) => { vec![StorageSlot::new( - get_storage_key(ns, ix, indices), + get_storage_key(storage_field_names, key), Bytes32::new([ *b as u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -128,7 +150,7 @@ pub fn serialize_to_storage_slots( // Similarly, other uint values are stored at the beginning of the storage slot. ConstantValue::Uint(n) if ty.is_uint(context) => { vec![StorageSlot::new( - get_storage_key(ns, ix, indices), + get_storage_key(storage_field_names, key), Bytes32::new( n.to_be_bytes() .iter() @@ -142,13 +164,13 @@ pub fn serialize_to_storage_slots( } ConstantValue::U256(b) if ty.is_uint_of(context, 256) => { vec![StorageSlot::new( - get_storage_key(ns, ix, indices), + get_storage_key(storage_field_names, key), Bytes32::new(b.to_be_bytes()), )] } ConstantValue::B256(b) if ty.is_b256(context) => { vec![StorageSlot::new( - get_storage_key(ns, ix, indices), + get_storage_key(storage_field_names, key), Bytes32::new(b.to_be_bytes()), )] } @@ -185,7 +207,7 @@ pub fn serialize_to_storage_slots( ty.as_string(context) ); (0..(type_size_in_bytes + 31) / 32) - .map(|i| add_to_b256(get_storage_key(ns, ix, indices), i)) + .map(|i| add_to_b256(get_storage_key(storage_field_names.clone(), key.clone()), i)) .zip((0..packed.len() / 4).map(|i| { Bytes32::new( Vec::from_iter((0..4).flat_map(|j| *packed[4 * i + j])) diff --git a/sway-core/src/language/parsed/declaration/storage.rs b/sway-core/src/language/parsed/declaration/storage.rs index 0530a819aba..070775c92b6 100644 --- a/sway-core/src/language/parsed/declaration/storage.rs +++ b/sway-core/src/language/parsed/declaration/storage.rs @@ -4,7 +4,7 @@ use crate::{ transform, type_system::*, }; -use sway_types::{ident::Ident, span::Span, Spanned}; +use sway_types::{ident::Ident, span::Span, u256::U256, Spanned}; #[derive(Debug, Clone)] /// A declaration of contract storage. Only valid within contract contexts. @@ -39,6 +39,7 @@ impl Spanned for StorageDeclaration { #[derive(Debug, Clone)] pub struct StorageField { pub name: Ident, + pub key: Option, pub attributes: transform::AttributesMap, pub type_argument: TypeArgument, pub span: Span, diff --git a/sway-core/src/language/ty/declaration/storage.rs b/sway-core/src/language/ty/declaration/storage.rs index d56ecb100e7..15194ab4fdf 100644 --- a/sway-core/src/language/ty/declaration/storage.rs +++ b/sway-core/src/language/ty/declaration/storage.rs @@ -4,12 +4,12 @@ use sway_error::{ error::{CompileError, StructFieldUsageContext}, handler::{ErrorEmitted, Handler}, }; -use sway_types::{state::StateIndex, Ident, Named, Span, Spanned}; +use sway_types::{u256::U256, Ident, Named, Span, Spanned}; use crate::{ engine_threading::*, language::{ty::*, Visibility}, - transform::{self, AttributeKind}, + transform::{self}, type_system::*, Namespace, }; @@ -95,22 +95,22 @@ impl TyStorageDecl { "Having at least one element in the storage load is guaranteed by the grammar.", ); - let (ix, initial_field_type) = match storage_fields - .iter() - .enumerate() - .find(|(_, sf)| &sf.name == first_field) - { - Some((ix, TyStorageField { type_argument, .. })) => { - (StateIndex::new(ix), type_argument.type_id) - } - None => { - return Err(handler.emit_err(CompileError::StorageFieldDoesNotExist { - field_name: first_field.into(), - available_fields: storage_fields.iter().map(|sf| sf.name.clone()).collect(), - storage_decl_span: self.span(), - })); - } - }; + let (initial_field_type, initial_field_key, initial_field_name) = + match storage_fields.iter().find(|sf| &sf.name == first_field) { + Some(TyStorageField { + type_argument, + key, + name, + .. + }) => (type_argument.type_id, key, name), + None => { + return Err(handler.emit_err(CompileError::StorageFieldDoesNotExist { + field_name: first_field.into(), + available_fields: storage_fields.iter().map(|sf| sf.name.clone()).collect(), + storage_decl_span: self.span(), + })); + } + }; access_descriptors.push(TyStorageAccessDescriptor { name: first_field.clone(), @@ -133,6 +133,8 @@ impl TyStorageDecl { _ => None, }; + let mut struct_field_names = vec![]; + for field in remaining_fields { match get_struct_decl(previous_field_type_id) { Some(struct_decl) => { @@ -161,6 +163,8 @@ impl TyStorageDecl { span: field.span(), }); + struct_field_names.push(field.as_str().to_string()); + previous_field = field; previous_field_type_id = current_field_type_id; } @@ -208,8 +212,9 @@ impl TyStorageDecl { Ok(( TyStorageAccess { fields: access_descriptors, - ix, - namespace: self.storage_namespace(), + key: initial_field_key.clone(), + storage_field_names: vec![initial_field_name.as_str().to_string()], + struct_field_names, storage_keyword_span, }, return_type, @@ -247,6 +252,7 @@ impl Spanned for TyStorageField { #[derive(Clone, Debug)] pub struct TyStorageField { pub name: Ident, + pub key: Option, pub type_argument: TypeArgument, pub initializer: TyExpression, pub(crate) span: Span, @@ -272,6 +278,7 @@ impl HashWithEngines for TyStorageField { // reliable source of obj v. obj distinction span: _, attributes: _, + key: _, } = self; name.hash(state); type_argument.hash(state, engines); diff --git a/sway-core/src/language/ty/expression/storage.rs b/sway-core/src/language/ty/expression/storage.rs index fe097923d90..0c8df60f6fa 100644 --- a/sway-core/src/language/ty/expression/storage.rs +++ b/sway-core/src/language/ty/expression/storage.rs @@ -1,6 +1,6 @@ use std::hash::{Hash, Hasher}; -use sway_types::{state::StateIndex, Ident, Span, Spanned}; +use sway_types::{u256::U256, Ident, Span, Spanned}; use crate::{engine_threading::*, type_system::TypeId}; @@ -8,17 +8,22 @@ use crate::{engine_threading::*, type_system::TypeId}; #[derive(Clone, Debug)] pub struct TyStorageAccess { pub fields: Vec, - pub(crate) namespace: Option, - pub(crate) ix: StateIndex, + pub storage_field_names: Vec, + pub struct_field_names: Vec, + pub key: Option, pub storage_keyword_span: Span, } impl EqWithEngines for TyStorageAccess {} impl PartialEqWithEngines for TyStorageAccess { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { - self.ix == other.ix - && self.fields.len() == other.fields.len() + self.fields.len() == other.fields.len() && self.fields.eq(&other.fields, ctx) + && self.storage_field_names.len() == other.storage_field_names.len() + && self.storage_field_names.eq(&other.storage_field_names) + && self.struct_field_names.len() == other.struct_field_names.len() + && self.struct_field_names.eq(&other.struct_field_names) + && self.key.eq(&other.key) } } @@ -26,13 +31,15 @@ impl HashWithEngines for TyStorageAccess { fn hash(&self, state: &mut H, engines: &Engines) { let TyStorageAccess { fields, - ix, - namespace, storage_keyword_span, + storage_field_names, + struct_field_names, + key, } = self; fields.hash(state, engines); - ix.hash(state); - namespace.hash(state); + storage_field_names.hash(state); + struct_field_names.hash(state); + key.hash(state); storage_keyword_span.hash(state); } } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index a5698c83186..df985581c23 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -440,6 +440,7 @@ impl TyDecl { let mut fields_buf = Vec::with_capacity(fields.len()); for parsed::StorageField { name, + key, initializer, mut type_argument, attributes, @@ -464,6 +465,7 @@ impl TyDecl { fields_buf.push(ty::TyStorageField { name, + key, type_argument, initializer, span: field_span, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs index 22e568ce153..d7b4378bb11 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs @@ -16,7 +16,7 @@ use sway_error::{ handler::{ErrorEmitted, Handler}, }; use sway_ir::{Context, Module}; -use sway_types::state::StateIndex; +use sway_types::u256::U256; impl ty::TyStorageDecl { pub(crate) fn get_initialized_storage_slots( @@ -31,15 +31,14 @@ impl ty::TyStorageDecl { let storage_slots = self .fields .iter() - .enumerate() - .map(|(i, f)| { + .map(|f| { f.get_initialized_storage_slots( engines, context, md_mgr, module, - self.storage_namespace().as_ref().map(|id| id.as_str()), - &StateIndex::new(i), + vec![f.name.as_str().to_string()], + f.key.clone(), ) }) .filter_map(|s| s.map_err(|e| handler.emit_err(e)).ok()) @@ -58,8 +57,8 @@ impl ty::TyStorageField { context: &mut Context, md_mgr: &mut MetadataManager, module: Module, - ns: Option<&str>, - ix: &StateIndex, + storage_field_names: Vec, + key: Option, ) -> Result, CompileError> { compile_constant_expression_to_constant( engines, @@ -71,7 +70,9 @@ impl ty::TyStorageField { &self.initializer, true, ) - .map(|constant| serialize_to_storage_slots(&constant, context, ix, ns, &constant.ty, &[])) + .map(|constant| { + serialize_to_storage_slots(&constant, context, storage_field_names, key, &constant.ty) + }) } } diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 86e9869a2d6..eca2aba4007 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -2478,9 +2478,22 @@ fn storage_field_to_storage_field( attributes: AttributesMap, ) -> Result { let span = storage_field.span(); + let mut key_opt = None; + if let Some(key_literal) = storage_field.key { + let key_literal2 = literal_to_literal(context, handler, key_literal.clone())?; + if let Literal::U256(key) = key_literal2 { + key_opt = Some(key); + } else { + handler.emit_err(CompileError::Internal( + "Expected U256 key in storage field.", + key_literal.span(), + )); + } + } let storage_field = StorageField { attributes, name: storage_field.name, + key: key_opt, type_argument: ty_to_type_argument(context, handler, engines, storage_field.ty)?, span, initializer: expr_to_expression(context, handler, engines, storage_field.initializer)?, diff --git a/sway-error/src/parser_error.rs b/sway-error/src/parser_error.rs index 170964db9c6..9f7d4e364f7 100644 --- a/sway-error/src/parser_error.rs +++ b/sway-error/src/parser_error.rs @@ -106,6 +106,8 @@ pub enum ParseErrorKind { ExpectedPathType, #[error("Expected ':'. Enum variants must be in the form `Variant: ()`, `Variant: `, or `Variant: (, ..., )`. E.g., `Foo: (), or `Bar: (bool, u32)`.")] MissingColonInEnumTypeField, + #[error("Expected storage key of type U256.")] + ExpectedStorageKeyU256, } #[derive(Debug, Error, Clone, PartialEq, Eq, Hash)] diff --git a/sway-parse/src/item/item_storage.rs b/sway-parse/src/item/item_storage.rs index 656226c7d5c..8ef7ddeac6b 100644 --- a/sway-parse/src/item/item_storage.rs +++ b/sway-parse/src/item/item_storage.rs @@ -1,16 +1,29 @@ use crate::{Parse, ParseResult, Parser}; -use sway_ast::{ItemStorage, StorageField}; +use sway_ast::{keywords::InToken, ItemStorage, Literal, StorageField}; +use sway_error::parser_error::ParseErrorKind; +use sway_types::Spanned; impl Parse for StorageField { fn parse(parser: &mut Parser) -> ParseResult { let name = parser.parse()?; + let in_token : Option = parser.take(); + let mut key_opt: Option = None; + if in_token.is_some() { + key_opt = Some(parser.parse()?); + return Err(parser.emit_error_with_span( + ParseErrorKind::ExpectedStorageKeyU256, + key_opt.unwrap().span(), + )); + } let colon_token = parser.parse()?; let ty = parser.parse()?; let eq_token = parser.parse()?; let initializer = parser.parse()?; Ok(StorageField { name, + in_token, + key: key_opt, colon_token, ty, eq_token, diff --git a/sway-types/src/lib.rs b/sway-types/src/lib.rs index f0f53752069..5d8e1cf95c1 100644 --- a/sway-types/src/lib.rs +++ b/sway-types/src/lib.rs @@ -20,8 +20,6 @@ pub use source_engine::*; pub mod span; pub use span::*; -pub mod state; - pub mod style; pub mod ast; diff --git a/sway-types/src/state.rs b/sway-types/src/state.rs deleted file mode 100644 index 5a7ea4d038e..00000000000 --- a/sway-types/src/state.rs +++ /dev/null @@ -1,30 +0,0 @@ -/// Represents the position in a storage statement that a field was declared. -/// For example, in the following storage declaration, `foo` has [StateIndex] 0 and `bar` has -/// [StateIndex] 1. -/// -/// ```ignore -/// storage { -/// foo: u32 = 0, -/// bar: u32 = 0, -/// } -/// ``` -/// -/// The actual [StorageSlot] is calculated as the sha256 hash of the domain separator -/// [sway_utils::constants::STORAGE_DOMAIN_SEPARATOR] concatenated with the index. -/// -/// Here, `foo`'s [StorageSlot] is `sha256(format!("{}{}", STORAGE_DOMAIN_SEPARATOR, 0))` or -/// `F383B0CE51358BE57DAA3B725FE44ACDB2D880604E367199080B4379C41BB6ED`. -/// -/// `bar`'s [StorageSlot] is `sha256(format!("{}{}", STORAGE_DOMAIN_SEPARATOR, 1))` or -/// `DE9090CB50E71C2588C773487D1DA7066D0C719849A7E58DC8B6397A25C567C0`. -#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash)] -pub struct StateIndex(usize); - -impl StateIndex { - pub fn new(raw: usize) -> Self { - StateIndex(raw) - } - pub fn to_usize(&self) -> usize { - self.0 - } -} diff --git a/sway-utils/src/constants.rs b/sway-utils/src/constants.rs index 30cf79ff401..9a6711cad5e 100644 --- a/sway-utils/src/constants.rs +++ b/sway-utils/src/constants.rs @@ -7,7 +7,9 @@ pub const USER_FORC_DIRECTORY: &str = ".forc"; pub const SRC_DIR: &str = "src"; pub const DEFAULT_NODE_URL: &str = "http://127.0.0.1:4000"; pub const LANGUAGE_NAME: &str = "Sway"; -pub const STORAGE_DOMAIN_SEPARATOR: &str = "storage_"; +pub const STORAGE_DOMAIN: &str = "storage"; +pub const STORAGE_FIELD_SEPARATOR: &str = "::"; +pub const STRUCT_FIELD_SEPARATOR: &str = "."; pub const LIB_ENTRY: &str = "lib.sw"; pub const MAIN_ENTRY: &str = "main.sw"; pub const FORC_INIT_MANIFEST_AUTHOR: &str = "FORC_INIT_MANIFEST_AUTHOR"; From 28e6e7016603c971fbce4c51ad416a42e0359e36 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Fri, 24 May 2024 11:39:18 +0100 Subject: [PATCH 02/14] Updates json_storage_slots_oracle. --- .../json_storage_slots_oracle.json | 50 +++++++-------- .../json_storage_slots_oracle.json | 2 +- .../json_storage_slots_oracle.json | 62 +++++++++---------- .../json_storage_slots_oracle.json | 10 +++ .../json_storage_slots_oracle.json | 56 ++++++++--------- .../json_storage_slots_oracle.json | 48 +++++++------- 6 files changed, 119 insertions(+), 109 deletions(-) create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_configurable/json_storage_slots_oracle.json diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json index 8477a8235b2..21eba0f8313 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json @@ -1,54 +1,54 @@ [ { - "key": "02dac99c283f16bc91b74f6942db7f012699a2ad51272b15207b9cc14a70dbae", - "value": "6161000000000000000000000000000000000000000000000000000000000000" + "key": "072c710c522c081d2ed4d054094cc45a52ad246f171b318f13a1a234fbf19595", + "value": "6161616161000000000000000000000000000000000000000000000000000000" }, { - "key": "0a860bae2f483542169820f52be34ca40c507a967660cdc5941c15815204bc4d", - "value": "6161616161616161610000000000000000000000000000000000000000000000" + "key": "3bdcc328346bf340ed83baea8fd16ea96c7354e395f0fd1a2dfc60d9c57e56ba", + "value": "6161616161616161616100000000000000000000000000000000000000000000" }, { - "key": "6294951dcb0a9111a517be5cf4785670ff4e166fb5ab9c33b17e6881b48e964f", - "value": "6161610000000000000000000000000000000000000000000000000000000000" + "key": "631bd8dfca7cbdea56b201574608ad86b79292de700ae72176408561c4974ddd", + "value": "6161616161616100000000000000000000000000000000000000000000000000" }, { - "key": "71217a24656901c411894bb65eb78a828dafa5a6844488ef5024eb5ac0cff79c", - "value": "0000000000000000000000000000000000000000000000000000000001234567" + "key": "65ab21209750ea9c5d50540dd1f34f681baf641675b708b8833c00db8d434c62", + "value": "6161616161610000000000000000000000000000000000000000000000000000" }, { - "key": "7f91d1a929dce734e7f930bbb279ccfccdb5474227502ea8845815c74bd930a7", - "value": "6161616161000000000000000000000000000000000000000000000000000000" + "key": "84da94101bf1f6d696f78b1763e38284fc568e88582d4a372252cff7df9ed0ec", + "value": "6100000000000000000000000000000000000000000000000000000000000000" }, { - "key": "8a89a0cce819e0426e565819a9a98711329087da5a802fb16edd223c47fa44ef", - "value": "6161616161610000000000000000000000000000000000000000000000000000" + "key": "8a64b133f6033d94b315b3be1e4a2d5d609859448e6418f1b0e4b8049e0f83b6", + "value": "6161000000000000000000000000000000000000000000000000000000000000" }, { - "key": "94b2b70d20da552763c7614981b2a4d984380d7ed4e54c01b28c914e79e44bd5", - "value": "6161616100000000000000000000000000000000000000000000000000000000" + "key": "9a05ffac71399945a623705708d64227c98aa0ab492df9e90a8791b5f8babf57", + "value": "0000000000000001000000000000000000000000000000000000000000000000" }, { - "key": "a9203bbb8366ca9d708705dce980acbb54d44fb753370ffe4c7d351b46b2abbc", - "value": "6161616161616100000000000000000000000000000000000000000000000000" + "key": "a603887c83e3ca59db93e6a6f9aa8192bc6d4bde49dc04b57391b0e6b303792a", + "value": "6161616161616161610000000000000000000000000000000000000000000000" }, { - "key": "b48b753af346966d0d169c0b2e3234611f65d5cfdb57c7b6e7cd6ca93707bee0", - "value": "6100000000000000000000000000000000000000000000000000000000000000" + "key": "a966dac681b019c01b28479acdd8861e1f403086ebf4c6e930f21430161e79f1", + "value": "6161616100000000000000000000000000000000000000000000000000000000" }, { - "key": "c5e69153be998bc6f957aeb6f8fd46a0e9c5bc2d3dff421a73e02f64a3012fbb", - "value": "6161616161616161000000000000000000000000000000000000000000000000" + "key": "cc5325c3a788ed2646b648ac3309a8cdf436ea80c4218d7ead794cfe18ee64bb", + "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "c7e08cdde76020f08f4ce5c3257422ae67f9676992689b64b85f35aa58752d9e", + "key": "e82244d91548d15ca4554062bc436a677487ec0412e11495ad0746c5828fe2b8", "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "d02e07f5a716bd3b6670aaf9a73352164e6b946c24db14f72005b7029e67d96a", - "value": "6161616161616161616100000000000000000000000000000000000000000000" + "key": "f47b91cf76a03a198609b7318e6a5ef450922282b59e80810aa6c4d74c2aadea", + "value": "6161610000000000000000000000000000000000000000000000000000000000" }, { - "key": "f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed", - "value": "0000000000000001000000000000000000000000000000000000000000000000" + "key": "f851b76f2bd8cfc0e952a16e596bf101e521339195d85cad0aba3afe24e90859", + "value": "6161616161616161000000000000000000000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json index 800315b033d..44b479e1850 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json @@ -1,6 +1,6 @@ [ { - "key": "f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed", + "key": "8580450cc7a7bfd8db92d80a47ae11f4854e7656fa424b754b4e6a37af66b6e2", "value": "0000000000000000000000000000000000000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json index e1e002af06f..03972c0f04e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json @@ -1,74 +1,74 @@ [ { - "key": "02dac99c283f16bc91b74f6942db7f012699a2ad51272b15207b9cc14a70dbae", - "value": "0100000000000000000000000000000000000000000000000000000000000000" - }, - { - "key": "6294951dcb0a9111a517be5cf4785670ff4e166fb5ab9c33b17e6881b48e964f", - "value": "0800000000000000000000000000000000000000000000000000000000000000" - }, - { - "key": "7f91d1a929dce734e7f930bbb279ccfccdb5474227502ea8845815c74bd930a7", - "value": "0000000000000020000000000000000000000000000000000000000000000000" + "key": "2f2c50fd1be2f5af223fce93c374b36dc18257b026180bf3761ef885a75de635", + "value": "0000000000000040000000000000000000000000000000000000000000000000" }, { - "key": "8a89a0cce819e0426e565819a9a98711329087da5a802fb16edd223c47fa44ef", + "key": "56b7c47d21a400c8c270206038fba089fffd1e68f7467d75a50816277d51de3b", "value": "0000000000000001000000000000000100000000000000020000000000000000" }, { - "key": "8a89a0cce819e0426e565819a9a98711329087da5a802fb16edd223c47fa44f0", + "key": "56b7c47d21a400c8c270206038fba089fffd1e68f7467d75a50816277d51de3c", "value": "0000000000000000000000000000000000000000000000030100000000000000" }, { - "key": "8a89a0cce819e0426e565819a9a98711329087da5a802fb16edd223c47fa44f1", + "key": "56b7c47d21a400c8c270206038fba089fffd1e68f7467d75a50816277d51de3d", "value": "0400000000000000000000000000000500000000000000060000000000000000" }, { - "key": "94b2b70d20da552763c7614981b2a4d984380d7ed4e54c01b28c914e79e44bd5", - "value": "0000000000000010000000000000000000000000000000000000000000000000" + "key": "639c65f568c14425f41b04036ad8180eacc76e84b957070436209824c852362a", + "value": "0800000000000000000000000000000000000000000000000000000000000000" }, { - "key": "a9203bbb8366ca9d708705dce980acbb54d44fb753370ffe4c7d351b46b2abbc", + "key": "80410561e8d7b049434921d2a8e6216c3ef7556a0f5ac56cc59017cf1b60c6b0", "value": "0000000000000000000000000000000000000000000000000000000000000000" }, { - "key": "a9203bbb8366ca9d708705dce980acbb54d44fb753370ffe4c7d351b46b2abbd", + "key": "80410561e8d7b049434921d2a8e6216c3ef7556a0f5ac56cc59017cf1b60c6b1", "value": "0000000000000000000000000000000000000000000000000000000000000000" }, { - "key": "a9203bbb8366ca9d708705dce980acbb54d44fb753370ffe4c7d351b46b2abbe", + "key": "80410561e8d7b049434921d2a8e6216c3ef7556a0f5ac56cc59017cf1b60c6b2", "value": "0000000000000000000000000000000000000000000003090000000000000000" }, { - "key": "b48b753af346966d0d169c0b2e3234611f65d5cfdb57c7b6e7cd6ca93707bee0", + "key": "87c40ac0fa5fece0d8ee86e8a397ba1f111c83d7cfe2435d010db207a25f46c5", + "value": "4141414141414141414141414141414141414141414141414141414141414141" + }, + { + "key": "87c40ac0fa5fece0d8ee86e8a397ba1f111c83d7cfe2435d010db207a25f46c6", + "value": "4141414141414141000000000000000000000000000000000000000000000000" + }, + { + "key": "8d40e955efb6d905b6d4cc695086bd0689b55879a7ad3d6e4d66f305e0a02ae2", + "value": "0000000000000020000000000000000000000000000000000000000000000000" + }, + { + "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca6", "value": "0000000000000001000000000000000200000000000000000000000000000000" }, { - "key": "b48b753af346966d0d169c0b2e3234611f65d5cfdb57c7b6e7cd6ca93707bee1", + "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca7", "value": "0000000000000000000000000000000300000000000000040000000000000005" }, { - "key": "b48b753af346966d0d169c0b2e3234611f65d5cfdb57c7b6e7cd6ca93707bee2", + "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca8", "value": "0000000000000000000000000000000000000000000000000000000000000006" }, { - "key": "b48b753af346966d0d169c0b2e3234611f65d5cfdb57c7b6e7cd6ca93707bee3", + "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca9", "value": "0100000000000000070000000000000000000000000000080000000000000009" }, { - "key": "c5e69153be998bc6f957aeb6f8fd46a0e9c5bc2d3dff421a73e02f64a3012fbb", - "value": "4141414141414141414141414141414141414141414141414141414141414141" - }, - { - "key": "c5e69153be998bc6f957aeb6f8fd46a0e9c5bc2d3dff421a73e02f64a3012fbc", - "value": "4141414141414141000000000000000000000000000000000000000000000000" + "key": "adbc79bc188f7824b140d7429535d6bd32efff129cf3becc0ce69b6116b222e2", + "value": "0100000000000000000000000000000000000000000000000000000000000000" }, { - "key": "de9090cb50e71c2588c773487d1da7066d0c719849a7e58dc8b6397a25c567c0", + "key": "caea1faf0f6604ab6ecca8624adb27603d2d667ee2108cf84657bde0cecd9715", "value": "0101010101010101010101010101010101010101010101010101010101010101" }, { - "key": "f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed", - "value": "0000000000000040000000000000000000000000000000000000000000000000" + "key": "f0c6c380b3847177f70873ddbd84c4715349191f6f5a88eb71affa8f187113b7", + "value": "0000000000000010000000000000000000000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_configurable/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_configurable/json_storage_slots_oracle.json new file mode 100644 index 00000000000..53131c4aef8 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_configurable/json_storage_slots_oracle.json @@ -0,0 +1,10 @@ +[ + { + "key": "f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "key": "f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ee", + "value": "0000000000000000000000000000000000000000000000000000000000000000" + } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json index 11850ac61d2..ec21371bdf8 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json @@ -1,62 +1,62 @@ [ { - "key": "02dac99c283f16bc91b74f6942db7f012699a2ad51272b15207b9cc14a70dbae", - "value": "0000000000000002000000000000000000000000000000000000000000000000" - }, - { - "key": "0a860bae2f483542169820f52be34ca40c507a967660cdc5941c15815204bc4d", - "value": "0000000000000001000000000000aa00000000000000bb00000000000000cc00" + "key": "0aea1a60b35c1352b7920c42b7e13007eeaae104db10c2d44c8c36a12e08964b", + "value": "00000000000000000000000000000000000000000000000000000000000000ee" }, { - "key": "6294951dcb0a9111a517be5cf4785670ff4e166fb5ab9c33b17e6881b48e964f", + "key": "5dd3f12390f860617a1d8cb643c383bb7b400ce81b8c8416e3c58aaa5f8e155c", "value": "0000000000000000000000000000000100000000000000000000000000000000" }, { - "key": "7f91d1a929dce734e7f930bbb279ccfccdb5474227502ea8845815c74bd930a7", - "value": "0000000000000002000000000000000000000000000000000000000000000000" + "key": "5e1556a4612be2e52bfc462109ffad79432d512f6ab72477ea2f8123b4d6157e", + "value": "0000000000000001000000000000aa00000000000000bb00000000000000cc00" }, { - "key": "8a89a0cce819e0426e565819a9a98711329087da5a802fb16edd223c47fa44ef", + "key": "5ee80e556c2db7702e9c298ef70329f25839421bf2d2132c6b85da71a9eca9a8", "value": "000000000000000000000000000000aa00000000000000000000000000000000" }, { - "key": "94b2b70d20da552763c7614981b2a4d984380d7ed4e54c01b28c914e79e44bd5", - "value": "000000000000000100000000000000cd00000000000000000000000000000000" + "key": "7cf3c16875639336aef3cf3818a29f1210a83d5992f6814e151ee34e385b913c", + "value": "0000000000000002000000000000000000000000000000000000000000000000" + }, + { + "key": "905c813864e60f1f5e35bfa5f8ab59455e52d7ce49ef20a6051b58ce1637a715", + "value": "000000000000000000000000000000ab00000000000000000000000000000000" }, { - "key": "a9203bbb8366ca9d708705dce980acbb54d44fb753370ffe4c7d351b46b2abbc", + "key": "912649db2c12ab1252a459205b0a580d828f4761b9d9044150944a125fd45d3e", "value": "0000000000000001000000000000bb0000000000000000000000000000000000" }, { - "key": "b48b753af346966d0d169c0b2e3234611f65d5cfdb57c7b6e7cd6ca93707bee0", + "key": "9c498f0e21208bd9d68741454a356cfc748e43e6d16c2c955ccfbeb59489f035", "value": "0000000000000000000000000000000100000000000000000000000000000000" }, { - "key": "c5e69153be998bc6f957aeb6f8fd46a0e9c5bc2d3dff421a73e02f64a3012fbb", - "value": "00000000000000000000000000000000000000000000000000000000000000ee" + "key": "9d322a178fee428b5e971c7f9aee368a65a5e17c029b5ef08aa832caa49d9b26", + "value": "0000000000000000000000000000000000000000000000000000000000000000" }, { - "key": "c7e08cdde76020f08f4ce5c3257422ae67f9676992689b64b85f35aa58752d9e", - "value": "0000000000000001000000000000ab00000000000000bc00000000000000cd00" + "key": "9d322a178fee428b5e971c7f9aee368a65a5e17c029b5ef08aa832caa49d9b27", + "value": "000000000000000000000000000000ff00000000000000000000000000000000" }, { - "key": "c7e08cdde76020f08f4ce5c3257422ae67f9676992689b64b85f35aa58752d9f", - "value": "000000000000de00000000000000ef0000000000000000000000000000000000" + "key": "a02498e7f4c209177cdc0467b27573a4ef5ac92538041c24ff8b47b9c346fa82", + "value": "000000000000000100000000000000cd00000000000000000000000000000000" }, { - "key": "d02e07f5a716bd3b6670aaf9a73352164e6b946c24db14f72005b7029e67d96a", - "value": "0000000000000000000000000000000000000000000000000000000000000000" + "key": "b9fda96766abb098f5fcdffe9becd16e30ade9bd3b2b7f4c7b05010f2cc3053d", + "value": "0000000000000001000000000000ab00000000000000bc00000000000000cd00" }, { - "key": "d02e07f5a716bd3b6670aaf9a73352164e6b946c24db14f72005b7029e67d96b", - "value": "000000000000000000000000000000ff00000000000000000000000000000000" + "key": "b9fda96766abb098f5fcdffe9becd16e30ade9bd3b2b7f4c7b05010f2cc3053e", + "value": "000000000000de00000000000000ef0000000000000000000000000000000000" }, { - "key": "de9090cb50e71c2588c773487d1da7066d0c719849a7e58dc8b6397a25c567c0", - "value": "000000000000000000000000000000ab00000000000000000000000000000000" + "key": "d6a33d4c06d6b1de28bf22606546c026df3cebb0ffe22c1650e834f3ebefab38", + "value": "000000000000000000000000000000cd00000000000000000000000000000000" }, { - "key": "f383b0ce51358be57daa3b725fe44acdb2d880604e367199080b4379c41bb6ed", - "value": "000000000000000000000000000000cd00000000000000000000000000000000" + "key": "ffd8d1fce9c0114aa6b113ae5e40495d54607880ac07b7acaa81528c60f86ba4", + "value": "0000000000000002000000000000000000000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json index c9c6e3d56aa..21eba0f8313 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json @@ -1,54 +1,54 @@ [ { - "key": "1cabb882ad94b0e00c6603259a68473d72c37a5afa388235798523db451b7435", - "value": "6161616161616161000000000000000000000000000000000000000000000000" + "key": "072c710c522c081d2ed4d054094cc45a52ad246f171b318f13a1a234fbf19595", + "value": "6161616161000000000000000000000000000000000000000000000000000000" }, { - "key": "256f94e8eaff16138bb2ac71a6db9dad1b3cb5ae657b6bc556d73e410532ffb7", - "value": "6161616100000000000000000000000000000000000000000000000000000000" + "key": "3bdcc328346bf340ed83baea8fd16ea96c7354e395f0fd1a2dfc60d9c57e56ba", + "value": "6161616161616161616100000000000000000000000000000000000000000000" }, { - "key": "29cc227d3bdd730793f247e195056ba7aaf20fbc902c56c9d7707f79039b334a", - "value": "6161616161610000000000000000000000000000000000000000000000000000" + "key": "631bd8dfca7cbdea56b201574608ad86b79292de700ae72176408561c4974ddd", + "value": "6161616161616100000000000000000000000000000000000000000000000000" }, { - "key": "52ddfc3aad75e658d4478fe4de4c1138528cb129ed2febf2db01a473ecc41ca7", - "value": "0000000000000001000000000000000000000000000000000000000000000000" + "key": "65ab21209750ea9c5d50540dd1f34f681baf641675b708b8833c00db8d434c62", + "value": "6161616161610000000000000000000000000000000000000000000000000000" }, { - "key": "7c52302f5f44f5e018951099f0a570522595f6cc8ac6903f58697111dacf7fc6", - "value": "6161616161616161616100000000000000000000000000000000000000000000" + "key": "84da94101bf1f6d696f78b1763e38284fc568e88582d4a372252cff7df9ed0ec", + "value": "6100000000000000000000000000000000000000000000000000000000000000" }, { - "key": "9ba84fa6a786b5b6695103aa5c585a53c13431aa0f0b42e6e8831c5f6df8ce51", + "key": "8a64b133f6033d94b315b3be1e4a2d5d609859448e6418f1b0e4b8049e0f83b6", "value": "6161000000000000000000000000000000000000000000000000000000000000" }, { - "key": "9de8a8fb10d236d1afea87fe118df7d8181284e2fea439d3fec1c52afbd46b4e", - "value": "6161610000000000000000000000000000000000000000000000000000000000" + "key": "9a05ffac71399945a623705708d64227c98aa0ab492df9e90a8791b5f8babf57", + "value": "0000000000000001000000000000000000000000000000000000000000000000" }, { - "key": "9f5382d0db2482d4c07835d1acb1b8d62cb800f21ce04577b0544c299a900d86", - "value": "6161616161616100000000000000000000000000000000000000000000000000" + "key": "a603887c83e3ca59db93e6a6f9aa8192bc6d4bde49dc04b57391b0e6b303792a", + "value": "6161616161616161610000000000000000000000000000000000000000000000" }, { - "key": "be6e48ba10d92b9a39255aa8cb2c4c8936a653793beeee86a1da5223a4c8504e", - "value": "6161616161000000000000000000000000000000000000000000000000000000" + "key": "a966dac681b019c01b28479acdd8861e1f403086ebf4c6e930f21430161e79f1", + "value": "6161616100000000000000000000000000000000000000000000000000000000" }, { - "key": "c709c6eda5d3ec0462d8f91208dbcbb8432422234cde38395e468fc2b9dab1a5", + "key": "cc5325c3a788ed2646b648ac3309a8cdf436ea80c4218d7ead794cfe18ee64bb", "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "e72b5126b101e06e36ff31629167a6b41c6f752daf41b308fae666ed6092be8d", - "value": "6161616161616161610000000000000000000000000000000000000000000000" + "key": "e82244d91548d15ca4554062bc436a677487ec0412e11495ad0746c5828fe2b8", + "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "ec544af52f548dd8627a0a0417c3856feb6493ae7728d27bebf2849511c530e8", - "value": "6100000000000000000000000000000000000000000000000000000000000000" + "key": "f47b91cf76a03a198609b7318e6a5ef450922282b59e80810aa6c4d74c2aadea", + "value": "6161610000000000000000000000000000000000000000000000000000000000" }, { - "key": "f472175bd2f643d824b2270804e2c8c2b62bb461cf1e365686aa2ef8393357b1", - "value": "0000000000000000000000000000000000000000000000000000000001234567" + "key": "f851b76f2bd8cfc0e952a16e596bf101e521339195d85cad0aba3afe24e90859", + "value": "6161616161616161000000000000000000000000000000000000000000000000" } ] \ No newline at end of file From 3d90480e4a7fa6dc93253601ea5af6fd75a9e4e0 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 27 May 2024 12:41:43 +0100 Subject: [PATCH 03/14] Changes storage keyword to accept any B256 const expression. --- sway-ast/src/item/item_storage.rs | 2 +- sway-core/src/ir_generation/function.rs | 13 ++++- .../language/parsed/declaration/storage.rs | 4 +- .../src/language/ty/declaration/storage.rs | 13 +++-- .../src/language/ty/expression/storage.rs | 12 ++-- .../ast_node/declaration/declaration.rs | 19 +++++- .../ast_node/declaration/storage.rs | 58 ++++++++++++++----- .../to_parsed_lang/convert_parse_tree.rs | 16 ++--- sway-parse/src/item/item_storage.rs | 14 ++--- .../test_contracts/basic_storage/src/main.sw | 7 ++- 10 files changed, 101 insertions(+), 57 deletions(-) diff --git a/sway-ast/src/item/item_storage.rs b/sway-ast/src/item/item_storage.rs index a526ad0e1fc..52c4067f7ad 100644 --- a/sway-ast/src/item/item_storage.rs +++ b/sway-ast/src/item/item_storage.rs @@ -16,7 +16,7 @@ impl Spanned for ItemStorage { pub struct StorageField { pub name: Ident, pub in_token: Option, - pub key: Option, + pub key_expr: Option, pub colon_token: ColonToken, pub ty: Ty, pub eq_token: EqToken, diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs index 289345c8f26..d64fe8d1953 100644 --- a/sway-core/src/ir_generation/function.rs +++ b/sway-core/src/ir_generation/function.rs @@ -11,7 +11,7 @@ use crate::{ compile_constant_expression, compile_constant_expression_to_constant, }, language::{ - ty::{self, ProjectionKind, TyConstantDecl, TyExpressionVariant}, + ty::{self, ProjectionKind, TyConstantDecl, TyExpressionVariant, TyStorageField}, *, }, metadata::MetadataManager, @@ -587,12 +587,19 @@ impl<'eng> FnCompiler<'eng> { Ok(TerminatorValue::new(val, context)) } ty::TyExpressionVariant::StorageAccess(access) => { - let span_md_idx = md_mgr.span_to_md(context, &access.span()); + let span_md_idx: Option = md_mgr.span_to_md(context, &access.span()); + let key = TyStorageField::get_key_expression_const( + &access.key_expression.clone().map(|v| *v), + self.engines, + context, + md_mgr, + self.module, + )?; self.compile_storage_access( context, access.storage_field_names.clone(), access.struct_field_names.clone(), - access.key.clone(), + key, &access.fields, span_md_idx, ) diff --git a/sway-core/src/language/parsed/declaration/storage.rs b/sway-core/src/language/parsed/declaration/storage.rs index 070775c92b6..b41491b3d6f 100644 --- a/sway-core/src/language/parsed/declaration/storage.rs +++ b/sway-core/src/language/parsed/declaration/storage.rs @@ -4,7 +4,7 @@ use crate::{ transform, type_system::*, }; -use sway_types::{ident::Ident, span::Span, u256::U256, Spanned}; +use sway_types::{ident::Ident, span::Span, Spanned}; #[derive(Debug, Clone)] /// A declaration of contract storage. Only valid within contract contexts. @@ -39,7 +39,7 @@ impl Spanned for StorageDeclaration { #[derive(Debug, Clone)] pub struct StorageField { pub name: Ident, - pub key: Option, + pub key_expression: Option, pub attributes: transform::AttributesMap, pub type_argument: TypeArgument, pub span: Span, diff --git a/sway-core/src/language/ty/declaration/storage.rs b/sway-core/src/language/ty/declaration/storage.rs index 15194ab4fdf..78d71e4259e 100644 --- a/sway-core/src/language/ty/declaration/storage.rs +++ b/sway-core/src/language/ty/declaration/storage.rs @@ -4,7 +4,7 @@ use sway_error::{ error::{CompileError, StructFieldUsageContext}, handler::{ErrorEmitted, Handler}, }; -use sway_types::{u256::U256, Ident, Named, Span, Spanned}; +use sway_types::{Ident, Named, Span, Spanned}; use crate::{ engine_threading::*, @@ -99,10 +99,10 @@ impl TyStorageDecl { match storage_fields.iter().find(|sf| &sf.name == first_field) { Some(TyStorageField { type_argument, - key, + key_expression, name, .. - }) => (type_argument.type_id, key, name), + }) => (type_argument.type_id, key_expression, name), None => { return Err(handler.emit_err(CompileError::StorageFieldDoesNotExist { field_name: first_field.into(), @@ -212,7 +212,7 @@ impl TyStorageDecl { Ok(( TyStorageAccess { fields: access_descriptors, - key: initial_field_key.clone(), + key_expression: initial_field_key.clone().map(|v| Box::new(v)), storage_field_names: vec![initial_field_name.as_str().to_string()], struct_field_names, storage_keyword_span, @@ -252,7 +252,7 @@ impl Spanned for TyStorageField { #[derive(Clone, Debug)] pub struct TyStorageField { pub name: Ident, - pub key: Option, + pub key_expression: Option, pub type_argument: TypeArgument, pub initializer: TyExpression, pub(crate) span: Span, @@ -272,15 +272,16 @@ impl HashWithEngines for TyStorageField { fn hash(&self, state: &mut H, engines: &Engines) { let TyStorageField { name, + key_expression, type_argument, initializer, // these fields are not hashed because they aren't relevant/a // reliable source of obj v. obj distinction span: _, attributes: _, - key: _, } = self; name.hash(state); + key_expression.hash(state, engines); type_argument.hash(state, engines); initializer.hash(state, engines); } diff --git a/sway-core/src/language/ty/expression/storage.rs b/sway-core/src/language/ty/expression/storage.rs index 0c8df60f6fa..127d64fd20b 100644 --- a/sway-core/src/language/ty/expression/storage.rs +++ b/sway-core/src/language/ty/expression/storage.rs @@ -1,16 +1,18 @@ use std::hash::{Hash, Hasher}; -use sway_types::{u256::U256, Ident, Span, Spanned}; +use sway_types::{Ident, Span, Spanned}; use crate::{engine_threading::*, type_system::TypeId}; +use super::TyExpression; + /// Describes the full storage access including all the subfields #[derive(Clone, Debug)] pub struct TyStorageAccess { pub fields: Vec, pub storage_field_names: Vec, pub struct_field_names: Vec, - pub key: Option, + pub key_expression: Option>, pub storage_keyword_span: Span, } @@ -23,7 +25,7 @@ impl PartialEqWithEngines for TyStorageAccess { && self.storage_field_names.eq(&other.storage_field_names) && self.struct_field_names.len() == other.struct_field_names.len() && self.struct_field_names.eq(&other.struct_field_names) - && self.key.eq(&other.key) + && self.key_expression.eq(&other.key_expression, ctx) } } @@ -34,12 +36,12 @@ impl HashWithEngines for TyStorageAccess { storage_keyword_span, storage_field_names, struct_field_names, - key, + key_expression, } = self; fields.hash(state, engines); storage_field_names.hash(state); struct_field_names.hash(state); - key.hash(state); + key_expression.hash(state, engines); storage_keyword_span.hash(state); } } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index df985581c23..0712166fe95 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -440,7 +440,7 @@ impl TyDecl { let mut fields_buf = Vec::with_capacity(fields.len()); for parsed::StorageField { name, - key, + key_expression, initializer, mut type_argument, attributes, @@ -463,9 +463,24 @@ impl TyDecl { let initializer = ty::TyExpression::type_check(handler, ctx.by_ref(), &initializer)?; + let mut key_ty_expression = None; + if let Some(key_expression) = key_expression { + let mut key_ctx = ctx.with_type_annotation(type_engine.insert( + engines, + TypeInfo::B256, + None, + )); + + key_ty_expression = Some(ty::TyExpression::type_check( + handler, + key_ctx.by_ref(), + &key_expression, + )?); + } + fields_buf.push(ty::TyStorageField { name, - key, + key_expression: key_ty_expression, type_argument, initializer, span: field_span, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs index d7b4378bb11..454bf5d5a48 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs @@ -3,7 +3,7 @@ use crate::{ ir_generation::{ const_eval::compile_constant_expression_to_constant, storage::serialize_to_storage_slots, }, - language::ty, + language::ty::{self, TyExpression}, metadata::MetadataManager, semantic_analysis::{ TypeCheckAnalysis, TypeCheckAnalysisContext, TypeCheckFinalization, @@ -15,7 +15,7 @@ use sway_error::{ error::CompileError, handler::{ErrorEmitted, Handler}, }; -use sway_ir::{Context, Module}; +use sway_ir::{ConstantValue, Context, Module}; use sway_types::u256::U256; impl ty::TyStorageDecl { @@ -31,16 +31,7 @@ impl ty::TyStorageDecl { let storage_slots = self .fields .iter() - .map(|f| { - f.get_initialized_storage_slots( - engines, - context, - md_mgr, - module, - vec![f.name.as_str().to_string()], - f.key.clone(), - ) - }) + .map(|f| f.get_initialized_storage_slots(engines, context, md_mgr, module)) .filter_map(|s| s.map_err(|e| handler.emit_err(e)).ok()) .flatten() .collect::>(); @@ -57,9 +48,9 @@ impl ty::TyStorageField { context: &mut Context, md_mgr: &mut MetadataManager, module: Module, - storage_field_names: Vec, - key: Option, ) -> Result, CompileError> { + let key = + Self::get_key_expression_const(&self.key_expression, engines, context, md_mgr, module)?; compile_constant_expression_to_constant( engines, context, @@ -71,9 +62,46 @@ impl ty::TyStorageField { true, ) .map(|constant| { - serialize_to_storage_slots(&constant, context, storage_field_names, key, &constant.ty) + serialize_to_storage_slots( + &constant, + context, + vec![self.name.as_str().to_string()], + key, + &constant.ty, + ) }) } + + pub(crate) fn get_key_expression_const( + key_expression: &Option, + engines: &Engines, + context: &mut Context, + md_mgr: &mut MetadataManager, + module: Module, + ) -> Result, CompileError> { + if let Some(key_expression) = key_expression { + let const_key = compile_constant_expression_to_constant( + engines, + context, + md_mgr, + module, + None, + None, + &key_expression, + true, + )?; + if let ConstantValue::B256(key) = const_key.value { + return Ok(Some(key)); + } else { + return Err(CompileError::Internal( + "Expected B256 key", + key_expression.span.clone(), + )); + } + } else { + Ok(None) + } + } } impl TypeCheckAnalysis for ty::TyStorageDecl { diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index eca2aba4007..2c7bed42ff4 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -2478,22 +2478,14 @@ fn storage_field_to_storage_field( attributes: AttributesMap, ) -> Result { let span = storage_field.span(); - let mut key_opt = None; - if let Some(key_literal) = storage_field.key { - let key_literal2 = literal_to_literal(context, handler, key_literal.clone())?; - if let Literal::U256(key) = key_literal2 { - key_opt = Some(key); - } else { - handler.emit_err(CompileError::Internal( - "Expected U256 key in storage field.", - key_literal.span(), - )); - } + let mut key_expr_opt = None; + if let Some(key_expr) = storage_field.key_expr { + key_expr_opt = Some(expr_to_expression(context, handler, engines, key_expr)?); } let storage_field = StorageField { attributes, name: storage_field.name, - key: key_opt, + key_expression: key_expr_opt, type_argument: ty_to_type_argument(context, handler, engines, storage_field.ty)?, span, initializer: expr_to_expression(context, handler, engines, storage_field.initializer)?, diff --git a/sway-parse/src/item/item_storage.rs b/sway-parse/src/item/item_storage.rs index 8ef7ddeac6b..ad1abec4a8d 100644 --- a/sway-parse/src/item/item_storage.rs +++ b/sway-parse/src/item/item_storage.rs @@ -1,20 +1,14 @@ use crate::{Parse, ParseResult, Parser}; -use sway_ast::{keywords::InToken, ItemStorage, Literal, StorageField}; -use sway_error::parser_error::ParseErrorKind; -use sway_types::Spanned; +use sway_ast::{keywords::InToken, Expr, ItemStorage, StorageField}; impl Parse for StorageField { fn parse(parser: &mut Parser) -> ParseResult { let name = parser.parse()?; - let in_token : Option = parser.take(); - let mut key_opt: Option = None; + let in_token: Option = parser.take(); + let mut key_opt: Option = None; if in_token.is_some() { key_opt = Some(parser.parse()?); - return Err(parser.emit_error_with_span( - ParseErrorKind::ExpectedStorageKeyU256, - key_opt.unwrap().span(), - )); } let colon_token = parser.parse()?; let ty = parser.parse()?; @@ -23,7 +17,7 @@ impl Parse for StorageField { Ok(StorageField { name, in_token, - key: key_opt, + key_expr: key_opt, colon_token, ty, eq_token, diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw index ae5b63dcc70..24cd4a44af5 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw @@ -5,8 +5,10 @@ use basic_storage_abi::*; const C1 = 1; const S5 = __to_str_array("aaaaa"); +const C1KEY: b256 = 0x933a534d4af4c376b0b569e8d8a2c62e635e26f403e124cb91d9c42e83d54373; + storage { - c1: u64 = C1, + c1 in C1KEY: u8 = C1, str0: str[0] = __to_str_array(""), str1: str[1] = __to_str_array("a"), str2: str[2] = __to_str_array("aa"), @@ -284,6 +286,9 @@ fn test_storage() { assert_eq(storage.const_b256.read(), 0x0000000000000000000000000000000000000000000000000000000001234567); storage.const_b256.write(0x0000000000000000000000000000000000000000000000000000000012345678); assert_eq(storage.const_b256.read(), 0x0000000000000000000000000000000000000000000000000000000012345678); + + assert_eq(storage.c1.slot(), C1KEY); + assert_eq(storage.const_b256.slot(), sha256("storage::const_b256")); } // If these comparisons are done inline just above then it blows out the register allocator due to From 12ef5fae54c86e586ea27bd6c9909aae292bc9ae Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 27 May 2024 12:46:33 +0100 Subject: [PATCH 04/14] Removes attribute namespace. --- sway-core/src/language/ty/declaration/storage.rs | 8 -------- sway-core/src/transform/attribute.rs | 6 ++---- .../src/transform/to_parsed_lang/convert_parse_tree.rs | 7 +++---- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/sway-core/src/language/ty/declaration/storage.rs b/sway-core/src/language/ty/declaration/storage.rs index 78d71e4259e..467e0c56cf3 100644 --- a/sway-core/src/language/ty/declaration/storage.rs +++ b/sway-core/src/language/ty/declaration/storage.rs @@ -56,14 +56,6 @@ impl Spanned for TyStorageDecl { } impl TyStorageDecl { - pub(crate) fn storage_namespace(&self) -> Option { - self.attributes - .get(&AttributeKind::Namespace) - .and_then(|attrs| attrs.first()) - .and_then(|attr| attr.args.first()) - .map(|arg| arg.name.clone()) - } - /// Given a path that consists of `fields`, where the first field is one of the storage fields, /// find the type information of all the elements in the path and return it as a [TyStorageAccess]. /// diff --git a/sway-core/src/transform/attribute.rs b/sway-core/src/transform/attribute.rs index d8e7a4b64ca..46d2acde691 100644 --- a/sway-core/src/transform/attribute.rs +++ b/sway-core/src/transform/attribute.rs @@ -67,7 +67,6 @@ pub enum AttributeKind { Allow, Cfg, Deprecated, - Namespace, Fallback, } @@ -80,7 +79,7 @@ impl AttributeKind { Doc | DocComment | Storage | Inline | Test | Payable | Deprecated | Fallback => { (0, None) } - Allow | Cfg | Namespace => (1, Some(1)), + Allow | Cfg => (1, Some(1)), } } @@ -88,8 +87,7 @@ impl AttributeKind { pub fn expected_args_values(self, _arg_index: usize) -> Option> { use AttributeKind::*; match self { - Deprecated | Namespace | Doc | DocComment | Storage | Inline | Test | Payable - | Fallback => None, + Deprecated | Doc | DocComment | Storage | Inline | Test | Payable | Fallback => None, Allow => Some(vec![ ALLOW_DEAD_CODE_NAME.to_string(), ALLOW_DEPRECATED_NAME.to_string(), diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 2c7bed42ff4..1919e8235a2 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -34,9 +34,9 @@ use sway_types::{ ALLOW_ATTRIBUTE_NAME, CFG_ATTRIBUTE_NAME, CFG_EXPERIMENTAL_NEW_ENCODING, CFG_PROGRAM_TYPE_ARG_NAME, CFG_TARGET_ARG_NAME, DEPRECATED_ATTRIBUTE_NAME, DOC_ATTRIBUTE_NAME, DOC_COMMENT_ATTRIBUTE_NAME, FALLBACK_ATTRIBUTE_NAME, - INLINE_ATTRIBUTE_NAME, NAMESPACE_ATTRIBUTE_NAME, PAYABLE_ATTRIBUTE_NAME, - STORAGE_PURITY_ATTRIBUTE_NAME, STORAGE_PURITY_READ_NAME, STORAGE_PURITY_WRITE_NAME, - TEST_ATTRIBUTE_NAME, VALID_ATTRIBUTE_NAMES, + INLINE_ATTRIBUTE_NAME, PAYABLE_ATTRIBUTE_NAME, STORAGE_PURITY_ATTRIBUTE_NAME, + STORAGE_PURITY_READ_NAME, STORAGE_PURITY_WRITE_NAME, TEST_ATTRIBUTE_NAME, + VALID_ATTRIBUTE_NAMES, }, integer_bits::IntegerBits, }; @@ -4651,7 +4651,6 @@ fn item_attrs_to_map( ALLOW_ATTRIBUTE_NAME => Some(AttributeKind::Allow), CFG_ATTRIBUTE_NAME => Some(AttributeKind::Cfg), DEPRECATED_ATTRIBUTE_NAME => Some(AttributeKind::Deprecated), - NAMESPACE_ATTRIBUTE_NAME => Some(AttributeKind::Namespace), FALLBACK_ATTRIBUTE_NAME => Some(AttributeKind::Fallback), _ => None, } { From 4179d1548a29bfb16695b2f45540d62e4db3eb43 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 29 May 2024 11:11:56 +0100 Subject: [PATCH 05/14] Implements storage namespaces. --- sway-ast/src/item/item_storage.rs | 25 +++- sway-ast/src/lib.rs | 2 +- .../language/parsed/declaration/storage.rs | 23 ++- .../src/language/ty/declaration/storage.rs | 4 + .../ast_node/declaration/declaration.rs | 136 +++++++++++------- .../semantic_analysis/node_dependencies.rs | 26 ++-- .../to_parsed_lang/convert_parse_tree.rs | 91 +++++++++--- sway-parse/src/item/item_storage.rs | 34 ++++- 8 files changed, 258 insertions(+), 83 deletions(-) diff --git a/sway-ast/src/item/item_storage.rs b/sway-ast/src/item/item_storage.rs index 52c4067f7ad..4c9cd025147 100644 --- a/sway-ast/src/item/item_storage.rs +++ b/sway-ast/src/item/item_storage.rs @@ -3,16 +3,37 @@ use crate::priv_prelude::*; #[derive(Clone, Debug, Serialize)] pub struct ItemStorage { pub storage_token: StorageToken, - pub fields: Braces, CommaToken>>, + pub entries: Braces, CommaToken>>, } impl Spanned for ItemStorage { fn span(&self) -> Span { - Span::join(self.storage_token.span(), &self.fields.span()) + Span::join(self.storage_token.span(), &self.entries.span()) } } #[derive(Clone, Debug, Serialize)] + +pub struct StorageEntry { + pub name: Ident, + pub namespace: Option>, CommaToken>>>, + pub field: Option, +} + +impl Spanned for StorageEntry { + fn span(&self) -> Span { + if let Some(namespace) = &self.namespace { + Span::join(self.name.span(), &namespace.span()) + } else if let Some(field) = &self.field { + Span::join(self.name.span(), &field.span()) + } else { + self.name.span() + } + } +} + +#[derive(Clone, Debug, Serialize)] + pub struct StorageField { pub name: Ident, pub in_token: Option, diff --git a/sway-ast/src/lib.rs b/sway-ast/src/lib.rs index 1b78f6be597..b1030cf040d 100644 --- a/sway-ast/src/lib.rs +++ b/sway-ast/src/lib.rs @@ -37,7 +37,7 @@ pub use crate::{ item_enum::ItemEnum, item_fn::ItemFn, item_impl::{ItemImpl, ItemImplItem}, - item_storage::{ItemStorage, StorageField}, + item_storage::{ItemStorage, StorageEntry, StorageField}, item_struct::ItemStruct, item_trait::{ItemTrait, ItemTraitItem, Traits}, item_type_alias::ItemTypeAlias, diff --git a/sway-core/src/language/parsed/declaration/storage.rs b/sway-core/src/language/parsed/declaration/storage.rs index b41491b3d6f..8af16aa818a 100644 --- a/sway-core/src/language/parsed/declaration/storage.rs +++ b/sway-core/src/language/parsed/declaration/storage.rs @@ -11,7 +11,7 @@ use sway_types::{ident::Ident, span::Span, Spanned}; /// All values in this struct are mutable and persistent among executions of the same contract deployment. pub struct StorageDeclaration { pub attributes: transform::AttributesMap, - pub fields: Vec, + pub entries: Vec, pub span: Span, pub storage_keyword: Ident, } @@ -32,6 +32,27 @@ impl Spanned for StorageDeclaration { } } +#[derive(Debug, Clone)] +pub struct StorageNamespace { + pub name: Ident, + pub entries: Vec>, +} + +#[derive(Debug, Clone)] +pub enum StorageEntry { + Namespace(StorageNamespace), + Field(StorageField), +} + +impl StorageEntry { + pub fn name(&self) -> Ident { + match self { + StorageEntry::Namespace(namespace) => namespace.name.clone(), + StorageEntry::Field(field) => field.name.clone(), + } + } +} + /// An individual field in a storage declaration. /// A type annotation _and_ initializer value must be provided. The initializer value must be a /// constant expression. For now, that basically means just a literal, but as constant folding diff --git a/sway-core/src/language/ty/declaration/storage.rs b/sway-core/src/language/ty/declaration/storage.rs index 467e0c56cf3..7b773e82c8c 100644 --- a/sway-core/src/language/ty/declaration/storage.rs +++ b/sway-core/src/language/ty/declaration/storage.rs @@ -244,6 +244,7 @@ impl Spanned for TyStorageField { #[derive(Clone, Debug)] pub struct TyStorageField { pub name: Ident, + pub namespace_names: Vec, pub key_expression: Option, pub type_argument: TypeArgument, pub initializer: TyExpression, @@ -255,6 +256,7 @@ impl EqWithEngines for TyStorageField {} impl PartialEqWithEngines for TyStorageField { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { self.name == other.name + && self.namespace_names.eq(&other.namespace_names) && self.type_argument.eq(&other.type_argument, ctx) && self.initializer.eq(&other.initializer, ctx) } @@ -264,6 +266,7 @@ impl HashWithEngines for TyStorageField { fn hash(&self, state: &mut H, engines: &Engines) { let TyStorageField { name, + namespace_names, key_expression, type_argument, initializer, @@ -273,6 +276,7 @@ impl HashWithEngines for TyStorageField { attributes: _, } = self; name.hash(state); + namespace_names.hash(state); key_expression.hash(state, engines); type_argument.hash(state, engines); initializer.hash(state, engines); diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index 0712166fe95..f46b4082424 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -1,11 +1,12 @@ +use fuel_vm::fuel_tx::field; use sway_error::handler::{ErrorEmitted, Handler}; use sway_types::{BaseIdent, Ident, Named, Spanned}; use crate::{ decl_engine::{DeclEngineGet, DeclEngineInsert, DeclRef, ReplaceFunctionImplementingType}, language::{ - parsed, - ty::{self, FunctionDecl, TyDecl}, + parsed::{self, StorageEntry}, + ty::{self, FunctionDecl, TyDecl, TyStorageField}, CallPath, }, namespace::{IsExtendingExistingImpl, IsImplSelf}, @@ -433,60 +434,97 @@ impl TyDecl { parsed::Declaration::StorageDeclaration(decl_id) => { let parsed::StorageDeclaration { span, - fields, + entries, attributes, storage_keyword, } = engines.pe().get_storage(&decl_id).as_ref().clone(); - let mut fields_buf = Vec::with_capacity(fields.len()); - for parsed::StorageField { - name, - key_expression, - initializer, - mut type_argument, - attributes, - span: field_span, - .. - } in fields - { - type_argument.type_id = ctx.resolve_type( - handler, - type_argument.type_id, - &name.span(), - EnforceTypeArguments::Yes, - None, - )?; - - let mut ctx = ctx - .by_ref() - .with_type_annotation(type_argument.type_id) - .with_storage_declaration(); - let initializer = - ty::TyExpression::type_check(handler, ctx.by_ref(), &initializer)?; - - let mut key_ty_expression = None; - if let Some(key_expression) = key_expression { - let mut key_ctx = ctx.with_type_annotation(type_engine.insert( - engines, - TypeInfo::B256, - None, - )); + let mut fields_buf = vec![]; + fn type_check_storage_entries( + handler: &Handler, + mut ctx: TypeCheckContext, + entries: Vec, + mut fields_buf: &mut Vec, + namespace_names: Vec, + ) -> Result<(), ErrorEmitted> { + let engines = ctx.engines; + for entry in entries { + if let StorageEntry::Field(parsed::StorageField { + name, + key_expression, + initializer, + mut type_argument, + attributes, + span: field_span, + .. + }) = entry + { + type_argument.type_id = ctx.by_ref().resolve_type( + handler, + type_argument.type_id, + &name.span(), + EnforceTypeArguments::Yes, + None, + )?; + + let mut ctx = ctx + .by_ref() + .with_type_annotation(type_argument.type_id) + .with_storage_declaration(); + let initializer = + ty::TyExpression::type_check(handler, ctx.by_ref(), &initializer)?; + + let mut key_ty_expression = None; + if let Some(key_expression) = key_expression { + let mut key_ctx = ctx.with_type_annotation(engines.te().insert( + engines, + TypeInfo::B256, + None, + )); - key_ty_expression = Some(ty::TyExpression::type_check( - handler, - key_ctx.by_ref(), - &key_expression, - )?); + key_ty_expression = Some(ty::TyExpression::type_check( + handler, + key_ctx.by_ref(), + &key_expression, + )?); + } + + fields_buf.push(ty::TyStorageField { + name, + namespace_names: namespace_names.clone(), + key_expression: key_ty_expression, + type_argument, + initializer, + span: field_span, + attributes, + }); + } else if let StorageEntry::Namespace(namespace) = entry { + let mut new_namespace_names = namespace_names.clone(); + new_namespace_names.push(namespace.name); + type_check_storage_entries( + handler, + ctx.by_ref(), + namespace + .entries + .iter() + .map(|e| (**e).clone()) + .collect::>(), + &mut fields_buf, + new_namespace_names, + )?; + } } - fields_buf.push(ty::TyStorageField { - name, - key_expression: key_ty_expression, - type_argument, - initializer, - span: field_span, - attributes, - }); + Ok(()) } + + type_check_storage_entries( + handler, + ctx.by_ref(), + entries, + &mut fields_buf, + vec![], + )?; + let decl = ty::TyStorageDecl { fields: fields_buf, span, diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index 735b625d7bd..41080d95912 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -455,16 +455,10 @@ impl Dependencies { }) } Declaration::StorageDeclaration(decl_id) => { - let StorageDeclaration { fields, .. } = &*engines.pe().get_storage(decl_id); - self.gather_from_iter( - fields.iter(), - |deps, - StorageField { - ref type_argument, .. - }| { - deps.gather_from_type_argument(engines, type_argument) - }, - ) + let StorageDeclaration { entries, .. } = &*engines.pe().get_storage(decl_id); + self.gather_from_iter(entries.iter(), |deps, entry| { + deps.gather_from_storage_entry(engines, entry) + }) } Declaration::TypeAliasDeclaration(decl_id) => { let TypeAliasDeclaration { ty, .. } = &*engines.pe().get_type_alias(decl_id); @@ -473,6 +467,18 @@ impl Dependencies { } } + fn gather_from_storage_entry(self, engines: &Engines, entry: &StorageEntry) -> Self { + match entry { + StorageEntry::Namespace(namespace) => self + .gather_from_iter(namespace.entries.iter(), |deps, entry| { + deps.gather_from_storage_entry(engines, &*entry) + }), + StorageEntry::Field(field) => { + self.gather_from_type_argument(engines, &field.type_argument) + } + } + } + fn gather_from_constant_decl( self, engines: &Engines, diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 1919e8235a2..67006505d31 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -1003,37 +1003,54 @@ fn item_storage_to_storage_declaration( ) -> Result, ErrorEmitted> { let mut errors = Vec::new(); let span = item_storage.span(); - let fields: Vec = item_storage - .fields + let entries: Vec = item_storage + .entries .into_inner() .into_iter() - .map(|storage_field| { - let attributes = item_attrs_to_map(context, handler, &storage_field.attribute_list)?; + .map(|storage_entry| { + let attributes = item_attrs_to_map(context, handler, &storage_entry.attribute_list)?; if !cfg_eval(context, handler, &attributes, context.experimental)? { return Ok(None); } - Ok(Some(storage_field_to_storage_field( + Ok(Some(storage_entry_to_storage_entry( context, handler, engines, - storage_field.value, + storage_entry.value, attributes, )?)) }) - .filter_map_ok(|field| field) + .filter_map_ok(|entry| entry) .collect::>()?; - // Make sure each storage field is declared once - let mut names_of_fields = std::collections::HashSet::new(); - for v in fields.iter() { - if !names_of_fields.insert(v.name.clone()) { - errors.push(ConvertParseTreeError::DuplicateStorageField { - name: v.name.clone(), - span: v.name.span(), - }); + fn check_duplicate_names( + entries: Vec, + mut errors: &mut Vec, + ) { + // Make sure each storage field is declared once + let mut names_of_fields = std::collections::HashSet::new(); + for v in entries { + if !names_of_fields.insert(v.name().clone()) { + errors.push(ConvertParseTreeError::DuplicateStorageField { + name: v.name().clone(), + span: v.name().span(), + }); + } + if let StorageEntry::Namespace(namespace) = v { + check_duplicate_names( + namespace + .entries + .iter() + .map(|e| (**e).clone()) + .collect::>(), + &mut errors, + ); + } } } + check_duplicate_names(entries.clone(), &mut errors); + if let Some(errors) = emit_all(handler, errors) { return Err(errors); } @@ -1041,7 +1058,7 @@ fn item_storage_to_storage_declaration( let storage_declaration = StorageDeclaration { attributes, span, - fields, + entries, storage_keyword: item_storage.storage_token.into(), }; let storage_declaration = engines.pe().insert(storage_declaration); @@ -2470,6 +2487,48 @@ fn op_call( }) } +fn storage_entry_to_storage_entry( + context: &mut Context, + handler: &Handler, + engines: &Engines, + storage_entry: sway_ast::StorageEntry, + attributes: AttributesMap, +) -> Result { + if let Some(storage_field) = storage_entry.field { + Ok(StorageEntry::Field(storage_field_to_storage_field( + context, + handler, + engines, + storage_field, + attributes, + )?)) + } else { + let mut entries = vec![]; + let namespace = storage_entry.namespace.unwrap(); + for entry in namespace.into_inner().into_iter().map(|storage_entry| { + let attributes = item_attrs_to_map(context, handler, &storage_entry.attribute_list)?; + if !cfg_eval(context, handler, &attributes, context.experimental)? { + return Ok::, ErrorEmitted>(None); + } + Ok(Some(storage_entry_to_storage_entry( + context, + handler, + engines, + *storage_entry.value, + attributes, + )?)) + }) { + if let Ok(Some(entry)) = entry { + entries.push(Box::new(entry)); + } + } + Ok(StorageEntry::Namespace(StorageNamespace { + name: storage_entry.name, + entries, + })) + } +} + fn storage_field_to_storage_field( context: &mut Context, handler: &Handler, diff --git a/sway-parse/src/item/item_storage.rs b/sway-parse/src/item/item_storage.rs index ad1abec4a8d..685f636a97b 100644 --- a/sway-parse/src/item/item_storage.rs +++ b/sway-parse/src/item/item_storage.rs @@ -1,10 +1,36 @@ use crate::{Parse, ParseResult, Parser}; -use sway_ast::{keywords::InToken, Expr, ItemStorage, StorageField}; +use sway_ast::{ + attribute::Annotated, + keywords::{ColonToken, InToken}, + Braces, CommaToken, Expr, ItemStorage, Punctuated, StorageEntry, StorageField, +}; +use sway_types::BaseIdent; + +impl Parse for StorageEntry { + fn parse(parser: &mut Parser) -> ParseResult { + let name: BaseIdent = parser.parse()?; + let mut field = None; + let mut namespace = None; + if parser.peek::().is_some() || parser.peek::().is_some() { + let mut f: StorageField = parser.parse()?; + f.name = name.clone(); + field = Some(f); + } else { + let n: Braces>, CommaToken>> = parser.parse()?; + namespace = Some(n); + } + Ok(StorageEntry { + name, + namespace, + field, + }) + } +} impl Parse for StorageField { fn parse(parser: &mut Parser) -> ParseResult { - let name = parser.parse()?; + let name = BaseIdent::dummy(); // Name will be overrided in StorageEntry parse. let in_token: Option = parser.take(); let mut key_opt: Option = None; if in_token.is_some() { @@ -29,10 +55,10 @@ impl Parse for StorageField { impl Parse for ItemStorage { fn parse(parser: &mut Parser) -> ParseResult { let storage_token = parser.parse()?; - let fields = parser.parse()?; + let entries = parser.parse()?; Ok(ItemStorage { storage_token, - fields, + entries, }) } } From 9eea18491bdefa394169b6a6b7c0e3d272c48dff Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 3 Jun 2024 12:26:08 +0100 Subject: [PATCH 06/14] Changes key hash string generation to match usage syntax. --- sway-core/src/ir_generation/storage.rs | 44 ++++++++++++++++++-------- sway-utils/src/constants.rs | 3 +- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/sway-core/src/ir_generation/storage.rs b/sway-core/src/ir_generation/storage.rs index 89f7088f277..ebc993be8ae 100644 --- a/sway-core/src/ir_generation/storage.rs +++ b/sway-core/src/ir_generation/storage.rs @@ -20,32 +20,50 @@ enum InByte8Padding { } /// Hands out storage keys using storage field names or an existing key. -/// Basically returns sha256("storage::::") +/// Basically returns sha256("storage::::.") /// or key if defined. pub(super) fn get_storage_key(storage_field_names: Vec, key: Option) -> Bytes32 { if let Some(key) = key { return key.to_be_bytes().into(); } - let data = format!( - "{}{}{}", - sway_utils::constants::STORAGE_DOMAIN, - sway_utils::constants::STORAGE_FIELD_SEPARATOR, - storage_field_names.join(sway_utils::constants::STORAGE_FIELD_SEPARATOR), - ); - Hasher::hash(data) + + Hasher::hash(get_storage_key_string(storage_field_names)) +} + +fn get_storage_key_string(storage_field_names: Vec) -> String { + if storage_field_names.len() == 1 { + format!( + "{}{}{}", + sway_utils::constants::STORAGE_DOMAIN, + sway_utils::constants::STORAGE_FIELD_SEPARATOR, + storage_field_names.last().unwrap(), + ) + } else { + format!( + "{}{}{}{}{}", + sway_utils::constants::STORAGE_DOMAIN, + sway_utils::constants::STORAGE_NAMESPACE_SEPARATOR, + storage_field_names + .iter() + .take(storage_field_names.len() - 1) + .cloned() + .collect::>() + .join(sway_utils::constants::STORAGE_NAMESPACE_SEPARATOR), + sway_utils::constants::STORAGE_FIELD_SEPARATOR, + storage_field_names.last().unwrap(), + ) + } } /// Hands out unique storage field ids using storage field names and struct field names. -/// Basically returns sha256("storage::::..") +/// Basically returns sha256("storage::::...") pub(super) fn get_storage_field_id( storage_field_names: Vec, struct_field_names: Vec, ) -> Bytes32 { let data = format!( - "{}{}{}{}", - sway_utils::constants::STORAGE_DOMAIN, - sway_utils::constants::STORAGE_FIELD_SEPARATOR, - storage_field_names.join(sway_utils::constants::STORAGE_FIELD_SEPARATOR), + "{}{}", + get_storage_key_string(storage_field_names), if struct_field_names.is_empty() { "".to_string() } else { diff --git a/sway-utils/src/constants.rs b/sway-utils/src/constants.rs index 9a6711cad5e..00214945ed5 100644 --- a/sway-utils/src/constants.rs +++ b/sway-utils/src/constants.rs @@ -8,7 +8,8 @@ pub const SRC_DIR: &str = "src"; pub const DEFAULT_NODE_URL: &str = "http://127.0.0.1:4000"; pub const LANGUAGE_NAME: &str = "Sway"; pub const STORAGE_DOMAIN: &str = "storage"; -pub const STORAGE_FIELD_SEPARATOR: &str = "::"; +pub const STORAGE_NAMESPACE_SEPARATOR: &str = "::"; +pub const STORAGE_FIELD_SEPARATOR: &str = "."; pub const STRUCT_FIELD_SEPARATOR: &str = "."; pub const LIB_ENTRY: &str = "lib.sw"; pub const MAIN_ENTRY: &str = "main.sw"; From 27fa45c8fa47e2f073ca17022ad7b297b4af1cbe Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 3 Jun 2024 12:36:54 +0100 Subject: [PATCH 07/14] Adds namespace_names to StorageAccessExpression. --- sway-core/src/language/parsed/expression/mod.rs | 1 + .../src/language/ty/declaration/storage.rs | 17 +++++++++++++++-- .../ast_node/declaration/storage.rs | 6 +++++- .../ast_node/expression/typed_expression.rs | 4 ++++ .../namespace/lexical_scope.rs | 2 ++ .../to_parsed_lang/convert_parse_tree.rs | 7 ++++++- 6 files changed, 33 insertions(+), 4 deletions(-) diff --git a/sway-core/src/language/parsed/expression/mod.rs b/sway-core/src/language/parsed/expression/mod.rs index b5e1977aa56..73ab3a33cbb 100644 --- a/sway-core/src/language/parsed/expression/mod.rs +++ b/sway-core/src/language/parsed/expression/mod.rs @@ -330,6 +330,7 @@ impl PartialEqWithEngines for ArrayIndexExpression { #[derive(Debug, Clone)] pub struct StorageAccessExpression { + pub namespace_names: Vec, pub field_names: Vec, pub storage_keyword_span: Span, } diff --git a/sway-core/src/language/ty/declaration/storage.rs b/sway-core/src/language/ty/declaration/storage.rs index 7b773e82c8c..2931f3ce8ac 100644 --- a/sway-core/src/language/ty/declaration/storage.rs +++ b/sway-core/src/language/ty/declaration/storage.rs @@ -70,6 +70,7 @@ impl TyStorageDecl { handler: &Handler, engines: &Engines, namespace: &Namespace, + namespace_names: &[Ident], fields: &[Ident], storage_fields: &[TyStorageField], storage_keyword_span: Span, @@ -88,7 +89,15 @@ impl TyStorageDecl { ); let (initial_field_type, initial_field_key, initial_field_name) = - match storage_fields.iter().find(|sf| &sf.name == first_field) { + match storage_fields.iter().find(|sf| { + &sf.name == first_field + && sf.namespace_names.len() == namespace_names.len() + && sf + .namespace_names + .iter() + .zip(namespace_names.iter()) + .all(|(n1, n2)| n1 == n2) + }) { Some(TyStorageField { type_argument, key_expression, @@ -205,7 +214,11 @@ impl TyStorageDecl { TyStorageAccess { fields: access_descriptors, key_expression: initial_field_key.clone().map(|v| Box::new(v)), - storage_field_names: vec![initial_field_name.as_str().to_string()], + storage_field_names: namespace_names + .iter() + .map(|n| n.as_str().to_string()) + .chain(vec![initial_field_name.as_str().to_string()]) + .collect(), struct_field_names, storage_keyword_span, }, diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs index 454bf5d5a48..6700a6dfc42 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs @@ -65,7 +65,11 @@ impl ty::TyStorageField { serialize_to_storage_slots( &constant, context, - vec![self.name.as_str().to_string()], + self.namespace_names + .iter() + .map(|i| i.as_str().to_string()) + .chain(vec![self.name.as_str().to_string()]) + .collect(), key, &constant.ty, ) diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index a209fc56677..0d7667802ee 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -332,6 +332,7 @@ impl ty::TyExpression { Self::type_check_array_index(handler, ctx, prefix, index, span) } ExpressionKind::StorageAccess(StorageAccessExpression { + namespace_names, field_names, storage_keyword_span, }) => { @@ -342,6 +343,7 @@ impl ty::TyExpression { Self::type_check_storage_access( handler, ctx, + namespace_names, field_names, storage_keyword_span.clone(), &span, @@ -1118,6 +1120,7 @@ impl ty::TyExpression { fn type_check_storage_access( handler: &Handler, ctx: TypeCheckContext, + namespace_names: &[Ident], checkee: &[Ident], storage_keyword_span: Span, span: &Span, @@ -1146,6 +1149,7 @@ impl ty::TyExpression { handler, ctx.engines, ctx.namespace(), + namespace_names, checkee, &storage_fields, storage_keyword_span.clone(), diff --git a/sway-core/src/semantic_analysis/namespace/lexical_scope.rs b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs index 4e471633fd0..e404e12a615 100644 --- a/sway-core/src/semantic_analysis/namespace/lexical_scope.rs +++ b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs @@ -99,6 +99,7 @@ impl Items { handler: &Handler, engines: &Engines, namespace: &Namespace, + namespace_names: &[Ident], fields: &[Ident], storage_fields: &[ty::TyStorageField], storage_keyword_span: Span, @@ -110,6 +111,7 @@ impl Items { handler, engines, namespace, + namespace_names, fields, storage_fields, storage_keyword_span, diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 67006505d31..6467fb65024 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -2177,11 +2177,15 @@ fn expr_to_expression( // Parent is `storage`. We found what we were looking for. Expr::Path(path_expr) if path_expr.root_opt.is_none() - && path_expr.suffix.is_empty() && path_expr.prefix.generics_opt.is_none() && path_expr.prefix.name.as_str() == "storage" => { break ExpressionKind::StorageAccess(StorageAccessExpression { + namespace_names: path_expr + .suffix + .iter() + .map(|s| s.1.name.clone()) + .collect(), field_names: idents.into_iter().rev().cloned().collect(), storage_keyword_span: path_expr.prefix.name.span(), }) @@ -4425,6 +4429,7 @@ fn assignable_to_expression( let field_names = field_names.into_iter().rev().cloned().collect(); Expression { kind: ExpressionKind::StorageAccess(StorageAccessExpression { + namespace_names: vec![], field_names, storage_keyword_span: storage_name.span(), }), From 2184d96c2f20164b8b1ada12984369f137596404 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 3 Jun 2024 16:36:01 +0100 Subject: [PATCH 08/14] Updates tests storage slots and contract ids. --- .../language/fallback_only/src/main.sw | 7 +- .../basic_storage/json_abi_oracle.json | 20 ++++- .../json_abi_oracle_new_encoding.json | 18 ++++- .../json_storage_slots_oracle.json | 50 ++++++------ .../test_contracts/basic_storage/src/main.sw | 11 ++- .../json_storage_slots_oracle.json | 2 +- .../json_storage_slots_oracle.json | 70 ++++++++--------- .../json_storage_slots_oracle.json | 58 +++++++------- .../json_storage_slots_oracle.json | 48 ++++++------ .../storage_namespace/src/main.sw | 77 ++++++++++--------- 10 files changed, 202 insertions(+), 159 deletions(-) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/fallback_only/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/fallback_only/src/main.sw index e078e4ce4cb..56294ea407a 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/fallback_only/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/fallback_only/src/main.sw @@ -2,13 +2,14 @@ contract; use std::execution::run_external; -#[namespace(SRC1822)] storage { - target: ContractId = ContractId::zero(), + SRC1822 { + target: ContractId = ContractId::zero(), + } } #[fallback] #[storage(read)] fn fallback() { - run_external(storage.target.read()) + run_external(storage::SRC1822.target.read()) } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle.json index ec0a0a7addf..1ac3be1b41d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle.json @@ -199,10 +199,10 @@ ], "loggedTypes": [ { - "logId": "1515152261580153489", + "logId": "14454674236531057292", "loggedType": { "name": "", - "type": 9, + "type": 10, "typeArguments": null } }, @@ -221,6 +221,14 @@ "type": 1, "typeArguments": null } + }, + { + "logId": "1515152261580153489", + "loggedType": { + "name": "", + "type": 9, + "typeArguments": null + } } ], "messagesTypes": [], @@ -350,6 +358,12 @@ "type": "u64", "typeId": 9, "typeParameters": null + }, + { + "components": null, + "type": "u8", + "typeId": 10, + "typeParameters": null } ] -} +} \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle_new_encoding.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle_new_encoding.json index 8e817c80160..1ac3be1b41d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle_new_encoding.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_abi_oracle_new_encoding.json @@ -199,10 +199,10 @@ ], "loggedTypes": [ { - "logId": "1515152261580153489", + "logId": "14454674236531057292", "loggedType": { "name": "", - "type": 9, + "type": 10, "typeArguments": null } }, @@ -221,6 +221,14 @@ "type": 1, "typeArguments": null } + }, + { + "logId": "1515152261580153489", + "loggedType": { + "name": "", + "type": 9, + "typeArguments": null + } } ], "messagesTypes": [], @@ -350,6 +358,12 @@ "type": "u64", "typeId": 9, "typeParameters": null + }, + { + "components": null, + "type": "u8", + "typeId": 10, + "typeParameters": null } ] } \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json index 21eba0f8313..b2063f1474b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/json_storage_slots_oracle.json @@ -1,54 +1,58 @@ [ { - "key": "072c710c522c081d2ed4d054094cc45a52ad246f171b318f13a1a234fbf19595", - "value": "6161616161000000000000000000000000000000000000000000000000000000" + "key": "26a0f316674277151cdb647fc857710df30dca882c9c61a48e35790d5cb75159", + "value": "6161616161616161000000000000000000000000000000000000000000000000" }, { - "key": "3bdcc328346bf340ed83baea8fd16ea96c7354e395f0fd1a2dfc60d9c57e56ba", - "value": "6161616161616161616100000000000000000000000000000000000000000000" + "key": "2873dd8e90786169217d1dc180cdbeb5642b04daf3979c26776d8b8e93720c12", + "value": "6161616161610000000000000000000000000000000000000000000000000000" }, { - "key": "631bd8dfca7cbdea56b201574608ad86b79292de700ae72176408561c4974ddd", - "value": "6161616161616100000000000000000000000000000000000000000000000000" + "key": "323860f3257dc73a83c0b26b915b97575ef2cf8cc150988eb0b0fae2fe61ad77", + "value": "6100000000000000000000000000000000000000000000000000000000000000" }, { - "key": "65ab21209750ea9c5d50540dd1f34f681baf641675b708b8833c00db8d434c62", - "value": "6161616161610000000000000000000000000000000000000000000000000000" + "key": "3c025b285aab5e23d355e104b29cb021a7581c1485c4aee6f93c3a37569636ef", + "value": "6161616161000000000000000000000000000000000000000000000000000000" }, { - "key": "84da94101bf1f6d696f78b1763e38284fc568e88582d4a372252cff7df9ed0ec", - "value": "6100000000000000000000000000000000000000000000000000000000000000" + "key": "533dcc8c8bc47b384931e0bdab958e580a48b65d633991b87ecf6f035a2ec53a", + "value": "0000000000000002000000000000000000000000000000000000000000000000" }, { - "key": "8a64b133f6033d94b315b3be1e4a2d5d609859448e6418f1b0e4b8049e0f83b6", + "key": "67572eb5ab2c5a6c11d8a7217f617a380ad7adbe7e7fed0ffa18be2a11ae78fc", "value": "6161000000000000000000000000000000000000000000000000000000000000" }, { - "key": "9a05ffac71399945a623705708d64227c98aa0ab492df9e90a8791b5f8babf57", - "value": "0000000000000001000000000000000000000000000000000000000000000000" + "key": "6c1f46e5e38cfa9767a552ab89186da5647f603b447e226eb8b0fdbdefb97f0e", + "value": "6161616161616161616100000000000000000000000000000000000000000000" }, { - "key": "a603887c83e3ca59db93e6a6f9aa8192bc6d4bde49dc04b57391b0e6b303792a", - "value": "6161616161616161610000000000000000000000000000000000000000000000" + "key": "933a534d4af4c376b0b569e8d8a2c62e635e26f403e124cb91d9c42e83d54373", + "value": "0100000000000000000000000000000000000000000000000000000000000000" }, { - "key": "a966dac681b019c01b28479acdd8861e1f403086ebf4c6e930f21430161e79f1", - "value": "6161616100000000000000000000000000000000000000000000000000000000" + "key": "98ba41aa317c3ee2a207b8deaf0a3386a1705b2548777944f29d8a288999c460", + "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "cc5325c3a788ed2646b648ac3309a8cdf436ea80c4218d7ead794cfe18ee64bb", + "key": "a605c78ce1b8f4b67230a55ea491e2b7c5f3d6099cbdcb67e8bf60c9678ae047", "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "e82244d91548d15ca4554062bc436a677487ec0412e11495ad0746c5828fe2b8", - "value": "0000000000000000000000000000000000000000000000000000000001234567" + "key": "c4085ef85fb993a44237f78f083c0e96be21522fa8d00bd74b8b8d51b8aa2e8a", + "value": "6161616100000000000000000000000000000000000000000000000000000000" }, { - "key": "f47b91cf76a03a198609b7318e6a5ef450922282b59e80810aa6c4d74c2aadea", + "key": "d40c4527ee86df5ab69139820872760c294318505804f4327672d6ce7ee2e15f", + "value": "6161616161616100000000000000000000000000000000000000000000000000" + }, + { + "key": "dc7ac8a34653cb050eb9eeb0792ed909ecaf9df17158e8c2a44820cada45805b", "value": "6161610000000000000000000000000000000000000000000000000000000000" }, { - "key": "f851b76f2bd8cfc0e952a16e596bf101e521339195d85cad0aba3afe24e90859", - "value": "6161616161616161000000000000000000000000000000000000000000000000" + "key": "eafb8114029f277e266bedc3d0b60a5576e8476bc97b96ea42482e20ad15e051", + "value": "6161616161616161610000000000000000000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw index 24cd4a44af5..261bd8cb0e8 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/basic_storage/src/main.sw @@ -3,6 +3,7 @@ use std::{hash::*, storage::storage_api::{read, write}}; use basic_storage_abi::*; const C1 = 1; +const NS1_NS2_C1 = 2; const S5 = __to_str_array("aaaaa"); const C1KEY: b256 = 0x933a534d4af4c376b0b569e8d8a2c62e635e26f403e124cb91d9c42e83d54373; @@ -23,6 +24,11 @@ storage { const_u256: u256 = 0x0000000000000000000000000000000000000000000000000000000001234567u256, const_b256: b256 = 0x0000000000000000000000000000000000000000000000000000000001234567, + ns1 { + ns2 { + c1: u64 = NS1_NS2_C1, + } + } } impl BasicStorage for Contract { @@ -287,8 +293,11 @@ fn test_storage() { storage.const_b256.write(0x0000000000000000000000000000000000000000000000000000000012345678); assert_eq(storage.const_b256.read(), 0x0000000000000000000000000000000000000000000000000000000012345678); + assert_eq(storage::ns1::ns2.c1.read(), NS1_NS2_C1); + assert_eq(storage.c1.slot(), C1KEY); - assert_eq(storage.const_b256.slot(), sha256("storage::const_b256")); + assert_eq(storage.const_b256.slot(), sha256("storage.const_b256")); + assert_eq(storage::ns1::ns2.c1.slot(), sha256("storage::ns1::ns2.c1")); } // If these comparisons are done inline just above then it blows out the register allocator due to diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json index 44b479e1850..27d01be9eb2 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/increment_contract/json_storage_slots_oracle.json @@ -1,6 +1,6 @@ [ { - "key": "8580450cc7a7bfd8db92d80a47ae11f4854e7656fa424b754b4e6a37af66b6e2", + "key": "1f5327d8b018fe8a341aec49e087546980b521535a650107a53efdc5e7038723", "value": "0000000000000000000000000000000000000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json index 03972c0f04e..24a5f2c6daf 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_access_contract/json_storage_slots_oracle.json @@ -1,74 +1,74 @@ [ { - "key": "2f2c50fd1be2f5af223fce93c374b36dc18257b026180bf3761ef885a75de635", - "value": "0000000000000040000000000000000000000000000000000000000000000000" + "key": "06ee74b45a12fd83e7df88440f9b3aef7a275760bf6742de13f2007316af87cb", + "value": "0000000000000001000000000000000200000000000000000000000000000000" }, { - "key": "56b7c47d21a400c8c270206038fba089fffd1e68f7467d75a50816277d51de3b", - "value": "0000000000000001000000000000000100000000000000020000000000000000" + "key": "06ee74b45a12fd83e7df88440f9b3aef7a275760bf6742de13f2007316af87cc", + "value": "0000000000000000000000000000000300000000000000040000000000000005" }, { - "key": "56b7c47d21a400c8c270206038fba089fffd1e68f7467d75a50816277d51de3c", - "value": "0000000000000000000000000000000000000000000000030100000000000000" + "key": "06ee74b45a12fd83e7df88440f9b3aef7a275760bf6742de13f2007316af87cd", + "value": "0000000000000000000000000000000000000000000000000000000000000006" }, { - "key": "56b7c47d21a400c8c270206038fba089fffd1e68f7467d75a50816277d51de3d", - "value": "0400000000000000000000000000000500000000000000060000000000000000" + "key": "06ee74b45a12fd83e7df88440f9b3aef7a275760bf6742de13f2007316af87ce", + "value": "0100000000000000070000000000000000000000000000080000000000000009" }, { - "key": "639c65f568c14425f41b04036ad8180eacc76e84b957070436209824c852362a", - "value": "0800000000000000000000000000000000000000000000000000000000000000" + "key": "5dc4bb371cab39153d3503dc677662a2c02b616d1789ffc8c7f11cd6838a5b8d", + "value": "0000000000000020000000000000000000000000000000000000000000000000" + }, + { + "key": "9a1c37d22e51c475d6284f621e29ad5753c418595c5d7b24a7d1684f11f31adf", + "value": "0100000000000000000000000000000000000000000000000000000000000000" }, { - "key": "80410561e8d7b049434921d2a8e6216c3ef7556a0f5ac56cc59017cf1b60c6b0", + "key": "a87982353688625e3011294e19aa0a5c027b02e2045c8df73c59cf2142416a37", + "value": "0000000000000010000000000000000000000000000000000000000000000000" + }, + { + "key": "aa834639bd045ecb5b8644fda6256196e090c28df31665d3ab8516fb89fb39cd", "value": "0000000000000000000000000000000000000000000000000000000000000000" }, { - "key": "80410561e8d7b049434921d2a8e6216c3ef7556a0f5ac56cc59017cf1b60c6b1", + "key": "aa834639bd045ecb5b8644fda6256196e090c28df31665d3ab8516fb89fb39ce", "value": "0000000000000000000000000000000000000000000000000000000000000000" }, { - "key": "80410561e8d7b049434921d2a8e6216c3ef7556a0f5ac56cc59017cf1b60c6b2", + "key": "aa834639bd045ecb5b8644fda6256196e090c28df31665d3ab8516fb89fb39cf", "value": "0000000000000000000000000000000000000000000003090000000000000000" }, { - "key": "87c40ac0fa5fece0d8ee86e8a397ba1f111c83d7cfe2435d010db207a25f46c5", + "key": "ae4a9d6171099362a9d5a398016d7bf8555a8ba706d68ef7c879d4a439c8a6d5", "value": "4141414141414141414141414141414141414141414141414141414141414141" }, { - "key": "87c40ac0fa5fece0d8ee86e8a397ba1f111c83d7cfe2435d010db207a25f46c6", + "key": "ae4a9d6171099362a9d5a398016d7bf8555a8ba706d68ef7c879d4a439c8a6d6", "value": "4141414141414141000000000000000000000000000000000000000000000000" }, { - "key": "8d40e955efb6d905b6d4cc695086bd0689b55879a7ad3d6e4d66f305e0a02ae2", - "value": "0000000000000020000000000000000000000000000000000000000000000000" - }, - { - "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca6", - "value": "0000000000000001000000000000000200000000000000000000000000000000" - }, - { - "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca7", - "value": "0000000000000000000000000000000300000000000000040000000000000005" + "key": "b9ffa363d401358f328bb44e635cded3208652b383e46c121afb23d599356f41", + "value": "0800000000000000000000000000000000000000000000000000000000000000" }, { - "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca8", - "value": "0000000000000000000000000000000000000000000000000000000000000006" + "key": "c979570128d5f52725e9a343a7f4992d8ed386d7c8cfd25f1c646c51c2ac6b4b", + "value": "0000000000000040000000000000000000000000000000000000000000000000" }, { - "key": "961e1c4eeabc15b791b5b508a0da65b0fa1fc97a3186e95acb183f0692a53ca9", - "value": "0100000000000000070000000000000000000000000000080000000000000009" + "key": "d95f4c8d717d52323d34c1118b3f0598a5ec3cabae386887507cabd6dd546a43", + "value": "0101010101010101010101010101010101010101010101010101010101010101" }, { - "key": "adbc79bc188f7824b140d7429535d6bd32efff129cf3becc0ce69b6116b222e2", - "value": "0100000000000000000000000000000000000000000000000000000000000000" + "key": "e153542f820f1e716d34120d0ea017c2fab2e2545c0556584bc7462f2dafb3bd", + "value": "0000000000000001000000000000000100000000000000020000000000000000" }, { - "key": "caea1faf0f6604ab6ecca8624adb27603d2d667ee2108cf84657bde0cecd9715", - "value": "0101010101010101010101010101010101010101010101010101010101010101" + "key": "e153542f820f1e716d34120d0ea017c2fab2e2545c0556584bc7462f2dafb3be", + "value": "0000000000000000000000000000000000000000000000030100000000000000" }, { - "key": "f0c6c380b3847177f70873ddbd84c4715349191f6f5a88eb71affa8f187113b7", - "value": "0000000000000010000000000000000000000000000000000000000000000000" + "key": "e153542f820f1e716d34120d0ea017c2fab2e2545c0556584bc7462f2dafb3bf", + "value": "0400000000000000000000000000000500000000000000060000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json index ec21371bdf8..569da2a8bea 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_enum_contract/json_storage_slots_oracle.json @@ -1,62 +1,62 @@ [ { - "key": "0aea1a60b35c1352b7920c42b7e13007eeaae104db10c2d44c8c36a12e08964b", + "key": "07692c5e306e34754c8507b83507787cd816e26e21a73f984267468c6a858c5f", "value": "00000000000000000000000000000000000000000000000000000000000000ee" }, { - "key": "5dd3f12390f860617a1d8cb643c383bb7b400ce81b8c8416e3c58aaa5f8e155c", - "value": "0000000000000000000000000000000100000000000000000000000000000000" + "key": "093917a687c53cb2abc027cec98a5bbf66c8ae7f5cd58a0880fc9c79617ce148", + "value": "0000000000000001000000000000aa00000000000000bb00000000000000cc00" }, { - "key": "5e1556a4612be2e52bfc462109ffad79432d512f6ab72477ea2f8123b4d6157e", - "value": "0000000000000001000000000000aa00000000000000bb00000000000000cc00" + "key": "1381e00cddf07f6fb1d14cdcb956f38a498a20369226d4528826287fd98e6d33", + "value": "0000000000000000000000000000000100000000000000000000000000000000" }, { - "key": "5ee80e556c2db7702e9c298ef70329f25839421bf2d2132c6b85da71a9eca9a8", - "value": "000000000000000000000000000000aa00000000000000000000000000000000" + "key": "163670615ae62a8f957b50ab4ce2c32b22427e70577a54b971439c44f1c4f6ac", + "value": "0000000000000001000000000000bb0000000000000000000000000000000000" }, { - "key": "7cf3c16875639336aef3cf3818a29f1210a83d5992f6814e151ee34e385b913c", - "value": "0000000000000002000000000000000000000000000000000000000000000000" + "key": "306d92806670cbeca4a1dcd450149e8aac249b1446ab7a4360b511de83dc031c", + "value": "0000000000000001000000000000ab00000000000000bc00000000000000cd00" }, { - "key": "905c813864e60f1f5e35bfa5f8ab59455e52d7ce49ef20a6051b58ce1637a715", - "value": "000000000000000000000000000000ab00000000000000000000000000000000" + "key": "306d92806670cbeca4a1dcd450149e8aac249b1446ab7a4360b511de83dc031d", + "value": "000000000000de00000000000000ef0000000000000000000000000000000000" }, { - "key": "912649db2c12ab1252a459205b0a580d828f4761b9d9044150944a125fd45d3e", - "value": "0000000000000001000000000000bb0000000000000000000000000000000000" + "key": "919b268af8b1d0e73ebd666050f0d8ca91c4a57c1f07de173500c1204f12b4b5", + "value": "0000000000000002000000000000000000000000000000000000000000000000" }, { - "key": "9c498f0e21208bd9d68741454a356cfc748e43e6d16c2c955ccfbeb59489f035", - "value": "0000000000000000000000000000000100000000000000000000000000000000" + "key": "b1852fd03d24006ecb20b244b4a807a5cc1901e1615b4c2cf38ad968da5778a3", + "value": "0000000000000002000000000000000000000000000000000000000000000000" }, { - "key": "9d322a178fee428b5e971c7f9aee368a65a5e17c029b5ef08aa832caa49d9b26", - "value": "0000000000000000000000000000000000000000000000000000000000000000" + "key": "b791faa009af5f959cb5b1e527897b5445b819ad012dbcdb4e6747fc67a74abf", + "value": "000000000000000000000000000000ab00000000000000000000000000000000" }, { - "key": "9d322a178fee428b5e971c7f9aee368a65a5e17c029b5ef08aa832caa49d9b27", - "value": "000000000000000000000000000000ff00000000000000000000000000000000" + "key": "ca79befa366adbeb06bd973bbb1c4edf732df97bfec0caf094cf9f83fee6dead", + "value": "0000000000000000000000000000000100000000000000000000000000000000" }, { - "key": "a02498e7f4c209177cdc0467b27573a4ef5ac92538041c24ff8b47b9c346fa82", - "value": "000000000000000100000000000000cd00000000000000000000000000000000" + "key": "d44c3a30232bc40cbe5f573493a6951cd072404880b4dde75e10903d0b0a5256", + "value": "000000000000000000000000000000aa00000000000000000000000000000000" }, { - "key": "b9fda96766abb098f5fcdffe9becd16e30ade9bd3b2b7f4c7b05010f2cc3053d", - "value": "0000000000000001000000000000ab00000000000000bc00000000000000cd00" + "key": "e487c22c16cab65d2a63a26de30fd41df1586b5abbad6746cacdf958aa539d49", + "value": "000000000000000000000000000000cd00000000000000000000000000000000" }, { - "key": "b9fda96766abb098f5fcdffe9becd16e30ade9bd3b2b7f4c7b05010f2cc3053e", - "value": "000000000000de00000000000000ef0000000000000000000000000000000000" + "key": "fb07f807a63ddfd1422b1cba4ed39940c50eade2002542e1faccea5c64d5b087", + "value": "000000000000000100000000000000cd00000000000000000000000000000000" }, { - "key": "d6a33d4c06d6b1de28bf22606546c026df3cebb0ffe22c1650e834f3ebefab38", - "value": "000000000000000000000000000000cd00000000000000000000000000000000" + "key": "fdfd23cb7462d11986f91b4f130b7ddb400b7bbc388ad6754175d93c2b00bd25", + "value": "0000000000000000000000000000000000000000000000000000000000000000" }, { - "key": "ffd8d1fce9c0114aa6b113ae5e40495d54607880ac07b7acaa81528c60f86ba4", - "value": "0000000000000002000000000000000000000000000000000000000000000000" + "key": "fdfd23cb7462d11986f91b4f130b7ddb400b7bbc388ad6754175d93c2b00bd26", + "value": "000000000000000000000000000000ff00000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json index 21eba0f8313..0b71f7ba584 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/json_storage_slots_oracle.json @@ -1,54 +1,54 @@ [ { - "key": "072c710c522c081d2ed4d054094cc45a52ad246f171b318f13a1a234fbf19595", - "value": "6161616161000000000000000000000000000000000000000000000000000000" + "key": "156750d12322b9d55699e5f250927c45dbc5a716ed514e5d5c6e001c72743958", + "value": "6161616161616161610000000000000000000000000000000000000000000000" }, { - "key": "3bdcc328346bf340ed83baea8fd16ea96c7354e395f0fd1a2dfc60d9c57e56ba", - "value": "6161616161616161616100000000000000000000000000000000000000000000" + "key": "1900d3c5816770f72962fcc1c2903deaef383aad2245f8dce3ea438edb50d5be", + "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "631bd8dfca7cbdea56b201574608ad86b79292de700ae72176408561c4974ddd", - "value": "6161616161616100000000000000000000000000000000000000000000000000" + "key": "316435c84dec635a59eafe5c7bbe948529d9b334642e3042790ccc24a48d020f", + "value": "6161610000000000000000000000000000000000000000000000000000000000" }, { - "key": "65ab21209750ea9c5d50540dd1f34f681baf641675b708b8833c00db8d434c62", - "value": "6161616161610000000000000000000000000000000000000000000000000000" + "key": "75c8aa025fcadccc0595011724f38d1c4502877ab67e96c2d5ac4e28c7c067d2", + "value": "6161616161000000000000000000000000000000000000000000000000000000" }, { - "key": "84da94101bf1f6d696f78b1763e38284fc568e88582d4a372252cff7df9ed0ec", - "value": "6100000000000000000000000000000000000000000000000000000000000000" + "key": "8d03529726cb560c58c7c256daa265105ab1657cc58f285a4e450ade5e3b99b9", + "value": "6161616161616161616100000000000000000000000000000000000000000000" + }, + { + "key": "8e2eedb0198112b5758b3ca68ff81ccf74f35bde89f59324c6349834b7446d42", + "value": "6161616161610000000000000000000000000000000000000000000000000000" }, { - "key": "8a64b133f6033d94b315b3be1e4a2d5d609859448e6418f1b0e4b8049e0f83b6", + "key": "96f53fe759d3f6112e66216565e101a4e3ad50e0b67047a2b1bc71f58e838b3b", "value": "6161000000000000000000000000000000000000000000000000000000000000" }, { - "key": "9a05ffac71399945a623705708d64227c98aa0ab492df9e90a8791b5f8babf57", + "key": "9cd3727531d07180cf222a86ab51e4d6933e82ffa5a846a51ee7554929eec408", "value": "0000000000000001000000000000000000000000000000000000000000000000" }, { - "key": "a603887c83e3ca59db93e6a6f9aa8192bc6d4bde49dc04b57391b0e6b303792a", - "value": "6161616161616161610000000000000000000000000000000000000000000000" + "key": "b48939b669452acd21e7e052008441cf16898ebecad0cf50ea5d1022cc91683d", + "value": "6161616161616100000000000000000000000000000000000000000000000000" }, { - "key": "a966dac681b019c01b28479acdd8861e1f403086ebf4c6e930f21430161e79f1", + "key": "c2cec376bf7389162e8706fbb83f4c7d322150bbae540c4d7a89711e86a54d0b", "value": "6161616100000000000000000000000000000000000000000000000000000000" }, { - "key": "cc5325c3a788ed2646b648ac3309a8cdf436ea80c4218d7ead794cfe18ee64bb", + "key": "c47aaa0a4460ad82387b70843b35804e6526ec4a4094793064abda38e789d70b", "value": "0000000000000000000000000000000000000000000000000000000001234567" }, { - "key": "e82244d91548d15ca4554062bc436a677487ec0412e11495ad0746c5828fe2b8", - "value": "0000000000000000000000000000000000000000000000000000000001234567" - }, - { - "key": "f47b91cf76a03a198609b7318e6a5ef450922282b59e80810aa6c4d74c2aadea", - "value": "6161610000000000000000000000000000000000000000000000000000000000" + "key": "dbaf1317f4011ad87979853011781f2088cdd8422250f19f27a90b5ce8037cac", + "value": "6161616161616161000000000000000000000000000000000000000000000000" }, { - "key": "f851b76f2bd8cfc0e952a16e596bf101e521339195d85cad0aba3afe24e90859", - "value": "6161616161616161000000000000000000000000000000000000000000000000" + "key": "f665e43dbe17620f6ef1e4beb22f9d4f1e2bb711e20c003a09dad812801f59e0", + "value": "6100000000000000000000000000000000000000000000000000000000000000" } ] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/src/main.sw index 6091131ef11..934376a211b 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/storage_namespace/src/main.sw @@ -5,23 +5,24 @@ use basic_storage_abi::*; const C1 = 1; const S5 = __to_str_array("aaaaa"); -#[namespace(my_storage_namespace)] storage { - c1: u64 = C1, - str0: str[0] = __to_str_array(""), - str1: str[1] = __to_str_array("a"), - str2: str[2] = __to_str_array("aa"), - str3: str[3] = __to_str_array("aaa"), - str4: str[4] = __to_str_array("aaaa"), - str5: str[5] = S5, - str6: str[6] = __to_str_array("aaaaaa"), - str7: str[7] = __to_str_array("aaaaaaa"), - str8: str[8] = __to_str_array("aaaaaaaa"), - str9: str[9] = __to_str_array("aaaaaaaaa"), - str10: str[10] = __to_str_array("aaaaaaaaaa"), - - const_u256: u256 = 0x0000000000000000000000000000000000000000000000000000000001234567u256, - const_b256: b256 = 0x0000000000000000000000000000000000000000000000000000000001234567, + my_storage_namespace { + c1: u64 = C1, + str0: str[0] = __to_str_array(""), + str1: str[1] = __to_str_array("a"), + str2: str[2] = __to_str_array("aa"), + str3: str[3] = __to_str_array("aaa"), + str4: str[4] = __to_str_array("aaaa"), + str5: str[5] = S5, + str6: str[6] = __to_str_array("aaaaaa"), + str7: str[7] = __to_str_array("aaaaaaa"), + str8: str[8] = __to_str_array("aaaaaaaa"), + str9: str[9] = __to_str_array("aaaaaaaaa"), + str10: str[10] = __to_str_array("aaaaaaaaaa"), + + const_u256: u256 = 0x0000000000000000000000000000000000000000000000000000000001234567u256, + const_b256: b256 = 0x0000000000000000000000000000000000000000000000000000000001234567, + } } impl BasicStorage for Contract { @@ -261,30 +262,30 @@ fn test_storage() { _ => assert(false), } - assert(storage.str0.try_read().is_none()); - - assert_streq(storage.str1.read(), "a"); - assert_streq(storage.str2.read(), "aa"); - assert_streq(storage.str3.read(), "aaa"); - assert_streq(storage.str4.read(), "aaaa"); - assert_streq(storage.str5.read(), "aaaaa"); - assert_streq(storage.str6.read(), "aaaaaa"); - assert_streq(storage.str7.read(), "aaaaaaa"); - assert_streq(storage.str8.read(), "aaaaaaaa"); - assert_streq(storage.str9.read(), "aaaaaaaaa"); - assert_streq(storage.str10.read(), "aaaaaaaaaa"); - - assert_eq(storage.c1.read(), C1); - storage.c1.write(2); - assert_eq(storage.c1.read(), 2); + assert(storage::my_storage_namespace.str0.try_read().is_none()); + + assert_streq(storage::my_storage_namespace.str1.read(), "a"); + assert_streq(storage::my_storage_namespace.str2.read(), "aa"); + assert_streq(storage::my_storage_namespace.str3.read(), "aaa"); + assert_streq(storage::my_storage_namespace.str4.read(), "aaaa"); + assert_streq(storage::my_storage_namespace.str5.read(), "aaaaa"); + assert_streq(storage::my_storage_namespace.str6.read(), "aaaaaa"); + assert_streq(storage::my_storage_namespace.str7.read(), "aaaaaaa"); + assert_streq(storage::my_storage_namespace.str8.read(), "aaaaaaaa"); + assert_streq(storage::my_storage_namespace.str9.read(), "aaaaaaaaa"); + assert_streq(storage::my_storage_namespace.str10.read(), "aaaaaaaaaa"); + + assert_eq(storage::my_storage_namespace.c1.read(), C1); + storage::my_storage_namespace.c1.write(2); + assert_eq(storage::my_storage_namespace.c1.read(), 2); - assert_eq(storage.const_u256.read(), 0x0000000000000000000000000000000000000000000000000000000001234567u256); - storage.const_u256.write(0x0000000000000000000000000000000000000000000000000000000012345678u256); - assert_eq(storage.const_u256.read(), 0x0000000000000000000000000000000000000000000000000000000012345678u256); + assert_eq(storage::my_storage_namespace.const_u256.read(), 0x0000000000000000000000000000000000000000000000000000000001234567u256); + storage::my_storage_namespace.const_u256.write(0x0000000000000000000000000000000000000000000000000000000012345678u256); + assert_eq(storage::my_storage_namespace.const_u256.read(), 0x0000000000000000000000000000000000000000000000000000000012345678u256); - assert_eq(storage.const_b256.read(), 0x0000000000000000000000000000000000000000000000000000000001234567); - storage.const_b256.write(0x0000000000000000000000000000000000000000000000000000000012345678); - assert_eq(storage.const_b256.read(), 0x0000000000000000000000000000000000000000000000000000000012345678); + assert_eq(storage::my_storage_namespace.const_b256.read(), 0x0000000000000000000000000000000000000000000000000000000001234567); + storage::my_storage_namespace.const_b256.write(0x0000000000000000000000000000000000000000000000000000000012345678); + assert_eq(storage::my_storage_namespace.const_b256.read(), 0x0000000000000000000000000000000000000000000000000000000012345678); } // If these comparisons are done inline just above then it blows out the register allocator due to From 21871c1666dbcb59a916e514cc149313cc914bd7 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 3 Jun 2024 17:34:22 +0100 Subject: [PATCH 09/14] Fixes cargo clippy warnings. --- sway-core/src/ir_generation/function.rs | 1 + .../src/language/ty/declaration/storage.rs | 3 +- .../ast_node/declaration/declaration.rs | 4 +- .../ast_node/declaration/storage.rs | 8 ++-- .../namespace/lexical_scope.rs | 1 + .../semantic_analysis/node_dependencies.rs | 2 +- .../to_parsed_lang/convert_parse_tree.rs | 43 ++++++++++--------- 7 files changed, 33 insertions(+), 29 deletions(-) diff --git a/sway-core/src/ir_generation/function.rs b/sway-core/src/ir_generation/function.rs index d64fe8d1953..e2e9439ec69 100644 --- a/sway-core/src/ir_generation/function.rs +++ b/sway-core/src/ir_generation/function.rs @@ -3875,6 +3875,7 @@ impl<'eng> FnCompiler<'eng> { Ok(TerminatorValue::new(val, context)) } + #[allow(clippy::too_many_arguments)] fn compile_storage_read( &mut self, context: &mut Context, diff --git a/sway-core/src/language/ty/declaration/storage.rs b/sway-core/src/language/ty/declaration/storage.rs index 2931f3ce8ac..cb1e9c6b648 100644 --- a/sway-core/src/language/ty/declaration/storage.rs +++ b/sway-core/src/language/ty/declaration/storage.rs @@ -65,6 +65,7 @@ impl TyStorageDecl { /// /// An error is returned if the above constraints are violated or if the access to the struct fields /// fails. E.g, if the struct field does not exists or is an inaccessible private field. + #[allow(clippy::too_many_arguments)] pub fn apply_storage_load( &self, handler: &Handler, @@ -213,7 +214,7 @@ impl TyStorageDecl { Ok(( TyStorageAccess { fields: access_descriptors, - key_expression: initial_field_key.clone().map(|v| Box::new(v)), + key_expression: initial_field_key.clone().map(Box::new), storage_field_names: namespace_names .iter() .map(|n| n.as_str().to_string()) diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index f46b4082424..d41003def48 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -443,7 +443,7 @@ impl TyDecl { handler: &Handler, mut ctx: TypeCheckContext, entries: Vec, - mut fields_buf: &mut Vec, + fields_buf: &mut Vec, namespace_names: Vec, ) -> Result<(), ErrorEmitted> { let engines = ctx.engines; @@ -508,7 +508,7 @@ impl TyDecl { .iter() .map(|e| (**e).clone()) .collect::>(), - &mut fields_buf, + fields_buf, new_namespace_names, )?; } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs index 6700a6dfc42..65a1af084f9 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/storage.rs @@ -91,16 +91,16 @@ impl ty::TyStorageField { module, None, None, - &key_expression, + key_expression, true, )?; if let ConstantValue::B256(key) = const_key.value { - return Ok(Some(key)); + Ok(Some(key)) } else { - return Err(CompileError::Internal( + Err(CompileError::Internal( "Expected B256 key", key_expression.span.clone(), - )); + )) } } else { Ok(None) diff --git a/sway-core/src/semantic_analysis/namespace/lexical_scope.rs b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs index e404e12a615..ea7b64602b3 100644 --- a/sway-core/src/semantic_analysis/namespace/lexical_scope.rs +++ b/sway-core/src/semantic_analysis/namespace/lexical_scope.rs @@ -94,6 +94,7 @@ impl Items { &self.symbols } + #[allow(clippy::too_many_arguments)] pub fn apply_storage_load( &self, handler: &Handler, diff --git a/sway-core/src/semantic_analysis/node_dependencies.rs b/sway-core/src/semantic_analysis/node_dependencies.rs index 41080d95912..9d74811182f 100644 --- a/sway-core/src/semantic_analysis/node_dependencies.rs +++ b/sway-core/src/semantic_analysis/node_dependencies.rs @@ -471,7 +471,7 @@ impl Dependencies { match entry { StorageEntry::Namespace(namespace) => self .gather_from_iter(namespace.entries.iter(), |deps, entry| { - deps.gather_from_storage_entry(engines, &*entry) + deps.gather_from_storage_entry(engines, entry) }), StorageEntry::Field(field) => { self.gather_from_type_argument(engines, &field.type_argument) diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 6467fb65024..4bb2d1fc74c 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -1023,10 +1023,7 @@ fn item_storage_to_storage_declaration( .filter_map_ok(|entry| entry) .collect::>()?; - fn check_duplicate_names( - entries: Vec, - mut errors: &mut Vec, - ) { + fn check_duplicate_names(entries: Vec, errors: &mut Vec) { // Make sure each storage field is declared once let mut names_of_fields = std::collections::HashSet::new(); for v in entries { @@ -1043,7 +1040,7 @@ fn item_storage_to_storage_declaration( .iter() .map(|e| (**e).clone()) .collect::>(), - &mut errors, + errors, ); } } @@ -2509,22 +2506,26 @@ fn storage_entry_to_storage_entry( } else { let mut entries = vec![]; let namespace = storage_entry.namespace.unwrap(); - for entry in namespace.into_inner().into_iter().map(|storage_entry| { - let attributes = item_attrs_to_map(context, handler, &storage_entry.attribute_list)?; - if !cfg_eval(context, handler, &attributes, context.experimental)? { - return Ok::, ErrorEmitted>(None); - } - Ok(Some(storage_entry_to_storage_entry( - context, - handler, - engines, - *storage_entry.value, - attributes, - )?)) - }) { - if let Ok(Some(entry)) = entry { - entries.push(Box::new(entry)); - } + for entry in namespace + .into_inner() + .into_iter() + .flat_map(|storage_entry| { + let attributes = + item_attrs_to_map(context, handler, &storage_entry.attribute_list)?; + if !cfg_eval(context, handler, &attributes, context.experimental)? { + return Ok::, ErrorEmitted>(None); + } + Ok(Some(storage_entry_to_storage_entry( + context, + handler, + engines, + *storage_entry.value, + attributes, + )?)) + }) + .flatten() + { + entries.push(Box::new(entry)); } Ok(StorageEntry::Namespace(StorageNamespace { name: storage_entry.name, From 3c6758e2cbbd054ab1c5f44aeb6de6857db01ad9 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Tue, 4 Jun 2024 18:27:59 +0100 Subject: [PATCH 10/14] Throws warning when deprecated namespace attribute is used. --- .../transform/to_parsed_lang/convert_parse_tree.rs | 13 ++++++++++--- sway-error/src/warning.rs | 8 ++++++++ sway-types/src/constants.rs | 1 - .../language/deprecated_attribute/Forc.lock | 8 ++++++++ .../language/deprecated_attribute/Forc.toml | 9 +++++++++ .../language/deprecated_attribute/src/main.sw | 7 +++++++ .../language/deprecated_attribute/test.toml | 12 ++++++++++++ 7 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/test.toml diff --git a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs index 4bb2d1fc74c..46049cdef2d 100644 --- a/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs +++ b/sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs @@ -34,9 +34,9 @@ use sway_types::{ ALLOW_ATTRIBUTE_NAME, CFG_ATTRIBUTE_NAME, CFG_EXPERIMENTAL_NEW_ENCODING, CFG_PROGRAM_TYPE_ARG_NAME, CFG_TARGET_ARG_NAME, DEPRECATED_ATTRIBUTE_NAME, DOC_ATTRIBUTE_NAME, DOC_COMMENT_ATTRIBUTE_NAME, FALLBACK_ATTRIBUTE_NAME, - INLINE_ATTRIBUTE_NAME, PAYABLE_ATTRIBUTE_NAME, STORAGE_PURITY_ATTRIBUTE_NAME, - STORAGE_PURITY_READ_NAME, STORAGE_PURITY_WRITE_NAME, TEST_ATTRIBUTE_NAME, - VALID_ATTRIBUTE_NAMES, + INLINE_ATTRIBUTE_NAME, NAMESPACE_ATTRIBUTE_NAME, PAYABLE_ATTRIBUTE_NAME, + STORAGE_PURITY_ATTRIBUTE_NAME, STORAGE_PURITY_READ_NAME, STORAGE_PURITY_WRITE_NAME, + TEST_ATTRIBUTE_NAME, VALID_ATTRIBUTE_NAMES, }, integer_bits::IntegerBits, }; @@ -4674,6 +4674,13 @@ fn item_attrs_to_map( let attrs = attr_decl.attribute.get().into_iter(); for attr in attrs { let name = attr.name.as_str(); + if name == NAMESPACE_ATTRIBUTE_NAME { + handler.emit_warn(CompileWarning { + span: attr_decl.span().clone(), + warning_content: Warning::NamespaceAttributeDeprecated, + }); + continue; + } if !VALID_ATTRIBUTE_NAMES.contains(&name) { handler.emit_warn(CompileWarning { span: attr_decl.span().clone(), diff --git a/sway-error/src/warning.rs b/sway-error/src/warning.rs index e06825c6411..f5dfbc115cb 100644 --- a/sway-error/src/warning.rs +++ b/sway-error/src/warning.rs @@ -101,6 +101,7 @@ pub enum Warning { UnrecognizedAttribute { attrib_name: Ident, }, + NamespaceAttributeDeprecated, AttributeExpectedNumberOfArguments { attrib_name: Ident, received_args: usize, @@ -239,6 +240,13 @@ impl fmt::Display for Warning { ), MatchExpressionUnreachableArm { .. } => write!(f, "This match arm is unreachable."), UnrecognizedAttribute {attrib_name} => write!(f, "Unknown attribute: \"{attrib_name}\"."), + NamespaceAttributeDeprecated => write!(f, "Attribute namespace is deprecated.\n\ + You can use namespaces inside storage:\n\ + storage {{\n\ + \tmy_storage_namespace {{\n\ + \t\tfield: u64 = 1, \n\ + \t}}\n\ + }}"), AttributeExpectedNumberOfArguments {attrib_name, received_args, expected_min_len, expected_max_len } => write!( f, "Attribute: \"{attrib_name}\" expected {} argument(s) received {received_args}.", diff --git a/sway-types/src/constants.rs b/sway-types/src/constants.rs index a53c772f393..5cbbabe1d97 100644 --- a/sway-types/src/constants.rs +++ b/sway-types/src/constants.rs @@ -68,7 +68,6 @@ pub const VALID_ATTRIBUTE_NAMES: &[&str] = &[ ALLOW_ATTRIBUTE_NAME, CFG_ATTRIBUTE_NAME, DEPRECATED_ATTRIBUTE_NAME, - NAMESPACE_ATTRIBUTE_NAME, FALLBACK_ATTRIBUTE_NAME, ]; diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.lock new file mode 100644 index 00000000000..1e81cf8a690 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.lock @@ -0,0 +1,8 @@ +[[package]] +name = "core" +source = "path+from-root-F66B05B51B812E20" + +[[package]] +name = "deprecated_attribute" +source = "member" +dependencies = ["core"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.toml new file mode 100644 index 00000000000..69bfc30b4af --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/Forc.toml @@ -0,0 +1,9 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "deprecated_attribute" +implicit-std = false + +[dependencies] +core = { path = "../../../../../../../sway-lib-core" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/src/main.sw new file mode 100644 index 00000000000..73a67d733cd --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/src/main.sw @@ -0,0 +1,7 @@ +contract; + +#[namespace(my_namespace)] +storage { + v:u64 = 1, +} + diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/test.toml new file mode 100644 index 00000000000..95ae0a24996 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/deprecated_attribute/test.toml @@ -0,0 +1,12 @@ +category = "compile" + +# check: $()#[namespace(my_namespace)] +# nextln: $()Attribute namespace is deprecated. +# nextln: $()You can use namespaces inside storage: +# nextln: $()storage { +# nextln: $()my_storage_namespace { +# nextln: $()field: u64 = 1, +# nextln: $()} +# nextln: $()} + +expected_warnings = 2 From 529445ec5fd7a7e48957d5ca9fca585b140ce753 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 5 Jun 2024 16:29:36 +0100 Subject: [PATCH 11/14] Updates swayfmt to handle storage namespaces. --- sway-types/src/span.rs | 6 + swayfmt/src/items/item_storage/mod.rs | 164 +++++++++++++++++------ swayfmt/src/utils/language/expr/mod.rs | 7 - swayfmt/src/utils/language/punctuated.rs | 43 +++++- swayfmt/src/utils/language/ty.rs | 4 +- swayfmt/tests/mod.rs | 8 ++ 6 files changed, 177 insertions(+), 55 deletions(-) diff --git a/sway-types/src/span.rs b/sway-types/src/span.rs index bf7eb181400..c757fb523da 100644 --- a/sway-types/src/span.rs +++ b/sway-types/src/span.rs @@ -239,6 +239,12 @@ pub trait Spanned { fn span(&self) -> Span; } +impl Spanned for Box { + fn span(&self) -> Span { + (**self).span() + } +} + #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct LineCol { pub line: usize, diff --git a/swayfmt/src/items/item_storage/mod.rs b/swayfmt/src/items/item_storage/mod.rs index ffbdeca3559..0d159711ede 100644 --- a/swayfmt/src/items/item_storage/mod.rs +++ b/swayfmt/src/items/item_storage/mod.rs @@ -10,9 +10,10 @@ use crate::{ CurlyBrace, }, }; -use std::fmt::Write; -use sway_ast::{keywords::Token, ItemStorage, StorageField}; -use sway_types::{ast::Delimiter, Spanned}; +use std::{collections::HashMap, fmt::Write}; +use sway_ast::{keywords::Token, ItemStorage, StorageEntry, StorageField}; +use sway_core::namespace; +use sway_types::{ast::Delimiter, IdentUnique, Spanned}; #[cfg(test)] mod tests; @@ -33,7 +34,7 @@ impl Format for ItemStorage { // Add storage token write!(formatted_code, "{}", self.storage_token.span().as_str())?; - let fields = self.fields.get(); + let entries = self.entries.get(); // Handle opening brace Self::open_curly_brace(formatted_code, formatter)?; @@ -44,7 +45,7 @@ impl Format for ItemStorage { match formatter.config.structures.field_alignment { FieldAlignment::AlignFields(storage_field_align_threshold) => { writeln!(formatted_code)?; - let value_pairs = &fields + let value_pairs = &entries .value_separator_pairs .iter() // TODO: Handle annotations instead of stripping them @@ -52,16 +53,40 @@ impl Format for ItemStorage { .collect::>(); // In first iteration we are going to be collecting the lengths of the // struct fields. - let field_length: Vec = value_pairs - .iter() - .map(|(storage_field, _)| storage_field.name.as_str().len()) - .collect(); + let mut field_lengths: HashMap = + HashMap::::new(); + fn collect_field_lengths( + entry: &StorageEntry, + ident_size: usize, + current_ident: usize, + field_lenghts: &mut HashMap, + ) { + if let Some(namespace) = &entry.namespace { + namespace.clone().into_inner().into_iter().for_each(|e| { + collect_field_lengths( + &e.value, + ident_size, + current_ident + ident_size, + field_lenghts, + ) + }); + } else if let Some(storage_field) = &entry.field { + field_lenghts.insert( + storage_field.name.clone().into(), + current_ident + storage_field.name.as_str().len(), + ); + } + } + let ident_size = formatter.config.whitespace.tab_spaces; + value_pairs.iter().for_each(|(storage_entry, _)| { + collect_field_lengths(storage_entry, ident_size, 0, &mut field_lengths) + }); // Find the maximum length in the `field_length` vector that is still // smaller than `storage_field_align_threshold`. `max_valid_field_length`: // the length of the field that we are taking as a reference to align. let mut max_valid_field_length = 0; - field_length.iter().for_each(|length| { + field_lengths.iter().for_each(|(_, length)| { if *length > max_valid_field_length && *length < storage_field_align_threshold { @@ -69,47 +94,84 @@ impl Format for ItemStorage { } }); - let value_pairs_iter = value_pairs.iter().enumerate(); - for (field_index, (storage_field, comma_token)) in value_pairs_iter.clone() - { - write!(formatted_code, "{}", formatter.indent_to_str()?)?; - // Add name - storage_field.name.format(formatted_code, formatter)?; - - // `current_field_length`: the length of the current field that we are - // trying to format. - let current_field_length = field_length[field_index]; - if current_field_length < max_valid_field_length { - // We need to add alignment between `:` and `ty` - let mut required_alignment = - max_valid_field_length - current_field_length; - while required_alignment != 0 { - write!(formatted_code, " ")?; - required_alignment -= 1; + fn format_entry( + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + entry: &StorageEntry, + field_lenghts: &HashMap, + max_valid_field_length: usize, + ) -> Result<(), FormatterError> { + if let Some(namespace) = &entry.namespace { + entry.name.format(formatted_code, formatter)?; + ItemStorage::open_curly_brace(formatted_code, formatter)?; + + formatter.shape.code_line.update_expr_new_line(true); + + namespace.clone().into_inner().into_iter().for_each(|e| { + format_entry( + formatted_code, + formatter, + &e.value, + field_lenghts, + max_valid_field_length, + ); + }); + + ItemStorage::close_curly_brace(formatted_code, formatter)?; + } else if let Some(storage_field) = &entry.field { + // Add name + storage_field.name.format(formatted_code, formatter)?; + + // `current_field_length`: the length of the current field that we are + // trying to format. + let current_field_length = field_lenghts + .get(&storage_field.name.clone().into()) + .unwrap() + .clone(); + if current_field_length < max_valid_field_length { + // We need to add alignment between `:` and `ty` + let mut required_alignment = + max_valid_field_length - current_field_length; + while required_alignment != 0 { + write!(formatted_code, " ")?; + required_alignment -= 1; + } } + // Add `:`, `ty` & `CommaToken` + write!( + formatted_code, + " {} ", + storage_field.colon_token.ident().as_str(), + )?; + storage_field.ty.format(formatted_code, formatter)?; + write!( + formatted_code, + " {} ", + storage_field.eq_token.ident().as_str() + )?; + storage_field + .initializer + .format(formatted_code, formatter)?; } - // Add `:`, `ty` & `CommaToken` - write!( - formatted_code, - " {} ", - storage_field.colon_token.ident().as_str(), - )?; - storage_field.ty.format(formatted_code, formatter)?; - write!( + + Ok(()) + } + for (storage_entry, comma_token) in value_pairs.iter().clone() { + write!(formatted_code, "{}", formatter.indent_to_str()?)?; + format_entry( formatted_code, - " {} ", - storage_field.eq_token.ident().as_str() - )?; - storage_field - .initializer - .format(formatted_code, formatter)?; + formatter, + &storage_entry, + &field_lengths, + max_valid_field_length, + ); writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } - if let Some(final_value) = &fields.final_value_opt { + if let Some(final_value) = &entries.final_value_opt { final_value.format(formatted_code, formatter)?; } } - FieldAlignment::Off => fields.format(formatted_code, formatter)?, + FieldAlignment::Off => entries.format(formatted_code, formatter)?, } // Handle closing brace @@ -164,11 +226,25 @@ impl CurlyBrace for ItemStorage { impl LeafSpans for ItemStorage { fn leaf_spans(&self) -> Vec { let mut collected_spans = vec![ByteSpan::from(self.storage_token.span())]; - collected_spans.append(&mut self.fields.leaf_spans()); + collected_spans.append(&mut self.entries.leaf_spans()); collected_spans } } +impl LeafSpans for StorageEntry { + fn leaf_spans(&self) -> Vec { + if let Some(namespace) = &self.namespace { + let mut collected_spans = vec![ByteSpan::from(self.name.span())]; + collected_spans.append(&mut namespace.leaf_spans()); + collected_spans + } else if let Some(field) = &self.field { + field.leaf_spans() + } else { + vec![] + } + } +} + impl LeafSpans for StorageField { fn leaf_spans(&self) -> Vec { let mut collected_spans = vec![ByteSpan::from(self.name.span())]; diff --git a/swayfmt/src/utils/language/expr/mod.rs b/swayfmt/src/utils/language/expr/mod.rs index 03af3cabfb4..a65eb3bc527 100644 --- a/swayfmt/src/utils/language/expr/mod.rs +++ b/swayfmt/src/utils/language/expr/mod.rs @@ -977,13 +977,6 @@ fn get_field_width( // Leaf Spans -// TODO: Find a better way of handling Boxed version -impl LeafSpans for Box { - fn leaf_spans(&self) -> Vec { - expr_leaf_spans(self) - } -} - impl LeafSpans for Expr { fn leaf_spans(&self) -> Vec { expr_leaf_spans(self) diff --git a/swayfmt/src/utils/language/punctuated.rs b/swayfmt/src/utils/language/punctuated.rs index 0c42d346da3..5fa43157a99 100644 --- a/swayfmt/src/utils/language/punctuated.rs +++ b/swayfmt/src/utils/language/punctuated.rs @@ -1,11 +1,15 @@ use crate::{ constants::RAW_MODIFIER, formatter::{shape::LineStyle, *}, - utils::map::byte_span::{ByteSpan, LeafSpans}, + utils::{ + map::byte_span::{ByteSpan, LeafSpans}, + CurlyBrace, + }, }; use std::fmt::Write; use sway_ast::{ - keywords::CommaToken, punctuated::Punctuated, ConfigurableField, StorageField, TypeField, + keywords::CommaToken, punctuated::Punctuated, ConfigurableField, ItemStorage, StorageEntry, + StorageField, TypeField, }; use sway_types::{ast::PunctKind, Ident, Spanned}; @@ -271,6 +275,41 @@ impl Format for StorageField { } } +impl Format for StorageEntry { + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + if let Some(field) = &self.field { + field.format(formatted_code, formatter); + } else if let Some(namespace) = &self.namespace { + self.name.format(formatted_code, formatter)?; + ItemStorage::open_curly_brace(formatted_code, formatter)?; + formatter.shape.code_line.update_expr_new_line(true); + namespace + .clone() + .into_inner() + .format(formatted_code, formatter)?; + ItemStorage::close_curly_brace(formatted_code, formatter)?; + } + + Ok(()) + } +} + +impl Format for Box { + fn format( + &self, + formatted_code: &mut FormattedCode, + formatter: &mut Formatter, + ) -> Result<(), FormatterError> { + (**self).format(formatted_code, formatter); + + Ok(()) + } +} + impl Format for CommaToken { fn format( &self, diff --git a/swayfmt/src/utils/language/ty.rs b/swayfmt/src/utils/language/ty.rs index e8f7f8584d9..1d764e83bd7 100644 --- a/swayfmt/src/utils/language/ty.rs +++ b/swayfmt/src/utils/language/ty.rs @@ -177,9 +177,9 @@ impl Format for TyTupleDescriptor { } } -impl LeafSpans for Box { +impl LeafSpans for Box { fn leaf_spans(&self) -> Vec { - self.as_ref().leaf_spans() + (**self).leaf_spans() } } diff --git a/swayfmt/tests/mod.rs b/swayfmt/tests/mod.rs index b71f2f148c4..2802538ec71 100644 --- a/swayfmt/tests/mod.rs +++ b/swayfmt/tests/mod.rs @@ -296,6 +296,7 @@ fn storage_without_alignment() { storage { var1: Type1=Type1{ foo: 8 }, var2: Type2=Type2{ bar: 9 }, + ns1 { var3: u64 = 1 }, } "#, r#"contract; @@ -311,6 +312,9 @@ struct Type2 { storage { var1: Type1 = Type1 { foo: 8 }, var2: Type2 = Type2 { bar: 9 }, + ns1 { + var3: u64 = 1, + } } "#, ); @@ -333,6 +337,7 @@ struct Type2 { storage { long_var_name: Type1=Type1{ foo: 8 }, var2: Type2=Type2{ bar: 9 }, + ns1 { var3: u64 = 1 }, } "#, r#"contract; @@ -348,6 +353,9 @@ struct Type2 { storage { long_var_name : Type1 = Type1 { foo: 8 }, var2 : Type2 = Type2 { bar: 9 }, + ns1 { + var3 : u64 = 1, + }, } "#, &mut formatter, From 4893a5919173e44c5afe4534429749d176dbe0af Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 5 Jun 2024 19:48:28 +0100 Subject: [PATCH 12/14] Fixes typos and adds missing trait impls. --- .../language/parsed/declaration/storage.rs | 20 ++++++++++++++++++- .../ast_node/declaration/declaration.rs | 1 - sway-parse/src/item/item_storage.rs | 2 +- swayfmt/src/items/item_storage/mod.rs | 12 +++++------ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/sway-core/src/language/parsed/declaration/storage.rs b/sway-core/src/language/parsed/declaration/storage.rs index 8af16aa818a..a7e3b663525 100644 --- a/sway-core/src/language/parsed/declaration/storage.rs +++ b/sway-core/src/language/parsed/declaration/storage.rs @@ -20,7 +20,7 @@ impl EqWithEngines for StorageDeclaration {} impl PartialEqWithEngines for StorageDeclaration { fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { self.attributes == other.attributes - && self.fields.eq(&other.fields, ctx) + && self.entries.eq(&other.entries, ctx) && self.span == other.span && self.storage_keyword == other.storage_keyword } @@ -38,6 +38,13 @@ pub struct StorageNamespace { pub entries: Vec>, } +impl EqWithEngines for StorageNamespace {} +impl PartialEqWithEngines for StorageNamespace { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + self.name.eq(&other.name) && self.entries.eq(&other.entries, ctx) + } +} + #[derive(Debug, Clone)] pub enum StorageEntry { Namespace(StorageNamespace), @@ -53,6 +60,17 @@ impl StorageEntry { } } +impl EqWithEngines for StorageEntry {} +impl PartialEqWithEngines for StorageEntry { + fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool { + match (self, other) { + (StorageEntry::Namespace(n1), StorageEntry::Namespace(n2)) => n1.eq(n2, ctx), + (StorageEntry::Field(f1), StorageEntry::Field(f2)) => f1.eq(f2, ctx), + _ => false, + } + } +} + /// An individual field in a storage declaration. /// A type annotation _and_ initializer value must be provided. The initializer value must be a /// constant expression. For now, that basically means just a literal, but as constant folding diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index d41003def48..d241cabae3e 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -1,4 +1,3 @@ -use fuel_vm::fuel_tx::field; use sway_error::handler::{ErrorEmitted, Handler}; use sway_types::{BaseIdent, Ident, Named, Spanned}; diff --git a/sway-parse/src/item/item_storage.rs b/sway-parse/src/item/item_storage.rs index 685f636a97b..03640e2fd68 100644 --- a/sway-parse/src/item/item_storage.rs +++ b/sway-parse/src/item/item_storage.rs @@ -30,7 +30,7 @@ impl Parse for StorageEntry { impl Parse for StorageField { fn parse(parser: &mut Parser) -> ParseResult { - let name = BaseIdent::dummy(); // Name will be overrided in StorageEntry parse. + let name = BaseIdent::dummy(); // Name will be overridden in StorageEntry parse. let in_token: Option = parser.take(); let mut key_opt: Option = None; if in_token.is_some() { diff --git a/swayfmt/src/items/item_storage/mod.rs b/swayfmt/src/items/item_storage/mod.rs index 0d159711ede..f3785ca4f5c 100644 --- a/swayfmt/src/items/item_storage/mod.rs +++ b/swayfmt/src/items/item_storage/mod.rs @@ -59,7 +59,7 @@ impl Format for ItemStorage { entry: &StorageEntry, ident_size: usize, current_ident: usize, - field_lenghts: &mut HashMap, + field_lengths: &mut HashMap, ) { if let Some(namespace) = &entry.namespace { namespace.clone().into_inner().into_iter().for_each(|e| { @@ -67,11 +67,11 @@ impl Format for ItemStorage { &e.value, ident_size, current_ident + ident_size, - field_lenghts, + field_lengths, ) }); } else if let Some(storage_field) = &entry.field { - field_lenghts.insert( + field_lengths.insert( storage_field.name.clone().into(), current_ident + storage_field.name.as_str().len(), ); @@ -98,7 +98,7 @@ impl Format for ItemStorage { formatted_code: &mut FormattedCode, formatter: &mut Formatter, entry: &StorageEntry, - field_lenghts: &HashMap, + field_lengths: &HashMap, max_valid_field_length: usize, ) -> Result<(), FormatterError> { if let Some(namespace) = &entry.namespace { @@ -112,7 +112,7 @@ impl Format for ItemStorage { formatted_code, formatter, &e.value, - field_lenghts, + field_lengths, max_valid_field_length, ); }); @@ -124,7 +124,7 @@ impl Format for ItemStorage { // `current_field_length`: the length of the current field that we are // trying to format. - let current_field_length = field_lenghts + let current_field_length = field_lengths .get(&storage_field.name.clone().into()) .unwrap() .clone(); From 12965a528db7fc10adca09b5ebf40a62f7e69861 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Wed, 5 Jun 2024 20:06:16 +0100 Subject: [PATCH 13/14] Fixes cargo clippy. --- swayfmt/src/items/item_storage/mod.rs | 16 +++++++--------- swayfmt/src/utils/language/punctuated.rs | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/swayfmt/src/items/item_storage/mod.rs b/swayfmt/src/items/item_storage/mod.rs index f3785ca4f5c..a99413fbfb6 100644 --- a/swayfmt/src/items/item_storage/mod.rs +++ b/swayfmt/src/items/item_storage/mod.rs @@ -12,7 +12,6 @@ use crate::{ }; use std::{collections::HashMap, fmt::Write}; use sway_ast::{keywords::Token, ItemStorage, StorageEntry, StorageField}; -use sway_core::namespace; use sway_types::{ast::Delimiter, IdentUnique, Spanned}; #[cfg(test)] @@ -107,15 +106,15 @@ impl Format for ItemStorage { formatter.shape.code_line.update_expr_new_line(true); - namespace.clone().into_inner().into_iter().for_each(|e| { + for e in namespace.clone().into_inner().into_iter() { format_entry( formatted_code, formatter, &e.value, field_lengths, max_valid_field_length, - ); - }); + )?; + } ItemStorage::close_curly_brace(formatted_code, formatter)?; } else if let Some(storage_field) = &entry.field { @@ -126,9 +125,8 @@ impl Format for ItemStorage { // trying to format. let current_field_length = field_lengths .get(&storage_field.name.clone().into()) - .unwrap() - .clone(); - if current_field_length < max_valid_field_length { + .unwrap(); + if *current_field_length < max_valid_field_length { // We need to add alignment between `:` and `ty` let mut required_alignment = max_valid_field_length - current_field_length; @@ -161,10 +159,10 @@ impl Format for ItemStorage { format_entry( formatted_code, formatter, - &storage_entry, + storage_entry, &field_lengths, max_valid_field_length, - ); + )?; writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } if let Some(final_value) = &entries.final_value_opt { diff --git a/swayfmt/src/utils/language/punctuated.rs b/swayfmt/src/utils/language/punctuated.rs index 5fa43157a99..0d6e7ce2cfc 100644 --- a/swayfmt/src/utils/language/punctuated.rs +++ b/swayfmt/src/utils/language/punctuated.rs @@ -282,7 +282,7 @@ impl Format for StorageEntry { formatter: &mut Formatter, ) -> Result<(), FormatterError> { if let Some(field) = &self.field { - field.format(formatted_code, formatter); + field.format(formatted_code, formatter)?; } else if let Some(namespace) = &self.namespace { self.name.format(formatted_code, formatter)?; ItemStorage::open_curly_brace(formatted_code, formatter)?; @@ -304,7 +304,7 @@ impl Format for Box { formatted_code: &mut FormattedCode, formatter: &mut Formatter, ) -> Result<(), FormatterError> { - (**self).format(formatted_code, formatter); + (**self).format(formatted_code, formatter)?; Ok(()) } From a449e6efe13e9d743cfb71b2ecd3dfd95b4e7f3e Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Thu, 6 Jun 2024 10:45:53 +0100 Subject: [PATCH 14/14] Adds handling of StorageEntry to the LSP. --- sway-lsp/src/core/token.rs | 5 ++-- sway-lsp/src/traverse/lexed_tree.rs | 22 +++++++++++++--- sway-lsp/src/traverse/parsed_tree.rs | 39 ++++++++++++++++++++++++---- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/sway-lsp/src/core/token.rs b/sway-lsp/src/core/token.rs index 1f4a72373ea..d869e87e0a4 100644 --- a/sway-lsp/src/core/token.rs +++ b/sway-lsp/src/core/token.rs @@ -8,8 +8,8 @@ use sway_core::{ AbiCastExpression, AmbiguousPathExpression, Declaration, DelineatedPathExpression, EnumVariant, Expression, FunctionApplicationExpression, FunctionParameter, IncludeStatement, MethodApplicationExpression, Scrutinee, StorageField, - StructExpression, StructExpressionField, StructField, StructScrutineeField, Supertrait, - TraitFn, UseStatement, + StorageNamespace, StructExpression, StructExpressionField, StructField, + StructScrutineeField, Supertrait, TraitFn, UseStatement, }, ty, }, @@ -44,6 +44,7 @@ pub enum AstToken { MethodApplicationExpression(MethodApplicationExpression), Scrutinee(Scrutinee), StorageField(StorageField), + StorageNamespace(StorageNamespace), StructExpression(StructExpression), StructExpressionField(StructExpressionField), StructField(StructField), diff --git a/sway-lsp/src/traverse/lexed_tree.rs b/sway-lsp/src/traverse/lexed_tree.rs index 9f0af530d56..f441321c500 100644 --- a/sway-lsp/src/traverse/lexed_tree.rs +++ b/sway-lsp/src/traverse/lexed_tree.rs @@ -9,7 +9,8 @@ use sway_ast::{ ExprTupleDescriptor, FnArg, FnArgs, FnSignature, IfCondition, IfExpr, ItemAbi, ItemConfigurable, ItemConst, ItemEnum, ItemFn, ItemImpl, ItemImplItem, ItemKind, ItemStorage, ItemStruct, ItemTrait, ItemTypeAlias, ItemUse, MatchBranchKind, ModuleKind, Pattern, - PatternStructField, Statement, StatementLet, StorageField, TraitType, Ty, TypeField, UseTree, + PatternStructField, Statement, StatementLet, StorageEntry, StorageField, TraitType, Ty, + TypeField, UseTree, }; use sway_core::language::{lexed::LexedProgram, HasSubmodules}; use sway_types::{Ident, Span, Spanned}; @@ -404,11 +405,26 @@ impl Parse for ItemStorage { fn parse(&self, ctx: &ParseContext) { insert_keyword(ctx, self.storage_token.span()); - self.fields + self.entries .get() .into_iter() .par_bridge() - .for_each(|field| field.value.parse(ctx)); + .for_each(|entry| entry.value.parse(ctx)); + } +} + +impl Parse for StorageEntry { + fn parse(&self, ctx: &ParseContext) { + if let Some(namespace) = &self.namespace { + namespace + .clone() + .into_inner() + .into_iter() + .par_bridge() + .for_each(|entry| entry.value.parse(ctx)); + } else if let Some(field) = &self.field { + field.parse(ctx); + } } } diff --git a/sway-lsp/src/traverse/parsed_tree.rs b/sway-lsp/src/traverse/parsed_tree.rs index 21cf83c954d..314b5210420 100644 --- a/sway-lsp/src/traverse/parsed_tree.rs +++ b/sway-lsp/src/traverse/parsed_tree.rs @@ -26,10 +26,10 @@ use sway_core::{ IncludeStatement, IntrinsicFunctionExpression, LazyOperatorExpression, MatchExpression, MethodApplicationExpression, MethodName, ParseModule, ParseProgram, ParseSubmodule, QualifiedPathType, ReassignmentExpression, ReassignmentTarget, RefExpression, - Scrutinee, StorageAccessExpression, StorageDeclaration, StorageField, - StructDeclaration, StructExpression, StructExpressionField, StructField, - StructScrutineeField, SubfieldExpression, Supertrait, TraitDeclaration, TraitFn, - TraitItem, TraitTypeDeclaration, TupleIndexExpression, TypeAliasDeclaration, + Scrutinee, StorageAccessExpression, StorageDeclaration, StorageEntry, StorageField, + StorageNamespace, StructDeclaration, StructExpression, StructExpressionField, + StructField, StructScrutineeField, SubfieldExpression, Supertrait, TraitDeclaration, + TraitFn, TraitItem, TraitTypeDeclaration, TupleIndexExpression, TypeAliasDeclaration, UseStatement, VariableDeclaration, WhileLoopExpression, }, CallPathTree, HasSubmodules, Literal, @@ -312,6 +312,7 @@ impl Parse for Expression { } ExpressionKind::StorageAccess(StorageAccessExpression { field_names, + namespace_names, storage_keyword_span, }) => { let storage_ident = Ident::new(storage_keyword_span.clone()); @@ -319,6 +320,15 @@ impl Parse for Expression { ctx.ident(&storage_ident), Token::from_parsed(AstToken::Ident(storage_ident), SymbolKind::Unknown), ); + adaptive_iter(namespace_names, |namespace_name| { + ctx.tokens.insert( + ctx.ident(namespace_name), + Token::from_parsed( + AstToken::Ident(namespace_name.clone()), + SymbolKind::Field, + ), + ); + }); adaptive_iter(field_names, |field_name| { ctx.tokens.insert( ctx.ident(field_name), @@ -885,11 +895,30 @@ impl Parse for ParsedDeclId { impl Parse for ParsedDeclId { fn parse(&self, ctx: &ParseContext) { let storage_decl = ctx.engines.pe().get_storage(self); - adaptive_iter(&storage_decl.fields, |field| field.parse(ctx)); + adaptive_iter(&storage_decl.entries, |entry| entry.parse(ctx)); storage_decl.attributes.parse(ctx); } } +impl Parse for StorageEntry { + fn parse(&self, ctx: &ParseContext) { + match self { + StorageEntry::Namespace(namespace) => namespace.parse(ctx), + StorageEntry::Field(field) => field.parse(ctx), + } + } +} + +impl Parse for StorageNamespace { + fn parse(&self, ctx: &ParseContext) { + ctx.tokens.insert( + ctx.ident(&self.name), + Token::from_parsed(AstToken::StorageNamespace(self.clone()), SymbolKind::Field), + ); + self.entries.iter().for_each(|entry| entry.parse(ctx)); + } +} + impl Parse for StorageField { fn parse(&self, ctx: &ParseContext) { ctx.tokens.insert(