diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d6ada1ab9..93de9ab2448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Implement `bn128` precompiles ‒ [2708](https://github.com/use-ink/ink/pull/2718) +- Add `packed` flag to `storage_item` attribute and improve related diagnostics - [](https://github.com/use-ink/ink/pull/2722) ### Changed - Refactor contract ref generation and add automatic re-exporting ‒ [#2710](https://github.com/use-ink/ink/pull/2710) diff --git a/crates/ink/codegen/src/generator/storage_item.rs b/crates/ink/codegen/src/generator/storage_item.rs index 701556a3c1f..5a07e1cd05d 100644 --- a/crates/ink/codegen/src/generator/storage_item.rs +++ b/crates/ink/codegen/src/generator/storage_item.rs @@ -53,9 +53,16 @@ impl GenerateCode for StorageItem<'_> { Data::Union(union_item) => self.generate_union(union_item), }; - let mut derive = quote! {}; - if self.item.config().derive() { - derive = quote! { + let config = self.item.config(); + let derive = if config.packed() { + quote! { + #[cfg_attr(feature = "std", derive( + ::ink::storage::traits::StorageLayout, + ))] + #[ink::scale_derive(Encode, Decode, TypeInfo)] + } + } else if config.derive() { + quote! { #[cfg_attr(feature = "std", derive( ::ink::storage::traits::StorageLayout, ))] @@ -65,10 +72,16 @@ impl GenerateCode for StorageItem<'_> { ::ink::storage::traits::StorageKey, ::ink::storage::traits::Storable, )] - }; - } + } + } else { + quote! {} + }; - let type_check = self.generate_type_check(); + let type_check = if self.item.config().packed() { + quote! {} + } else { + self.generate_type_check() + }; quote! { #type_check @@ -88,22 +101,32 @@ impl StorageItem<'_> { let generics = item.generics(); let salt = item.salt(); - let fields = struct_item.fields.iter().enumerate().map(|(i, field)| { - convert_into_storage_field(struct_ident, None, &salt, i, field) - }); + let fields = if self.item.config().packed() { + let fields = struct_item.fields.iter(); + quote! { + #(#fields),* + } + } else { + let fields = struct_item.fields.iter().enumerate().map(|(i, field)| { + convert_into_storage_field(struct_ident, None, &salt, i, field) + }); + quote! { + #(#fields),* + } + }; match struct_item.fields { Fields::Unnamed(_) => { quote! { #vis struct #struct_ident #generics ( - #(#fields),* + #fields ); } } _ => { quote! { #vis struct #struct_ident #generics { - #(#fields),* + #fields } } } @@ -126,11 +149,13 @@ impl StorageItem<'_> { quote! {} }; - let fields: Vec<_> = variant - .fields - .iter() - .enumerate() - .map(|(i, field)| { + let fields = if self.item.config().packed() { + let fields = variant.fields.iter(); + quote! { + #(#fields),* + } + } else { + let fields = variant.fields.iter().enumerate().map(|(i, field)| { convert_into_storage_field( enum_ident, Some(variant_ident), @@ -138,12 +163,15 @@ impl StorageItem<'_> { i, field, ) - }) - .collect(); + }); + quote! { + #(#fields),* + } + }; let fields = match variant.fields { - Fields::Named(_) => quote! { { #(#fields),* } }, - Fields::Unnamed(_) => quote! { ( #(#fields),* ) }, + Fields::Named(_) => quote! { { #fields } }, + Fields::Unnamed(_) => quote! { ( #fields ) }, Fields::Unit => quote! {}, }; @@ -167,18 +195,28 @@ impl StorageItem<'_> { let generics = item.generics(); let salt = item.salt(); - let fields = union_item - .fields - .named - .iter() - .enumerate() - .map(|(i, field)| { - convert_into_storage_field(union_ident, None, &salt, i, field) - }); + let fields = if self.item.config().packed() { + let fields = union_item.fields.named.iter(); + quote! { + #(#fields),* + } + } else { + let fields = union_item + .fields + .named + .iter() + .enumerate() + .map(|(i, field)| { + convert_into_storage_field(union_ident, None, &salt, i, field) + }); + quote! { + #(#fields),* + } + }; quote! { #vis union #union_ident #generics { - #(#fields),* + #fields } } } diff --git a/crates/ink/ir/src/ir/storage_item/config.rs b/crates/ink/ir/src/ir/storage_item/config.rs index a6aa26e2d19..c3825b50394 100644 --- a/crates/ink/ir/src/ir/storage_item/config.rs +++ b/crates/ink/ir/src/ir/storage_item/config.rs @@ -12,14 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +use syn::spanned::Spanned; + use crate::{ ast, utils::duplicate_config_err, }; -/// The ink! configuration. -#[derive(Debug, Default, PartialEq, Eq)] +/// The ink! storage item configuration. +#[derive(Debug, PartialEq, Eq)] pub struct StorageItemConfig { + /// If set to `true`, the derived storage item will use a "packed" layout. + /// If set to `false`, the derived storage item will use a "non-packed" layout, + /// this is the default value. + packed: bool, /// If set to `true`, all storage related traits are implemented automatically, /// this is the default value. /// If set to `false`, implementing all storage traits is disabled. In some cases @@ -27,13 +33,37 @@ pub struct StorageItemConfig { derive: bool, } +impl Default for StorageItemConfig { + fn default() -> Self { + Self { + packed: false, + derive: true, + } + } +} + impl TryFrom for StorageItemConfig { type Error = syn::Error; fn try_from(args: ast::AttributeArgs) -> Result { + let mut packed: Option = None; let mut derive: Option = None; - for arg in args.into_iter() { - if arg.name().is_ident("derive") { + let args_span = args.span(); + for arg in args { + if arg.name().is_ident("packed") { + if let Some(path) = packed { + return Err(duplicate_config_err(path, arg, "packed", "storage item")); + } + if let ast::Meta::Path(path) = arg { + packed = Some(path) + } else { + return Err(format_err_spanned!( + arg, + "encountered an unexpected value for `packed` ink! storage item configuration argument. \ + Did you mean `#[ink::storage_item(packed)]` ?", + )); + } + } else if arg.name().is_ident("derive") { if let Some(lit_bool) = derive { return Err(duplicate_config_err( lit_bool, @@ -58,15 +88,86 @@ impl TryFrom for StorageItemConfig { )); } } - Ok(StorageItemConfig { - derive: derive.map(|lit_bool| lit_bool.value).unwrap_or(true), - }) + + // Sanitize user-provided configuration. + let (packed, derive) = match (packed, derive.map(|lit_bool| lit_bool.value)) { + // `packed` (i.e. `packed=true`) and `derive=false` conflict. + // Note: There's really no reasonable use case for this combination. + (Some(_), Some(false)) => { + return Err(format_err!( + args_span, + "cannot use `derive = false` with `packed` flag", + )) + } + // Otherwise, accept the user provided configuration, + // while defaulting to "non-packed" layout (resolved as `packed=false`) and + // `derive=true`. + (packed, derive) => (packed.is_some(), derive.unwrap_or(true)), + }; + + Ok(StorageItemConfig { packed, derive }) } } impl StorageItemConfig { - /// Returns the derive configuration argument. + /// Returns the `packed` configuration argument. + pub fn packed(&self) -> bool { + self.packed + } + + /// Returns the `derive` configuration argument. pub fn derive(&self) -> bool { self.derive } } + +#[cfg(test)] +mod tests { + use super::*; + use quote::quote; + + #[test] + fn valid_args_works() { + for (config, packed, derive) in [ + // Defaults are "non-packed" layout (resolved as `packed=false`) with + // `derive=true`. + (quote!(), false, true), + // `packed` (resolved as `packed=true`) works only with `derive=true`. + (quote! { packed }, true, true), + (quote! { packed, derive = true }, true, true), + // "non-packed" layout (resolved as `packed=false`) works with any `derive` + // arg. + (quote! { derive = true }, false, true), + (quote! { derive = false }, false, false), + ] { + let parsed_config = syn::parse2::(config).unwrap(); + let result = StorageItemConfig::try_from(parsed_config); + assert!(result.is_ok()); + let storage_item_config = result.unwrap(); + assert_eq!(storage_item_config.packed(), packed); + assert_eq!(storage_item_config.derive(), derive); + } + } + + #[test] + #[should_panic = "cannot use `derive = false` with `packed` flag"] + fn conflicting_args_fails() { + let config = quote! { + // `packed` and `derive = false` conflict. + packed, derive = false + }; + let parsed_config = syn::parse2::(config).unwrap(); + StorageItemConfig::try_from(parsed_config).unwrap(); + } + + #[test] + #[should_panic = "encountered an unexpected value for `packed` ink! storage item configuration argument. Did you mean `#[ink::storage_item(packed)]` ?"] + fn invalid_packed_value_fails() { + let config = quote! { + // `packed` arg doesn't accept a value. + packed = true + }; + let parsed_config = syn::parse2::(config).unwrap(); + StorageItemConfig::try_from(parsed_config).unwrap(); + } +} diff --git a/crates/ink/macro/src/lib.rs b/crates/ink/macro/src/lib.rs index d29b2545478..5270d488ea4 100644 --- a/crates/ink/macro/src/lib.rs +++ b/crates/ink/macro/src/lib.rs @@ -897,13 +897,8 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { /// }; /// use ink::storage::traits::Storable; /// -/// // Deriving `scale::Decode` and `scale::Encode` also derives blanket implementation of all -/// // required traits to be storable. -/// #[derive(scale::Decode, scale::Encode)] -/// #[cfg_attr( -/// feature = "std", -/// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) -/// )] +/// // Example of how to define a packed type. +/// #[ink::storage_item(packed)] /// #[derive(Default, Debug)] /// struct Packed { /// s1: u128, @@ -912,12 +907,8 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { /// // s3: Vec, /// } /// -/// // Example of how to define the packed type with generic. -/// #[derive(scale::Decode, scale::Encode)] -/// #[cfg_attr( -/// feature = "std", -/// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) -/// )] +/// // Example of how to define the packed type with generics. +/// #[ink::storage_item(packed)] /// #[derive(Default, Debug)] /// struct PackedGeneric { /// s1: (u128, bool), @@ -926,6 +917,8 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { /// } /// /// // Example of how to define the non-packed type. +/// // Note: `packed` argument defaults to `false`, so it can be omitted for non-packed types, +/// // so the definition below is equivalent to `#[ink::storage_item(packed = false)]`. /// #[ink::storage_item] /// #[derive(Default, Debug)] /// struct NonPacked { @@ -934,6 +927,19 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { /// } /// /// // Example of how to define the non-packed generic type. +/// #[ink::storage_item] +/// #[derive(Default, Debug)] +/// struct NonPackedGeneric +/// where +/// T: Default + core::fmt::Debug, +/// T: ink::storage::traits::Packed, +/// { +/// s1: u32, +/// s2: T, +/// s3: Mapping, +/// } +/// +/// // Example of how to define the non-packed generic type with manually derived storage traits. /// #[ink::storage_item(derive = false)] /// #[derive(Storable, StorableHint, StorageKey)] /// #[cfg_attr( @@ -941,7 +947,7 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { /// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) /// )] /// #[derive(Default, Debug)] -/// struct NonPackedGeneric +/// struct NonPackedGenericManual /// where /// T: Default + core::fmt::Debug, /// T: ink::storage::traits::Packed, @@ -952,11 +958,7 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { /// } /// /// // Example of how to define a complex packed type. -/// #[derive(scale::Decode, scale::Encode)] -/// #[cfg_attr( -/// feature = "std", -/// derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout) -/// )] +/// #[ink::storage_item(packed)] /// #[derive(Default, Debug)] /// struct PackedComplex { /// s1: u128, @@ -985,6 +987,26 @@ pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { /// The `#[ink::storage_item]` macro can be provided with an additional comma-separated /// header argument: /// +/// - `packed: flag` +/// +/// Storage items flagged as `packed` use "packed" layout . +/// +/// **Usage Example:** +/// ``` +/// use ink::storage::Mapping; +/// +/// #[ink::storage_item(packed)] +/// struct PackedGeneric { +/// s1: (u128, bool), +/// s2: Vec, +/// s3: String, +/// } +/// ``` +/// +/// **Default value:** not set. +/// **Note**: The default behavior is to use "non-packed" layout, and automatically +/// derive storage keys for each field. +/// /// - `derive: bool` /// /// The `derive` configuration parameter is used to enable/disable auto deriving of diff --git a/crates/ink/tests/ui/storage_item/fail/collections_only_packed_1.stderr b/crates/ink/tests/ui/storage_item/fail/collections_only_packed_1.stderr index 8819826a56a..36b6fe26bac 100644 --- a/crates/ink/tests/ui/storage_item/fail/collections_only_packed_1.stderr +++ b/crates/ink/tests/ui/storage_item/fail/collections_only_packed_1.stderr @@ -1,36 +1,26 @@ -error[E0277]: the trait bound `Vec: Packed` is not satisfied +error[E0277]: expected `Vec` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:8 | 11 | a: Vec, - | ^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `Vec` + | ^^^^^^^^^^^^^^ `Vec` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `Vec` - = note: required for `Vec` to implement `Packed` + = help: the trait `Packed` is not implemented for `Vec` + = note: consider adding `#[ink::storage_item(packed)]` to `Vec` + = note: if `Vec` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `Vec` to implement `StorableHint<()>` = note: required for `Vec` to implement `AutoStorableHint>` -error[E0277]: the trait bound `[NonPacked]: Encode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:8 - | -11 | a: Vec, - | ^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `[NonPacked]` - | - = help: the following other types implement trait `Encode`: - [T; N] - [T] - = note: required for `Vec` to implement `Encode` - = note: required for `Vec` to implement `Packed` - = note: required for `Vec` to implement `StorableHint<()>` - = note: required for `Vec` to implement `AutoStorableHint>` - -error[E0277]: the trait bound `Vec: ink::parity_scale_codec::Decode` is not satisfied +error[E0277]: expected `Vec` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_1.rs:10:8 | 10 | struct Contract { - | ^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `Vec` + | ^^^^^^^^ `Vec` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `Vec` - = note: required for `Vec` to implement `Packed` + = help: the trait `Packed` is not implemented for `Vec` + = note: consider adding `#[ink::storage_item(packed)]` to `Vec` + = note: if `Vec` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `Vec` to implement `StorableHint<()>` = note: required for `Vec` to implement `AutoStorableHint>` note: required because it appears within the type `Contract` @@ -44,62 +34,16 @@ note: required by a bound in `ink_storage::ink_storage_traits::StorableHint::Typ | type Type: Storable; | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `StorableHint::Type` -error[E0277]: the trait bound `[NonPacked]: Encode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ the trait `Encode` is not implemented for `[NonPacked]` - | - = help: the following other types implement trait `Encode`: - [T; N] - [T] - = note: required for `Vec` to implement `Encode` - = note: required for `Vec` to implement `Packed` - = note: required for `Vec` to implement `StorableHint<()>` - = note: required for `Vec` to implement `AutoStorableHint>` -note: required because it appears within the type `Contract` - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ -note: required by a bound in `ink_storage::ink_storage_traits::StorableHint::Type` - --> $WORKSPACE/crates/storage/traits/src/storage.rs - | - | type Type: Storable; - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `StorableHint::Type` - -error[E0277]: the trait bound `Vec: ink::parity_scale_codec::Decode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `Vec` - | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `Vec` - = note: required for `Vec` to implement `Packed` - = note: required for `Vec` to implement `StorableHint<()>` - = note: required for `Vec` to implement `AutoStorableHint>` -note: required because it appears within the type `Contract` - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ -note: required by a bound in `Storable` - --> $WORKSPACE/crates/storage/traits/src/storage.rs - | - | pub trait Storable: Sized { - | ^^^^^ required by this bound in `Storable` - -error[E0277]: the trait bound `[NonPacked]: Encode` is not satisfied +error[E0277]: expected `Vec` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_1.rs:10:8 | 10 | struct Contract { - | ^^^^^^^^ the trait `Encode` is not implemented for `[NonPacked]` + | ^^^^^^^^ `Vec` does not currently use a "packed" layout | - = help: the following other types implement trait `Encode`: - [T; N] - [T] - = note: required for `Vec` to implement `Encode` - = note: required for `Vec` to implement `Packed` + = help: the trait `Packed` is not implemented for `Vec` + = note: consider adding `#[ink::storage_item(packed)]` to `Vec` + = note: if `Vec` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `Vec` to implement `StorableHint<()>` = note: required for `Vec` to implement `AutoStorableHint>` note: required because it appears within the type `Contract` @@ -113,14 +57,16 @@ note: required by a bound in `Storable` | pub trait Storable: Sized { | ^^^^^ required by this bound in `Storable` -error[E0277]: the trait bound `Vec: ink::parity_scale_codec::Decode` is not satisfied +error[E0277]: expected `Vec` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_1.rs:9:1 | 9 | #[ink::storage_item] - | ^^^^^^^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^ `Vec` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `Vec` - = note: required for `Vec` to implement `Packed` + = help: the trait `Packed` is not implemented for `Vec` + = note: consider adding `#[ink::storage_item(packed)]` to `Vec` + = note: if `Vec` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `Vec` to implement `StorableHint<()>` = note: required for `Vec` to implement `AutoStorableHint>` note: required because it appears within the type `Contract` @@ -135,120 +81,45 @@ note: required by an implicit `Sized` bound in `Result` | ^ required by the implicit `Sized` requirement on this type parameter in `Result` = note: this error originates in the derive macro `::ink::storage::traits::Storable` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `[NonPacked]: Encode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:9:1 - | -9 | #[ink::storage_item] - | ^^^^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `[NonPacked]` - | - = help: the following other types implement trait `Encode`: - [T; N] - [T] - = note: required for `Vec` to implement `Encode` - = note: required for `Vec` to implement `Packed` - = note: required for `Vec` to implement `StorableHint<()>` - = note: required for `Vec` to implement `AutoStorableHint>` -note: required because it appears within the type `Contract` - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ -note: required by an implicit `Sized` bound in `Result` - --> $RUST/core/src/result.rs - | - | pub enum Result { - | ^ required by the implicit `Sized` requirement on this type parameter in `Result` - = note: this error originates in the derive macro `::ink::storage::traits::Storable` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `Vec: Packed` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:5 - | -11 | a: Vec, - | ^^^^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `Vec` - | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `Vec` - = note: required for `Vec` to implement `Packed` - = note: required for `Vec` to implement `StorableHint<()>` - = note: required for `Vec` to implement `AutoStorableHint>` - -error[E0277]: the trait bound `[NonPacked]: Encode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:5 - | -11 | a: Vec, - | ^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `[NonPacked]` - | - = help: the following other types implement trait `Encode`: - [T; N] - [T] - = note: required for `Vec` to implement `Encode` - = note: required for `Vec` to implement `Packed` - = note: required for `Vec` to implement `StorableHint<()>` - = note: required for `Vec` to implement `AutoStorableHint>` - -error[E0277]: the trait bound `Vec: Packed` is not satisfied +error[E0277]: expected `Vec` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:5 | -9 | #[ink::storage_item] - | -------------------- in this procedural macro expansion -10 | struct Contract { 11 | a: Vec, - | ^^^^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^ `Vec` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `Vec` - = note: required for `Vec` to implement `Packed` + = help: the trait `Packed` is not implemented for `Vec` + = note: consider adding `#[ink::storage_item(packed)]` to `Vec` + = note: if `Vec` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `Vec` to implement `StorableHint<()>` = note: required for `Vec` to implement `AutoStorableHint>` - = note: this error originates in the derive macro `::ink::storage::traits::Storable` which comes from the expansion of the attribute macro `ink::storage_item` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `[NonPacked]: Encode` is not satisfied +error[E0277]: expected `Vec` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:5 | 9 | #[ink::storage_item] | -------------------- in this procedural macro expansion 10 | struct Contract { 11 | a: Vec, - | ^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `[NonPacked]` + | ^^^^^^^^^^^^^^^^^ `Vec` does not currently use a "packed" layout | - = help: the following other types implement trait `Encode`: - [T; N] - [T] - = note: required for `Vec` to implement `Encode` - = note: required for `Vec` to implement `Packed` + = help: the trait `Packed` is not implemented for `Vec` + = note: consider adding `#[ink::storage_item(packed)]` to `Vec` + = note: if `Vec` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `Vec` to implement `StorableHint<()>` = note: required for `Vec` to implement `AutoStorableHint>` = note: this error originates in the derive macro `::ink::storage::traits::Storable` which comes from the expansion of the attribute macro `ink::storage_item` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NonPacked: WrapperTypeDecode` is not satisfied +error[E0277]: expected `NonPacked` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:8 | 11 | a: Vec, - | ^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonPacked` - | - = help: the following other types implement trait `WrapperTypeDecode`: - Arc - Box - Rc - sp_core::Bytes - = note: required for `NonPacked` to implement `ink::parity_scale_codec::Decode` - = note: required for `NonPacked` to implement `Packed` - = note: required for `Vec` to implement `StorageLayout` - -error[E0277]: the trait bound `NonPacked: WrapperTypeEncode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_1.rs:11:8 + | ^^^^^^^^^^^^^^ `NonPacked` does not currently use a "packed" layout | -11 | a: Vec, - | ^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonPacked` - | - = help: the following other types implement trait `WrapperTypeEncode`: - &T - &mut T - Arc - Box - Cow<'_, T> - Rc - String - Vec - and $N others - = note: required for `NonPacked` to implement `Encode` - = note: required for `NonPacked` to implement `Packed` + = help: the trait `Packed` is not implemented for `NonPacked` + = note: consider adding `#[ink::storage_item(packed)]` to `NonPacked` + = note: if `NonPacked` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout + = help: the trait `StorageLayout` is implemented for `Vec` = note: required for `Vec` to implement `StorageLayout` diff --git a/crates/ink/tests/ui/storage_item/fail/collections_only_packed_2.stderr b/crates/ink/tests/ui/storage_item/fail/collections_only_packed_2.stderr index 548e414bd7a..1b8d0fbcb0e 100644 --- a/crates/ink/tests/ui/storage_item/fail/collections_only_packed_2.stderr +++ b/crates/ink/tests/ui/storage_item/fail/collections_only_packed_2.stderr @@ -1,33 +1,26 @@ -error[E0277]: the trait bound `BTreeMap: Packed` is not satisfied +error[E0277]: expected `BTreeMap` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:8 | 11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `BTreeMap` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `BTreeMap` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` + = help: the trait `Packed` is not implemented for `BTreeMap` + = note: consider adding `#[ink::storage_item(packed)]` to `BTreeMap` + = note: if `BTreeMap` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `BTreeMap` to implement `StorableHint<()>` = note: required for `BTreeMap` to implement `AutoStorableHint>` -error[E0277]: the trait bound `BTreeMap: Packed` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:8 - | -11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `BTreeMap` - | - = help: the trait `Encode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` - = note: required for `BTreeMap` to implement `StorableHint<()>` - = note: required for `BTreeMap` to implement `AutoStorableHint>` - -error[E0277]: the trait bound `BTreeMap: ink::parity_scale_codec::Decode` is not satisfied +error[E0277]: expected `BTreeMap` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_2.rs:10:8 | 10 | struct Contract { - | ^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `BTreeMap` + | ^^^^^^^^ `BTreeMap` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` + = help: the trait `Packed` is not implemented for `BTreeMap` + = note: consider adding `#[ink::storage_item(packed)]` to `BTreeMap` + = note: if `BTreeMap` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `BTreeMap` to implement `StorableHint<()>` = note: required for `BTreeMap` to implement `AutoStorableHint>` note: required because it appears within the type `Contract` @@ -41,56 +34,16 @@ note: required by a bound in `ink_storage::ink_storage_traits::StorableHint::Typ | type Type: Storable; | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `StorableHint::Type` -error[E0277]: the trait bound `BTreeMap: Encode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ the trait `Encode` is not implemented for `BTreeMap` - | - = help: the trait `Encode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` - = note: required for `BTreeMap` to implement `StorableHint<()>` - = note: required for `BTreeMap` to implement `AutoStorableHint>` -note: required because it appears within the type `Contract` - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ -note: required by a bound in `ink_storage::ink_storage_traits::StorableHint::Type` - --> $WORKSPACE/crates/storage/traits/src/storage.rs - | - | type Type: Storable; - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `StorableHint::Type` - -error[E0277]: the trait bound `BTreeMap: ink::parity_scale_codec::Decode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `BTreeMap` - | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` - = note: required for `BTreeMap` to implement `StorableHint<()>` - = note: required for `BTreeMap` to implement `AutoStorableHint>` -note: required because it appears within the type `Contract` - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ -note: required by a bound in `Storable` - --> $WORKSPACE/crates/storage/traits/src/storage.rs - | - | pub trait Storable: Sized { - | ^^^^^ required by this bound in `Storable` - -error[E0277]: the trait bound `BTreeMap: Encode` is not satisfied +error[E0277]: expected `BTreeMap` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_2.rs:10:8 | 10 | struct Contract { - | ^^^^^^^^ the trait `Encode` is not implemented for `BTreeMap` + | ^^^^^^^^ `BTreeMap` does not currently use a "packed" layout | - = help: the trait `Encode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` + = help: the trait `Packed` is not implemented for `BTreeMap` + = note: consider adding `#[ink::storage_item(packed)]` to `BTreeMap` + = note: if `BTreeMap` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `BTreeMap` to implement `StorableHint<()>` = note: required for `BTreeMap` to implement `AutoStorableHint>` note: required because it appears within the type `Contract` @@ -104,14 +57,16 @@ note: required by a bound in `Storable` | pub trait Storable: Sized { | ^^^^^ required by this bound in `Storable` -error[E0277]: the trait bound `BTreeMap: ink::parity_scale_codec::Decode` is not satisfied +error[E0277]: expected `BTreeMap` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_2.rs:9:1 | 9 | #[ink::storage_item] - | ^^^^^^^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `BTreeMap` + | ^^^^^^^^^^^^^^^^^^^^ `BTreeMap` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` + = help: the trait `Packed` is not implemented for `BTreeMap` + = note: consider adding `#[ink::storage_item(packed)]` to `BTreeMap` + = note: if `BTreeMap` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `BTreeMap` to implement `StorableHint<()>` = note: required for `BTreeMap` to implement `AutoStorableHint>` note: required because it appears within the type `Contract` @@ -126,111 +81,45 @@ note: required by an implicit `Sized` bound in `Result` | ^ required by the implicit `Sized` requirement on this type parameter in `Result` = note: this error originates in the derive macro `::ink::storage::traits::Storable` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `BTreeMap: Encode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:9:1 - | -9 | #[ink::storage_item] - | ^^^^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `BTreeMap` - | - = help: the trait `Encode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` - = note: required for `BTreeMap` to implement `StorableHint<()>` - = note: required for `BTreeMap` to implement `AutoStorableHint>` -note: required because it appears within the type `Contract` - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:10:8 - | -10 | struct Contract { - | ^^^^^^^^ -note: required by an implicit `Sized` bound in `Result` - --> $RUST/core/src/result.rs - | - | pub enum Result { - | ^ required by the implicit `Sized` requirement on this type parameter in `Result` - = note: this error originates in the derive macro `::ink::storage::traits::Storable` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `BTreeMap: Packed` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:5 - | -11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `BTreeMap` - | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` - = note: required for `BTreeMap` to implement `StorableHint<()>` - = note: required for `BTreeMap` to implement `AutoStorableHint>` - -error[E0277]: the trait bound `BTreeMap: Packed` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:5 - | -11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `BTreeMap` - | - = help: the trait `Encode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` - = note: required for `BTreeMap` to implement `StorableHint<()>` - = note: required for `BTreeMap` to implement `AutoStorableHint>` - -error[E0277]: the trait bound `BTreeMap: Packed` is not satisfied +error[E0277]: expected `BTreeMap` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:5 | -9 | #[ink::storage_item] - | -------------------- in this procedural macro expansion -10 | struct Contract { 11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ink::parity_scale_codec::Decode` is not implemented for `BTreeMap` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `BTreeMap` does not currently use a "packed" layout | - = help: the trait `ink::parity_scale_codec::Decode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` + = help: the trait `Packed` is not implemented for `BTreeMap` + = note: consider adding `#[ink::storage_item(packed)]` to `BTreeMap` + = note: if `BTreeMap` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `BTreeMap` to implement `StorableHint<()>` = note: required for `BTreeMap` to implement `AutoStorableHint>` - = note: this error originates in the derive macro `::ink::storage::traits::Storable` which comes from the expansion of the attribute macro `ink::storage_item` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `BTreeMap: Packed` is not satisfied +error[E0277]: expected `BTreeMap` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:5 | 9 | #[ink::storage_item] | -------------------- in this procedural macro expansion 10 | struct Contract { 11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `BTreeMap` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `BTreeMap` does not currently use a "packed" layout | - = help: the trait `Encode` is implemented for `BTreeMap` - = note: required for `BTreeMap` to implement `Packed` + = help: the trait `Packed` is not implemented for `BTreeMap` + = note: consider adding `#[ink::storage_item(packed)]` to `BTreeMap` + = note: if `BTreeMap` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout = note: required for `BTreeMap` to implement `StorableHint<()>` = note: required for `BTreeMap` to implement `AutoStorableHint>` = note: this error originates in the derive macro `::ink::storage::traits::Storable` which comes from the expansion of the attribute macro `ink::storage_item` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NonPacked: WrapperTypeDecode` is not satisfied +error[E0277]: expected `NonPacked` to use a "packed" layout --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:8 | 11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonPacked` - | - = help: the following other types implement trait `WrapperTypeDecode`: - Arc - Box - Rc - sp_core::Bytes - = note: required for `NonPacked` to implement `ink::parity_scale_codec::Decode` - = note: required for `NonPacked` to implement `Packed` - = note: required for `BTreeMap` to implement `StorageLayout` - -error[E0277]: the trait bound `NonPacked: WrapperTypeEncode` is not satisfied - --> tests/ui/storage_item/fail/collections_only_packed_2.rs:11:8 + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `NonPacked` does not currently use a "packed" layout | -11 | a: BTreeMap, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonPacked` - | - = help: the following other types implement trait `WrapperTypeEncode`: - &T - &mut T - Arc - Box - Cow<'_, T> - Rc - String - Vec - and $N others - = note: required for `NonPacked` to implement `Encode` - = note: required for `NonPacked` to implement `Packed` + = help: the trait `Packed` is not implemented for `NonPacked` + = note: consider adding `#[ink::storage_item(packed)]` to `NonPacked` + = note: if `NonPacked` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout + = help: the trait `StorageLayout` is implemented for `BTreeMap` = note: required for `BTreeMap` to implement `StorageLayout` diff --git a/crates/ink/tests/ui/storage_item/fail/packed_is_not_derived_automatically.stderr b/crates/ink/tests/ui/storage_item/fail/packed_is_not_derived_automatically.stderr index 098f9442a6f..45a7c68e693 100644 --- a/crates/ink/tests/ui/storage_item/fail/packed_is_not_derived_automatically.stderr +++ b/crates/ink/tests/ui/storage_item/fail/packed_is_not_derived_automatically.stderr @@ -1,40 +1,13 @@ -error[E0277]: the trait bound `NonPacked: Packed` is not satisfied +error[E0277]: expected `NonPacked` to use a "packed" layout --> tests/ui/storage_item/fail/packed_is_not_derived_automatically.rs:15:30 | 15 | let _ = consume_packed::(); - | ^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonPacked` + | ^^^^^^^^^ `NonPacked` does not currently use a "packed" layout | - = help: the following other types implement trait `WrapperTypeDecode`: - Arc - Box - Rc - sp_core::Bytes - = note: required for `NonPacked` to implement `ink::parity_scale_codec::Decode` - = note: required for `NonPacked` to implement `Packed` -note: required by a bound in `consume_packed` - --> tests/ui/storage_item/fail/packed_is_not_derived_automatically.rs:12:22 - | -12 | fn consume_packed() {} - | ^^^^^^ required by this bound in `consume_packed` - -error[E0277]: the trait bound `NonPacked: Packed` is not satisfied - --> tests/ui/storage_item/fail/packed_is_not_derived_automatically.rs:15:30 - | -15 | let _ = consume_packed::(); - | ^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonPacked` - | - = help: the following other types implement trait `WrapperTypeEncode`: - &T - &mut T - Arc - Box - Cow<'_, T> - Rc - String - Vec - and $N others - = note: required for `NonPacked` to implement `Encode` - = note: required for `NonPacked` to implement `Packed` + = help: the trait `Packed` is not implemented for `NonPacked` + = note: consider adding `#[ink::storage_item(packed)]` to `NonPacked` + = note: if `NonPacked` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T` + = note: learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout note: required by a bound in `consume_packed` --> tests/ui/storage_item/fail/packed_is_not_derived_automatically.rs:12:22 | diff --git a/crates/ink/tests/ui/storage_item/pass/complex_non_packed_enum.rs b/crates/ink/tests/ui/storage_item/pass/complex_non_packed_enum.rs index e9670ae7dbc..a559912a5c2 100644 --- a/crates/ink/tests/ui/storage_item/pass/complex_non_packed_enum.rs +++ b/crates/ink/tests/ui/storage_item/pass/complex_non_packed_enum.rs @@ -10,8 +10,7 @@ use ink_storage::{ }; #[derive(Default)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] enum Packed { #[default] None, diff --git a/crates/ink/tests/ui/storage_item/pass/complex_non_packed_struct.rs b/crates/ink/tests/ui/storage_item/pass/complex_non_packed_struct.rs index afc510bcbe0..a956c9edea1 100644 --- a/crates/ink/tests/ui/storage_item/pass/complex_non_packed_struct.rs +++ b/crates/ink/tests/ui/storage_item/pass/complex_non_packed_struct.rs @@ -10,8 +10,7 @@ use ink_storage::{ }; #[derive(Default)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] struct Packed { a: u8, b: u16, diff --git a/crates/ink/tests/ui/storage_item/pass/complex_packed_enum.rs b/crates/ink/tests/ui/storage_item/pass/complex_packed_enum.rs index ba1d4a4ec45..cfb6aad23ae 100644 --- a/crates/ink/tests/ui/storage_item/pass/complex_packed_enum.rs +++ b/crates/ink/tests/ui/storage_item/pass/complex_packed_enum.rs @@ -8,8 +8,7 @@ use ink_prelude::{ use ink::storage::traits::Storable; #[derive(Default, PartialEq, Eq, PartialOrd, Ord)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] enum Deep2 { #[default] None, @@ -27,8 +26,7 @@ enum Deep2 { } #[derive(Default)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] enum Deep1 { #[default] None, diff --git a/crates/ink/tests/ui/storage_item/pass/complex_packed_struct.rs b/crates/ink/tests/ui/storage_item/pass/complex_packed_struct.rs index 43cc25e21fb..d7939d8ac93 100644 --- a/crates/ink/tests/ui/storage_item/pass/complex_packed_struct.rs +++ b/crates/ink/tests/ui/storage_item/pass/complex_packed_struct.rs @@ -8,8 +8,7 @@ use ink_prelude::{ use ink::storage::traits::Storable; #[derive(Default, PartialEq, Eq, PartialOrd, Ord)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] struct Deep2 { a: u8, b: u16, @@ -20,8 +19,7 @@ struct Deep2 { } #[derive(Default)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] struct Deep1 { a: Deep2, b: (Deep2, Deep2), @@ -31,8 +29,7 @@ struct Deep1 { } #[derive(Default)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] struct Contract { a: Deep1, b: Deep2, diff --git a/crates/ink/tests/ui/storage_item/pass/packed_tuple_struct.rs b/crates/ink/tests/ui/storage_item/pass/packed_tuple_struct.rs index 34f51c6cfe8..3625747c40f 100644 --- a/crates/ink/tests/ui/storage_item/pass/packed_tuple_struct.rs +++ b/crates/ink/tests/ui/storage_item/pass/packed_tuple_struct.rs @@ -1,8 +1,7 @@ use ink::storage::traits::Storable; #[derive(Default)] -#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] -#[ink::scale_derive(Encode, Decode, TypeInfo)] +#[ink::storage_item(packed)] struct Contract(String, u128); fn main() { diff --git a/crates/storage/traits/src/impls/mod.rs b/crates/storage/traits/src/impls/mod.rs index 754dbf1240a..ec7ce97571e 100644 --- a/crates/storage/traits/src/impls/mod.rs +++ b/crates/storage/traits/src/impls/mod.rs @@ -125,6 +125,7 @@ where } impl

super::storage::private::Sealed for P where P: scale::Decode + scale::Encode {} +#[diagnostic::do_not_recommend] impl

Packed for P where P: scale::Decode + scale::Encode {} impl

StorageKey for P diff --git a/crates/storage/traits/src/storage.rs b/crates/storage/traits/src/storage.rs index ec2dd03d1be..5035b1a5d92 100644 --- a/crates/storage/traits/src/storage.rs +++ b/crates/storage/traits/src/storage.rs @@ -80,6 +80,13 @@ pub(crate) mod private { /// /// The trait is automatically implemented for types that implement [`scale::Codec`] /// via blanket implementation. +#[diagnostic::on_unimplemented( + message = "expected `{Self}` to use a \"packed\" layout", + label = "`{Self}` does not currently use a \"packed\" layout", + note = "consider adding `#[ink::storage_item(packed)]` to `{Self}`", + note = "if `{Self}` is a standard library collection like `Vec`, then consider adding `#[ink::storage_item(packed)]` to `T`", + note = "learn more at https://use.ink/docs/v6/datastructures/storage-layout#packed-vs-non-packed-layout" +)] pub trait Packed: Storable + scale::Codec + private::Sealed {} /// Holds storage key for the type. diff --git a/integration-tests/internal/mother/lib.rs b/integration-tests/internal/mother/lib.rs index 1d819741f14..e28d5e0991b 100755 --- a/integration-tests/internal/mother/lib.rs +++ b/integration-tests/internal/mother/lib.rs @@ -36,14 +36,12 @@ mod mother { /// Vector index corresponds to sample number. /// Wrapping vector, just added for testing UI components. #[derive(Default, PartialEq, Eq, Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct Bids(Vec>>); /// Auction outline. #[derive(PartialEq, Eq, Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub enum Outline { NoWinner, WinnerDetected, @@ -54,8 +52,7 @@ mod mother { /// Logic inspired by /// [Parachain Auction](https://github.com/paritytech/polkadot/blob/master/runtime/common/src/traits.rs#L160) #[derive(PartialEq, Eq, Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub enum Status { /// An auction has not started yet. NotStarted, @@ -76,8 +73,7 @@ mod mother { /// Struct for storing auction data. #[derive(Debug, PartialEq, Eq, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct Auction { /// Branded name of the auction event. name: String, diff --git a/integration-tests/internal/storage-types/lib.rs b/integration-tests/internal/storage-types/lib.rs index e3cd663bb8a..192e6ab643a 100755 --- a/integration-tests/internal/storage-types/lib.rs +++ b/integration-tests/internal/storage-types/lib.rs @@ -14,8 +14,7 @@ mod storage_types { }; #[derive(Debug)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] #[allow(clippy::enum_variant_names)] pub enum CustomError { EmptyError, @@ -25,8 +24,7 @@ mod storage_types { } #[derive(Debug, PartialEq, Eq, Clone, Default)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub enum EnumWithoutValues { #[default] A, @@ -35,8 +33,7 @@ mod storage_types { } #[derive(Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub enum EnumWithValues { OneValue(u32), TwoValues(u32, u32), @@ -44,8 +41,7 @@ mod storage_types { } #[derive(Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct PrimitiveTypes { bool_value: bool, enum_without_values: EnumWithoutValues, @@ -56,8 +52,7 @@ mod storage_types { } #[derive(Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct SignedIntegers { i128_value_max: i128, i128_value_min: i128, @@ -72,8 +67,7 @@ mod storage_types { } #[derive(Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct SubstrateTypes { account_id_value: AccountId, balance_value_max: Balance, @@ -82,8 +76,7 @@ mod storage_types { } #[derive(Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct InkPreludeTypes { string_value: String, vec_string_value: Vec, @@ -91,8 +84,7 @@ mod storage_types { } #[derive(Debug, Clone)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct UnsignedIntegers { u128_value_max: u128, u128_value_min: u128, diff --git a/integration-tests/public/lazyvec/lib.rs b/integration-tests/public/lazyvec/lib.rs index 5588f0cae95..54924d4ee51 100755 --- a/integration-tests/public/lazyvec/lib.rs +++ b/integration-tests/public/lazyvec/lib.rs @@ -9,8 +9,7 @@ mod lazyvec { storage::StorageVec, }; - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub struct Proposal { data: Vec, until: BlockNumber, diff --git a/integration-tests/public/multi-contract-caller/lib.rs b/integration-tests/public/multi-contract-caller/lib.rs index 70b3043b90e..adcbfa5f0cc 100644 --- a/integration-tests/public/multi-contract-caller/lib.rs +++ b/integration-tests/public/multi-contract-caller/lib.rs @@ -13,8 +13,7 @@ mod multi_contract_caller { /// /// The initial state is `Adder`. #[derive(Debug, Copy, Clone, PartialEq, Eq)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub enum Which { Adder, Subber, diff --git a/integration-tests/public/multisig/lib.rs b/integration-tests/public/multisig/lib.rs index e9e26e2ace3..9407f488fc2 100755 --- a/integration-tests/public/multisig/lib.rs +++ b/integration-tests/public/multisig/lib.rs @@ -99,8 +99,7 @@ mod multisig { /// Indicates whether a transaction is already confirmed or needs further /// confirmations. #[derive(Clone, Copy)] - #[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] - #[ink::scale_derive(Encode, Decode, TypeInfo)] + #[ink::storage_item(packed)] pub enum ConfirmationStatus { /// The transaction is already confirmed. Confirmed,