From 04cf460ca3da9a631f5f076aa58688613ac9b500 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 28 Jan 2021 11:00:51 +0100 Subject: [PATCH 001/493] add new codegen constructs to ink_lang crate --- crates/lang/src/lib.rs | 2 ++ crates/lang/src/traits.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index eb4fce178a..bbf9d179ea 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -75,6 +75,8 @@ pub use self::{ MessageMut, MessageRef, True, + TraitDefinitionRegistry, + NoDynamicCallForwarder, }, }; pub use ::static_assertions; diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index fa78cb490e..f346e1304a 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -120,3 +120,39 @@ pub trait MessageMut: FnInput + FnOutput + FnSelector + FnState { /// Indicates that some compile time expression is expected to be `true`. #[doc(hidden)] pub trait True {} + +/// This type is known to ink! to implement all defined ink! trait definitions. +/// This property can be guaranteed by `#[ink::trait_definition]` proc. macro. +/// +/// By the introduction of an new internal and hidden associated type called +/// `__ink_DynamicCallForwarder` for all ink! trait definitions it is possible +/// for ink! to map from any given ink! trait definition back to a concrete +/// Rust type. +/// Whenever the `ChainExtensionRegistry` implements an ink! trait definition +/// all calls are defaulted to produce linker errors (ideally compiler errors +/// if that was possible) and the only relevant implementation is the new +/// `__ink_DynamicCallForwarder` associated type that links to a concrete +/// type implementing `FromAccountId` and the ink! trait definition with +/// proper implementations. +/// +/// Then ink! can map from the ink! trait definition `MyTrait` to this concrete +/// dynamic call forwarder type by: +/// ```no_compile +/// <::ink_lang::TraitDefinitionRegistry as MyTrait>::__ink_DynamicCallForwarder +/// ``` +/// Normal implementations of ink! trait definitions default the new +/// `__ink_DynamicCallForwarder` associated type to `::ink_lang::NoDynamicCallForwarder`. +/// +/// This is the technique used by ink! to resolve `&dyn MyTrait`, `&mut dyn MyTrait` +/// in message parameters or `dyn MyTrait` in ink! storage fields to concrete types +/// that ink! can serialize and deserialize as if it was an `AccountId` and call +/// ink! messages on it according to the ink! trait definition interface. +#[doc(hidden)] +pub enum TraitDefinitionRegistry {} + +/// The default type that ink! trait definition implementations use for the +/// `__ink_DynamicCallForwarder` associated type. +/// +/// Read more about its use [here][TraitDefinitionRegistry]. +#[doc(hidden)] +pub enum NoDynamicCallForwarder {} From 9ca2907edcc1d641bd85820d93e8f89ef32cf05c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 29 Jan 2021 17:26:04 +0100 Subject: [PATCH 002/493] rename utility types in ink_lang for trait definitions --- crates/lang/src/lib.rs | 4 ++-- crates/lang/src/traits.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index bbf9d179ea..129e9e3e57 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -75,8 +75,8 @@ pub use self::{ MessageMut, MessageRef, True, - TraitDefinitionRegistry, - NoDynamicCallForwarder, + ConcreteImplementers, + NoConcreteImplementer, }, }; pub use ::static_assertions; diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index f346e1304a..da158385f4 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -148,11 +148,11 @@ pub trait True {} /// that ink! can serialize and deserialize as if it was an `AccountId` and call /// ink! messages on it according to the ink! trait definition interface. #[doc(hidden)] -pub enum TraitDefinitionRegistry {} +pub enum ConcreteImplementers {} /// The default type that ink! trait definition implementations use for the /// `__ink_DynamicCallForwarder` associated type. /// /// Read more about its use [here][TraitDefinitionRegistry]. #[doc(hidden)] -pub enum NoDynamicCallForwarder {} +pub enum NoConcreteImplementer {} From 2b91e21b89152648750b11e27263855b1beb269f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 29 Jan 2021 17:26:28 +0100 Subject: [PATCH 003/493] add __ink_ConcreteImplementer assoc type to all ink! trait definitions --- crates/lang/codegen/src/generator/item_impls.rs | 1 + crates/lang/codegen/src/generator/trait_def.rs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 2771187fbd..91d4f5f94e 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -157,6 +157,7 @@ impl ItemImpls<'_> { #( #attrs )* impl #trait_path for #self_type { type __ink_Checksum = [(); #checksum]; + type __ink_ConcreteImplementer = ::ink_lang::NoConcreteImplementer; #( #constructors )* #( #messages )* diff --git a/crates/lang/codegen/src/generator/trait_def.rs b/crates/lang/codegen/src/generator/trait_def.rs index 1f2ad385a8..984bc53a34 100644 --- a/crates/lang/codegen/src/generator/trait_def.rs +++ b/crates/lang/codegen/src/generator/trait_def.rs @@ -101,6 +101,13 @@ impl GenerateCode for TraitDefinition<'_> { #[allow(non_camel_case_types)] type __ink_Checksum: #helper_ident; + /// Used to map from trait to a concrete `AccountId` thin-wrapper + /// implementing the exact same trait. This defaults to + /// `ink_lang::NoConcreteImplementer` for user provided implementations. + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_ConcreteImplementer; + #(#constructors)* #(#messages)* } From 558e218556111b2a52fe31a18db98c6a6c51003e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 29 Jan 2021 18:24:26 +0100 Subject: [PATCH 004/493] make ConcreteImplementers generic over E: Environment --- crates/lang/src/traits.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index da158385f4..33d96bdf9a 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::marker::PhantomData; use ink_env::{ call::{ utils::{ @@ -148,7 +149,11 @@ pub trait True {} /// that ink! can serialize and deserialize as if it was an `AccountId` and call /// ink! messages on it according to the ink! trait definition interface. #[doc(hidden)] -pub enum ConcreteImplementers {} +pub struct ConcreteImplementers { + marker: PhantomData E>, +} + +unsafe impl CheckedInkTrait<[(); N]> for ConcreteImplementers {} /// The default type that ink! trait definition implementations use for the /// `__ink_DynamicCallForwarder` associated type. From 1e47bcd942b5c3fbd13156fa905159c994966405 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 29 Jan 2021 18:24:50 +0100 Subject: [PATCH 005/493] add codegen for ConcreteImplementers trait impls --- .../lang/codegen/src/generator/trait_def.rs | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def.rs b/crates/lang/codegen/src/generator/trait_def.rs index 984bc53a34..6bcf6c2f9d 100644 --- a/crates/lang/codegen/src/generator/trait_def.rs +++ b/crates/lang/codegen/src/generator/trait_def.rs @@ -66,6 +66,85 @@ impl<'a> TraitDefinition<'a> { fn #ident(#inputs) -> Self::#output_ident; ) } + + fn generate_for_constructor_never_call( + constructor: ir::InkTraitConstructor<'a>, + ) -> TokenStream2 { + let span = constructor.span(); + let attrs = constructor.attrs(); + let sig = constructor.sig(); + let ident = &sig.ident; + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let input_bindings = sig + .inputs + .iter() + .enumerate() + .map(|(n, fn_arg)| { + match fn_arg { + syn::FnArg::Typed(pat_type) => { + let ident = format_ident!("__ink_binding_{}", n); + let ty = &pat_type.ty; + quote! { #ident : #ty } + } + syn::FnArg::Receiver(receiver) => quote! { #receiver }, + } + }) + .collect::>(); + let linker_error_ident = + format_ident!("{}", "__ink_enforce_error_for_constructor"); + quote_spanned!(span => + /// Output type of the respective trait constructor. + type #output_ident = ::ink_lang::NeverReturns; + + #(#attrs)* + fn #ident(#(#input_bindings),*) -> Self::#output_ident { + extern { + fn #linker_error_ident() -> !; + } + unsafe { #linker_error_ident() } + } + ) + } + + fn generate_for_message_never_call(message: ir::InkTraitMessage<'a>) -> TokenStream2 { + let span = message.span(); + let attrs = message.attrs(); + let sig = message.sig(); + let ident = &sig.ident; + let output = match &sig.output { + syn::ReturnType::Default => quote! { () }, + syn::ReturnType::Type(_, ty) => quote! { #ty }, + }; + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let input_bindings = sig + .inputs + .iter() + .enumerate() + .map(|(n, fn_arg)| { + match fn_arg { + syn::FnArg::Typed(pat_type) => { + let ident = format_ident!("__ink_binding_{}", n); + let ty = &pat_type.ty; + quote! { #ident : #ty } + } + syn::FnArg::Receiver(receiver) => quote! { #receiver }, + } + }) + .collect::>(); + let linker_error_ident = format_ident!("{}", "__ink_enforce_error_for_message"); + quote_spanned!(span => + /// Output type of the respective trait constructor. + type #output_ident = #output; + + #(#attrs)* + fn #ident(#(#input_bindings),*) -> Self::#output_ident { + extern { + fn #linker_error_ident() -> !; + } + unsafe { #linker_error_ident() } + } + ) + } } impl GenerateCode for TraitDefinition<'_> { @@ -82,6 +161,14 @@ impl GenerateCode for TraitDefinition<'_> { hash[2], hash[3] ); + let concrete_implementer_ident = format_ident!( + "__ink_ConcreteImplementer{}_0x{:X}{:X}{:X}{:X}", + ident, + hash[0], + hash[1], + hash[2], + hash[3] + ); let verify_hash_id = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; let constructors = self @@ -94,6 +181,16 @@ impl GenerateCode for TraitDefinition<'_> { .iter_items() .flat_map(ir::InkTraitItem::filter_map_message) .map(Self::generate_for_message); + let constructors_never_call = self + .trait_def + .iter_items() + .flat_map(ir::InkTraitItem::filter_map_constructor) + .map(Self::generate_for_constructor_never_call); + let messages_never_call = self + .trait_def + .iter_items() + .flat_map(ir::InkTraitItem::filter_map_message) + .map(Self::generate_for_message_never_call); quote_spanned!(span => #(#attrs)* pub trait #ident: ::ink_lang::CheckedInkTrait<[(); #verify_hash_id]> { @@ -118,6 +215,63 @@ impl GenerateCode for TraitDefinition<'_> { const _: () = { unsafe impl #helper_ident for [(); #verify_hash_id] {} + + /// A universal concrete implementer of the ink! trait definition. + #[doc(hidden)] + #[allow(non_camel_case_types)] + pub struct #concrete_implementer_ident + where + E: ::ink_env::Environment, + { + account_id: ::AccountId, + } + + impl ::ink_env::call::FromAccountId for #concrete_implementer_ident + where + E: ::ink_env::Environment, + { + #[inline] + fn from_account_id(account_id: ::AccountId) -> Self { + Self { account_id } + } + } + + impl ::ink_lang::ToAccountId for #concrete_implementer_ident + where + E: ::ink_env::Environment, + ::AccountId: Clone, + { + #[inline] + fn to_account_id(&self) -> ::AccountId { + self.account_id.clone() + } + } + + impl ::core::clone::Clone for #concrete_implementer_ident + where + E: ::ink_env::Environment, + ::AccountId: Clone, + { + fn clone(&self) -> Self { + Self { account_id: self.account_id.clone() } + } + } + + impl #ident for ::ink_lang::ConcreteImplementers + where + E: ::ink_env::Environment, + { + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_Checksum = [(); #verify_hash_id]; + + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_ConcreteImplementer = #concrete_implementer_ident; + + #(#constructors_never_call)* + #(#messages_never_call)* + } }; ) } From 82a974f44fa82b6191bfe7b495f681a25fd3c43e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 16 Feb 2021 16:24:38 +0100 Subject: [PATCH 006/493] adjust .rustfmt.toml for new imports_granularity --- .rustfmt.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index ac50f9aa0b..9b8d3bafdb 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -19,7 +19,7 @@ fn_single_line = false where_single_line = false imports_indent = "Block" imports_layout = "Vertical" # changed -merge_imports = true # changed +imports_granularity="Crate" # changed reorder_imports = true reorder_modules = true reorder_impl_items = false From 59cba891dde1e3b18a2c71ed8f1f0c64a6cb5621 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 16 Feb 2021 16:25:00 +0100 Subject: [PATCH 007/493] apply rustfmt --- crates/lang/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 129e9e3e57..b426c35e31 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -66,6 +66,7 @@ pub use self::{ }, traits::{ CheckedInkTrait, + ConcreteImplementers, Constructor, FnInput, FnOutput, @@ -74,9 +75,8 @@ pub use self::{ ImpliesReturn, MessageMut, MessageRef, - True, - ConcreteImplementers, NoConcreteImplementer, + True, }, }; pub use ::static_assertions; From a32ee8385c4f1a0375a21c1e4afe07d0eb6b3353 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 3 Mar 2021 10:36:13 +0100 Subject: [PATCH 008/493] allow selector attribute on ink! trait definition messages and constructors --- crates/lang/ir/src/ir/trait_def.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index 1d081ea828..c6cbdc54b5 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -500,7 +500,8 @@ impl InkTrait { &ir::AttributeArgKind::Constructor, |arg| { match arg.kind() { - ir::AttributeArg::Constructor => Ok(()), + ir::AttributeArg::Constructor | + ir::AttributeArg::Selector(_) => Ok(()), _ => Err(None), } }, @@ -552,7 +553,8 @@ impl InkTrait { &ir::AttributeArgKind::Message, |arg| { match arg.kind() { - ir::AttributeArg::Message => Ok(()), + ir::AttributeArg::Message | + ir::AttributeArg::Selector(_) => Ok(()), _ => Err(None), } }, @@ -987,6 +989,23 @@ mod tests { ) } + #[test] + fn trait_def_with_selectors_ok() { + assert!( + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(constructor, selector = "0xC0DECAFE")] + fn my_constructor() -> Self; + #[ink(message, selector = "0xDEADBEEF")] + fn my_message(&self); + #[ink(message, selector = "0xC0FEFEED")] + fn my_message_mut(&mut self); + } + }) + .is_ok() + ) + } + #[test] fn iter_constructors_works() { let ink_trait = From 9923eba9a4566ccf2cbc8b26821452dd622ae59f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 3 Mar 2021 17:17:32 +0100 Subject: [PATCH 009/493] add new compose selector API --- crates/lang/ir/src/ir/mod.rs | 5 +- crates/lang/ir/src/ir/selector.rs | 88 +++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/mod.rs b/crates/lang/ir/src/ir/mod.rs index 2de6f82630..ad5984853b 100644 --- a/crates/lang/ir/src/ir/mod.rs +++ b/crates/lang/ir/src/ir/mod.rs @@ -76,7 +76,10 @@ pub use self::{ IterEvents, IterItemImpls, }, - selector::Selector, + selector::{ + Selector, + TraitPrefix, + }, trait_def::{ InkTrait, InkTraitConstructor, diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index e74eab0f40..eb4623e00c 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -24,6 +24,42 @@ pub struct Selector { bytes: [u8; 4], } +/// The trait prefix to compute a composed selector for trait implementation blocks. +#[derive(Debug)] +pub struct TraitPrefix<'a> { + /// The namespace of the ink! trait definition. + /// + /// By default this is equal to the `module_path!` at the ink! trait definition site. + /// It can be customized by the ink! trait definition author using `#[ink(namespace = N)]` + /// ink! attribute. + namespace: Vec, + /// The Rust identifier of the ink! trait definition. + trait_ident: &'a syn::Ident, +} + +impl<'a> TraitPrefix<'a> { + /// Creates a new trait prefix. + pub fn new(trait_ident: &'a syn::Ident, namespace: N) -> Self + where + N: IntoIterator, + { + Self { + trait_ident, + namespace: namespace.into_iter().collect::>(), + } + } + + /// Returns a shared slice over the bytes of the namespace. + pub fn namespace_bytes(&self) -> &[u8] { + self.namespace.as_slice() + } + + /// Returns a shared reference to the Rust identifier of the trait. + pub fn trait_ident(&self) -> &'a syn::Ident { + &self.trait_ident + } +} + impl Selector { /// Creates a new selector from the given raw bytes. pub fn from_bytes(bytes: [u8; 4]) -> Self { @@ -37,6 +73,58 @@ impl Selector { Self::from_bytes([output[0], output[1], output[2], output[3]]) } + /// # Note + /// + /// - `trait_prefix` is `None` when computing the selector of ink! constructors + /// and messages in inherent implementation blocks. + /// - `trait_prefix` is `Some` when computing the selector of ink! constructors + /// and messages in trait implementation blocks. In this case the `namespace` + /// is either the full path of the trait definition gained by Rust's + /// `module_path!` macro by default or it is customized by manual application + /// of the `#[ink(namespace = "my_namespace")]` ink! attribute. In the + /// example `my_namespace` concatenated with `::` and the identifier of the + /// trait definition would then be part of the provided `trait_prefix` parameter. + /// - `fn_ident` refers to the ink! constructor or message identifier. + /// + /// # Inherent Implementation Blocks + /// + /// For inherent implementation blocks, when `trait_prefix` is `None` the composed + /// selector is computed as follows: + /// + /// 1. Apply `BLAKE2` 256-bit hash `H` on the bytes of the ascii representation of + /// the `fn_ident` identifier. + /// 1. The first 4 bytes of `H` make up the selector. + /// + /// # Trait Implementation Blocks + /// + /// For trait implementation blocks, when `trait_prefix` is + /// `Some((namespace, trait_ident))` the composed selector is computed as follows: + /// + /// 1. Compute the ascii byte representation of `fn_ident` and call it `F`. + /// 1. Compute the ascii byte representation of `namespace` and call it `N`. + /// 1. Compute the ascii byte representation of `trait_ident` and call it `T`. + /// 1. Concatenate `N`, `T` and `F` using `::` as separator and call it `C`. + /// 1. Apply the `BLAKE2` 256-bit hash `H` of `C`. + /// 1. The first 4 bytes of `H` make up the selector. + pub fn compose<'a, T>(trait_prefix: T, fn_ident: &syn::Ident) -> Self + where + T: Into>>, + { + let separator = &b"::"[..]; + let fn_ident = fn_ident.to_string().into_bytes(); + let input_bytes: Vec = match trait_prefix.into() { + Some(trait_prefix) => { + let namespace = trait_prefix.namespace_bytes(); + let trait_ident = trait_prefix.trait_ident().to_string().into_bytes(); + [namespace, &trait_ident, &fn_ident].join(separator) + } + None => { + fn_ident.to_vec() + } + }; + Self::new(&input_bytes) + } + /// Returns the underlying four bytes. pub fn as_bytes(&self) -> &[u8; 4] { &self.bytes From 3f5b67e0952b4fcd4cc74bea75ec2c6624d606a7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 3 Mar 2021 17:17:52 +0100 Subject: [PATCH 010/493] apply rustfmt --- crates/lang/ir/src/ir/selector.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index eb4623e00c..f62c70462e 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -118,9 +118,7 @@ impl Selector { let trait_ident = trait_prefix.trait_ident().to_string().into_bytes(); [namespace, &trait_ident, &fn_ident].join(separator) } - None => { - fn_ident.to_vec() - } + None => fn_ident.to_vec(), }; Self::new(&input_bytes) } From 4a313d82dbc23a6dfc8e3dcfe052e3cb9ea58db9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 3 Mar 2021 23:15:23 +0100 Subject: [PATCH 011/493] refactor attribute getters for InkTrait{Message, Constructor} --- crates/lang/ir/src/ir/trait_def.rs | 97 ++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 26 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index c6cbdc54b5..eab6de2f3e 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use super::attrs::InkAttribute; use crate::{ ir, ir::idents_lint, @@ -210,9 +211,43 @@ pub struct InkTraitConstructor<'a> { } impl<'a> InkTraitConstructor<'a> { + /// Panic message in case a user encounters invalid attributes. + const INVALID_ATTRIBUTES_ERRSTR: &'static str = + "encountered invalid attributes for ink! trait constructor"; + + /// Analyses and extracts the ink! and non-ink! attributes of an ink! trait constructor. + fn extract_attributes( + span: Span, + attrs: &[syn::Attribute], + ) -> Result<(InkAttribute, Vec)> { + let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes( + span, + attrs.iter().cloned(), + &ir::AttributeArgKind::Constructor, + |arg| { + match arg.kind() { + ir::AttributeArg::Constructor | ir::AttributeArg::Selector(_) => { + Ok(()) + } + _ => Err(None), + } + }, + )?; + Ok((ink_attrs, non_ink_attrs)) + } + /// Returns all non-ink! attributes. pub fn attrs(&self) -> Vec { - extract_rust_attributes(&self.item.attrs) + let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + rust_attrs + } + + /// Returns all ink! attributes. + fn ink_attrs(&self) -> InkAttribute { + let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + ink_attrs } /// Returns the original signature of the ink! constructor. @@ -233,9 +268,41 @@ pub struct InkTraitMessage<'a> { } impl<'a> InkTraitMessage<'a> { + /// Panic message in case a user encounters invalid attributes. + const INVALID_ATTRIBUTES_ERRSTR: &'static str = + "encountered invalid attributes for ink! trait message"; + + /// Analyses and extracts the ink! and non-ink! attributes of an ink! trait message. + fn extract_attributes( + span: Span, + attrs: &[syn::Attribute], + ) -> Result<(InkAttribute, Vec)> { + let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes( + span, + attrs.iter().cloned(), + &ir::AttributeArgKind::Message, + |arg| { + match arg.kind() { + ir::AttributeArg::Message | ir::AttributeArg::Selector(_) => Ok(()), + _ => Err(None), + } + }, + )?; + Ok((ink_attrs, non_ink_attrs)) + } + /// Returns all non-ink! attributes. pub fn attrs(&self) -> Vec { - extract_rust_attributes(&self.item.attrs) + let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + rust_attrs + } + + /// Returns all ink! attributes. + fn ink_attrs(&self) -> InkAttribute { + let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + ink_attrs } /// Returns the original signature of the ink! message. @@ -494,18 +561,7 @@ impl InkTrait { /// - If the constructor has a `self` receiver as first argument. /// - If the constructor has no `Self` return type. fn analyse_constructor(constructor: &syn::TraitItemMethod) -> Result<()> { - ir::sanitize_attributes( - constructor.span(), - constructor.attrs.clone(), - &ir::AttributeArgKind::Constructor, - |arg| { - match arg.kind() { - ir::AttributeArg::Constructor | - ir::AttributeArg::Selector(_) => Ok(()), - _ => Err(None), - } - }, - )?; + InkTraitConstructor::extract_attributes(constructor.span(), &constructor.attrs)?; if let Some(receiver) = constructor.sig.receiver() { return Err(format_err_spanned!( receiver, @@ -547,18 +603,7 @@ impl InkTrait { /// /// - If the message has no `&self` or `&mut self` receiver. fn analyse_message(message: &syn::TraitItemMethod) -> Result<()> { - ir::sanitize_attributes( - message.span(), - message.attrs.clone(), - &ir::AttributeArgKind::Message, - |arg| { - match arg.kind() { - ir::AttributeArg::Message | - ir::AttributeArg::Selector(_) => Ok(()), - _ => Err(None), - } - }, - )?; + InkTraitMessage::extract_attributes(message.span(), &message.attrs)?; match message.sig.receiver() { None | Some(syn::FnArg::Typed(_)) => { return Err(format_err_spanned!( From d7dce293cd5c48b5d44e5cd8ee183656414afac0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 12:34:53 +0100 Subject: [PATCH 012/493] minor refactoring in Selector::compose --- crates/lang/ir/src/ir/selector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index f62c70462e..85a70346b0 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -110,12 +110,12 @@ impl Selector { where T: Into>>, { - let separator = &b"::"[..]; let fn_ident = fn_ident.to_string().into_bytes(); let input_bytes: Vec = match trait_prefix.into() { Some(trait_prefix) => { let namespace = trait_prefix.namespace_bytes(); let trait_ident = trait_prefix.trait_ident().to_string().into_bytes(); + let separator = &b"::"[..]; [namespace, &trait_ident, &fn_ident].join(separator) } None => fn_ident.to_vec(), From cf5e468be6d387b4daf5f8cb4aca9eaf11bc16bf Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 13:49:09 +0100 Subject: [PATCH 013/493] impl Default for Namespace --- crates/lang/ir/src/ir/attrs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index da65d48791..6e72236a98 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -484,7 +484,7 @@ impl core::fmt::Display for AttributeArg { } /// An ink! namespace applicable to a trait implementation block. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Namespace { /// The underlying bytes. bytes: Vec, From fbd43d07936c0830300e4af5c4ad90d943a6cc79 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 13:49:39 +0100 Subject: [PATCH 014/493] allow ir::sanitize_attributes to handle cases with no first attribute This does not break existing code. --- crates/lang/ir/src/ir/attrs.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 6e72236a98..b7df087b98 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -585,13 +585,14 @@ where /// - If there are duplicate ink! attributes. /// - If the first ink! attribute is not matching the expected. /// - If there are conflicting ink! attributes. -pub fn sanitize_attributes( +pub fn sanitize_attributes<'a, F, I, C>( parent_span: Span, attrs: I, - is_valid_first: &ir::AttributeArgKind, + is_valid_first: F, mut is_conflicting_attr: C, ) -> Result<(InkAttribute, Vec), syn::Error> where + F: Into>, I: IntoIterator, C: FnMut(&ir::AttributeFrag) -> Result<(), Option>, { @@ -599,13 +600,15 @@ where let normalized = ir::InkAttribute::from_expanded(ink_attrs).map_err(|err| { err.into_combine(format_err!(parent_span, "at this invocation",)) })?; - normalized.ensure_first(is_valid_first).map_err(|err| { - err.into_combine(format_err!( - parent_span, - "expected {} as first ink! attribute argument", - is_valid_first, - )) - })?; + if let Some(is_valid_first) = is_valid_first.into() { + normalized.ensure_first(is_valid_first).map_err(|err| { + err.into_combine(format_err!( + parent_span, + "expected {} as first ink! attribute argument", + is_valid_first, + )) + })?; + } normalized.ensure_no_conflicts(|arg| is_conflicting_attr(arg))?; Ok((normalized, other_attrs)) } From ad8447afc4b908e0ff046870c9044f5133237595 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 13:49:55 +0100 Subject: [PATCH 015/493] make use of Namespace instead of using raw Vec --- crates/lang/ir/src/ir/selector.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 85a70346b0..98d02e56bb 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::Namespace; + use super::blake2::blake2b_256; /// A function selector. @@ -25,33 +27,30 @@ pub struct Selector { } /// The trait prefix to compute a composed selector for trait implementation blocks. -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub struct TraitPrefix<'a> { /// The namespace of the ink! trait definition. /// /// By default this is equal to the `module_path!` at the ink! trait definition site. /// It can be customized by the ink! trait definition author using `#[ink(namespace = N)]` /// ink! attribute. - namespace: Vec, + namespace: &'a Namespace, /// The Rust identifier of the ink! trait definition. trait_ident: &'a syn::Ident, } impl<'a> TraitPrefix<'a> { /// Creates a new trait prefix. - pub fn new(trait_ident: &'a syn::Ident, namespace: N) -> Self - where - N: IntoIterator, - { + pub fn new(trait_ident: &'a syn::Ident, namespace: &'a Namespace) -> Self { Self { trait_ident, - namespace: namespace.into_iter().collect::>(), + namespace, } } /// Returns a shared slice over the bytes of the namespace. pub fn namespace_bytes(&self) -> &[u8] { - self.namespace.as_slice() + self.namespace.as_bytes() } /// Returns a shared reference to the Rust identifier of the trait. From 378b8552fc5f4b14c14e6defbc88b413d4cd498c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:24:36 +0100 Subject: [PATCH 016/493] rollback changes to sanitize_attributes We are going to introduce just another API. --- crates/lang/ir/src/ir/attrs.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index b7df087b98..8b172db8ad 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -585,14 +585,14 @@ where /// - If there are duplicate ink! attributes. /// - If the first ink! attribute is not matching the expected. /// - If there are conflicting ink! attributes. -pub fn sanitize_attributes<'a, F, I, C>( +/// - if there are no ink! attributes. +pub fn sanitize_attributes( parent_span: Span, attrs: I, - is_valid_first: F, + is_valid_first: &ir::AttributeArgKind, mut is_conflicting_attr: C, ) -> Result<(InkAttribute, Vec), syn::Error> where - F: Into>, I: IntoIterator, C: FnMut(&ir::AttributeFrag) -> Result<(), Option>, { @@ -600,15 +600,13 @@ where let normalized = ir::InkAttribute::from_expanded(ink_attrs).map_err(|err| { err.into_combine(format_err!(parent_span, "at this invocation",)) })?; - if let Some(is_valid_first) = is_valid_first.into() { - normalized.ensure_first(is_valid_first).map_err(|err| { - err.into_combine(format_err!( - parent_span, - "expected {} as first ink! attribute argument", - is_valid_first, - )) - })?; - } + normalized.ensure_first(is_valid_first).map_err(|err| { + err.into_combine(format_err!( + parent_span, + "expected {} as first ink! attribute argument", + is_valid_first, + )) + })?; normalized.ensure_no_conflicts(|arg| is_conflicting_attr(arg))?; Ok((normalized, other_attrs)) } From 3c3c98d70918063c60bddf9b75f30d2fe6b8c1a3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:25:03 +0100 Subject: [PATCH 017/493] add ir::sanitize_optional_attributes --- crates/lang/ir/src/ir/attrs.rs | 39 ++++++++++++++++++++++++++++++++++ crates/lang/ir/src/ir/mod.rs | 1 + 2 files changed, 40 insertions(+) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 8b172db8ad..3da2dbb385 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -611,6 +611,45 @@ where Ok((normalized, other_attrs)) } +/// Sanitizes the given optional attributes. +/// +/// This partitions the attributes into ink! and non-ink! attributes. +/// If there are ink! attributes they are normalized and deduplicated. +/// Also checks to guard against conflicting ink! attributes are provided. +/// +/// Returns the optional partitioned ink! and non-ink! attributes. +/// +/// # Parameters +/// +/// The `is_conflicting_attr` closure returns `Ok` if the attribute does not conflict, +/// returns `Err(None)` if the attribute conflicts but without providing further reasoning +/// and `Err(Some(reason))` if the attribute conflicts given additional context information. +/// +/// # Errors +/// +/// - If there are invalid ink! attributes. +/// - If there are duplicate ink! attributes. +/// - If there are conflicting ink! attributes. +pub fn sanitize_optional_attributes( + parent_span: Span, + attrs: I, + mut is_conflicting_attr: C, +) -> Result<(Option, Vec), syn::Error> +where + I: IntoIterator, + C: FnMut(&ir::AttributeFrag) -> Result<(), Option>, +{ + let (ink_attrs, rust_attrs) = ir::partition_attributes(attrs)?; + if ink_attrs.is_empty() { + return Ok((None, rust_attrs)) + } + let normalized = ir::InkAttribute::from_expanded(ink_attrs).map_err(|err| { + err.into_combine(format_err!(parent_span, "at this invocation",)) + })?; + normalized.ensure_no_conflicts(|arg| is_conflicting_attr(arg))?; + Ok((Some(normalized), rust_attrs)) +} + impl Attribute { /// Returns `Ok` if the given iterator yields no duplicate ink! attributes. /// diff --git a/crates/lang/ir/src/ir/mod.rs b/crates/lang/ir/src/ir/mod.rs index ad5984853b..5140748976 100644 --- a/crates/lang/ir/src/ir/mod.rs +++ b/crates/lang/ir/src/ir/mod.rs @@ -36,6 +36,7 @@ use self::attrs::{ first_ink_attribute, partition_attributes, sanitize_attributes, + sanitize_optional_attributes, AttributeArg, AttributeArgKind, AttributeFrag, From 9e08d2ceb6ddd28c68a86570a4efd2bf29f7cea8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:25:42 +0100 Subject: [PATCH 018/493] add InkTraitItem::ident --- crates/lang/ir/src/ir/trait_def.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index eab6de2f3e..94b032bb9e 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -176,6 +176,14 @@ pub enum InkTraitItem<'a> { } impl<'a> InkTraitItem<'a> { + /// Returns the Rust identifier of the ink! trait item. + pub fn ident(&self) -> &syn::Ident { + match self { + Self::Constructor(constructor) => constructor.ident(), + Self::Message(message) => message.ident(), + } + } + /// Returns `Some` if the ink! trait item is a constructor. pub fn filter_map_constructor(self) -> Option> { match self { @@ -255,6 +263,11 @@ impl<'a> InkTraitConstructor<'a> { &self.item.sig } + /// Returns the Rust identifier of the ink! constructor. + pub fn ident(&self) -> &syn::Ident { + &self.item.sig.ident + } + /// Returns the span of the ink! constructor. pub fn span(&self) -> Span { self.item.span() @@ -310,6 +323,11 @@ impl<'a> InkTraitMessage<'a> { &self.item.sig } + /// Returns the Rust identifier of the ink! message. + pub fn ident(&self) -> &syn::Ident { + &self.item.sig.ident + } + /// Returns the span of the ink! message. pub fn span(&self) -> Span { self.item.span() From 91fe0f62240114c563935e402ab5cc8d511b4f35 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:26:03 +0100 Subject: [PATCH 019/493] add InkTraitItem::ink_attrs --- crates/lang/ir/src/ir/trait_def.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index 94b032bb9e..db03ef3c5f 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -184,6 +184,14 @@ impl<'a> InkTraitItem<'a> { } } + /// Returns the ink! attributes of the ink! trait item. + pub fn ink_attrs(&self) -> InkAttribute { + match self { + Self::Constructor(constructor) => constructor.ink_attrs(), + Self::Message(message) => message.ink_attrs(), + } + } + /// Returns `Some` if the ink! trait item is a constructor. pub fn filter_map_constructor(self) -> Option> { match self { @@ -252,7 +260,7 @@ impl<'a> InkTraitConstructor<'a> { } /// Returns all ink! attributes. - fn ink_attrs(&self) -> InkAttribute { + pub fn ink_attrs(&self) -> InkAttribute { let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) .expect(Self::INVALID_ATTRIBUTES_ERRSTR); ink_attrs @@ -312,7 +320,7 @@ impl<'a> InkTraitMessage<'a> { } /// Returns all ink! attributes. - fn ink_attrs(&self) -> InkAttribute { + pub fn ink_attrs(&self) -> InkAttribute { let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) .expect(Self::INVALID_ATTRIBUTES_ERRSTR); ink_attrs From b63f5d4a1013a9bd9fe197e0f66ae55d69914676 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:26:17 +0100 Subject: [PATCH 020/493] allow #[ink(payable)] for ink! trait messages --- crates/lang/ir/src/ir/trait_def.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index db03ef3c5f..a52eacd573 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -304,7 +304,9 @@ impl<'a> InkTraitMessage<'a> { &ir::AttributeArgKind::Message, |arg| { match arg.kind() { - ir::AttributeArg::Message | ir::AttributeArg::Selector(_) => Ok(()), + ir::AttributeArg::Message + | ir::AttributeArg::Payable + | ir::AttributeArg::Selector(_) => Ok(()), _ => Err(None), } }, From d5f8ca17ebeeb765461389332c8c2c362bf16954 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:30:22 +0100 Subject: [PATCH 021/493] implement ink! trait definition selectors extraction --- crates/lang/ir/src/ir/trait_def.rs | 80 +++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index a52eacd573..5a9b592556 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -16,13 +16,16 @@ use super::attrs::InkAttribute; use crate::{ ir, ir::idents_lint, + Selector, }; use core::convert::TryFrom; +use ir::TraitPrefix; use proc_macro2::{ Ident, Span, TokenStream as TokenStream2, }; +use std::collections::HashMap; use syn::{ spanned::Spanned as _, Result, @@ -32,6 +35,8 @@ use syn::{ #[derive(Debug, PartialEq, Eq)] pub struct InkTrait { item: syn::ItemTrait, + message_selectors: HashMap, + constructor_selectors: HashMap, } impl TryFrom for InkTrait { @@ -41,7 +46,18 @@ impl TryFrom for InkTrait { idents_lint::ensure_no_ink_identifiers(&item_trait)?; Self::analyse_properties(&item_trait)?; Self::analyse_items(&item_trait)?; - Ok(Self { item: item_trait }) + let mut message_selectors = >::new(); + let mut constructor_selectors = >::new(); + Self::extract_selectors( + &item_trait, + &mut message_selectors, + &mut constructor_selectors, + ); + Ok(Self { + item: item_trait, + message_selectors, + constructor_selectors, + }) } } @@ -131,6 +147,13 @@ impl<'a> IterInkTraitItems<'a> { iter: item_trait.item.items.iter(), } } + + /// Creates a new iterator yielding ink! trait items over the raw Rust trait definition. + fn from_raw(item_trait: &'a syn::ItemTrait) -> Self { + Self { + iter: item_trait.items.iter(), + } + } } impl<'a> Iterator for IterInkTraitItems<'a> { @@ -650,6 +673,59 @@ impl InkTrait { } Ok(()) } + + /// Extract selectors for ink! trait constructors and messages. + /// + /// The composed or manually specified selectors are stored into the provided + /// hashtables for later look-up when querying ink! constructors or messages. + /// This way we are more flexible with regard to the underlying structures of the IR. + /// + /// In this step we assume that all sanitation checks have taken place prior so + /// instead of returning errors we simply panic upon failures. + fn extract_selectors( + item_trait: &syn::ItemTrait, + message_selectors: &mut HashMap, + constructor_selectors: &mut HashMap, + ) { + let (ink_attrs, _) = ir::sanitize_optional_attributes( + item_trait.span(), + item_trait.attrs.iter().cloned(), + |arg| { + match arg.kind() { + ir::AttributeArg::Namespace(_) => Ok(()), + _ => Err(None), + } + }, + ) + .expect("encountered unexpected invalid attributes on ink! trait definition"); + let namespace = ink_attrs + .as_ref() + .map(InkAttribute::namespace) + .flatten() + .unwrap_or_else(Default::default); + let ident = &item_trait.ident; + let trait_prefix = TraitPrefix::new(ident, &namespace); + for callable in IterInkTraitItems::from_raw(item_trait) { + let ident = callable.ident(); + let ink_attrs = callable.ink_attrs(); + let selector = match ink_attrs.selector() { + Some(manual_selector) => manual_selector, + None => Selector::compose(trait_prefix, ident), + }; + let prev = match callable { + InkTraitItem::Constructor(_) => { + constructor_selectors.insert(ident.clone(), selector) + } + InkTraitItem::Message(_) => { + message_selectors.insert(ident.clone(), selector) + } + }; + assert!( + prev.is_none(), + "encountered unexpected overlapping ink! trait constructor or message" + ); + } + } } #[cfg(test)] @@ -1039,7 +1115,7 @@ mod tests { error: "encountered conflicting ink! attribute argument", pub trait MyTrait { #[ink(message)] - #[ink(payable)] + #[ink(anonymous)] fn does_not_return_self(&self); } ); From 03ec44d9053566bfd8471bae3a4a8e291ef404ff Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:45:01 +0100 Subject: [PATCH 022/493] add check for overlapping ink! trait constructor and message selectors --- crates/lang/ir/src/ir/trait_def.rs | 58 ++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index 5a9b592556..c8e17ba7c4 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -52,7 +52,7 @@ impl TryFrom for InkTrait { &item_trait, &mut message_selectors, &mut constructor_selectors, - ); + )?; Ok(Self { item: item_trait, message_selectors, @@ -682,11 +682,19 @@ impl InkTrait { /// /// In this step we assume that all sanitation checks have taken place prior so /// instead of returning errors we simply panic upon failures. + /// + /// # Errors + /// + /// Returns an error if there are overlapping selectors for ink! constructors + /// or ink! messages. Note that overlaps between ink! constructor and message + /// selectors are allowed. fn extract_selectors( item_trait: &syn::ItemTrait, message_selectors: &mut HashMap, constructor_selectors: &mut HashMap, - ) { + ) -> Result<()> { + let mut seen_constructor_selectors = >::new(); + let mut seen_message_selectors = >::new(); let (ink_attrs, _) = ir::sanitize_optional_attributes( item_trait.span(), item_trait.attrs.iter().cloned(), @@ -712,19 +720,39 @@ impl InkTrait { Some(manual_selector) => manual_selector, None => Selector::compose(trait_prefix, ident), }; - let prev = match callable { + let (duplicate_selector, duplicate_ident) = match callable { InkTraitItem::Constructor(_) => { - constructor_selectors.insert(ident.clone(), selector) + let duplicate_selector = + seen_constructor_selectors.insert(selector, ident.clone()); + let duplicate_ident = + constructor_selectors.insert(ident.clone(), selector); + (duplicate_selector, duplicate_ident) } InkTraitItem::Message(_) => { - message_selectors.insert(ident.clone(), selector) + let duplicate_selector = + seen_message_selectors.insert(selector, ident.clone()); + let duplicate_ident = + message_selectors.insert(ident.clone(), selector); + (duplicate_selector, duplicate_ident) } }; + if let Some(duplicate_selector) = duplicate_selector { + use crate::error::ExtError as _; + return Err(format_err_spanned!( + ident, + "encountered duplicate selector ({:x?}) in the same ink! trait definition", + selector.as_bytes(), + ).into_combine(format_err_spanned!( + duplicate_selector, + "first ink! trait constructor or message with same selector found here", + ))) + } assert!( - prev.is_none(), - "encountered unexpected overlapping ink! trait constructor or message" + duplicate_ident.is_none(), + "encountered unexpected overlapping ink! trait constructor or message identifier", ); } + Ok(()) } } @@ -1155,6 +1183,22 @@ mod tests { ) } + #[test] + fn trait_def_with_overlapping_selectors() { + assert_ink_trait_eq_err!( + error: "encountered duplicate selector ([c0, de, ca, fe]) \ + in the same ink! trait definition", + pub trait MyTrait { + #[ink(constructor, selector = "0xC0DECAFE")] + fn my_constructor() -> Self; + #[ink(message, selector = "0xC0DECAFE")] + fn my_message(&self); + #[ink(message, selector = "0xC0DECAFE")] + fn my_message_mut(&mut self); + } + ); + } + #[test] fn iter_constructors_works() { let ink_trait = From 75742e7f24790784429c84057bbbf43fe32aff80 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:53:13 +0100 Subject: [PATCH 023/493] add test for payable ink! trait messages --- crates/lang/ir/src/ir/trait_def.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index c8e17ba7c4..ed3a3ffb15 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -1183,6 +1183,21 @@ mod tests { ) } + #[test] + fn trait_def_with_payable_ok() { + assert!( + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(message, payable)] + fn my_message(&self); + #[ink(message, payable)] + fn my_message_mut(&mut self); + } + }) + .is_ok() + ) + } + #[test] fn trait_def_with_overlapping_selectors() { assert_ink_trait_eq_err!( From e05768e7f9b72a249feae1e9aeeb697f1ab68f2c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:56:13 +0100 Subject: [PATCH 024/493] add unit test using ink! trait definition with namespace attribute --- crates/lang/ir/src/ir/trait_def.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index ed3a3ffb15..d9f8be508e 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -1166,6 +1166,24 @@ mod tests { ) } + #[test] + fn trait_def_with_namespace_is_ok() { + assert!( + >::try_from(syn::parse_quote! { + #[ink(namespace = "my_namespace")] + pub trait MyTrait { + #[ink(constructor)] + fn my_constructor() -> Self; + #[ink(message)] + fn my_message(&self); + #[ink(message)] + fn my_message_mut(&mut self); + } + }) + .is_ok() + ) + } + #[test] fn trait_def_with_selectors_ok() { assert!( From 08c6594b81aa965922882834baf746d3e761a5e9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 14:58:52 +0100 Subject: [PATCH 025/493] add unit test testing all valid combinations with attributes --- crates/lang/ir/src/ir/trait_def.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def.rs index d9f8be508e..c984969fec 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def.rs @@ -1216,6 +1216,34 @@ mod tests { ) } + #[test] + fn trait_def_with_everything_combined_ok() { + assert!( + >::try_from(syn::parse_quote! { + #[ink(namespace = "my_namespace")] + pub trait MyTrait { + #[ink(constructor)] + fn my_constructor_1() -> Self; + #[ink(constructor, selector = "0xC0DECAFE")] + fn my_constructor_2() -> Self; + #[ink(message)] + fn my_message_1(&self); + #[ink(message, payable)] + fn my_message_2(&self); + #[ink(message, payable, selector = "0xDEADBEEF")] + fn my_message_3(&self); + #[ink(message)] + fn my_message_mut_1(&mut self); + #[ink(message, payable)] + fn my_message_mut_2(&mut self); + #[ink(message, payable, selector = "0xC0DEBEEF")] + fn my_message_mut_3(&mut self); + } + }) + .is_ok() + ) + } + #[test] fn trait_def_with_overlapping_selectors() { assert_ink_trait_eq_err!( From dc7798ca9478d15d603a94af74f628193c981200 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 15:04:17 +0100 Subject: [PATCH 026/493] move trait_def.rs into its own module directory This is to move unit tests into their own file to improve compile times. --- .../src/ir/{trait_def.rs => trait_def/mod.rs} | 635 +---------------- crates/lang/ir/src/ir/trait_def/tests.rs | 642 ++++++++++++++++++ 2 files changed, 645 insertions(+), 632 deletions(-) rename crates/lang/ir/src/ir/{trait_def.rs => trait_def/mod.rs} (57%) create mode 100644 crates/lang/ir/src/ir/trait_def/tests.rs diff --git a/crates/lang/ir/src/ir/trait_def.rs b/crates/lang/ir/src/ir/trait_def/mod.rs similarity index 57% rename from crates/lang/ir/src/ir/trait_def.rs rename to crates/lang/ir/src/ir/trait_def/mod.rs index c984969fec..0155ae20d7 100644 --- a/crates/lang/ir/src/ir/trait_def.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(test)] +mod tests; + use super::attrs::InkAttribute; use crate::{ ir, @@ -755,635 +758,3 @@ impl InkTrait { Ok(()) } } - -#[cfg(test)] -mod tests { - use super::*; - - /// Checks if the token stream in `$trait_def` results in the expected error message. - macro_rules! assert_ink_trait_eq_err { - ( error: $err_str:literal, $($trait_def:tt)* ) => { - assert_eq!( - >::try_from(syn::parse_quote! { - $( $trait_def )* - }) - .map_err(|err| err.to_string()), - Err( - $err_str.to_string() - ) - ) - }; - } - - #[test] - fn unsafe_trait_def_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! trait definitions cannot be unsafe", - pub unsafe trait MyTrait {} - ); - } - - #[test] - fn auto_trait_def_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! trait definitions cannot be automatically implemented traits", - pub auto trait MyTrait {} - ); - } - - #[test] - fn non_pub_trait_def_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! trait definitions must have public visibility", - trait MyTrait {} - ); - assert_ink_trait_eq_err!( - error: "ink! trait definitions must have public visibility", - pub(crate) trait MyTrait {} - ); - } - - #[test] - fn generic_trait_def_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! trait definitions must not be generic", - pub trait MyTrait {} - ); - } - - #[test] - fn trait_def_with_supertraits_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! trait definitions with supertraits are not supported, yet", - pub trait MyTrait: SuperTrait {} - ); - } - - #[test] - fn trait_def_containing_const_item_is_denied() { - assert_ink_trait_eq_err!( - error: "associated constants in ink! trait definitions are not supported, yet", - pub trait MyTrait { - const T: i32; - } - ); - } - - #[test] - fn trait_def_containing_associated_type_is_denied() { - assert_ink_trait_eq_err!( - error: "associated types in ink! trait definitions are not supported, yet", - pub trait MyTrait { - type Type; - } - ); - } - - #[test] - fn trait_def_containing_macro_is_denied() { - assert_ink_trait_eq_err!( - error: "macros in ink! trait definitions are not supported", - pub trait MyTrait { - my_macro_call!(); - } - ); - } - - #[test] - fn trait_def_containing_non_flagged_method_is_denied() { - assert_ink_trait_eq_err!( - error: "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method", - pub trait MyTrait { - fn non_flagged_1(&self); - } - ); - assert_ink_trait_eq_err!( - error: "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method", - pub trait MyTrait { - fn non_flagged_2(&mut self); - } - ); - assert_ink_trait_eq_err!( - error: "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method", - pub trait MyTrait { - fn non_flagged_3() -> Self; - } - ); - } - - #[test] - fn trait_def_containing_default_implemented_methods_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! trait methods with default implementations are not supported", - pub trait MyTrait { - #[ink(constructor)] - fn default_implemented() -> Self {} - } - ); - assert_ink_trait_eq_err!( - error: "ink! trait methods with default implementations are not supported", - pub trait MyTrait { - #[ink(message)] - fn default_implemented(&self) {} - } - ); - } - - #[test] - fn trait_def_containing_const_methods_is_denied() { - assert_ink_trait_eq_err!( - error: "const ink! trait methods are not supported", - pub trait MyTrait { - #[ink(constructor)] - const fn const_constructor() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "const ink! trait methods are not supported", - pub trait MyTrait { - #[ink(message)] - const fn const_message(&self); - } - ); - } - - #[test] - fn trait_def_containing_async_methods_is_denied() { - assert_ink_trait_eq_err!( - error: "async ink! trait methods are not supported", - pub trait MyTrait { - #[ink(constructor)] - async fn const_constructor() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "async ink! trait methods are not supported", - pub trait MyTrait { - #[ink(message)] - async fn const_message(&self); - } - ); - } - - #[test] - fn trait_def_containing_unsafe_methods_is_denied() { - assert_ink_trait_eq_err!( - error: "unsafe ink! trait methods are not supported", - pub trait MyTrait { - #[ink(constructor)] - unsafe fn const_constructor() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "unsafe ink! trait methods are not supported", - pub trait MyTrait { - #[ink(message)] - unsafe fn const_message(&self); - } - ); - } - - #[test] - fn trait_def_containing_methods_using_explicit_abi_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! trait methods with non default ABI are not supported", - pub trait MyTrait { - #[ink(constructor)] - extern fn const_constructor() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! trait methods with non default ABI are not supported", - pub trait MyTrait { - #[ink(message)] - extern fn const_message(&self); - } - ); - } - - #[test] - fn trait_def_containing_variadic_methods_is_denied() { - assert_ink_trait_eq_err!( - error: "variadic ink! trait methods are not supported", - pub trait MyTrait { - #[ink(constructor)] - fn const_constructor(...) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "variadic ink! trait methods are not supported", - pub trait MyTrait { - #[ink(message)] - fn const_message(&self, ...); - } - ); - } - - #[test] - fn trait_def_containing_generic_methods_is_denied() { - assert_ink_trait_eq_err!( - error: "generic ink! trait methods are not supported", - pub trait MyTrait { - #[ink(constructor)] - fn const_constructor() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "generic ink! trait methods are not supported", - pub trait MyTrait { - #[ink(message)] - fn const_message(&self); - } - ); - } - - #[test] - fn trait_def_containing_method_with_unsupported_ink_attribute_is_denied() { - assert_ink_trait_eq_err!( - error: "encountered unsupported ink! attribute for ink! trait method", - pub trait MyTrait { - #[ink(payable)] - fn unsupported_ink_attribute(&self); - } - ); - assert_ink_trait_eq_err!( - error: "unknown ink! attribute (path)", - pub trait MyTrait { - #[ink(unknown)] - fn unknown_ink_attribute(&self); - } - ); - } - - #[test] - fn trait_def_containing_invalid_constructor_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(&self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(&mut self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(self: &Self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(self: Self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must return Self", - pub trait MyTrait { - #[ink(constructor)] - fn does_not_return_self(); - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must return Self", - pub trait MyTrait { - #[ink(constructor)] - fn does_not_return_self() -> i32; - } - ); - } - - #[test] - fn trait_def_containing_invalid_message_is_denied() { - assert_ink_trait_eq_err!( - error: "missing or malformed `&self` or `&mut self` receiver for ink! message", - pub trait MyTrait { - #[ink(message)] - fn does_not_return_self(); - } - ); - assert_ink_trait_eq_err!( - error: "missing or malformed `&self` or `&mut self` receiver for ink! message", - pub trait MyTrait { - #[ink(message)] - fn does_not_return_self(self: &Self); - } - ); - assert_ink_trait_eq_err!( - error: "self receiver of ink! message must be `&self` or `&mut self`", - pub trait MyTrait { - #[ink(message)] - fn does_not_return_self(self); - } - ); - } - - #[test] - fn trait_def_containing_constructor_with_invalid_ink_attributes_is_denied() { - assert_ink_trait_eq_err!( - error: "encountered duplicate ink! attribute", - pub trait MyTrait { - #[ink(constructor)] - #[ink(constructor)] - fn does_not_return_self() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "encountered conflicting ink! attribute argument", - pub trait MyTrait { - #[ink(constructor)] - #[ink(message)] - fn does_not_return_self() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "encountered conflicting ink! attribute argument", - pub trait MyTrait { - #[ink(constructor)] - #[ink(payable)] - fn does_not_return_self() -> Self; - } - ); - } - - #[test] - fn trait_def_containing_message_with_invalid_ink_attributes_is_denied() { - assert_ink_trait_eq_err!( - error: "encountered duplicate ink! attribute", - pub trait MyTrait { - #[ink(message)] - #[ink(message)] - fn does_not_return_self(&self); - } - ); - assert_ink_trait_eq_err!( - error: "encountered conflicting ink! attribute argument", - pub trait MyTrait { - #[ink(message)] - #[ink(constructor)] - fn does_not_return_self(&self); - } - ); - assert_ink_trait_eq_err!( - error: "encountered conflicting ink! attribute argument", - pub trait MyTrait { - #[ink(message)] - #[ink(anonymous)] - fn does_not_return_self(&self); - } - ); - } - - #[test] - fn trait_def_is_ok() { - assert!( - >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(constructor)] - fn my_constructor() -> Self; - #[ink(message)] - fn my_message(&self); - #[ink(message)] - fn my_message_mut(&mut self); - } - }) - .is_ok() - ) - } - - #[test] - fn trait_def_with_namespace_is_ok() { - assert!( - >::try_from(syn::parse_quote! { - #[ink(namespace = "my_namespace")] - pub trait MyTrait { - #[ink(constructor)] - fn my_constructor() -> Self; - #[ink(message)] - fn my_message(&self); - #[ink(message)] - fn my_message_mut(&mut self); - } - }) - .is_ok() - ) - } - - #[test] - fn trait_def_with_selectors_ok() { - assert!( - >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(constructor, selector = "0xC0DECAFE")] - fn my_constructor() -> Self; - #[ink(message, selector = "0xDEADBEEF")] - fn my_message(&self); - #[ink(message, selector = "0xC0FEFEED")] - fn my_message_mut(&mut self); - } - }) - .is_ok() - ) - } - - #[test] - fn trait_def_with_payable_ok() { - assert!( - >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(message, payable)] - fn my_message(&self); - #[ink(message, payable)] - fn my_message_mut(&mut self); - } - }) - .is_ok() - ) - } - - #[test] - fn trait_def_with_everything_combined_ok() { - assert!( - >::try_from(syn::parse_quote! { - #[ink(namespace = "my_namespace")] - pub trait MyTrait { - #[ink(constructor)] - fn my_constructor_1() -> Self; - #[ink(constructor, selector = "0xC0DECAFE")] - fn my_constructor_2() -> Self; - #[ink(message)] - fn my_message_1(&self); - #[ink(message, payable)] - fn my_message_2(&self); - #[ink(message, payable, selector = "0xDEADBEEF")] - fn my_message_3(&self); - #[ink(message)] - fn my_message_mut_1(&mut self); - #[ink(message, payable)] - fn my_message_mut_2(&mut self); - #[ink(message, payable, selector = "0xC0DEBEEF")] - fn my_message_mut_3(&mut self); - } - }) - .is_ok() - ) - } - - #[test] - fn trait_def_with_overlapping_selectors() { - assert_ink_trait_eq_err!( - error: "encountered duplicate selector ([c0, de, ca, fe]) \ - in the same ink! trait definition", - pub trait MyTrait { - #[ink(constructor, selector = "0xC0DECAFE")] - fn my_constructor() -> Self; - #[ink(message, selector = "0xC0DECAFE")] - fn my_message(&self); - #[ink(message, selector = "0xC0DECAFE")] - fn my_message_mut(&mut self); - } - ); - } - - #[test] - fn iter_constructors_works() { - let ink_trait = - >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2() -> Self; - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self); - } - }) - .unwrap(); - let actual = ink_trait - .iter_items() - .flat_map(|item| { - item.filter_map_constructor() - .map(|constructor| constructor.sig().ident.to_string()) - }) - .collect::>(); - let expected = vec!["constructor_1".to_string(), "constructor_2".to_string()]; - assert_eq!(actual, expected); - } - - #[test] - fn iter_messages_works() { - let ink_trait = - >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2() -> Self; - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self); - } - }) - .unwrap(); - let actual = ink_trait - .iter_items() - .flat_map(|item| { - item.filter_map_message() - .map(|message| message.sig().ident.to_string()) - }) - .collect::>(); - let expected = vec!["message_1".to_string(), "message_2".to_string()]; - assert_eq!(actual, expected); - } - - fn assert_verify_hash2_works_with(ink_trait: InkTrait, expected: &str) { - let expected = expected.to_string().into_bytes(); - let actual = ink_trait.verify_hash(); - let expected: [u8; 32] = { - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&expected).split(); - head_32.into() - }; - assert_eq!(actual, expected); - } - - macro_rules! ink_trait { - ( $($tt:tt)* ) => {{ - >::try_from(syn::parse_quote! { - $( $tt )* - }) - .unwrap() - }}; - } - - #[test] - fn verify_hash_works() { - let ink_trait = ink_trait! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2(a: i32, b: i32) -> Self; - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self, a: i32, b: i32) -> i32; - } - }; - assert_verify_hash2_works_with( - ink_trait, - "__ink_trait::MyTrait::constructor_1:0,constructor_2:2::message_1:1:r,message_2:3:w" - ); - } - - #[test] - fn verify_hash_works_without_constructors() { - let ink_trait = ink_trait! { - pub trait MyTrait { - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self, a: i32, b: i32) -> i32; - } - }; - assert_verify_hash2_works_with( - ink_trait, - "__ink_trait::MyTrait::message_1:1:r,message_2:3:w", - ); - } - - #[test] - fn verify_hash_works_without_messages() { - let ink_trait = ink_trait! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2(a: i32, b: i32) -> Self; - } - }; - assert_verify_hash2_works_with( - ink_trait, - "__ink_trait::MyTrait::constructor_1:0,constructor_2:2", - ); - } -} diff --git a/crates/lang/ir/src/ir/trait_def/tests.rs b/crates/lang/ir/src/ir/trait_def/tests.rs new file mode 100644 index 0000000000..801c750f4b --- /dev/null +++ b/crates/lang/ir/src/ir/trait_def/tests.rs @@ -0,0 +1,642 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::*; + +/// Checks if the token stream in `$trait_def` results in the expected error message. +macro_rules! assert_ink_trait_eq_err { + ( error: $err_str:literal, $($trait_def:tt)* ) => { + assert_eq!( + >::try_from(syn::parse_quote! { + $( $trait_def )* + }) + .map_err(|err| err.to_string()), + Err( + $err_str.to_string() + ) + ) + }; +} + +#[test] +fn unsafe_trait_def_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! trait definitions cannot be unsafe", + pub unsafe trait MyTrait {} + ); +} + +#[test] +fn auto_trait_def_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! trait definitions cannot be automatically implemented traits", + pub auto trait MyTrait {} + ); +} + +#[test] +fn non_pub_trait_def_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! trait definitions must have public visibility", + trait MyTrait {} + ); + assert_ink_trait_eq_err!( + error: "ink! trait definitions must have public visibility", + pub(crate) trait MyTrait {} + ); +} + +#[test] +fn generic_trait_def_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! trait definitions must not be generic", + pub trait MyTrait {} + ); +} + +#[test] +fn trait_def_with_supertraits_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! trait definitions with supertraits are not supported, yet", + pub trait MyTrait: SuperTrait {} + ); +} + +#[test] +fn trait_def_containing_const_item_is_denied() { + assert_ink_trait_eq_err!( + error: "associated constants in ink! trait definitions are not supported, yet", + pub trait MyTrait { + const T: i32; + } + ); +} + +#[test] +fn trait_def_containing_associated_type_is_denied() { + assert_ink_trait_eq_err!( + error: "associated types in ink! trait definitions are not supported, yet", + pub trait MyTrait { + type Type; + } + ); +} + +#[test] +fn trait_def_containing_macro_is_denied() { + assert_ink_trait_eq_err!( + error: "macros in ink! trait definitions are not supported", + pub trait MyTrait { + my_macro_call!(); + } + ); +} + +#[test] +fn trait_def_containing_non_flagged_method_is_denied() { + assert_ink_trait_eq_err!( + error: "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method", + pub trait MyTrait { + fn non_flagged_1(&self); + } + ); + assert_ink_trait_eq_err!( + error: "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method", + pub trait MyTrait { + fn non_flagged_2(&mut self); + } + ); + assert_ink_trait_eq_err!( + error: "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method", + pub trait MyTrait { + fn non_flagged_3() -> Self; + } + ); +} + +#[test] +fn trait_def_containing_default_implemented_methods_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! trait methods with default implementations are not supported", + pub trait MyTrait { + #[ink(constructor)] + fn default_implemented() -> Self {} + } + ); + assert_ink_trait_eq_err!( + error: "ink! trait methods with default implementations are not supported", + pub trait MyTrait { + #[ink(message)] + fn default_implemented(&self) {} + } + ); +} + +#[test] +fn trait_def_containing_const_methods_is_denied() { + assert_ink_trait_eq_err!( + error: "const ink! trait methods are not supported", + pub trait MyTrait { + #[ink(constructor)] + const fn const_constructor() -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "const ink! trait methods are not supported", + pub trait MyTrait { + #[ink(message)] + const fn const_message(&self); + } + ); +} + +#[test] +fn trait_def_containing_async_methods_is_denied() { + assert_ink_trait_eq_err!( + error: "async ink! trait methods are not supported", + pub trait MyTrait { + #[ink(constructor)] + async fn const_constructor() -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "async ink! trait methods are not supported", + pub trait MyTrait { + #[ink(message)] + async fn const_message(&self); + } + ); +} + +#[test] +fn trait_def_containing_unsafe_methods_is_denied() { + assert_ink_trait_eq_err!( + error: "unsafe ink! trait methods are not supported", + pub trait MyTrait { + #[ink(constructor)] + unsafe fn const_constructor() -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "unsafe ink! trait methods are not supported", + pub trait MyTrait { + #[ink(message)] + unsafe fn const_message(&self); + } + ); +} + +#[test] +fn trait_def_containing_methods_using_explicit_abi_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! trait methods with non default ABI are not supported", + pub trait MyTrait { + #[ink(constructor)] + extern fn const_constructor() -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "ink! trait methods with non default ABI are not supported", + pub trait MyTrait { + #[ink(message)] + extern fn const_message(&self); + } + ); +} + +#[test] +fn trait_def_containing_variadic_methods_is_denied() { + assert_ink_trait_eq_err!( + error: "variadic ink! trait methods are not supported", + pub trait MyTrait { + #[ink(constructor)] + fn const_constructor(...) -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "variadic ink! trait methods are not supported", + pub trait MyTrait { + #[ink(message)] + fn const_message(&self, ...); + } + ); +} + +#[test] +fn trait_def_containing_generic_methods_is_denied() { + assert_ink_trait_eq_err!( + error: "generic ink! trait methods are not supported", + pub trait MyTrait { + #[ink(constructor)] + fn const_constructor() -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "generic ink! trait methods are not supported", + pub trait MyTrait { + #[ink(message)] + fn const_message(&self); + } + ); +} + +#[test] +fn trait_def_containing_method_with_unsupported_ink_attribute_is_denied() { + assert_ink_trait_eq_err!( + error: "encountered unsupported ink! attribute for ink! trait method", + pub trait MyTrait { + #[ink(payable)] + fn unsupported_ink_attribute(&self); + } + ); + assert_ink_trait_eq_err!( + error: "unknown ink! attribute (path)", + pub trait MyTrait { + #[ink(unknown)] + fn unknown_ink_attribute(&self); + } + ); +} + +#[test] +fn trait_def_containing_invalid_constructor_is_denied() { + assert_ink_trait_eq_err!( + error: "ink! constructors must not have a `self` receiver", + pub trait MyTrait { + #[ink(constructor)] + fn has_self_receiver(&self) -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "ink! constructors must not have a `self` receiver", + pub trait MyTrait { + #[ink(constructor)] + fn has_self_receiver(&mut self) -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "ink! constructors must not have a `self` receiver", + pub trait MyTrait { + #[ink(constructor)] + fn has_self_receiver(self) -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "ink! constructors must not have a `self` receiver", + pub trait MyTrait { + #[ink(constructor)] + fn has_self_receiver(self: &Self) -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "ink! constructors must not have a `self` receiver", + pub trait MyTrait { + #[ink(constructor)] + fn has_self_receiver(self: Self) -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "ink! constructors must return Self", + pub trait MyTrait { + #[ink(constructor)] + fn does_not_return_self(); + } + ); + assert_ink_trait_eq_err!( + error: "ink! constructors must return Self", + pub trait MyTrait { + #[ink(constructor)] + fn does_not_return_self() -> i32; + } + ); +} + +#[test] +fn trait_def_containing_invalid_message_is_denied() { + assert_ink_trait_eq_err!( + error: "missing or malformed `&self` or `&mut self` receiver for ink! message", + pub trait MyTrait { + #[ink(message)] + fn does_not_return_self(); + } + ); + assert_ink_trait_eq_err!( + error: "missing or malformed `&self` or `&mut self` receiver for ink! message", + pub trait MyTrait { + #[ink(message)] + fn does_not_return_self(self: &Self); + } + ); + assert_ink_trait_eq_err!( + error: "self receiver of ink! message must be `&self` or `&mut self`", + pub trait MyTrait { + #[ink(message)] + fn does_not_return_self(self); + } + ); +} + +#[test] +fn trait_def_containing_constructor_with_invalid_ink_attributes_is_denied() { + assert_ink_trait_eq_err!( + error: "encountered duplicate ink! attribute", + pub trait MyTrait { + #[ink(constructor)] + #[ink(constructor)] + fn does_not_return_self() -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "encountered conflicting ink! attribute argument", + pub trait MyTrait { + #[ink(constructor)] + #[ink(message)] + fn does_not_return_self() -> Self; + } + ); + assert_ink_trait_eq_err!( + error: "encountered conflicting ink! attribute argument", + pub trait MyTrait { + #[ink(constructor)] + #[ink(payable)] + fn does_not_return_self() -> Self; + } + ); +} + +#[test] +fn trait_def_containing_message_with_invalid_ink_attributes_is_denied() { + assert_ink_trait_eq_err!( + error: "encountered duplicate ink! attribute", + pub trait MyTrait { + #[ink(message)] + #[ink(message)] + fn does_not_return_self(&self); + } + ); + assert_ink_trait_eq_err!( + error: "encountered conflicting ink! attribute argument", + pub trait MyTrait { + #[ink(message)] + #[ink(constructor)] + fn does_not_return_self(&self); + } + ); + assert_ink_trait_eq_err!( + error: "encountered conflicting ink! attribute argument", + pub trait MyTrait { + #[ink(message)] + #[ink(anonymous)] + fn does_not_return_self(&self); + } + ); +} + +#[test] +fn trait_def_is_ok() { + assert!( + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(constructor)] + fn my_constructor() -> Self; + #[ink(message)] + fn my_message(&self); + #[ink(message)] + fn my_message_mut(&mut self); + } + }) + .is_ok() + ) +} + +#[test] +fn trait_def_with_namespace_is_ok() { + assert!( + >::try_from(syn::parse_quote! { + #[ink(namespace = "my_namespace")] + pub trait MyTrait { + #[ink(constructor)] + fn my_constructor() -> Self; + #[ink(message)] + fn my_message(&self); + #[ink(message)] + fn my_message_mut(&mut self); + } + }) + .is_ok() + ) +} + +#[test] +fn trait_def_with_selectors_ok() { + assert!( + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(constructor, selector = "0xC0DECAFE")] + fn my_constructor() -> Self; + #[ink(message, selector = "0xDEADBEEF")] + fn my_message(&self); + #[ink(message, selector = "0xC0FEFEED")] + fn my_message_mut(&mut self); + } + }) + .is_ok() + ) +} + +#[test] +fn trait_def_with_payable_ok() { + assert!( + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(message, payable)] + fn my_message(&self); + #[ink(message, payable)] + fn my_message_mut(&mut self); + } + }) + .is_ok() + ) +} + +#[test] +fn trait_def_with_everything_combined_ok() { + assert!( + >::try_from(syn::parse_quote! { + #[ink(namespace = "my_namespace")] + pub trait MyTrait { + #[ink(constructor)] + fn my_constructor_1() -> Self; + #[ink(constructor, selector = "0xC0DECAFE")] + fn my_constructor_2() -> Self; + #[ink(message)] + fn my_message_1(&self); + #[ink(message, payable)] + fn my_message_2(&self); + #[ink(message, payable, selector = "0xDEADBEEF")] + fn my_message_3(&self); + #[ink(message)] + fn my_message_mut_1(&mut self); + #[ink(message, payable)] + fn my_message_mut_2(&mut self); + #[ink(message, payable, selector = "0xC0DEBEEF")] + fn my_message_mut_3(&mut self); + } + }) + .is_ok() + ) +} + +#[test] +fn trait_def_with_overlapping_selectors() { + assert_ink_trait_eq_err!( + error: "encountered duplicate selector ([c0, de, ca, fe]) \ + in the same ink! trait definition", + pub trait MyTrait { + #[ink(constructor, selector = "0xC0DECAFE")] + fn my_constructor() -> Self; + #[ink(message, selector = "0xC0DECAFE")] + fn my_message(&self); + #[ink(message, selector = "0xC0DECAFE")] + fn my_message_mut(&mut self); + } + ); +} + +#[test] +fn iter_constructors_works() { + let ink_trait = + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(constructor)] + fn constructor_1() -> Self; + #[ink(constructor)] + fn constructor_2() -> Self; + #[ink(message)] + fn message_1(&self); + #[ink(message)] + fn message_2(&mut self); + } + }) + .unwrap(); + let actual = ink_trait + .iter_items() + .flat_map(|item| { + item.filter_map_constructor() + .map(|constructor| constructor.sig().ident.to_string()) + }) + .collect::>(); + let expected = vec!["constructor_1".to_string(), "constructor_2".to_string()]; + assert_eq!(actual, expected); +} + +#[test] +fn iter_messages_works() { + let ink_trait = + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(constructor)] + fn constructor_1() -> Self; + #[ink(constructor)] + fn constructor_2() -> Self; + #[ink(message)] + fn message_1(&self); + #[ink(message)] + fn message_2(&mut self); + } + }) + .unwrap(); + let actual = ink_trait + .iter_items() + .flat_map(|item| { + item.filter_map_message() + .map(|message| message.sig().ident.to_string()) + }) + .collect::>(); + let expected = vec!["message_1".to_string(), "message_2".to_string()]; + assert_eq!(actual, expected); +} + +fn assert_verify_hash2_works_with(ink_trait: InkTrait, expected: &str) { + let expected = expected.to_string().into_bytes(); + let actual = ink_trait.verify_hash(); + let expected: [u8; 32] = { + use blake2::digest::generic_array::sequence::Split as _; + let (head_32, _rest) = + ::digest(&expected).split(); + head_32.into() + }; + assert_eq!(actual, expected); +} + +macro_rules! ink_trait { + ( $($tt:tt)* ) => {{ + >::try_from(syn::parse_quote! { + $( $tt )* + }) + .unwrap() + }}; +} + +#[test] +fn verify_hash_works() { + let ink_trait = ink_trait! { + pub trait MyTrait { + #[ink(constructor)] + fn constructor_1() -> Self; + #[ink(constructor)] + fn constructor_2(a: i32, b: i32) -> Self; + #[ink(message)] + fn message_1(&self); + #[ink(message)] + fn message_2(&mut self, a: i32, b: i32) -> i32; + } + }; + assert_verify_hash2_works_with( + ink_trait, + "__ink_trait::MyTrait::constructor_1:0,constructor_2:2::message_1:1:r,message_2:3:w" + ); +} + +#[test] +fn verify_hash_works_without_constructors() { + let ink_trait = ink_trait! { + pub trait MyTrait { + #[ink(message)] + fn message_1(&self); + #[ink(message)] + fn message_2(&mut self, a: i32, b: i32) -> i32; + } + }; + assert_verify_hash2_works_with( + ink_trait, + "__ink_trait::MyTrait::message_1:1:r,message_2:3:w", + ); +} + +#[test] +fn verify_hash_works_without_messages() { + let ink_trait = ink_trait! { + pub trait MyTrait { + #[ink(constructor)] + fn constructor_1() -> Self; + #[ink(constructor)] + fn constructor_2(a: i32, b: i32) -> Self; + } + }; + assert_verify_hash2_works_with( + ink_trait, + "__ink_trait::MyTrait::constructor_1:0,constructor_2:2", + ); +} \ No newline at end of file From 0b024537dc310c8cf2178efbb1075c4ca4c3f215 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 17:17:23 +0100 Subject: [PATCH 027/493] split up trait_def module --- crates/lang/ir/src/ir/trait_def/mod.rs | 216 +---------------- crates/lang/ir/src/ir/trait_def/trait_item.rs | 219 ++++++++++++++++++ 2 files changed, 228 insertions(+), 207 deletions(-) create mode 100644 crates/lang/ir/src/ir/trait_def/trait_item.rs diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index 0155ae20d7..b7a61c18dd 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -12,9 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod trait_item; + #[cfg(test)] mod tests; +pub use self::trait_item::{ + InkTraitItem, + InkTraitMessage, + InkTraitConstructor, +}; use super::attrs::InkAttribute; use crate::{ ir, @@ -176,14 +183,10 @@ impl<'a> Iterator for IterInkTraitItems<'a> { .clone(); match first_attr { ir::AttributeArg::Constructor => { - return Some(InkTraitItem::Constructor(InkTraitConstructor { - item: method, - })) + return Some(InkTraitItem::Constructor(InkTraitConstructor::new(method))) } ir::AttributeArg::Message => { - return Some(InkTraitItem::Message(InkTraitMessage { - item: method, - })) + return Some(InkTraitItem::Message(InkTraitMessage::new(method))) } _ => continue 'outer, } @@ -194,207 +197,6 @@ impl<'a> Iterator for IterInkTraitItems<'a> { } } -/// An ink! item within an ink! trait definition. -#[derive(Debug, Clone)] -pub enum InkTraitItem<'a> { - Constructor(InkTraitConstructor<'a>), - Message(InkTraitMessage<'a>), -} - -impl<'a> InkTraitItem<'a> { - /// Returns the Rust identifier of the ink! trait item. - pub fn ident(&self) -> &syn::Ident { - match self { - Self::Constructor(constructor) => constructor.ident(), - Self::Message(message) => message.ident(), - } - } - - /// Returns the ink! attributes of the ink! trait item. - pub fn ink_attrs(&self) -> InkAttribute { - match self { - Self::Constructor(constructor) => constructor.ink_attrs(), - Self::Message(message) => message.ink_attrs(), - } - } - - /// Returns `Some` if the ink! trait item is a constructor. - pub fn filter_map_constructor(self) -> Option> { - match self { - Self::Constructor(ink_trait_constructor) => Some(ink_trait_constructor), - _ => None, - } - } - - /// Returns `Some` if the ink! trait item is a message. - pub fn filter_map_message(self) -> Option> { - match self { - Self::Message(ink_trait_message) => Some(ink_trait_message), - _ => None, - } - } -} - -/// Returns all non-ink! attributes. -/// -/// # Panics -/// -/// If there are malformed ink! attributes in the input. -fn extract_rust_attributes(attributes: &[syn::Attribute]) -> Vec { - let (_ink_attrs, rust_attrs) = ir::partition_attributes(attributes.to_vec()) - .expect("encountered unexpected invalid ink! attributes"); - rust_attrs -} - -/// A checked ink! constructor of an ink! trait definition. -#[derive(Debug, Clone)] -pub struct InkTraitConstructor<'a> { - item: &'a syn::TraitItemMethod, -} - -impl<'a> InkTraitConstructor<'a> { - /// Panic message in case a user encounters invalid attributes. - const INVALID_ATTRIBUTES_ERRSTR: &'static str = - "encountered invalid attributes for ink! trait constructor"; - - /// Analyses and extracts the ink! and non-ink! attributes of an ink! trait constructor. - fn extract_attributes( - span: Span, - attrs: &[syn::Attribute], - ) -> Result<(InkAttribute, Vec)> { - let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes( - span, - attrs.iter().cloned(), - &ir::AttributeArgKind::Constructor, - |arg| { - match arg.kind() { - ir::AttributeArg::Constructor | ir::AttributeArg::Selector(_) => { - Ok(()) - } - _ => Err(None), - } - }, - )?; - Ok((ink_attrs, non_ink_attrs)) - } - - /// Returns all non-ink! attributes. - pub fn attrs(&self) -> Vec { - let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs) - .expect(Self::INVALID_ATTRIBUTES_ERRSTR); - rust_attrs - } - - /// Returns all ink! attributes. - pub fn ink_attrs(&self) -> InkAttribute { - let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) - .expect(Self::INVALID_ATTRIBUTES_ERRSTR); - ink_attrs - } - - /// Returns the original signature of the ink! constructor. - pub fn sig(&self) -> &syn::Signature { - &self.item.sig - } - - /// Returns the Rust identifier of the ink! constructor. - pub fn ident(&self) -> &syn::Ident { - &self.item.sig.ident - } - - /// Returns the span of the ink! constructor. - pub fn span(&self) -> Span { - self.item.span() - } -} - -/// A checked ink! message of an ink! trait definition. -#[derive(Debug, Clone)] -pub struct InkTraitMessage<'a> { - item: &'a syn::TraitItemMethod, -} - -impl<'a> InkTraitMessage<'a> { - /// Panic message in case a user encounters invalid attributes. - const INVALID_ATTRIBUTES_ERRSTR: &'static str = - "encountered invalid attributes for ink! trait message"; - - /// Analyses and extracts the ink! and non-ink! attributes of an ink! trait message. - fn extract_attributes( - span: Span, - attrs: &[syn::Attribute], - ) -> Result<(InkAttribute, Vec)> { - let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes( - span, - attrs.iter().cloned(), - &ir::AttributeArgKind::Message, - |arg| { - match arg.kind() { - ir::AttributeArg::Message - | ir::AttributeArg::Payable - | ir::AttributeArg::Selector(_) => Ok(()), - _ => Err(None), - } - }, - )?; - Ok((ink_attrs, non_ink_attrs)) - } - - /// Returns all non-ink! attributes. - pub fn attrs(&self) -> Vec { - let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs) - .expect(Self::INVALID_ATTRIBUTES_ERRSTR); - rust_attrs - } - - /// Returns all ink! attributes. - pub fn ink_attrs(&self) -> InkAttribute { - let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) - .expect(Self::INVALID_ATTRIBUTES_ERRSTR); - ink_attrs - } - - /// Returns the original signature of the ink! message. - pub fn sig(&self) -> &syn::Signature { - &self.item.sig - } - - /// Returns the Rust identifier of the ink! message. - pub fn ident(&self) -> &syn::Ident { - &self.item.sig.ident - } - - /// Returns the span of the ink! message. - pub fn span(&self) -> Span { - self.item.span() - } - - /// Returns `true` if the ink! message may mutate the contract storage. - pub fn mutates(&self) -> bool { - self.sig() - .receiver() - .map(|fn_arg| { - match fn_arg { - syn::FnArg::Receiver(receiver) if receiver.mutability.is_some() => { - true - } - syn::FnArg::Typed(pat_type) => { - match &*pat_type.ty { - syn::Type::Reference(reference) - if reference.mutability.is_some() => - { - true - } - _ => false, - } - } - _ => false, - } - }) - .expect("encountered missing receiver for ink! message") - } -} - impl InkTrait { /// Returns `Ok` if the trait matches all requirements for an ink! trait definition. pub fn new(attr: TokenStream2, input: TokenStream2) -> Result { diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/trait_item.rs new file mode 100644 index 0000000000..5397bd73a6 --- /dev/null +++ b/crates/lang/ir/src/ir/trait_def/trait_item.rs @@ -0,0 +1,219 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::ir; + +use super::super::InkAttribute; +use proc_macro2::Span; +use syn::{Result, spanned::Spanned as _}; + +/// An ink! item within an ink! trait definition. +#[derive(Debug, Clone)] +pub enum InkTraitItem<'a> { + Constructor(InkTraitConstructor<'a>), + Message(InkTraitMessage<'a>), +} + +impl<'a> InkTraitItem<'a> { + /// Returns the Rust identifier of the ink! trait item. + pub fn ident(&self) -> &syn::Ident { + match self { + Self::Constructor(constructor) => constructor.ident(), + Self::Message(message) => message.ident(), + } + } + + /// Returns the ink! attributes of the ink! trait item. + pub fn ink_attrs(&self) -> InkAttribute { + match self { + Self::Constructor(constructor) => constructor.ink_attrs(), + Self::Message(message) => message.ink_attrs(), + } + } + + /// Returns `Some` if the ink! trait item is a constructor. + pub fn filter_map_constructor(self) -> Option> { + match self { + Self::Constructor(ink_trait_constructor) => Some(ink_trait_constructor), + _ => None, + } + } + + /// Returns `Some` if the ink! trait item is a message. + pub fn filter_map_message(self) -> Option> { + match self { + Self::Message(ink_trait_message) => Some(ink_trait_message), + _ => None, + } + } +} + +/// A checked ink! constructor of an ink! trait definition. +#[derive(Debug, Clone)] +pub struct InkTraitConstructor<'a> { + item: &'a syn::TraitItemMethod, +} + +impl<'a> InkTraitConstructor<'a> { + /// Panic message in case a user encounters invalid attributes. + const INVALID_ATTRIBUTES_ERRSTR: &'static str = + "encountered invalid attributes for ink! trait constructor"; + + /// Creates a new ink! trait definition constructor. + pub(super) fn new(item: &'a syn::TraitItemMethod) -> Self { + Self { item } + } + + /// Analyses and extracts the ink! and non-ink! attributes of an ink! trait constructor. + pub(super) fn extract_attributes( + span: Span, + attrs: &[syn::Attribute], + ) -> Result<(InkAttribute, Vec)> { + let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes( + span, + attrs.iter().cloned(), + &ir::AttributeArgKind::Constructor, + |arg| { + match arg.kind() { + ir::AttributeArg::Constructor | ir::AttributeArg::Selector(_) => { + Ok(()) + } + _ => Err(None), + } + }, + )?; + Ok((ink_attrs, non_ink_attrs)) + } + + /// Returns all non-ink! attributes. + pub fn attrs(&self) -> Vec { + let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + rust_attrs + } + + /// Returns all ink! attributes. + pub fn ink_attrs(&self) -> InkAttribute { + let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + ink_attrs + } + + /// Returns the original signature of the ink! constructor. + pub fn sig(&self) -> &syn::Signature { + &self.item.sig + } + + /// Returns the Rust identifier of the ink! constructor. + pub fn ident(&self) -> &syn::Ident { + &self.item.sig.ident + } + + /// Returns the span of the ink! constructor. + pub fn span(&self) -> Span { + self.item.span() + } +} + +/// A checked ink! message of an ink! trait definition. +#[derive(Debug, Clone)] +pub struct InkTraitMessage<'a> { + item: &'a syn::TraitItemMethod, +} + +impl<'a> InkTraitMessage<'a> { + /// Panic message in case a user encounters invalid attributes. + const INVALID_ATTRIBUTES_ERRSTR: &'static str = + "encountered invalid attributes for ink! trait message"; + + /// Creates a new ink! trait definition message. + pub(super) fn new(item: &'a syn::TraitItemMethod) -> Self { + Self { item } + } + + /// Analyses and extracts the ink! and non-ink! attributes of an ink! trait message. + pub(super) fn extract_attributes( + span: Span, + attrs: &[syn::Attribute], + ) -> Result<(InkAttribute, Vec)> { + let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes( + span, + attrs.iter().cloned(), + &ir::AttributeArgKind::Message, + |arg| { + match arg.kind() { + ir::AttributeArg::Message + | ir::AttributeArg::Payable + | ir::AttributeArg::Selector(_) => Ok(()), + _ => Err(None), + } + }, + )?; + Ok((ink_attrs, non_ink_attrs)) + } + + /// Returns all non-ink! attributes. + pub fn attrs(&self) -> Vec { + let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + rust_attrs + } + + /// Returns all ink! attributes. + pub fn ink_attrs(&self) -> InkAttribute { + let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) + .expect(Self::INVALID_ATTRIBUTES_ERRSTR); + ink_attrs + } + + /// Returns the original signature of the ink! message. + pub fn sig(&self) -> &syn::Signature { + &self.item.sig + } + + /// Returns the Rust identifier of the ink! message. + pub fn ident(&self) -> &syn::Ident { + &self.item.sig.ident + } + + /// Returns the span of the ink! message. + pub fn span(&self) -> Span { + self.item.span() + } + + /// Returns `true` if the ink! message may mutate the contract storage. + pub fn mutates(&self) -> bool { + self.sig() + .receiver() + .map(|fn_arg| { + match fn_arg { + syn::FnArg::Receiver(receiver) if receiver.mutability.is_some() => { + true + } + syn::FnArg::Typed(pat_type) => { + match &*pat_type.ty { + syn::Type::Reference(reference) + if reference.mutability.is_some() => + { + true + } + _ => false, + } + } + _ => false, + } + }) + .expect("encountered missing receiver for ink! message") + } +} From 453d65f7aa52a7dd954d165aa047e12a338c182b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 17:20:14 +0100 Subject: [PATCH 028/493] move ink! trait items iterator into its own file --- crates/lang/ir/src/ir/trait_def/iter.rs | 77 +++++++++++++++++++++++++ crates/lang/ir/src/ir/trait_def/mod.rs | 54 +---------------- 2 files changed, 79 insertions(+), 52 deletions(-) create mode 100644 crates/lang/ir/src/ir/trait_def/iter.rs diff --git a/crates/lang/ir/src/ir/trait_def/iter.rs b/crates/lang/ir/src/ir/trait_def/iter.rs new file mode 100644 index 0000000000..03e2f2c5d6 --- /dev/null +++ b/crates/lang/ir/src/ir/trait_def/iter.rs @@ -0,0 +1,77 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + ir, + InkTrait, + InkTraitConstructor, + InkTraitItem, + InkTraitMessage, +}; + +/// Iterator over all the ink! trait items of an ink! trait definition. +pub struct IterInkTraitItems<'a> { + iter: core::slice::Iter<'a, syn::TraitItem>, +} + +impl<'a> IterInkTraitItems<'a> { + /// Creates a new iterator yielding ink! trait items. + pub(super) fn new(item_trait: &'a InkTrait) -> Self { + Self { + iter: item_trait.item.items.iter(), + } + } + + /// Creates a new iterator yielding ink! trait items over the raw Rust trait definition. + pub(super) fn from_raw(item_trait: &'a syn::ItemTrait) -> Self { + Self { + iter: item_trait.items.iter(), + } + } +} + +impl<'a> Iterator for IterInkTraitItems<'a> { + type Item = InkTraitItem<'a>; + + fn next(&mut self) -> Option { + 'outer: loop { + match self.iter.next() { + None => return None, + Some(syn::TraitItem::Method(method)) => { + let first_attr = ir::first_ink_attribute(&method.attrs) + .ok() + .flatten() + .expect("unexpected missing ink! attribute for trait method") + .first() + .kind() + .clone(); + match first_attr { + ir::AttributeArg::Constructor => { + return Some(InkTraitItem::Constructor( + InkTraitConstructor::new(method), + )) + } + ir::AttributeArg::Message => { + return Some(InkTraitItem::Message(InkTraitMessage::new( + method, + ))) + } + _ => continue 'outer, + } + } + Some(_) => continue 'outer, + } + } + } +} diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index b7a61c18dd..ea334d5537 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -13,10 +13,12 @@ // limitations under the License. mod trait_item; +mod iter; #[cfg(test)] mod tests; +pub use self::iter::IterInkTraitItems; pub use self::trait_item::{ InkTraitItem, InkTraitMessage, @@ -145,58 +147,6 @@ impl InkTrait { } } -/// Iterator over all the ink! trait items of an ink! trait definition. -pub struct IterInkTraitItems<'a> { - iter: core::slice::Iter<'a, syn::TraitItem>, -} - -impl<'a> IterInkTraitItems<'a> { - /// Creates a new iterator yielding ink! trait items. - fn new(item_trait: &'a InkTrait) -> Self { - Self { - iter: item_trait.item.items.iter(), - } - } - - /// Creates a new iterator yielding ink! trait items over the raw Rust trait definition. - fn from_raw(item_trait: &'a syn::ItemTrait) -> Self { - Self { - iter: item_trait.items.iter(), - } - } -} - -impl<'a> Iterator for IterInkTraitItems<'a> { - type Item = InkTraitItem<'a>; - - fn next(&mut self) -> Option { - 'outer: loop { - match self.iter.next() { - None => return None, - Some(syn::TraitItem::Method(method)) => { - let first_attr = ir::first_ink_attribute(&method.attrs) - .ok() - .flatten() - .expect("unexpected missing ink! attribute for trait method") - .first() - .kind() - .clone(); - match first_attr { - ir::AttributeArg::Constructor => { - return Some(InkTraitItem::Constructor(InkTraitConstructor::new(method))) - } - ir::AttributeArg::Message => { - return Some(InkTraitItem::Message(InkTraitMessage::new(method))) - } - _ => continue 'outer, - } - } - Some(_) => continue 'outer, - } - } - } -} - impl InkTrait { /// Returns `Ok` if the trait matches all requirements for an ink! trait definition. pub fn new(attr: TokenStream2, input: TokenStream2) -> Result { From 30da88402c8086e0c64c3f4a6269c9eb7aabd0ea Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 4 Mar 2021 17:20:36 +0100 Subject: [PATCH 029/493] apply rustfmt --- crates/lang/ir/src/ir/trait_def/mod.rs | 14 +++-- crates/lang/ir/src/ir/trait_def/tests.rs | 56 +++++++++---------- crates/lang/ir/src/ir/trait_def/trait_item.rs | 5 +- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index ea334d5537..a614e0eee1 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -12,17 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod trait_item; mod iter; +mod trait_item; #[cfg(test)] mod tests; -pub use self::iter::IterInkTraitItems; -pub use self::trait_item::{ - InkTraitItem, - InkTraitMessage, - InkTraitConstructor, +pub use self::{ + iter::IterInkTraitItems, + trait_item::{ + InkTraitConstructor, + InkTraitItem, + InkTraitMessage, + }, }; use super::attrs::InkAttribute; use crate::{ diff --git a/crates/lang/ir/src/ir/trait_def/tests.rs b/crates/lang/ir/src/ir/trait_def/tests.rs index 801c750f4b..f26bc90777 100644 --- a/crates/lang/ir/src/ir/trait_def/tests.rs +++ b/crates/lang/ir/src/ir/trait_def/tests.rs @@ -516,20 +516,19 @@ fn trait_def_with_overlapping_selectors() { #[test] fn iter_constructors_works() { - let ink_trait = - >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2() -> Self; - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self); - } - }) - .unwrap(); + let ink_trait = >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(constructor)] + fn constructor_1() -> Self; + #[ink(constructor)] + fn constructor_2() -> Self; + #[ink(message)] + fn message_1(&self); + #[ink(message)] + fn message_2(&mut self); + } + }) + .unwrap(); let actual = ink_trait .iter_items() .flat_map(|item| { @@ -543,20 +542,19 @@ fn iter_constructors_works() { #[test] fn iter_messages_works() { - let ink_trait = - >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2() -> Self; - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self); - } - }) - .unwrap(); + let ink_trait = >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(constructor)] + fn constructor_1() -> Self; + #[ink(constructor)] + fn constructor_2() -> Self; + #[ink(message)] + fn message_1(&self); + #[ink(message)] + fn message_2(&mut self); + } + }) + .unwrap(); let actual = ink_trait .iter_items() .flat_map(|item| { @@ -639,4 +637,4 @@ fn verify_hash_works_without_messages() { ink_trait, "__ink_trait::MyTrait::constructor_1:0,constructor_2:2", ); -} \ No newline at end of file +} diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/trait_item.rs index 5397bd73a6..c6be129784 100644 --- a/crates/lang/ir/src/ir/trait_def/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/trait_item.rs @@ -16,7 +16,10 @@ use crate::ir; use super::super::InkAttribute; use proc_macro2::Span; -use syn::{Result, spanned::Spanned as _}; +use syn::{ + spanned::Spanned as _, + Result, +}; /// An ink! item within an ink! trait definition. #[derive(Debug, Clone)] From f2e11b7c96c26b05238d996333b89cfefae57b4a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 12 Mar 2021 13:53:22 +0100 Subject: [PATCH 030/493] make IterInkTraitItems yield selectors along constructs and messages These are the final selectors computed through the trait definitions and optional #[ink(selector = N)] attributes. --- .../lang/codegen/src/generator/trait_def.rs | 4 ++ crates/lang/ir/src/ir/trait_def/iter.rs | 52 +++++++++++++++---- crates/lang/ir/src/ir/trait_def/mod.rs | 5 +- crates/lang/ir/src/ir/trait_def/tests.rs | 2 + crates/lang/ir/src/ir/trait_def/trait_item.rs | 3 +- 5 files changed, 53 insertions(+), 13 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def.rs b/crates/lang/codegen/src/generator/trait_def.rs index 6bcf6c2f9d..b0cb544bfb 100644 --- a/crates/lang/codegen/src/generator/trait_def.rs +++ b/crates/lang/codegen/src/generator/trait_def.rs @@ -174,21 +174,25 @@ impl GenerateCode for TraitDefinition<'_> { let constructors = self .trait_def .iter_items() + .map(|(item, _)| item) .flat_map(ir::InkTraitItem::filter_map_constructor) .map(Self::generate_for_constructor); let messages = self .trait_def .iter_items() + .map(|(item, _)| item) .flat_map(ir::InkTraitItem::filter_map_message) .map(Self::generate_for_message); let constructors_never_call = self .trait_def .iter_items() + .map(|(item, _)| item) .flat_map(ir::InkTraitItem::filter_map_constructor) .map(Self::generate_for_constructor_never_call); let messages_never_call = self .trait_def .iter_items() + .map(|(item, _)| item) .flat_map(ir::InkTraitItem::filter_map_message) .map(Self::generate_for_message_never_call); quote_spanned!(span => diff --git a/crates/lang/ir/src/ir/trait_def/iter.rs b/crates/lang/ir/src/ir/trait_def/iter.rs index 03e2f2c5d6..8f0ac02d47 100644 --- a/crates/lang/ir/src/ir/trait_def/iter.rs +++ b/crates/lang/ir/src/ir/trait_def/iter.rs @@ -18,21 +18,16 @@ use crate::{ InkTraitConstructor, InkTraitItem, InkTraitMessage, + Selector, }; +use std::collections::HashMap; /// Iterator over all the ink! trait items of an ink! trait definition. -pub struct IterInkTraitItems<'a> { +pub struct IterInkTraitItemsRaw<'a> { iter: core::slice::Iter<'a, syn::TraitItem>, } -impl<'a> IterInkTraitItems<'a> { - /// Creates a new iterator yielding ink! trait items. - pub(super) fn new(item_trait: &'a InkTrait) -> Self { - Self { - iter: item_trait.item.items.iter(), - } - } - +impl<'a> IterInkTraitItemsRaw<'a> { /// Creates a new iterator yielding ink! trait items over the raw Rust trait definition. pub(super) fn from_raw(item_trait: &'a syn::ItemTrait) -> Self { Self { @@ -41,7 +36,7 @@ impl<'a> IterInkTraitItems<'a> { } } -impl<'a> Iterator for IterInkTraitItems<'a> { +impl<'a> Iterator for IterInkTraitItemsRaw<'a> { type Item = InkTraitItem<'a>; fn next(&mut self) -> Option { @@ -75,3 +70,40 @@ impl<'a> Iterator for IterInkTraitItems<'a> { } } } + +/// Iterator over all the ink! trait items of an ink! trait definition. +pub struct IterInkTraitItems<'a> { + iter: IterInkTraitItemsRaw<'a>, + message_selectors: &'a HashMap, + constructor_selectors: &'a HashMap, +} + +impl<'a> IterInkTraitItems<'a> { + /// Creates a new iterator yielding ink! trait items. + pub(super) fn new(item_trait: &'a InkTrait) -> Self { + Self { + iter: IterInkTraitItemsRaw::from_raw(&item_trait.item), + message_selectors: &item_trait.message_selectors, + constructor_selectors: &item_trait.constructor_selectors, + } + } +} + +impl<'a> Iterator for IterInkTraitItems<'a> { + type Item = (InkTraitItem<'a>, Selector); + + fn next(&mut self) -> Option { + match self.iter.next() { + None => None, + Some(item @ InkTraitItem::Constructor(_)) => { + let selector = self.constructor_selectors[item.ident()]; + Some((item, selector)) + } + Some(item @ InkTraitItem::Message(_)) => { + let selector = self.message_selectors[item.ident()]; + Some((item, selector)) + + } + } + } +} diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index a614e0eee1..00a65c3b30 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -18,6 +18,7 @@ mod trait_item; #[cfg(test)] mod tests; +use self::iter::IterInkTraitItemsRaw; pub use self::{ iter::IterInkTraitItems, trait_item::{ @@ -131,6 +132,7 @@ impl InkTrait { Self::compute_verify_hash( trait_name, self.iter_items() + .map(|(item, _)| item) .flat_map(InkTraitItem::filter_map_constructor) .map(|constructor| { let name = constructor.sig().ident.clone(); @@ -138,6 +140,7 @@ impl InkTrait { (name, len_inputs) }), self.iter_items() + .map(|(item, _)| item) .flat_map(InkTraitItem::filter_map_message) .map(|message| { let name = message.sig().ident.clone(); @@ -470,7 +473,7 @@ impl InkTrait { .unwrap_or_else(Default::default); let ident = &item_trait.ident; let trait_prefix = TraitPrefix::new(ident, &namespace); - for callable in IterInkTraitItems::from_raw(item_trait) { + for callable in IterInkTraitItemsRaw::from_raw(item_trait) { let ident = callable.ident(); let ink_attrs = callable.ink_attrs(); let selector = match ink_attrs.selector() { diff --git a/crates/lang/ir/src/ir/trait_def/tests.rs b/crates/lang/ir/src/ir/trait_def/tests.rs index f26bc90777..c067eb7f5d 100644 --- a/crates/lang/ir/src/ir/trait_def/tests.rs +++ b/crates/lang/ir/src/ir/trait_def/tests.rs @@ -531,6 +531,7 @@ fn iter_constructors_works() { .unwrap(); let actual = ink_trait .iter_items() + .map(|(item, _)| item) .flat_map(|item| { item.filter_map_constructor() .map(|constructor| constructor.sig().ident.to_string()) @@ -557,6 +558,7 @@ fn iter_messages_works() { .unwrap(); let actual = ink_trait .iter_items() + .map(|(item, _)| item) .flat_map(|item| { item.filter_map_message() .map(|message| message.sig().ident.to_string()) diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/trait_item.rs index c6be129784..db9a25968e 100644 --- a/crates/lang/ir/src/ir/trait_def/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/trait_item.rs @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::ir; - use super::super::InkAttribute; +use crate::ir; use proc_macro2::Span; use syn::{ spanned::Spanned as _, From c3596cb8ece38c5894478c3207407d223ebe7a9a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 16 Mar 2021 20:18:20 +0100 Subject: [PATCH 031/493] split trait_def.rs into multiple sub-modules --- .../concretizer.rs} | 253 ++++++------------ .../src/generator/trait_def/definition.rs | 117 ++++++++ .../codegen/src/generator/trait_def/mod.rs | 39 +++ 3 files changed, 237 insertions(+), 172 deletions(-) rename crates/lang/codegen/src/generator/{trait_def.rs => trait_def/concretizer.rs} (68%) create mode 100644 crates/lang/codegen/src/generator/trait_def/definition.rs create mode 100644 crates/lang/codegen/src/generator/trait_def/mod.rs diff --git a/crates/lang/codegen/src/generator/trait_def.rs b/crates/lang/codegen/src/generator/trait_def/concretizer.rs similarity index 68% rename from crates/lang/codegen/src/generator/trait_def.rs rename to crates/lang/codegen/src/generator/trait_def/concretizer.rs index b0cb544bfb..1d7b1b7c3d 100644 --- a/crates/lang/codegen/src/generator/trait_def.rs +++ b/crates/lang/codegen/src/generator/trait_def/concretizer.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::GenerateCode; -use derive_more::From; +use super::TraitDefinition; use heck::CamelCase as _; use proc_macro2::TokenStream as TokenStream2; use quote::{ @@ -22,145 +21,11 @@ use quote::{ quote_spanned, }; -/// Generator to create the ink! storage struct and important trait impls. -#[derive(From)] -pub struct TraitDefinition<'a> { - trait_def: &'a ir::InkTrait, -} - impl<'a> TraitDefinition<'a> { - fn generate_for_constructor( - constructor: ir::InkTraitConstructor<'a>, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let sig = constructor.sig(); - let ident = &sig.ident; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let inputs = &sig.inputs; - quote_spanned!(span => - /// Output type of the respective trait constructor. - type #output_ident; - - #(#attrs)* - fn #ident(#inputs) -> Self::#output_ident; - ) - } - - fn generate_for_message(message: ir::InkTraitMessage<'a>) -> TokenStream2 { - let span = message.span(); - let attrs = message.attrs(); - let sig = message.sig(); - let ident = &sig.ident; - let inputs = &sig.inputs; - let output = match &sig.output { - syn::ReturnType::Default => quote! { () }, - syn::ReturnType::Type(_, ty) => quote! { #ty }, - }; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - quote_spanned!(span => - /// Output type of the respective trait message. - type #output_ident: ::ink_lang::ImpliesReturn<#output>; - - #(#attrs)* - fn #ident(#inputs) -> Self::#output_ident; - ) - } - - fn generate_for_constructor_never_call( - constructor: ir::InkTraitConstructor<'a>, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let sig = constructor.sig(); - let ident = &sig.ident; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let input_bindings = sig - .inputs - .iter() - .enumerate() - .map(|(n, fn_arg)| { - match fn_arg { - syn::FnArg::Typed(pat_type) => { - let ident = format_ident!("__ink_binding_{}", n); - let ty = &pat_type.ty; - quote! { #ident : #ty } - } - syn::FnArg::Receiver(receiver) => quote! { #receiver }, - } - }) - .collect::>(); - let linker_error_ident = - format_ident!("{}", "__ink_enforce_error_for_constructor"); - quote_spanned!(span => - /// Output type of the respective trait constructor. - type #output_ident = ::ink_lang::NeverReturns; - - #(#attrs)* - fn #ident(#(#input_bindings),*) -> Self::#output_ident { - extern { - fn #linker_error_ident() -> !; - } - unsafe { #linker_error_ident() } - } - ) - } - - fn generate_for_message_never_call(message: ir::InkTraitMessage<'a>) -> TokenStream2 { - let span = message.span(); - let attrs = message.attrs(); - let sig = message.sig(); - let ident = &sig.ident; - let output = match &sig.output { - syn::ReturnType::Default => quote! { () }, - syn::ReturnType::Type(_, ty) => quote! { #ty }, - }; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let input_bindings = sig - .inputs - .iter() - .enumerate() - .map(|(n, fn_arg)| { - match fn_arg { - syn::FnArg::Typed(pat_type) => { - let ident = format_ident!("__ink_binding_{}", n); - let ty = &pat_type.ty; - quote! { #ident : #ty } - } - syn::FnArg::Receiver(receiver) => quote! { #receiver }, - } - }) - .collect::>(); - let linker_error_ident = format_ident!("{}", "__ink_enforce_error_for_message"); - quote_spanned!(span => - /// Output type of the respective trait constructor. - type #output_ident = #output; - - #(#attrs)* - fn #ident(#(#input_bindings),*) -> Self::#output_ident { - extern { - fn #linker_error_ident() -> !; - } - unsafe { #linker_error_ident() } - } - ) - } -} - -impl GenerateCode for TraitDefinition<'_> { - fn generate_code(&self) -> TokenStream2 { + pub(super) fn generate_trait_concretizer(&self) -> TokenStream2 { let span = self.trait_def.span(); - let attrs = self.trait_def.attrs(); let hash = self.trait_def.verify_hash(); let ident = self.trait_def.ident(); - let helper_ident = format_ident!( - "__ink_Checked{}_0x{:X}{:X}{:X}{:X}", - ident, - hash[0], - hash[1], - hash[2], - hash[3] - ); let concrete_implementer_ident = format_ident!( "__ink_ConcreteImplementer{}_0x{:X}{:X}{:X}{:X}", ident, @@ -171,18 +36,6 @@ impl GenerateCode for TraitDefinition<'_> { ); let verify_hash_id = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; - let constructors = self - .trait_def - .iter_items() - .map(|(item, _)| item) - .flat_map(ir::InkTraitItem::filter_map_constructor) - .map(Self::generate_for_constructor); - let messages = self - .trait_def - .iter_items() - .map(|(item, _)| item) - .flat_map(ir::InkTraitItem::filter_map_message) - .map(Self::generate_for_message); let constructors_never_call = self .trait_def .iter_items() @@ -196,30 +49,7 @@ impl GenerateCode for TraitDefinition<'_> { .flat_map(ir::InkTraitItem::filter_map_message) .map(Self::generate_for_message_never_call); quote_spanned!(span => - #(#attrs)* - pub trait #ident: ::ink_lang::CheckedInkTrait<[(); #verify_hash_id]> { - #[doc(hidden)] - #[allow(non_camel_case_types)] - type __ink_Checksum: #helper_ident; - - /// Used to map from trait to a concrete `AccountId` thin-wrapper - /// implementing the exact same trait. This defaults to - /// `ink_lang::NoConcreteImplementer` for user provided implementations. - #[doc(hidden)] - #[allow(non_camel_case_types)] - type __ink_ConcreteImplementer; - - #(#constructors)* - #(#messages)* - } - - #[doc(hidden)] - #[allow(non_camel_case_types)] - pub unsafe trait #helper_ident {} - const _: () = { - unsafe impl #helper_ident for [(); #verify_hash_id] {} - /// A universal concrete implementer of the ink! trait definition. #[doc(hidden)] #[allow(non_camel_case_types)] @@ -279,4 +109,83 @@ impl GenerateCode for TraitDefinition<'_> { }; ) } + + fn generate_for_constructor_never_call( + constructor: ir::InkTraitConstructor<'a>, + ) -> TokenStream2 { + let span = constructor.span(); + let attrs = constructor.attrs(); + let sig = constructor.sig(); + let ident = &sig.ident; + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let input_bindings = sig + .inputs + .iter() + .enumerate() + .map(|(n, fn_arg)| { + match fn_arg { + syn::FnArg::Typed(pat_type) => { + let ident = format_ident!("__ink_binding_{}", n); + let ty = &pat_type.ty; + quote! { #ident : #ty } + } + syn::FnArg::Receiver(receiver) => quote! { #receiver }, + } + }) + .collect::>(); + let linker_error_ident = + format_ident!("{}", "__ink_enforce_error_for_constructor"); + quote_spanned!(span => + /// Output type of the respective trait constructor. + type #output_ident = ::ink_lang::NeverReturns; + + #(#attrs)* + fn #ident(#(#input_bindings),*) -> Self::#output_ident { + extern { + fn #linker_error_ident() -> !; + } + unsafe { #linker_error_ident() } + } + ) + } + + fn generate_for_message_never_call(message: ir::InkTraitMessage<'a>) -> TokenStream2 { + let span = message.span(); + let attrs = message.attrs(); + let sig = message.sig(); + let ident = &sig.ident; + let output = match &sig.output { + syn::ReturnType::Default => quote! { () }, + syn::ReturnType::Type(_, ty) => quote! { #ty }, + }; + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let input_bindings = sig + .inputs + .iter() + .enumerate() + .map(|(n, fn_arg)| { + match fn_arg { + syn::FnArg::Typed(pat_type) => { + let ident = format_ident!("__ink_binding_{}", n); + let ty = &pat_type.ty; + quote! { #ident : #ty } + } + syn::FnArg::Receiver(receiver) => quote! { #receiver }, + } + }) + .collect::>(); + let linker_error_ident = format_ident!("{}", "__ink_enforce_error_for_message"); + quote_spanned!(span => + /// Output type of the respective trait constructor. + type #output_ident = #output; + + #(#attrs)* + fn #ident(#(#input_bindings),*) -> Self::#output_ident { + extern { + fn #linker_error_ident() -> !; + } + unsafe { #linker_error_ident() } + } + ) + } } diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs new file mode 100644 index 0000000000..50934ce459 --- /dev/null +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -0,0 +1,117 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::TraitDefinition; +use heck::CamelCase as _; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ + format_ident, + quote, + quote_spanned, +}; + +impl<'a> TraitDefinition<'a> { + fn generate_for_constructor( + constructor: ir::InkTraitConstructor<'a>, + ) -> TokenStream2 { + let span = constructor.span(); + let attrs = constructor.attrs(); + let sig = constructor.sig(); + let ident = &sig.ident; + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let inputs = &sig.inputs; + quote_spanned!(span => + /// Output type of the respective trait constructor. + type #output_ident; + + #(#attrs)* + fn #ident(#inputs) -> Self::#output_ident; + ) + } + + fn generate_for_message(message: ir::InkTraitMessage<'a>) -> TokenStream2 { + let span = message.span(); + let attrs = message.attrs(); + let sig = message.sig(); + let ident = &sig.ident; + let inputs = &sig.inputs; + let output = match &sig.output { + syn::ReturnType::Default => quote! { () }, + syn::ReturnType::Type(_, ty) => quote! { #ty }, + }; + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + quote_spanned!(span => + /// Output type of the respective trait message. + type #output_ident: ::ink_lang::ImpliesReturn<#output>; + + #(#attrs)* + fn #ident(#inputs) -> Self::#output_ident; + ) + } +} + +impl TraitDefinition<'_> { + pub(super) fn generate_trait_definition(&self) -> TokenStream2 { + let span = self.trait_def.span(); + let attrs = self.trait_def.attrs(); + let hash = self.trait_def.verify_hash(); + let ident = self.trait_def.ident(); + let helper_ident = format_ident!( + "__ink_Checked{}_0x{:X}{:X}{:X}{:X}", + ident, + hash[0], + hash[1], + hash[2], + hash[3] + ); + let verify_hash_id = + u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; + let constructors = self + .trait_def + .iter_items() + .map(|(item, _)| item) + .flat_map(ir::InkTraitItem::filter_map_constructor) + .map(Self::generate_for_constructor); + let messages = self + .trait_def + .iter_items() + .map(|(item, _)| item) + .flat_map(ir::InkTraitItem::filter_map_message) + .map(Self::generate_for_message); + quote_spanned!(span => + #(#attrs)* + pub trait #ident: ::ink_lang::CheckedInkTrait<[(); #verify_hash_id]> { + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_Checksum: #helper_ident; + + /// Used to map from trait to a concrete `AccountId` thin-wrapper + /// implementing the exact same trait. This defaults to + /// `ink_lang::NoConcreteImplementer` for user provided implementations. + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_ConcreteImplementer; + + #(#constructors)* + #(#messages)* + } + + #[doc(hidden)] + #[allow(non_camel_case_types)] + pub unsafe trait #helper_ident {} + + unsafe impl #helper_ident for [(); #verify_hash_id] {} + ) + } +} diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs new file mode 100644 index 0000000000..5d0e76790b --- /dev/null +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -0,0 +1,39 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod concretizer; +mod definition; + +use crate::GenerateCode; +use derive_more::From; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote_spanned; + +/// Generator to create the ink! storage struct and important trait impls. +#[derive(From)] +pub struct TraitDefinition<'a> { + trait_def: &'a ir::InkTrait, +} + +impl GenerateCode for TraitDefinition<'_> { + fn generate_code(&self) -> TokenStream2 { + let span = self.trait_def.span(); + let trait_definition = self.generate_trait_definition(); + let trait_concretizer = self.generate_trait_concretizer(); + quote_spanned!(span => + #trait_definition + #trait_concretizer + ) + } +} From e5ccd255e3b0c0c2704999696f08e1069d2c23df Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 16 Mar 2021 23:49:14 +0100 Subject: [PATCH 032/493] add doc comments to trait_def sub-modules --- .../lang/codegen/src/generator/trait_def/concretizer.rs | 8 ++++++++ crates/lang/codegen/src/generator/trait_def/definition.rs | 2 ++ 2 files changed, 10 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/concretizer.rs b/crates/lang/codegen/src/generator/trait_def/concretizer.rs index 1d7b1b7c3d..2a339f64ae 100644 --- a/crates/lang/codegen/src/generator/trait_def/concretizer.rs +++ b/crates/lang/codegen/src/generator/trait_def/concretizer.rs @@ -12,6 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Generates the definition and implementations for the ink! trait definition resolver. +//! +//! This is used in order code in order to resolve an ink! trait definition to a proper +//! Rust type that can be used in the Rust type system and used as instance. This is +//! for example required in order to cross-call a trait based contract implementation or +//! to allow for contract references in arguments that implement a trait by definition +//! of the API. + use super::TraitDefinition; use heck::CamelCase as _; use proc_macro2::TokenStream as TokenStream2; diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 50934ce459..5844dbf035 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Generates the ink! trait definition item. + use super::TraitDefinition; use heck::CamelCase as _; use proc_macro2::TokenStream as TokenStream2; From 3d39538b4e2d97f03cfe7bb72dbd44a4b7b938a1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 16 Mar 2021 23:49:38 +0100 Subject: [PATCH 033/493] move const item definition in generated code --- .../src/generator/trait_def/concretizer.rs | 96 +++++++++---------- .../codegen/src/generator/trait_def/mod.rs | 6 +- 2 files changed, 52 insertions(+), 50 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/concretizer.rs b/crates/lang/codegen/src/generator/trait_def/concretizer.rs index 2a339f64ae..b776b9b313 100644 --- a/crates/lang/codegen/src/generator/trait_def/concretizer.rs +++ b/crates/lang/codegen/src/generator/trait_def/concretizer.rs @@ -57,64 +57,62 @@ impl<'a> TraitDefinition<'a> { .flat_map(ir::InkTraitItem::filter_map_message) .map(Self::generate_for_message_never_call); quote_spanned!(span => - const _: () = { - /// A universal concrete implementer of the ink! trait definition. - #[doc(hidden)] - #[allow(non_camel_case_types)] - pub struct #concrete_implementer_ident - where - E: ::ink_env::Environment, - { - account_id: ::AccountId, - } + /// A universal concrete implementer of the ink! trait definition. + #[doc(hidden)] + #[allow(non_camel_case_types)] + pub struct #concrete_implementer_ident + where + E: ::ink_env::Environment, + { + account_id: ::AccountId, + } - impl ::ink_env::call::FromAccountId for #concrete_implementer_ident - where - E: ::ink_env::Environment, - { - #[inline] - fn from_account_id(account_id: ::AccountId) -> Self { - Self { account_id } - } + impl ::ink_env::call::FromAccountId for #concrete_implementer_ident + where + E: ::ink_env::Environment, + { + #[inline] + fn from_account_id(account_id: ::AccountId) -> Self { + Self { account_id } } + } - impl ::ink_lang::ToAccountId for #concrete_implementer_ident - where - E: ::ink_env::Environment, - ::AccountId: Clone, - { - #[inline] - fn to_account_id(&self) -> ::AccountId { - self.account_id.clone() - } + impl ::ink_lang::ToAccountId for #concrete_implementer_ident + where + E: ::ink_env::Environment, + ::AccountId: Clone, + { + #[inline] + fn to_account_id(&self) -> ::AccountId { + self.account_id.clone() } + } - impl ::core::clone::Clone for #concrete_implementer_ident - where - E: ::ink_env::Environment, - ::AccountId: Clone, - { - fn clone(&self) -> Self { - Self { account_id: self.account_id.clone() } - } + impl ::core::clone::Clone for #concrete_implementer_ident + where + E: ::ink_env::Environment, + ::AccountId: Clone, + { + fn clone(&self) -> Self { + Self { account_id: self.account_id.clone() } } + } - impl #ident for ::ink_lang::ConcreteImplementers - where - E: ::ink_env::Environment, - { - #[doc(hidden)] - #[allow(non_camel_case_types)] - type __ink_Checksum = [(); #verify_hash_id]; + impl #ident for ::ink_lang::ConcreteImplementers + where + E: ::ink_env::Environment, + { + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_Checksum = [(); #verify_hash_id]; - #[doc(hidden)] - #[allow(non_camel_case_types)] - type __ink_ConcreteImplementer = #concrete_implementer_ident; + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_ConcreteImplementer = #concrete_implementer_ident; - #(#constructors_never_call)* - #(#messages_never_call)* - } - }; + #(#constructors_never_call)* + #(#messages_never_call)* + } ) } diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 5d0e76790b..e466032a16 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -14,6 +14,8 @@ mod concretizer; mod definition; +mod short_call; +mod long_call; use crate::GenerateCode; use derive_more::From; @@ -33,7 +35,9 @@ impl GenerateCode for TraitDefinition<'_> { let trait_concretizer = self.generate_trait_concretizer(); quote_spanned!(span => #trait_definition - #trait_concretizer + const _: () = { + #trait_concretizer + }; ) } } From 618b476f1590f427a868efd3ae7b6d371d23a547 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 17 Mar 2021 00:15:51 +0100 Subject: [PATCH 034/493] add utility methods to InkTrait{Message,Constructor} types --- crates/lang/ir/src/ir/trait_def/mod.rs | 1 + crates/lang/ir/src/ir/trait_def/trait_item.rs | 74 ++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index 00a65c3b30..13c2a7e1df 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -22,6 +22,7 @@ use self::iter::IterInkTraitItemsRaw; pub use self::{ iter::IterInkTraitItems, trait_item::{ + InputsIter, InkTraitConstructor, InkTraitItem, InkTraitMessage, diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/trait_item.rs index db9a25968e..47ac29a6dc 100644 --- a/crates/lang/ir/src/ir/trait_def/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/trait_item.rs @@ -13,7 +13,7 @@ // limitations under the License. use super::super::InkAttribute; -use crate::ir; +use crate::{Receiver, ir}; use proc_macro2::Span; use syn::{ spanned::Spanned as _, @@ -117,6 +117,11 @@ impl<'a> InkTraitConstructor<'a> { &self.item.sig } + /// Returns an iterator over the inputs of the ink! trait message. + pub fn inputs(&self) -> InputsIter { + InputsIter::from(self) + } + /// Returns the Rust identifier of the ink! constructor. pub fn ident(&self) -> &syn::Ident { &self.item.sig.ident @@ -184,6 +189,36 @@ impl<'a> InkTraitMessage<'a> { &self.item.sig } + /// Returns the `self` receiver of the ink! trait message. + /// + /// Returns `Ref` for `&self` messages and `RefMut` for `&mut self` messages. + pub fn receiver(&self) -> Receiver { + match self.item.sig.inputs.iter().next() { + Some(syn::FnArg::Receiver(receiver)) => { + debug_assert!(receiver.reference.is_some()); + if receiver.mutability.is_some() { + Receiver::RefMut + } else { + Receiver::Ref + } + } + _ => unreachable!("encountered invalid receiver argument for ink! message"), + } + } + + /// Returns an iterator over the inputs of the ink! trait message. + pub fn inputs(&self) -> InputsIter { + InputsIter::from(self) + } + + /// Returns the return type of the ink! message if any. + pub fn output(&self) -> Option<&syn::Type> { + match &self.item.sig.output { + syn::ReturnType::Default => None, + syn::ReturnType::Type(_, return_type) => Some(return_type), + } + } + /// Returns the Rust identifier of the ink! message. pub fn ident(&self) -> &syn::Ident { &self.item.sig.ident @@ -219,3 +254,40 @@ impl<'a> InkTraitMessage<'a> { .expect("encountered missing receiver for ink! message") } } + +/// Iterator over the input parameters of an ink! message or constructor. +/// +/// Does not yield the self receiver of ink! messages. +pub struct InputsIter<'a> { + iter: syn::punctuated::Iter<'a, syn::FnArg>, +} + +impl<'a> From<&'a InkTraitMessage<'a>> for InputsIter<'a> { + fn from(message: &'a InkTraitMessage) -> Self { + Self { + iter: message.item.sig.inputs.iter(), + } + } +} + +impl<'a> From<&'a InkTraitConstructor<'a>> for InputsIter<'a> { + fn from(constructor: &'a InkTraitConstructor) -> Self { + Self { + iter: constructor.item.sig.inputs.iter(), + } + } +} + +impl<'a> Iterator for InputsIter<'a> { + type Item = &'a syn::PatType; + + fn next(&mut self) -> Option { + 'repeat: loop { + match self.iter.next() { + None => return None, + Some(syn::FnArg::Typed(pat_typed)) => return Some(pat_typed), + Some(syn::FnArg::Receiver(_)) => continue 'repeat, + } + } + } +} From ddd9d538dbe2c23f2e2bcf5dce9d4e3d2fd5cf76 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 17 Mar 2021 00:37:16 +0100 Subject: [PATCH 035/493] add initial version of the short-hand calling impls --- .../codegen/src/generator/trait_def/mod.rs | 4 +- .../src/generator/trait_def/short_call.rs | 195 ++++++++++++++++++ 2 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 crates/lang/codegen/src/generator/trait_def/short_call.rs diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index e466032a16..c196592ff2 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -14,8 +14,8 @@ mod concretizer; mod definition; -mod short_call; mod long_call; +mod short_call; use crate::GenerateCode; use derive_more::From; @@ -33,10 +33,12 @@ impl GenerateCode for TraitDefinition<'_> { let span = self.trait_def.span(); let trait_definition = self.generate_trait_definition(); let trait_concretizer = self.generate_trait_concretizer(); + let trait_concretizer_impls = self.generate_trait_impl_block(); quote_spanned!(span => #trait_definition const _: () = { #trait_concretizer + #trait_concretizer_impls }; ) } diff --git a/crates/lang/codegen/src/generator/trait_def/short_call.rs b/crates/lang/codegen/src/generator/trait_def/short_call.rs new file mode 100644 index 0000000000..fb26dff6f1 --- /dev/null +++ b/crates/lang/codegen/src/generator/trait_def/short_call.rs @@ -0,0 +1,195 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Generates code to implement an ink! trait definition for the concretized +//! type using the short-hand calling notation. + +use super::TraitDefinition; +use heck::CamelCase as _; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ + format_ident, + quote, + quote_spanned, +}; + +impl<'a> TraitDefinition<'a> { + /// Generates the code to allow short-hand cross-chain contract calls for messages. + /// + /// Unlike the generated code for ink! trait constructors the generated code uses + /// the long-hand calling versions under the hood. + fn generate_trait_impl_block_message( + &self, + message: ir::InkTraitMessage, + _selector: ir::Selector, + ) -> TokenStream2 { + let implementer_ident = self.concrete_implementer_ident(); + let span = message.span(); + let ident = message.ident(); + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let ident_str = ident.to_string(); + let trait_ident = self.trait_def.ident(); + let error_str = format!( + "encountered error while calling <{} as {}>::{}", + implementer_ident, trait_ident, ident_str + ); + let inputs_sig = message.inputs(); + let inputs_params = message.inputs().map(|pat_type| &pat_type.pat); + let output_ty = message + .output() + .cloned() + .unwrap_or_else(|| syn::parse_quote! { () }); + let receiver = message.receiver(); + let forward_ident = match receiver { + ir::Receiver::Ref => format_ident!("call"), + ir::Receiver::RefMut => format_ident!("call_mut"), + }; + let forward_trait = match receiver { + ir::Receiver::Ref => format_ident!("ForwardCall"), + ir::Receiver::RefMut => format_ident!("ForwardCallMut"), + }; + let opt_mut = match receiver { + ir::Receiver::Ref => None, + ir::Receiver::RefMut => Some(quote! { mut }), + }; + quote_spanned!(span => + type #output_ident = #output_ty; + + #[inline] + fn #ident( #receiver #(, #inputs_sig )* ) -> Self::#output_ident { + <&#opt_mut Self as ::ink_lang::#forward_trait>::#forward_ident(self) + .#ident( #( #inputs_params ),* ) + .fire() + .expect(#error_str) + } + ) + } + + /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. + fn generate_arg_list<'b, Args>(args: Args) -> TokenStream2 + where + Args: IntoIterator, + ::IntoIter: DoubleEndedIterator, + { + args.into_iter().fold( + quote! { ::ink_env::call::utils::EmptyArgumentList }, + |rest, arg| quote! { + ::ink_env::call::utils::ArgumentList<::ink_env::call::utils::Argument<#arg>, #rest> + } + ) + } + + /// Generates the code to allow cross-chain contract calls for trait constructors. + fn generate_trait_impl_block_constructor( + &self, + constructor: ir::InkTraitConstructor, + selector: ir::Selector, + ) -> TokenStream2 { + let span = constructor.span(); + let attrs = constructor.attrs(); + let ident = constructor.ident(); + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let selector_bytes = selector.as_bytes().to_owned(); + let input_bindings = constructor + .inputs() + .enumerate() + .map(|(n, _)| format_ident!("__ink_binding_{}", n)) + .collect::>(); + let input_types = constructor + .inputs() + .map(|pat_type| &*pat_type.ty) + .collect::>(); + let arg_list = Self::generate_arg_list(input_types.iter().cloned()); + quote_spanned!(span => + #[allow(clippy::type_complexity)] + type #output_ident = ::ink_env::call::CreateBuilder< + Environment, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, + ::ink_env::call::utils::Unset<::ink_env::call::state::Salt>, + Self, + >; + + #( #attrs )* + #[inline] + fn #ident( + #( #input_bindings : #input_types ),* + ) -> Self::#output_ident { + ::ink_env::call::build_create::() + .exec_input( + ::ink_env::call::ExecutionInput::new( + ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) + ) + #( + .push_arg(#input_bindings) + )* + ) + } + ) + } + + /// Returns the identifier of the concrete implementer for the ink! trait. + fn concrete_implementer_ident(&self) -> syn::Ident { + let hash = self.trait_def.verify_hash(); + let ident = self.trait_def.ident(); + format_ident!( + "__ink_ConcreteImplementer{}_0x{:X}{:X}{:X}{:X}", + ident, + hash[0], + hash[1], + hash[2], + hash[3] + ) + } + + /// Generates the short-hand calling implementations for the ink! trait concretizer. + pub(super) fn generate_trait_impl_block(&self) -> TokenStream2 { + let span = self.trait_def.span(); + let attrs = self.trait_def.attrs(); + let hash = self.trait_def.verify_hash(); + let trait_ident = self.trait_def.ident(); + let self_ident = self.concrete_implementer_ident(); + let verify_hash_id = + u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; + let messages = self.trait_def.iter_items().filter_map(|(item, selector)| { + match item { + ir::InkTraitItem::Message(message) => { + Some(self.generate_trait_impl_block_message(message, selector)) + } + _ => None, + } + }); + let constructors = self.trait_def.iter_items().filter_map(|(item, selector)| { + match item { + ir::InkTraitItem::Constructor(constructor) => { + Some(self.generate_trait_impl_block_constructor(constructor, selector)) + } + _ => None, + } + }); + quote_spanned!(span => + unsafe impl ::ink_lang::CheckedInkTrait<[(); #verify_hash_id]> for #self_ident {} + + #( #attrs )* + impl #trait_ident for #self_ident { + type __ink_Checksum = [(); #verify_hash_id]; + + #( #messages )* + #( #constructors )* + } + ) + } +} From 88fe5abc5b9c5ee3c2657ccce39da064294a1ab3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 17 Mar 2021 11:10:08 +0100 Subject: [PATCH 036/493] add empty long_call.rs file to make codebase compile again --- .../codegen/src/generator/trait_def/long_call.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 crates/lang/codegen/src/generator/trait_def/long_call.rs diff --git a/crates/lang/codegen/src/generator/trait_def/long_call.rs b/crates/lang/codegen/src/generator/trait_def/long_call.rs new file mode 100644 index 0000000000..27489b06ec --- /dev/null +++ b/crates/lang/codegen/src/generator/trait_def/long_call.rs @@ -0,0 +1,16 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Generates code to implement an ink! trait definition for the concretized +//! type using the more elaborate and customizable long-hand calling notation. From edf865bbc8710fffa0b222acf87e9bbd2bdec5f4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 17 Mar 2021 12:58:56 +0100 Subject: [PATCH 037/493] apply clippy suggestion --- crates/lang/ir/src/ir/selector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 98d02e56bb..8b0e30e37e 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -43,8 +43,8 @@ impl<'a> TraitPrefix<'a> { /// Creates a new trait prefix. pub fn new(trait_ident: &'a syn::Ident, namespace: &'a Namespace) -> Self { Self { - trait_ident, namespace, + trait_ident, } } From 20c19416318e8e6002820aff0bc478febab1b750 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 17 Mar 2021 13:07:51 +0100 Subject: [PATCH 038/493] apply rustfmt --- crates/lang/codegen/src/generator/trait_def/short_call.rs | 4 +++- crates/lang/ir/src/ir/trait_def/iter.rs | 1 - crates/lang/ir/src/ir/trait_def/mod.rs | 2 +- crates/lang/ir/src/ir/trait_def/trait_item.rs | 5 ++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/short_call.rs b/crates/lang/codegen/src/generator/trait_def/short_call.rs index fb26dff6f1..7653909701 100644 --- a/crates/lang/codegen/src/generator/trait_def/short_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/short_call.rs @@ -175,7 +175,9 @@ impl<'a> TraitDefinition<'a> { let constructors = self.trait_def.iter_items().filter_map(|(item, selector)| { match item { ir::InkTraitItem::Constructor(constructor) => { - Some(self.generate_trait_impl_block_constructor(constructor, selector)) + Some( + self.generate_trait_impl_block_constructor(constructor, selector), + ) } _ => None, } diff --git a/crates/lang/ir/src/ir/trait_def/iter.rs b/crates/lang/ir/src/ir/trait_def/iter.rs index 8f0ac02d47..b1734555cb 100644 --- a/crates/lang/ir/src/ir/trait_def/iter.rs +++ b/crates/lang/ir/src/ir/trait_def/iter.rs @@ -102,7 +102,6 @@ impl<'a> Iterator for IterInkTraitItems<'a> { Some(item @ InkTraitItem::Message(_)) => { let selector = self.message_selectors[item.ident()]; Some((item, selector)) - } } } diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index 13c2a7e1df..ac14dae2fd 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -22,10 +22,10 @@ use self::iter::IterInkTraitItemsRaw; pub use self::{ iter::IterInkTraitItems, trait_item::{ - InputsIter, InkTraitConstructor, InkTraitItem, InkTraitMessage, + InputsIter, }, }; use super::attrs::InkAttribute; diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/trait_item.rs index 47ac29a6dc..d790beb94b 100644 --- a/crates/lang/ir/src/ir/trait_def/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/trait_item.rs @@ -13,7 +13,10 @@ // limitations under the License. use super::super::InkAttribute; -use crate::{Receiver, ir}; +use crate::{ + ir, + Receiver, +}; use proc_macro2::Span; use syn::{ spanned::Spanned as _, From 17498dcfd2877ad39ce813c46f7c6de3ca9d96b0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 18 Mar 2021 19:33:47 +0100 Subject: [PATCH 039/493] apply rustfmt --- crates/lang/ir/src/ir/selector.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 8b0e30e37e..72ee9771f2 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::Namespace; - use super::blake2::blake2b_256; +use crate::Namespace; /// A function selector. /// From 039324cb4bf911fbfa59a6ecada8b60b69d3326f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 18 Mar 2021 19:34:17 +0100 Subject: [PATCH 040/493] make generate_arg_list pub to super --- crates/lang/codegen/src/generator/trait_def/short_call.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/short_call.rs b/crates/lang/codegen/src/generator/trait_def/short_call.rs index 7653909701..bd66064cc1 100644 --- a/crates/lang/codegen/src/generator/trait_def/short_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/short_call.rs @@ -77,7 +77,7 @@ impl<'a> TraitDefinition<'a> { } /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. - fn generate_arg_list<'b, Args>(args: Args) -> TokenStream2 + pub(super) fn generate_arg_list<'b, Args>(args: Args) -> TokenStream2 where Args: IntoIterator, ::IntoIter: DoubleEndedIterator, From 1dda6eade03add04fd7741992cf4d357aed18187 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 18 Mar 2021 19:34:38 +0100 Subject: [PATCH 041/493] add important attributes to trait concretizer --- .../codegen/src/generator/trait_def/concretizer.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/concretizer.rs b/crates/lang/codegen/src/generator/trait_def/concretizer.rs index b776b9b313..60fe4971da 100644 --- a/crates/lang/codegen/src/generator/trait_def/concretizer.rs +++ b/crates/lang/codegen/src/generator/trait_def/concretizer.rs @@ -60,6 +60,20 @@ impl<'a> TraitDefinition<'a> { /// A universal concrete implementer of the ink! trait definition. #[doc(hidden)] #[allow(non_camel_case_types)] + #[derive( + Debug, + ::scale::Encode, + ::scale::Decode, + ::ink_storage::traits::SpreadLayout, + ::ink_storage::traits::PackedLayout, + )] + #[cfg_attr( + feature = "std", + derive( + ::scale_info::TypeInfo, + ::ink_storage::traits::StorageLayout, + ) + )] pub struct #concrete_implementer_ident where E: ::ink_env::Environment, From efc79494387bc0891a77204247934ea8725cb5e3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 18 Mar 2021 19:34:59 +0100 Subject: [PATCH 042/493] refactor old-style cross-calling code --- .../codegen/src/generator/cross_calling.rs | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index f907027f12..2b30c2fba1 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -199,28 +199,26 @@ impl CrossCalling<'_> { format_ident!("__ink_CallForwarder") } + /// Create the identifier of an enforced ink! compilation error. + fn enforce_error_ident(error: EnforcedErrors) -> syn::Ident { + format_ident!( + "__ink_enforce_error_{}", + serde_hex::to_hex(&scale::Encode::encode(&error), false) + ) + } + + /// Returns the identifier for the generated `Out*` assoc. type. + fn out_assoc_type_ident(method_ident: &Ident) -> syn::Ident { + format_ident!("{}Out", method_ident.to_string().to_camel_case()) + } + fn generate_call_forwarder_trait_ghost_message( message: ir::CallableWithSelector, ) -> TokenStream2 { let span = message.span(); let ident = message.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = Self::out_assoc_type_ident(ident); let composed_selector = message.composed_selector().as_bytes().to_owned(); - let trait_ident = message - .item_impl() - .trait_ident() - .expect("trait identifier must exist") - .to_string(); - let linker_error = EnforcedErrors::CannotCallTraitMessage { - trait_ident, - message_ident: ident.to_string(), - message_selector: composed_selector, - message_mut: message.receiver().is_ref_mut(), - }; - let linker_error_ident = format_ident!( - "__ink_enforce_error_{}", - serde_hex::to_hex(&scale::Encode::encode(&linker_error), false) - ); let attrs = message.attrs(); let input_bindings = message .inputs() @@ -231,6 +229,18 @@ impl CrossCalling<'_> { .inputs() .map(|pat_type| &*pat_type.ty) .collect::>(); + let trait_ident = message + .item_impl() + .trait_ident() + .expect("trait identifier must exist") + .to_string(); + let linker_error_ident = + Self::enforce_error_ident(EnforcedErrors::CannotCallTraitMessage { + trait_ident, + message_ident: ident.to_string(), + message_selector: composed_selector, + message_mut: message.receiver().is_ref_mut(), + }); let output_ty = message .output() .cloned() @@ -266,7 +276,7 @@ impl CrossCalling<'_> { ) -> TokenStream2 { let span = message.span(); let ident = message.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = Self::out_assoc_type_ident(ident); let composed_selector = message.composed_selector().as_bytes().to_owned(); let attrs = message.attrs(); let input_bindings = message @@ -288,9 +298,9 @@ impl CrossCalling<'_> { Some(_) => None, None => Some(quote! { pub }), }; - let receiver = match message.receiver() { - ir::Receiver::Ref => Some(quote! { &self }), - ir::Receiver::RefMut => Some(quote! { &mut self }), + let mut_tok = match message.receiver() { + ir::Receiver::Ref => None, + ir::Receiver::RefMut => Some(quote! { mut }), }; quote_spanned!(span=> #[allow(clippy::type_complexity)] @@ -306,7 +316,7 @@ impl CrossCalling<'_> { #( #attrs )* #[inline] #pub_tok fn #ident( - #receiver #(, #input_bindings : #input_types )* + & #mut_tok #(, #input_bindings : #input_types )* ) -> Self::#output_ident { ::ink_env::call::build_call::() .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) From 676f60baa8e81fb9311ea9724a728616ef5f3d09 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 18 Mar 2021 19:35:19 +0100 Subject: [PATCH 043/493] add #[inline] for Clone impl of trait concretizer --- crates/lang/codegen/src/generator/trait_def/concretizer.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/lang/codegen/src/generator/trait_def/concretizer.rs b/crates/lang/codegen/src/generator/trait_def/concretizer.rs index 60fe4971da..ef1a7e6e9f 100644 --- a/crates/lang/codegen/src/generator/trait_def/concretizer.rs +++ b/crates/lang/codegen/src/generator/trait_def/concretizer.rs @@ -107,6 +107,7 @@ impl<'a> TraitDefinition<'a> { E: ::ink_env::Environment, ::AccountId: Clone, { + #[inline] fn clone(&self) -> Self { Self { account_id: self.account_id.clone() } } From 770e14f22fcc06e06b739ac44d06e814bf3cc210 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 18 Mar 2021 19:35:36 +0100 Subject: [PATCH 044/493] add initial impl for long-hand calls of trait concretizers --- .../src/generator/trait_def/long_call.rs | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/long_call.rs b/crates/lang/codegen/src/generator/trait_def/long_call.rs index 27489b06ec..e06db79c4b 100644 --- a/crates/lang/codegen/src/generator/trait_def/long_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/long_call.rs @@ -14,3 +14,213 @@ //! Generates code to implement an ink! trait definition for the concretized //! type using the more elaborate and customizable long-hand calling notation. + +#![allow(dead_code)] + +use super::TraitDefinition; +use heck::CamelCase as _; +use impl_serde::serialize as serde_hex; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ + format_ident, + quote, + quote_spanned, +}; + +/// Errors which may occur when forwarding a call is not allowed. +/// +/// We insert markers for these errors in the generated contract code. +/// This is necessary since we can't check these errors at compile time +/// of the contract. +/// `cargo-contract` checks the contract code for these error markers +/// when building a contract and fails if it finds markers. +#[derive(scale::Encode, scale::Decode)] +pub enum EnforcedErrors { + /// The below error represents calling a `&mut self` message in a context that + /// only allows for `&self` messages. This may happen under certain circumstances + /// when ink! trait implementations are involved with long-hand calling notation. + #[codec(index = 1)] + CannotCallTraitMessage { + /// The trait that defines the called message. + trait_ident: String, + /// The name of the called message. + message_ident: String, + /// The selector of the called message. + message_selector: [u8; 4], + /// Is `true` if the `self` receiver of the ink! message is `&mut self`. + message_mut: bool, + }, + /// The below error represents calling a constructor in a context that does + /// not allow calling it. This may happen when the constructor defined in a + /// trait is cross-called in another contract. + /// This is not allowed since the contract to which a call is forwarded must + /// already exist at the point when the call to it is made. + #[codec(index = 2)] + CannotCallTraitConstructor { + /// The trait that defines the called constructor. + trait_ident: String, + /// The name of the called constructor. + constructor_ident: String, + /// The selector of the called constructor. + constructor_selector: [u8; 4], + }, +} + +impl EnforcedErrors { + /// Create the identifier of an enforced ink! compilation error. + fn enforce_error_ident(&self) -> syn::Ident { + format_ident!( + "__ink_enforce_error_{}", + serde_hex::to_hex(&scale::Encode::encode(&self), false) + ) + } +} + +impl<'a> TraitDefinition<'a> { + /// Returns the identifier for the generated call forwarder utility. + fn call_forwarder_ident() -> syn::Ident { + format_ident!("__ink_CallForwarder") + } + + /// Returns the identifier for the generated `Out*` assoc. type. + fn out_assoc_type_ident(method_ident: &syn::Ident) -> syn::Ident { + format_ident!("{}Out", method_ident.to_string().to_camel_case()) + } + + /// Returns the sequence of input parameter bindings for the message. + fn input_bindings(message: &ir::InkTraitMessage) -> Vec { + message + .inputs() + .enumerate() + .map(|(n, _)| format_ident!("__ink_binding_{}", n)) + .collect::>() + } + + /// Returns the sequence of input types for the message. + fn input_types<'b>(message: &'b ir::InkTraitMessage) -> Vec<&'b syn::Type> { + message + .inputs() + .map(|pat_type| &*pat_type.ty) + .collect::>() + } + + /// Create an enforced ink! message error. + fn create_enforced_message_error( + &self, + message: &ir::InkTraitMessage, + selector: ir::Selector, + ) -> syn::Ident { + let trait_ident = self.trait_def.ident(); + EnforcedErrors::CannotCallTraitMessage { + trait_ident: trait_ident.to_string(), + message_ident: message.ident().to_string(), + message_selector: selector.as_bytes().to_owned(), + message_mut: message.receiver().is_ref_mut(), + } + .enforce_error_ident() + } + + fn generate_ghost_message( + &self, + message: ir::InkTraitMessage, + selector: ir::Selector, + ) -> TokenStream2 { + let span = message.span(); + let ident = message.ident(); + let output_ident = Self::out_assoc_type_ident(ident); + let attrs = message.attrs(); + let mut_tok = message.mutates().then(|| quote! { mut }); + let input_bindings = Self::input_bindings(&message); + let input_types = Self::input_types(&message); + let enforced_error = self.create_enforced_message_error(&message, selector); + let output_ty = message + .output() + .cloned() + .unwrap_or_else(|| syn::parse_quote! { () }); + quote_spanned!(span=> + type #output_ident = #output_ty; + + #( #attrs )* + #[cold] + #[doc(hidden)] + fn #ident( + & #mut_tok self, + #( #input_bindings : #input_types ),* + ) -> Self::#output_ident { + extern { + fn #enforced_error() -> !; + } + unsafe { #enforced_error() } + } + ) + } + + fn generate_proper_message( + &self, + message: ir::InkTraitMessage, + selector: ir::Selector, + ) -> TokenStream2 { + let span = message.span(); + let ident = message.ident(); + let output_ident = Self::out_assoc_type_ident(ident); + let attrs = message.attrs(); + let mut_tok = message.mutates().then(|| quote! { mut }); + let input_bindings = Self::input_bindings(&message); + let input_types = Self::input_types(&message); + let selector_bytes = selector.as_bytes(); + let arg_list = Self::generate_arg_list(input_types.iter().cloned()); + let output = message.output(); + let output_sig = output.map_or_else( + || quote! { () }, + |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, + ); + quote_spanned!(span=> + #[allow(clippy::type_complexity)] + type #output_ident = ::ink_env::call::CallBuilder< + Environment, + ::ink_env::call::utils::Set, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, + ::ink_env::call::utils::Set<#output_sig>, + >; + + #( #attrs )* + #[inline] + fn #ident( + & #mut_tok #(, #input_bindings : #input_types )* + ) -> Self::#output_ident { + ::ink_env::call::build_call::() + .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) + .exec_input( + ::ink_env::call::ExecutionInput::new( + ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) + ) + #( + .push_arg(#input_bindings) + )* + ) + .returns::<#output_sig>() + } + ) + } + + /// Generates code for a single call forwarder trait message. + /// + /// The `mutable` parameter indicates whether only read-only (`false`) or + /// write-only (`true`) messages shall be valid calls. For non valid messages + /// an invalid implementation is provided so that actually calling those + /// will result in a compiler or linker error. + fn generate_proper_or_ghost_message( + &self, + mutable: bool, + message: ir::InkTraitMessage, + selector: ir::Selector, + ) -> TokenStream2 { + if mutable == message.receiver().is_ref_mut() { + self.generate_proper_message(message, selector) + } else { + self.generate_ghost_message(message, selector) + } + } +} From 8d6bedc4b6217c78f51c8b7a519e7fa88a5d7b99 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:37:27 +0100 Subject: [PATCH 045/493] refactor short_call.rs --- .../src/generator/trait_def/short_call.rs | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/short_call.rs b/crates/lang/codegen/src/generator/trait_def/short_call.rs index bd66064cc1..21808e9722 100644 --- a/crates/lang/codegen/src/generator/trait_def/short_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/short_call.rs @@ -165,22 +165,14 @@ impl<'a> TraitDefinition<'a> { let verify_hash_id = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; let messages = self.trait_def.iter_items().filter_map(|(item, selector)| { - match item { - ir::InkTraitItem::Message(message) => { - Some(self.generate_trait_impl_block_message(message, selector)) - } - _ => None, - } + item.filter_map_message().map(|message| { + self.generate_trait_impl_block_message(message, selector) + }) }); let constructors = self.trait_def.iter_items().filter_map(|(item, selector)| { - match item { - ir::InkTraitItem::Constructor(constructor) => { - Some( - self.generate_trait_impl_block_constructor(constructor, selector), - ) - } - _ => None, - } + item.filter_map_constructor().map(|constructor| { + self.generate_trait_impl_block_constructor(constructor, selector) + }) }); quote_spanned!(span => unsafe impl ::ink_lang::CheckedInkTrait<[(); #verify_hash_id]> for #self_ident {} From b2c1fa5fabf8fd36940e063c120cffe1de53724d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:38:09 +0100 Subject: [PATCH 046/493] refactor concretizer.rs --- .../codegen/src/generator/trait_def/concretizer.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/concretizer.rs b/crates/lang/codegen/src/generator/trait_def/concretizer.rs index ef1a7e6e9f..da388d894f 100644 --- a/crates/lang/codegen/src/generator/trait_def/concretizer.rs +++ b/crates/lang/codegen/src/generator/trait_def/concretizer.rs @@ -30,18 +30,24 @@ use quote::{ }; impl<'a> TraitDefinition<'a> { - pub(super) fn generate_trait_concretizer(&self) -> TokenStream2 { - let span = self.trait_def.span(); + pub(super) fn concretizer_ident(&self) -> syn::Ident { let hash = self.trait_def.verify_hash(); let ident = self.trait_def.ident(); - let concrete_implementer_ident = format_ident!( + format_ident!( "__ink_ConcreteImplementer{}_0x{:X}{:X}{:X}{:X}", ident, hash[0], hash[1], hash[2], hash[3] - ); + ) + } + + pub(super) fn generate_trait_concretizer(&self) -> TokenStream2 { + let span = self.trait_def.span(); + let hash = self.trait_def.verify_hash(); + let ident = self.trait_def.ident(); + let concrete_implementer_ident = self.concretizer_ident(); let verify_hash_id = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; let constructors_never_call = self From dbd82f117c34b620eb637c6f02582031a5b12c9c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:39:56 +0100 Subject: [PATCH 047/493] refactor input_bindings utility method --- .../src/generator/trait_def/long_call.rs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/long_call.rs b/crates/lang/codegen/src/generator/trait_def/long_call.rs index e06db79c4b..f1399b5083 100644 --- a/crates/lang/codegen/src/generator/trait_def/long_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/long_call.rs @@ -20,6 +20,7 @@ use super::TraitDefinition; use heck::CamelCase as _; use impl_serde::serialize as serde_hex; +use ir::TraitItemInputsIter; use proc_macro2::TokenStream as TokenStream2; use quote::{ format_ident, @@ -88,20 +89,16 @@ impl<'a> TraitDefinition<'a> { } /// Returns the sequence of input parameter bindings for the message. - fn input_bindings(message: &ir::InkTraitMessage) -> Vec { - message - .inputs() + fn input_bindings(inputs: TraitItemInputsIter) -> Vec { + inputs .enumerate() .map(|(n, _)| format_ident!("__ink_binding_{}", n)) .collect::>() } /// Returns the sequence of input types for the message. - fn input_types<'b>(message: &'b ir::InkTraitMessage) -> Vec<&'b syn::Type> { - message - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>() + fn input_types<'b>(inputs: TraitItemInputsIter<'b>) -> Vec<&'b syn::Type> { + inputs.map(|pat_type| &*pat_type.ty).collect::>() } /// Create an enforced ink! message error. @@ -130,8 +127,8 @@ impl<'a> TraitDefinition<'a> { let output_ident = Self::out_assoc_type_ident(ident); let attrs = message.attrs(); let mut_tok = message.mutates().then(|| quote! { mut }); - let input_bindings = Self::input_bindings(&message); - let input_types = Self::input_types(&message); + let input_bindings = Self::input_bindings(message.inputs()); + let input_types = Self::input_types(message.inputs()); let enforced_error = self.create_enforced_message_error(&message, selector); let output_ty = message .output() @@ -165,8 +162,8 @@ impl<'a> TraitDefinition<'a> { let output_ident = Self::out_assoc_type_ident(ident); let attrs = message.attrs(); let mut_tok = message.mutates().then(|| quote! { mut }); - let input_bindings = Self::input_bindings(&message); - let input_types = Self::input_types(&message); + let input_bindings = Self::input_bindings(message.inputs()); + let input_types = Self::input_types(message.inputs()); let selector_bytes = selector.as_bytes(); let arg_list = Self::generate_arg_list(input_types.iter().cloned()); let output = message.output(); From 9d45f725e38e4113cf8556acb279b185ad2ab5b1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:40:13 +0100 Subject: [PATCH 048/493] add missing doc comments --- .../codegen/src/generator/trait_def/long_call.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/long_call.rs b/crates/lang/codegen/src/generator/trait_def/long_call.rs index f1399b5083..9546dc4b4c 100644 --- a/crates/lang/codegen/src/generator/trait_def/long_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/long_call.rs @@ -117,6 +117,15 @@ impl<'a> TraitDefinition<'a> { .enforce_error_ident() } + /// Generate code for cross-calling an invalid ink! trait message. + /// + /// Trying to call the generated message will always yield a link-time + /// error which is caught by the `cargo-contract` CLI tool. + /// + /// # Note + /// + /// This is implemented for the call forwarder in case the mutability + /// overlaps with the message's mutability. fn generate_ghost_message( &self, message: ir::InkTraitMessage, @@ -152,6 +161,12 @@ impl<'a> TraitDefinition<'a> { ) } + /// Generate code for cross-calling an ink! trait message. + /// + /// # Note + /// + /// This is implemented for the call forwarder in case the mutability + /// overlaps with the message's mutability. fn generate_proper_message( &self, message: ir::InkTraitMessage, From 0613c1b7d25ed1b1ed4196ee546c68f2b40d3fb7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:40:58 +0100 Subject: [PATCH 049/493] add codegen for ink! trait constructors (long-hand) --- .../src/generator/trait_def/long_call.rs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/long_call.rs b/crates/lang/codegen/src/generator/trait_def/long_call.rs index 9546dc4b4c..cc0af421fc 100644 --- a/crates/lang/codegen/src/generator/trait_def/long_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/long_call.rs @@ -117,6 +117,21 @@ impl<'a> TraitDefinition<'a> { .enforce_error_ident() } + /// Create an enforced ink! message error. + fn create_enforced_constructor_error( + &self, + constructor: &ir::InkTraitConstructor, + selector: ir::Selector, + ) -> syn::Ident { + let trait_ident = self.trait_def.ident(); + EnforcedErrors::CannotCallTraitConstructor { + trait_ident: trait_ident.to_string(), + constructor_ident: constructor.ident().to_string(), + constructor_selector: selector.as_bytes().to_owned(), + } + .enforce_error_ident() + } + /// Generate code for cross-calling an invalid ink! trait message. /// /// Trying to call the generated message will always yield a link-time @@ -235,4 +250,40 @@ impl<'a> TraitDefinition<'a> { self.generate_ghost_message(message, selector) } } + + /// Generates code for a single call forwarder trait constructor. + /// + /// Note that constructors never need to be forwarded and that we only + /// provide their implementations to satisfy the implementation block. + /// We generally try to generate code in a way that actually calling + /// those constructors will result in a compiler or linker error. + fn generate_ghost_constructor( + &self, + constructor: ir::InkTraitConstructor, + selector: ir::Selector, + ) -> TokenStream2 { + let span = constructor.span(); + let attrs = constructor.attrs(); + let ident = constructor.ident(); + let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let enforced_error = + self.create_enforced_constructor_error(&constructor, selector); + let input_bindings = Self::input_bindings(constructor.inputs()); + let input_types = Self::input_types(constructor.inputs()); + quote_spanned!(span => + type #output_ident = ::ink_lang::NeverReturns; + + #( #attrs )* + #[cold] + #[doc(hidden)] + fn #ident( + #( #input_bindings : #input_types ),* + ) -> Self::#output_ident { + extern { + fn #enforced_error() -> !; + } + unsafe { #enforced_error() } + } + ) + } } From d4489cb3c8a8340966a3f1b86d152e22cef4786b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:41:21 +0100 Subject: [PATCH 050/493] add root API for long-hand codegen for ink! trait items --- .../src/generator/trait_def/long_call.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/long_call.rs b/crates/lang/codegen/src/generator/trait_def/long_call.rs index cc0af421fc..86f58c62a0 100644 --- a/crates/lang/codegen/src/generator/trait_def/long_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/long_call.rs @@ -286,4 +286,44 @@ impl<'a> TraitDefinition<'a> { } ) } + + /// Generates code for a single call forwarder trait implementation block. + /// + /// The `mutable` parameter indicates whether only read-only (`false`) or + /// write-only (`true`) messages and constructors are to be considered. + fn generate_trait_impl_longhand(&self, mutable: bool) -> TokenStream2 { + let span = self.trait_def.span(); + let attrs = self.trait_def.attrs(); + let forwarder_ident = Self::call_forwarder_ident(); + let verify_hash = self.trait_def.verify_hash(); + let checksum = u32::from_be_bytes([ + verify_hash[0], + verify_hash[1], + verify_hash[2], + verify_hash[3], + ]) as usize; + let trait_ident = self.trait_def.ident(); + let self_ident = self.concretizer_ident(); + let mut_tok = mutable.then(|| quote! { mut }); + let messages = self.trait_def.iter_items().filter_map(|(item, selector)| { + item.filter_map_message().map(|message| { + self.generate_proper_or_ghost_message(mutable, message, selector) + }) + }); + let constructors = self.trait_def.iter_items().filter_map(|(item, selector)| { + item.filter_map_constructor() + .map(|constructor| self.generate_ghost_constructor(constructor, selector)) + }); + quote_spanned!(span => + unsafe impl<'a> ::ink_lang::CheckedInkTrait<[(); #checksum]> for #forwarder_ident<&'a #mut_tok #self_ident> {} + + #( #attrs )* + impl<'a> #trait_ident for #forwarder_ident<&'a #mut_tok #self_ident> { + type __ink_Checksum = [(); #checksum]; + + #( #constructors )* + #( #messages )* + } + ) + } } From 121490fd6b6c3f3019aa7cf16fcd27f6bf358638 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:41:43 +0100 Subject: [PATCH 051/493] re-export TraitItemInputsIter from ink_lang_ir crate --- crates/lang/ir/src/ir/mod.rs | 1 + crates/lang/ir/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/lang/ir/src/ir/mod.rs b/crates/lang/ir/src/ir/mod.rs index 5140748976..d62e9cd6fa 100644 --- a/crates/lang/ir/src/ir/mod.rs +++ b/crates/lang/ir/src/ir/mod.rs @@ -87,5 +87,6 @@ pub use self::{ InkTraitItem, InkTraitMessage, IterInkTraitItems, + InputsIter as TraitItemInputsIter, }, }; diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index e051fb76f1..b6285b60c4 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -65,5 +65,6 @@ pub use self::ir::{ Receiver, Selector, Storage, + TraitItemInputsIter, Visibility, }; From 86efb3a290f0013c4e4887cdb62b3762b5bed05e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 23 Mar 2021 19:42:06 +0100 Subject: [PATCH 052/493] add (commented-out) codegen for long-hand ink! trait items --- crates/lang/codegen/src/generator/trait_def/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index c196592ff2..8b6eb7a4bd 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -34,6 +34,7 @@ impl GenerateCode for TraitDefinition<'_> { let trait_definition = self.generate_trait_definition(); let trait_concretizer = self.generate_trait_concretizer(); let trait_concretizer_impls = self.generate_trait_impl_block(); + // let long_hand_impls = self.generate_trait_impl_longhand(); quote_spanned!(span => #trait_definition const _: () = { From 1f8079a8a93b3fe763c83b8d8605a33f0b0ff5b4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 5 May 2021 16:42:38 +0200 Subject: [PATCH 053/493] add trait-incrementer This example contract uses 2 different traits as show case. --- examples/trait-incrementer/.gitignore | 9 +++ examples/trait-incrementer/Cargo.toml | 38 +++++++++++ examples/trait-incrementer/lib.rs | 95 +++++++++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 examples/trait-incrementer/.gitignore create mode 100644 examples/trait-incrementer/Cargo.toml create mode 100644 examples/trait-incrementer/lib.rs diff --git a/examples/trait-incrementer/.gitignore b/examples/trait-incrementer/.gitignore new file mode 100644 index 0000000000..bf910de10a --- /dev/null +++ b/examples/trait-incrementer/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock \ No newline at end of file diff --git a/examples/trait-incrementer/Cargo.toml b/examples/trait-incrementer/Cargo.toml new file mode 100644 index 0000000000..60340d84f9 --- /dev/null +++ b/examples/trait-incrementer/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "flipper" +version = "3.0.0-rc3" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +ink_primitives = { version = "3.0.0-rc3", path = "../../crates/primitives", default-features = false } +ink_metadata = { version = "3.0.0-rc3", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } +ink_env = { version = "3.0.0-rc3", path = "../../crates/env", default-features = false } +ink_storage = { version = "3.0.0-rc3", path = "../../crates/storage", default-features = false } +ink_lang = { version = "3.0.0-rc3", path = "../../crates/lang", default-features = false } + +scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] } +scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } + +# Should be removed once bitvecto-rs/bitvec#105 is resolved +funty = "=1.1.0" + +[lib] +name = "flipper" +path = "lib.rs" +crate-type = ["cdylib"] + +[features] +default = ["std"] +std = [ + "ink_primitives/std", + "ink_metadata", + "ink_metadata/std", + "ink_env/std", + "ink_storage/std", + "ink_lang/std", + "scale/std", + "scale-info", + "scale-info/std", +] +ink-as-dependency = [] diff --git a/examples/trait-incrementer/lib.rs b/examples/trait-incrementer/lib.rs new file mode 100644 index 0000000000..49308eeca1 --- /dev/null +++ b/examples/trait-incrementer/lib.rs @@ -0,0 +1,95 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] + +use ink_lang as ink; + +/// Allows to increment and get the current value. +#[ink::trait_definition] +pub trait Increment { + /// Increments the current value of the implementer by 1. + #[ink(message)] + fn inc(&mut self); + + /// Returns the current value of the implementer. + #[ink(message)] + fn get(&self) -> u64; +} + +/// Allows to reset the current value. +#[ink::trait_definition] +pub trait Reset { + /// Increments the current value of the implementer by 1. + #[ink(message)] + fn reset(&mut self); +} + +#[ink::contract] +pub mod incrementer { + use super::{Increment, Reset}; + + #[ink(storage)] + pub struct Incrementer { + value: u64, + } + + impl Incrementer { + /// Creates a new incrementer smart contract initialized with `0`. + #[ink(constructor)] + pub fn new() -> Self { + Self { value: Default::default() } + } + } + + impl Increment for Incrementer { + #[ink(message)] + fn inc(&mut self) { + self.value += 1; + } + + #[ink(message)] + fn get(&self) -> bool { + self.value + } + } + + impl Reset for Incrementer { + #[ink(message)] + fn reset(&mut self) { + self.value = 0; + } + } + + // #[cfg(test)] + // mod tests { + // use super::*; + + // #[test] + // fn default_works() { + // let flipper = Flipper::default(); + // assert_eq!(flipper.get(), false); + // } + + // #[test] + // fn it_works() { + // let mut flipper = Flipper::new(false); + // // Can call using universal call syntax using the trait. + // assert_eq!(::get(&flipper), false); + // ::flip(&mut flipper); + // // Normal call syntax possible to as long as the trait is in scope. + // assert_eq!(flipper.get(), true); + // } + // } +} From c2f18cd8e1a180819ba7f5ad7c00370dc51f7a1a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 5 May 2021 16:49:25 +0200 Subject: [PATCH 054/493] add new utility traits for upcoming ink! codegen --- crates/lang/src/traits.rs | 77 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 33d96bdf9a..2f8d48ee5f 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -161,3 +161,80 @@ unsafe impl CheckedInkTrait<[(); N]> for ConcreteImplementers /// Read more about its use [here][TraitDefinitionRegistry]. #[doc(hidden)] pub enum NoConcreteImplementer {} + +/// The global call builder type for an ink! trait definition. +pub trait TraitCallBuilder { + /// The call builder type. + type Builder; + + /// Returns a shared reference to the global call builder type. + /// + /// This allows to call `&self` ink! trait messages. + fn call(&self) -> &Self::Builder; + + /// Returns an exclusive reference to the global call builder type. + /// + /// This allows to call any ink! trait message. + fn call_mut(&mut self) -> &mut Self::Builder; +} + +/// Implemented by the global trait info provider. +/// +/// This communicates the `u32` number that uniquely identifies +/// the ink! trait definition. +pub trait TraitUniqueId { + /// The unique trait `u32` identifier. + const ID: u32; +} + +/// Implemented by the global trait info provider. +/// +/// It is used to query the global trait call forwarder. +/// There is one global trait call forwarder that implements +/// the call forwarding (short- and long-form) for all calls +/// to this trait in `ink-as-dependency` configuration. +pub trait TraitCallForwarder { + /// The call forwarder type. + type Forwarder: TraitCallBuilder; +} + +/// Implemented by call builders of smart contracts. +/// +/// These might be implementing multiple different ink! traits. +/// The codegen makes them implement this trait once for every +/// ink! trait they have to implement. +/// +/// While the trait is not necessary it encapsulates a lot of +/// utility and auxiliary code required for the actual ink! trait +/// implementations. +pub trait TraitCallForwarderFor { + type Forwarder: TraitCallBuilder; + + /// Forwards the `&self` call. + /// + /// # Note + /// + /// This is used for the short-hand calling syntax. + fn forward(&self) -> &Self::Forwarder; + + /// Forwards the `&mut self` call. + /// + /// # Note + /// + /// This is used for the short-hand calling syntax. + fn forward_mut(&mut self) -> &mut Self::Forwarder; + + /// Builds up the `&self` call. + /// + /// # Note + /// + /// This is used for the long-hand calling syntax. + fn build(&self) -> &::Builder; + + /// Builds up the `&mut self` call. + /// + /// # Note + /// + /// This is used for the long-hand calling syntax. + fn build_mut(&mut self) -> &mut ::Builder; +} From 32badb83e4d40335311e9c238e5ab95ca70a1d23 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 5 May 2021 16:49:41 +0200 Subject: [PATCH 055/493] rename some utility ink! codegen traits --- crates/lang/src/traits.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 2f8d48ee5f..9d69ef07c0 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -30,7 +30,7 @@ use ink_storage::traits::SpreadLayout; /// Trait used to indicate that an ink! trait definition has been checked /// by the `#[ink::trait_definition]` proc. macro. #[doc(hidden)] -pub unsafe trait CheckedInkTrait {} +pub unsafe trait TraitImplementer {} /// Trait used by `#[ink::trait_definition]` to ensure that the associated /// return type for each trait message is correct. @@ -149,11 +149,11 @@ pub trait True {} /// that ink! can serialize and deserialize as if it was an `AccountId` and call /// ink! messages on it according to the ink! trait definition interface. #[doc(hidden)] -pub struct ConcreteImplementers { +pub struct TraitCallForwarderRegistry { marker: PhantomData E>, } -unsafe impl CheckedInkTrait<[(); N]> for ConcreteImplementers {} +unsafe impl TraitImplementer for TraitCallForwarderRegistry {} /// The default type that ink! trait definition implementations use for the /// `__ink_DynamicCallForwarder` associated type. From 112618f8b8d123a8fab7ee9d9ac395e92ec6c8a5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 5 May 2021 16:49:54 +0200 Subject: [PATCH 056/493] properly export all ink! codegen utility traits --- crates/lang/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index b426c35e31..57f9c6fff8 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -65,8 +65,7 @@ pub use self::{ EmitEvent, }, traits::{ - CheckedInkTrait, - ConcreteImplementers, + TraitImplementer, Constructor, FnInput, FnOutput, @@ -76,6 +75,11 @@ pub use self::{ MessageMut, MessageRef, NoConcreteImplementer, + TraitCallBuilder, + TraitCallForwarder, + TraitCallForwarderRegistry, + TraitUniqueId, + TraitCallForwarderFor, True, }, }; From bb9b5bcece784ccb8f27a60f13de83385f7c1d74 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 5 May 2021 16:50:19 +0200 Subject: [PATCH 057/493] remove invalid Salt parameter for codegen of instantiation in traits --- crates/lang/codegen/src/generator/trait_def/short_call.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/short_call.rs b/crates/lang/codegen/src/generator/trait_def/short_call.rs index 21808e9722..b618feb941 100644 --- a/crates/lang/codegen/src/generator/trait_def/short_call.rs +++ b/crates/lang/codegen/src/generator/trait_def/short_call.rs @@ -128,7 +128,7 @@ impl<'a> TraitDefinition<'a> { fn #ident( #( #input_bindings : #input_types ),* ) -> Self::#output_ident { - ::ink_env::call::build_create::() + ::ink_env::call::build_create::() .exec_input( ::ink_env::call::ExecutionInput::new( ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) From 821bc81deef1d11faeeeea618ab51e0b65a16156 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:32:13 +0200 Subject: [PATCH 058/493] [ir] add TraitDefinition::unique_id getter --- crates/lang/ir/src/ir/trait_def/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index ac14dae2fd..cc606a7e4b 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -151,6 +151,12 @@ impl InkTrait { }), ) } + + /// Returns the unique trait identifier. + pub fn unique_id(&self) -> u32 { + let [h1, h2, h3, h4, ..] = self.verify_hash(); + u32::from_be_bytes([h1, h2, h3, h4]) + } } impl InkTrait { From 498320c85e5ac29cc71339549d3b9f2ae6bce0f6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:33:09 +0200 Subject: [PATCH 059/493] [lang] add traits for the trait registry information object --- crates/lang/src/lib.rs | 1 + crates/lang/src/traits.rs | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 57f9c6fff8..91f3f849db 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -80,6 +80,7 @@ pub use self::{ TraitCallForwarderRegistry, TraitUniqueId, TraitCallForwarderFor, + TraitModulePath, True, }, }; diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 9d69ef07c0..dda6e64742 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -198,6 +198,23 @@ pub trait TraitCallForwarder { type Forwarder: TraitCallBuilder; } +/// Captures the module path of the ink! trait definition. +/// +/// This can be used to differentiate between two equally named +/// ink! trait definitions and also for metadata. +pub trait TraitModulePath { + /// The module path of the ink! trait definition. + /// + /// This is equivalent to Rust's builtin `module_path!` macro + /// invokation at the definition site of the ink! trait. + const PATH: &'static str; + + /// The full path and name of the ink! trait separated with `::`. + /// + /// This is just for convenience. + const FULL: &'static str; +} + /// Implemented by call builders of smart contracts. /// /// These might be implementing multiple different ink! traits. @@ -238,3 +255,31 @@ pub trait TraitCallForwarderFor { /// This is used for the long-hand calling syntax. fn build_mut(&mut self) -> &mut ::Builder; } + +/// Stores information per trait message. +/// +/// This information includes if the ink! trait message has been +/// annotated with `#[ink(payable)]`. +/// +/// In the future this info trait might be extended to contain +/// more information about a single ink! trait message. +/// +/// The information provided through this trait can be used on the +/// implementer side of an ink! trait to check and guard certain +/// properties on a Rust type system level. This is important since +/// ink! cannot be guaranteed to have both the ink! trait definition +/// and all of its implementers under its scope and radar. +/// +/// # Note +/// +/// - The `TRAIT_ID` is the `u32` identifier uniquely identifying the +/// ink! trait. +/// - The `MSG_ID` is the `u32` identifier derived from the selector +/// that uniquely identifies the message. +pub trait TraitMessageInfo { + /// Is `true` if the ink! trait message has been annotated with `#[ink(payable)]`. + const PAYABLE: bool; + + /// The unique selector of the ink! trait message. + const SELECTOR: [u8; 4]; +} From 0b530276024305a630fc2fa107cbff042375ae98 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:33:59 +0200 Subject: [PATCH 060/493] add utility methods to trait definition codegen --- .../codegen/src/generator/trait_def/mod.rs | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 8b6eb7a4bd..f686442504 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -17,17 +17,51 @@ mod definition; mod long_call; mod short_call; +use heck::CamelCase as _; use crate::GenerateCode; use derive_more::From; -use proc_macro2::TokenStream as TokenStream2; -use quote::quote_spanned; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::{ + format_ident, + quote_spanned, +}; /// Generator to create the ink! storage struct and important trait impls. -#[derive(From)] +#[derive(From, Copy, Clone)] pub struct TraitDefinition<'a> { trait_def: &'a ir::InkTrait, } +impl<'a> TraitDefinition<'a> { + /// Appends the trait suffix to the string and forms an identifier. + /// + /// This appends the `_$NAME_$TRAIT_ID` string to the prefix string + /// were `$NAME` is the non-unique name of the trait and `$TRAIT_ID` + /// is the hex representation of the unique 4-byte trait identifier. + fn append_trait_suffix(&self, prefix: &str) -> syn::Ident { + let unique_id = self.trait_def.unique_id().to_be_bytes(); + format_ident!( + "__ink_{}_{}_0x{:X}{:X}{:X}{:X}", + prefix, + self.trait_def.ident(), + unique_id[0], + unique_id[1], + unique_id[2], + unique_id[3] + ) + } + + /// Returns the span of the underlying ink! trait definition. + fn span(&self) -> Span { + self.trait_def.span() + } + + /// Returns the associated output type for an ink! trait message. + fn output_ident(&self, message_name: &syn::Ident) -> syn::Ident { + format_ident!("{}Output", message_name.to_string().to_camel_case()) + } +} + impl GenerateCode for TraitDefinition<'_> { fn generate_code(&self) -> TokenStream2 { let span = self.trait_def.span(); From 89d75a3097bfa1cf6be9370715e3873e9eacbad0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:34:23 +0200 Subject: [PATCH 061/493] add trait registry codegen --- .../codegen/src/generator/trait_def/mod.rs | 3 + .../src/generator/trait_def/trait_registry.rs | 252 ++++++++++++++++++ 2 files changed, 255 insertions(+) create mode 100644 crates/lang/codegen/src/generator/trait_def/trait_registry.rs diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index f686442504..b42a704a80 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -16,6 +16,7 @@ mod concretizer; mod definition; mod long_call; mod short_call; +mod trait_registry; use heck::CamelCase as _; use crate::GenerateCode; @@ -69,11 +70,13 @@ impl GenerateCode for TraitDefinition<'_> { let trait_concretizer = self.generate_trait_concretizer(); let trait_concretizer_impls = self.generate_trait_impl_block(); // let long_hand_impls = self.generate_trait_impl_longhand(); + let trait_registry = self.generate_trait_registry_impl(); quote_spanned!(span => #trait_definition const _: () = { #trait_concretizer #trait_concretizer_impls + #trait_registry }; ) } diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs new file mode 100644 index 0000000000..7f8176cf3f --- /dev/null +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -0,0 +1,252 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! The global registry with which it is possible to refer back to the global +//! trait call builder and call forwarder types using only the trait identifier. +//! +//! This works by making the global trait registry type defined in the `ink_lang` +//! crate implement each and every ink! trait definition and defining associated +//! types for the trait's respective call builder and call forwarder. + +use super::TraitDefinition; +use crate::{ + generator::enforced_error::EnforcedErrors, + traits::GenerateCode, +}; +use derive_more::From; +use proc_macro2::{ + Span, + TokenStream as TokenStream2, +}; +use quote::{ + format_ident, + quote, + quote_spanned, +}; + +impl<'a> TraitDefinition<'a> { + /// Generates the code for the global trait registry implementation. + /// + /// This also generates the code for the global trait info object which + /// implements some `ink_lang` traits to provide common information about + /// the ink! trait definition such as its unique identifier. + pub fn generate_trait_registry_impl(&self) -> TokenStream2 { + TraitRegistry::from(*self).generate_code() + } + + /// Returns the identifier for the ink! trait definition info object. + pub fn trait_info_ident(&self) -> syn::Ident { + self.append_trait_suffix("TraitInfo") + } +} + +/// Generates code for the global ink! trait registry implementation. +#[derive(From)] +struct TraitRegistry<'a> { + trait_def: TraitDefinition<'a>, +} + +impl GenerateCode for TraitRegistry<'_> { + fn generate_code(&self) -> TokenStream2 { + let registry_impl = self.generate_registry_impl(); + let trait_info = self.generate_trait_info_object(); + quote! { + #registry_impl + #trait_info + } + } +} + +impl TraitRegistry<'_> { + /// Returns the span of the ink! trait definition. + fn span(&self) -> Span { + self.trait_def.span() + } + + /// Returns the identifier of the ink! trait definition. + fn trait_ident(&self) -> &syn::Ident { + self.trait_def.trait_def.ident() + } + + /// Returns the associated output type for an ink! trait message. + fn output_ident(&self, message_name: &syn::Ident) -> syn::Ident { + self.trait_def.output_ident(message_name) + } + + /// Generates the global trait registry implementation for the ink! trait. + /// + /// This makes it possible to refer back to the global call forwarder and + /// call builder specific to this ink! trait from anywhere with just the Rust + /// trait identifier which allows for type safe access. + /// + /// # Note + /// + /// Through this implementation we register the previously defined ink! trait + /// call forwarder and call builder types as such for the ink! trait. + /// + /// This is done by the fact that ink! implements all ink! traits by the + /// ink_lang::TraitCallForwarderRegistry type and uses the __ink_ConcreteImplementer + /// associated type to refer back to the actual call forwarder and call builder types. + fn generate_registry_impl(&self) -> TokenStream2 { + let span = self.span(); + let name = self.trait_ident(); + let trait_info_ident = self.trait_def.call_forwarder_ident(); + let messages = self.generate_registry_messages(); + quote_spanned!(span=> + impl #name for ::ink_lang::TraitCallForwarderRegistry + where + E: ::ink_env::Environment, + { + type Env = E; + + /// Holds general and global information about the trait. + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_TraitInfo = #trait_info_ident; + + #messages + } + ) + } + + /// Generate the code for all ink! trait messages implemented by the trait registry. + fn generate_registry_messages(&self) -> TokenStream2 { + let messages = + self.trait_def + .trait_def + .iter_items() + .filter_map(|(item, selector)| { + item.filter_map_message().map(|message| { + self.generate_registry_for_message(&message, selector) + }) + }); + quote! { + #( #messages )* + } + } + + /// Generate the code for a single ink! trait message implemented by the trait registry. + /// + /// Generally the implementation of any ink! trait of the ink! trait registry + fn generate_registry_for_message( + &self, + message: &ir::InkTraitMessage, + selector: ir::Selector, + ) -> TokenStream2 { + let span = message.span(); + let ident = message.ident(); + let attrs = message.attrs(); + let output_ident = self.output_ident(message.ident()); + let (input_bindings, input_types) = + Self::input_bindings_and_types(message.inputs()); + let linker_error_ident = EnforcedErrors::cannot_call_trait_message( + self.trait_ident(), + message.ident(), + selector, + message.mutates(), + ); + quote_spanned!(span => + type #output_ident = ::ink_lang::NeverReturns; + + #( #attrs )* + #[cold] + #[doc(hidden)] + fn #ident( + #( #input_bindings : #input_types ),* + ) -> Self::#output_ident { + /// We enforce linking errors in case this is ever actually called. + /// These linker errors are properly resolved by the cargo-contract tool. + extern "C" { + #[no_mangle] + fn #linker_error_ident() -> !; + } + unsafe { #linker_error_ident() } + } + ) + } + + /// Returns a pair of input bindings `__ink_bindings_N` and types. + fn input_bindings_and_types<'b>( + inputs: ir::TraitItemInputsIter<'b>, + ) -> (Vec, Vec<&'b syn::Type>) { + inputs + .enumerate() + .map(|(n, pat_type)| { + let binding = format_ident!("__ink_binding_{}", n); + let ty = &*pat_type.ty; + (binding, ty) + }) + .unzip() + } + + /// Phantom type that implements the following traits for every ink! trait: + /// + /// - `ink_lang::TraitImplementer` (unsafe impl) + /// - `ink_lang::TraitUniqueId` + /// - `ink_lang::TraitCallForwarder` + /// + /// It is mainly used to access global information about the ink! trait. + fn generate_trait_info_object(&self) -> TokenStream2 { + let span = self.span(); + let trait_ident = self.trait_ident(); + let unique_id = self.trait_def.trait_def.unique_id(); + let trait_info_ident = self.trait_def.trait_info_ident(); + let trait_call_forwarder = self.trait_def.call_forwarder_ident(); + quote_spanned!(span => + #[doc(hidden)] + #[allow(non_camel_case_types)] + pub struct #trait_info_ident { + marker: ::core::marker::PhantomData E>, + } + + unsafe impl ::ink_lang::TraitImplementer<#unique_id> + for #trait_info_ident + where + E: ::ink_env::Environment, + { + } + + impl ::ink_lang::TraitUniqueId for #trait_info_ident + where + E: ::ink_env::Environment, + { + const ID: ::core::primitive::u32 = #unique_id; + } + + impl ::ink_lang::TraitModulePath for #trait_info_ident + where + E: ::ink_env::Environment, + { + const PATH: &'static ::core::primitive::str = ::core::module_path!(); + + const FULL: &'static ::core::primitive::str = ::core::concat!( + // We cannot reuse `Self::PATH` here since only literals + // are allow to be passed into the `concat!` macro. + // Fortunately the Rust compiler produces a string literal + // in place of the `module_path!` macro invokation. + ::core::module_path!(), + "::", + #trait_ident, + ); + } + + impl ::ink_lang::TraitCallForwarder for #trait_info_ident + where + E: ::ink_env::Environment, + { + type Forwarder = #trait_call_forwarder; + } + ) + } +} From 75d378ff7014a5d6ab2ece146c095c90625ae3cb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:34:45 +0200 Subject: [PATCH 062/493] add global trait call builder codegen --- .../src/generator/trait_def/call_builder.rs | 439 ++++++++++++++++++ .../codegen/src/generator/trait_def/mod.rs | 3 + 2 files changed, 442 insertions(+) create mode 100644 crates/lang/codegen/src/generator/trait_def/call_builder.rs diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs new file mode 100644 index 0000000000..3facb8759b --- /dev/null +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -0,0 +1,439 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::TraitDefinition; +use crate::traits::GenerateCode; +use derive_more::From; +use proc_macro2::{ + Span, + TokenStream as TokenStream2, +}; +use quote::{format_ident, quote, quote_spanned}; + +impl<'a> TraitDefinition<'a> { + /// Generates code for the global trait call builder for an ink! trait. + /// + /// # Note + /// + /// - The generated call builder type implements the ink! trait definition + /// and allows to build up contract calls that allow for customization by + /// the user to provide gas limit, endowment etc. + /// - The call builder is used directly by the generated call forwarder. + /// There exists one global call forwarder and call builder pair for every + /// ink! trait definition. + pub fn generate_call_builder(&self) -> TokenStream2 { + CallBuilder::from(*self).generate_code() + } + + /// The identifier of the ink! trait call builder. + pub fn call_builder_ident(&self) -> syn::Ident { + self.append_trait_suffix(CallBuilder::SUFFIX) + } +} + +/// Generates code for the global ink! trait call builder. +#[derive(From)] +struct CallBuilder<'a> { + trait_def: TraitDefinition<'a>, +} + +impl GenerateCode for CallBuilder<'_> { + fn generate_code(&self) -> TokenStream2 { + let struct_definition = self.generate_struct_definition(); + let storage_layout_impl = self.generate_storage_layout_impl(); + let spread_layout_impl = self.generate_spread_layout_impl(); + let packed_layout_impl = self.generate_packed_layout_impl(); + let auxiliary_trait_impls = self.generate_auxiliary_trait_impls(); + let to_from_account_id_impls = self.generate_to_from_account_id_impls(); + let ink_trait_impl = self.generate_ink_trait_impl(); + quote! { + #struct_definition + #storage_layout_impl + #spread_layout_impl + #packed_layout_impl + #auxiliary_trait_impls + #to_from_account_id_impls + #ink_trait_impl + } + } +} + +impl CallBuilder<'_> { + /// The name suffix for ink! trait call builder. + const SUFFIX: &'static str = "TraitCallBuilder"; + + /// Returns the span of the ink! trait definition. + fn span(&self) -> Span { + self.trait_def.span() + } + + /// Returns the identifier of the ink! trait call builder. + fn ident(&self) -> syn::Ident { + self.trait_def.call_builder_ident() + } + + /// Generates the struct type definition for the account wrapper type. + /// + /// This type is going to implement the trait so that invoking its trait + /// methods will perform contract calls via SEAL's contract execution + /// abstraction. + /// + /// # Note + /// + /// Unlike the layout specific traits it is possible to derive the SCALE + /// `Encode` and `Decode` traits since they generate trait bounds per field + /// instead of per generic parameter which is exactly what we need here. + /// However, it should be noted that this is not Rust default behaviour. + fn generate_struct_definition(&self) -> TokenStream2 { + let span = self.span(); + let call_builder_ident = self.ident(); + quote_spanned!(span => + /// The global call builder type for all trait implementers. + /// + /// All calls to types (contracts) implementing the trait will be built by this type. + #[doc(hidden)] + #[allow(non_camel_case_types)] + #[derive(::scale::Encode, ::scale::Decode)] + #[repr(transparent)] + pub struct #call_builder_ident + where + E: ::ink_env::Environment, + { + account_id: ::AccountId, + } + ) + } + + /// Generates the `StorageLayout` trait implementation for the account wrapper. + /// + /// # Note + /// + /// Due to the generic parameter `E` and Rust's default rules for derive generated + /// trait bounds it is not recommended to derive the `StorageLayout` trait implementation. + fn generate_storage_layout_impl(&self) -> TokenStream2 { + let span = self.span(); + let call_builder_ident = self.ident(); + quote_spanned!(span=> + #[cfg(feature = "std")] + impl ::ink_storage::traits::StorageLayout + for #call_builder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::ink_storage::traits::StorageLayout, + { + fn layout( + __key_ptr: &mut ::ink_storage::traits::KeyPtr, + ) -> ::ink_metadata::layout::Layout { + ::ink_metadata::layout::Layout::Struct( + ::ink_metadata::layout::StructLayout::new( + <[_]>::into_vec(::std::vec![ + ::ink_metadata::layout::FieldLayout::new( + Some("account_id"), + <::AccountId + as ::ink_storage::traits::StorageLayout>::layout(__key_ptr) + ) + ].into_boxed_slice()) + ) + ) + } + } + ) + } + + /// Generates the `SpreadLayout` trait implementation for the account wrapper. + /// + /// # Note + /// + /// Due to the generic parameter `E` and Rust's default rules for derive generated + /// trait bounds it is not recommended to derive the `SpreadLayout` trait implementation. + fn generate_spread_layout_impl(&self) -> TokenStream2 { + let span = self.span(); + let call_builder_ident = self.ident(); + quote_spanned!(span=> + /// We require this manual impl since the derive produces incorrect trait bounds. + impl ::ink_storage::traits::SpreadLayout + for #call_builder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::ink_storage::traits::SpreadLayout, + { + const FOOTPRINT: ::core::primitive::u64 = 1; + const REQUIRES_DEEP_CLEAN_UP: ::core::primitive::bool = false; + + #[inline] + fn pull_spread(ptr: &mut ::ink_primitives::KeyPtr) -> Self { + Self { + account_id: <::AccountId + as ::ink_storage::traits::SpreadLayout>::pull_spread(ptr) + } + } + + #[inline] + fn push_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + <::AccountId + as ::ink_storage::traits::SpreadLayout>::push_spread(&self.account_id, ptr) + } + + #[inline] + fn clear_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + <::AccountId + as ::ink_storage::traits::SpreadLayout>::clear_spread(&self.account_id, ptr) + } + } + ) + } + + /// Generates the `PackedLayout` trait implementation for the account wrapper. + /// + /// # Note + /// + /// Due to the generic parameter `E` and Rust's default rules for derive generated + /// trait bounds it is not recommended to derive the `PackedLayout` trait implementation. + fn generate_packed_layout_impl(&self) -> TokenStream2 { + let span = self.span(); + let call_builder_ident = self.ident(); + quote_spanned!(span=> + /// We require this manual impl since the derive produces incorrect trait bounds. + impl ::ink_storage::traits::PackedLayout + for #call_builder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::ink_storage::traits::PackedLayout, + { + #[inline(always)] + fn pull_packed(&mut self, _at: &::ink_primitives::Key) {} + #[inline(always)] + fn push_packed(&self, _at: &::ink_primitives::Key) {} + #[inline(always)] + fn clear_packed(&self, _at: &::ink_primitives::Key) {} + } + ) + } + + /// Generates trait implementations for auxiliary traits for the account wrapper. + /// + /// # Note + /// + /// Auxiliary traits currently include: + /// + /// - `Clone`: To allow cloning contract references in the long run. + /// - `Debug`: To better debug internal contract state. + fn generate_auxiliary_trait_impls(&self) -> TokenStream2 { + let span = self.span(); + let call_builder_ident = self.ident(); + let call_builder_name = call_builder_ident.to_string(); + quote_spanned!(span=> + /// We require this manual impl since the derive produces incorrect trait bounds. + impl ::core::clone::Clone for #call_builder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::core::clone::Clone, + { + #[inline] + fn clone(&self) -> Self { + Self { + account_id: ::core::clone::Clone::clone(&self.account_id), + } + } + } + + /// We require this manual impl since the derive produces incorrect trait bounds. + impl ::core::fmt::Debug for #call_builder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::core::fmt::Debug, + { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct(#call_builder_name) + .field("account_id", &self.account_id) + .finish() + } + } + ) + } + + /// Generate trait impls for `FromAccountId` and `ToAccountId` for the account wrapper. + /// + /// # Note + /// + /// This allows user code to conveniently transform from and to `AccountId` when + /// interacting with typed contracts. + fn generate_to_from_account_id_impls(&self) -> TokenStream2 { + let span = self.span(); + let call_builder_ident = self.ident(); + quote_spanned!(span=> + impl ::ink_env::call::FromAccountId + for #call_builder_ident + where + E: ::ink_env::Environment, + { + #[inline] + fn from_account_id(account_id: ::AccountId) -> Self { + Self { account_id } + } + } + + impl ::ink_lang::ToAccountId for #call_builder_ident + where + E: ::ink_env::Environment, + { + #[inline] + fn to_account_id(&self) -> ::AccountId { + self.account_id.clone() + } + } + ) + } + + /// Generates the implementation of the associated ink! trait definition. + /// + /// # Note + /// + /// The implemented messages call the SEAL host runtime in order to dispatch + /// the respective ink! trait message calls of the called smart contract + /// instance. + /// The way these messages are built-up allows the caller to customize message + /// parameters such as gas limit and transferred balance. + fn generate_ink_trait_impl(&self) -> TokenStream2 { + let span = self.trait_def.span(); + let trait_ident = self.trait_def.trait_def.ident(); + let trait_uid = self.trait_def.trait_def.unique_id(); + let trait_info_ident = self.trait_def.trait_info_ident(); + let builder_ident = self.ident(); + let message_impls = self.generate_ink_trait_impl_messages(); + quote_spanned!(span=> + unsafe impl ::ink_lang::TraitImplementer<#trait_uid> + for #builder_ident + where + E: ::ink_env::Environment, + { + } + + impl #trait_ident for #builder_ident + where + E: ::ink_env::Environment, + { + type Env = E; + + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_TraitInfo = #trait_info_ident; + + #message_impls + } + ) + } + + /// Generate the code for all ink! trait messages implemented by the trait call builder. + fn generate_ink_trait_impl_messages(&self) -> TokenStream2 { + let messages = self + .trait_def + .trait_def + .iter_items() + .filter_map(|(item, selector)| { + item.filter_map_message() + .map(|message| self.generate_ink_trait_impl_for_message(&message, selector)) + }); + quote! { + #( #messages )* + } + } + + /// Generate the code for a single ink! trait message implemented by the trait call builder. + fn generate_ink_trait_impl_for_message( + &self, + message: &ir::InkTraitMessage, + selector: ir::Selector, + ) -> TokenStream2 { + let span = message.span(); + let message_ident = message.ident(); + let attrs = message.attrs(); + let output_ident = self.trait_def.output_ident(message.ident()); + let output = message.output(); + let output_sig = output.map_or_else( + || quote! { () }, + |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, + ); + let selector_bytes = selector.as_bytes(); + let input_bindings = Self::input_bindings(message.inputs()); + let input_types = Self::input_types(message.inputs()); + let arg_list = Self::generate_argument_list_for(input_types.iter().cloned()); + let mut_tok = message.mutates().then(|| quote! { mut }); + quote_spanned!(span => + #[allow(clippy::type_complexity)] + type #output_ident = ::ink_env::call::CallBuilder< + Self::Env, + ::ink_env::call::utils::Set< ::AccountId >, + ::ink_env::call::utils::Unset< ::core::primitive::u64 >, + ::ink_env::call::utils::Unset< ::Balance >, + ::ink_env::call::utils::Set< ::ink_env::call::ExecutionInput<#arg_list> >, + ::ink_env::call::utils::Set<#output_sig>, + >; + + #( #attrs )* + #[inline] + fn #message_ident( + & #mut_tok #(, #input_bindings : #input_types )* + ) -> Self::#output_ident { + ::ink_env::call::build_call::() + .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) + .exec_input( + ::ink_env::call::ExecutionInput::new( + ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) + ) + #( + .push_arg(#input_bindings) + )* + ) + .returns::<#output_sig>() + } + ) + } + + /// Returns the sequence of artificial input parameter bindings for the message. + /// + /// # Note + /// + /// This returns `__ink_binding_N` for every message input where `N` is the number + /// of the input from first to last. + fn input_bindings(inputs: ir::TraitItemInputsIter) -> Vec { + inputs + .enumerate() + .map(|(n, _)| format_ident!("__ink_binding_{}", n)) + .collect::>() + } + + /// Returns the sequence of input types for the message. + fn input_types<'b>(inputs: ir::TraitItemInputsIter<'b>) -> Vec<&'b syn::Type> { + inputs.map(|pat_type| &*pat_type.ty).collect::>() + } + + /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. + fn generate_argument_list_for<'b, Args>(args: Args) -> TokenStream2 + where + Args: IntoIterator, + ::IntoIter: DoubleEndedIterator, + { + use syn::spanned::Spanned as _; + args.into_iter().fold( + quote! { ::ink_env::call::utils::EmptyArgumentList }, + |rest, arg| { + let span = arg.span(); + quote_spanned!(span=> + ::ink_env::call::utils::ArgumentList<::ink_env::call::utils::Argument<#arg>, #rest> + ) + } + ) + } +} diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index b42a704a80..59dc05eb41 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -17,6 +17,7 @@ mod definition; mod long_call; mod short_call; mod trait_registry; +mod call_builder; use heck::CamelCase as _; use crate::GenerateCode; @@ -71,12 +72,14 @@ impl GenerateCode for TraitDefinition<'_> { let trait_concretizer_impls = self.generate_trait_impl_block(); // let long_hand_impls = self.generate_trait_impl_longhand(); let trait_registry = self.generate_trait_registry_impl(); + let trait_call_builder = self.generate_call_builder(); quote_spanned!(span => #trait_definition const _: () = { #trait_concretizer #trait_concretizer_impls #trait_registry + #trait_call_builder }; ) } From d31981a03d0f1a0df1434314698103fd772cfdc2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:35:04 +0200 Subject: [PATCH 063/493] add global trait call forwarder codegen --- .../src/generator/trait_def/call_forwarder.rs | 423 ++++++++++++++++++ .../codegen/src/generator/trait_def/mod.rs | 3 + 2 files changed, 426 insertions(+) create mode 100644 crates/lang/codegen/src/generator/trait_def/call_forwarder.rs diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs new file mode 100644 index 0000000000..8bbae1295d --- /dev/null +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -0,0 +1,423 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use super::TraitDefinition; +use crate::traits::GenerateCode; +use derive_more::From; +use proc_macro2::{ + Span, + TokenStream as TokenStream2, +}; +use quote::{ + quote, + quote_spanned, +}; + +impl<'a> TraitDefinition<'a> { + /// Generates code for the global trait call forwarder for an ink! trait. + /// + /// # Note + /// + /// - The generated call forwarder type implements the ink! trait definition + /// and allows to build up contract calls that allow for customization by + /// the user to provide gas limit, endowment etc. + /// - The call forwarder is associated to the call builder for the same ink! + /// trait definition and handles all ink! trait calls into another contract + /// instance on-chain. For constructing custom calls it forwards to the call + /// builder. + pub fn generate_call_forwarder(&self) -> TokenStream2 { + CallForwarder::from(*self).generate_code() + } + + /// The identifier of the ink! trait call forwarder. + pub fn call_forwarder_ident(&self) -> syn::Ident { + self.append_trait_suffix(CallForwarder::SUFFIX) + } +} + +/// Generates code for the global ink! trait call forwarder. +#[derive(From)] +struct CallForwarder<'a> { + trait_def: TraitDefinition<'a>, +} + +impl GenerateCode for CallForwarder<'_> { + fn generate_code(&self) -> TokenStream2 { + let struct_definition = self.generate_struct_definition(); + let storage_layout_impl = self.generate_storage_layout_impl(); + let spread_layout_impl = self.generate_spread_layout_impl(); + let packed_layout_impl = self.generate_packed_layout_impl(); + let auxiliary_trait_impls = self.generate_auxiliary_trait_impls(); + let to_from_account_id_impls = self.generate_to_from_account_id_impls(); + let call_builder_impl = self.generate_call_builder_trait_impl(); + let ink_trait_impl = self.generate_ink_trait_impl(); + quote! { + #struct_definition + #storage_layout_impl + #spread_layout_impl + #packed_layout_impl + #auxiliary_trait_impls + #to_from_account_id_impls + #call_builder_impl + #ink_trait_impl + } + } +} + +impl CallForwarder<'_> { + /// The name suffix for ink! trait call forwarder. + const SUFFIX: &'static str = "TraitCallForwarder"; + + /// Returns the span of the ink! trait definition. + fn span(&self) -> Span { + self.trait_def.span() + } + + /// Returns the identifier of the ink! trait call forwarder. + fn ident(&self) -> syn::Ident { + self.trait_def.call_builder_ident() + } + + /// Generates the struct type definition for the account wrapper type. + /// + /// This type is going to implement the trait so that invoking its trait + /// methods will perform contract calls via SEAL's contract execution + /// abstraction. + /// + /// # Note + /// + /// Unlike the layout specific traits it is possible to derive the SCALE + /// `Encode` and `Decode` traits since they generate trait bounds per field + /// instead of per generic parameter which is exactly what we need here. + /// However, it should be noted that this is not Rust default behaviour. + fn generate_struct_definition(&self) -> TokenStream2 { + let span = self.span(); + let call_forwarder_ident = self.ident(); + quote_spanned!(span => + /// The global call forwarder for the ink! trait definition. + /// + /// All cross-contract calls to contracts implementing the associated ink! trait + /// will be handled by this type. + #[doc(hidden)] + #[allow(non_camel_case_types)] + #[derive(::scale::Encode, ::scale::Decode)] + #[repr(transparent)] + pub struct #call_forwarder_ident + where + E: ::ink_env::Environment, + { + builder: ::Builder, + } + ) + } + + /// Generates the `StorageLayout` trait implementation for the account wrapper. + /// + /// # Note + /// + /// Due to the generic parameter `E` and Rust's default rules for derive generated + /// trait bounds it is not recommended to derive the `StorageLayout` trait implementation. + fn generate_storage_layout_impl(&self) -> TokenStream2 { + let span = self.span(); + let call_forwarder_ident = self.ident(); + quote_spanned!(span=> + #[cfg(feature = "std")] + impl ::ink_storage::traits::StorageLayout + for #call_forwarder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::ink_storage::traits::StorageLayout, + { + fn layout( + __key_ptr: &mut ::ink_storage::traits::KeyPtr, + ) -> ::ink_metadata::layout::Layout { + <::Builder + as ::ink_storage::traits::StorageLayout>::layout(__key_ptr) + } + } + ) + } + + /// Generates the `SpreadLayout` trait implementation for the account wrapper. + /// + /// # Note + /// + /// Due to the generic parameter `E` and Rust's default rules for derive generated + /// trait bounds it is not recommended to derive the `SpreadLayout` trait implementation. + fn generate_spread_layout_impl(&self) -> TokenStream2 { + let span = self.span(); + let call_forwarder_ident = self.ident(); + quote_spanned!(span=> + impl ::ink_storage::traits::SpreadLayout + for #call_forwarder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::ink_storage::traits::SpreadLayout, + { + const FOOTPRINT: ::core::primitive::u64 = 1; + const REQUIRES_DEEP_CLEAN_UP: ::core::primitive::bool = false; + + #[inline] + fn pull_spread(ptr: &mut ::ink_primitives::KeyPtr) -> Self { + Self { + builder: <::Builder + as ::ink_storage::traits::SpreadLayout>::pull_spread(ptr) + } + } + + #[inline] + fn push_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + <::Builder + as ::ink_storage::traits::SpreadLayout>::push_spread(&self.builder, ptr) + } + + #[inline] + fn clear_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + <::Builder + as ::ink_storage::traits::SpreadLayout>::clear_spread(&self.builder, ptr) + } + } + ) + } + + /// Generates the `PackedLayout` trait implementation for the account wrapper. + /// + /// # Note + /// + /// Due to the generic parameter `E` and Rust's default rules for derive generated + /// trait bounds it is not recommended to derive the `PackedLayout` trait implementation. + fn generate_packed_layout_impl(&self) -> TokenStream2 { + let span = self.span(); + let call_forwarder_ident = self.ident(); + quote_spanned!(span=> + impl ::ink_storage::traits::PackedLayout + for #call_forwarder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::ink_storage::traits::PackedLayout, + { + #[inline] + fn pull_packed(&mut self, _at: &::ink_primitives::Key) {} + #[inline] + fn push_packed(&self, _at: &::ink_primitives::Key) {} + #[inline] + fn clear_packed(&self, _at: &::ink_primitives::Key) {} + } + ) + } + + /// Generates trait implementations for auxiliary traits for the account wrapper. + /// + /// # Note + /// + /// Auxiliary traits currently include: + /// + /// - `Clone`: To allow cloning contract references in the long run. + /// - `Debug`: To better debug internal contract state. + fn generate_auxiliary_trait_impls(&self) -> TokenStream2 { + let span = self.span(); + let call_forwarder_ident = self.ident(); + let call_forwarder_name = call_forwarder_ident.to_string(); + quote_spanned!(span=> + impl ::core::clone::Clone for #call_forwarder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::core::clone::Clone, + { + #[inline] + fn clone(&self) -> Self { + Self { + builder: <::Builder + as ::core::clone::Clone>::clone(&self.builder), + } + } + } + + impl ::core::fmt::Debug for #call_forwarder_ident + where + E: ::ink_env::Environment, + ::AccountId: ::core::fmt::Debug, + { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + f.debug_struct(#call_forwarder_name) + .field("account_id", &self.builder.account_id) + .finish() + } + } + ) + } + + /// Generate trait impls for `FromAccountId` and `ToAccountId` for the account wrapper. + /// + /// # Note + /// + /// This allows user code to conveniently transform from and to `AccountId` when + /// interacting with typed contracts. + fn generate_to_from_account_id_impls(&self) -> TokenStream2 { + let span = self.span(); + let call_forwarder_ident = self.ident(); + quote_spanned!(span=> + impl ::ink_env::call::FromAccountId + for #call_forwarder_ident + where + E: ::ink_env::Environment, + { + #[inline] + fn from_account_id(account_id: ::AccountId) -> Self { + Self { builder: <::Builder + as ::ink_env::call::FromAccountId>::from_account_id(account_id) } + } + } + + impl ::ink_lang::ToAccountId for #call_forwarder_ident + where + E: ::ink_env::Environment, + { + #[inline] + fn to_account_id(&self) -> ::AccountId { + <::Builder + as ::ink_lang::ToAccountId>::to_account_id(&self.builder) + } + } + ) + } + + /// Generate the trait impl for `CallBuilder` for the ink! trait call forwarder. + /// + /// # Note + /// + /// Through the implementation of this trait it is possible to refer to the + /// ink! trait call builder that is associated to this ink! trait call forwarder. + fn generate_call_builder_trait_impl(&self) -> TokenStream2 { + let span = self.trait_def.span(); + let call_forwarder_ident = self.ident(); + let call_builder_ident = self.trait_def.call_builder_ident(); + quote_spanned!(span=> + /// This trait allows to bridge from call forwarder to call builder. + /// + /// Also this explains why we designed the generated code so that we have + /// both types and why the forwarder is a thin-wrapper around the builder + /// as this allows to perform this operation safely. + impl ::ink_lang::TraitCallBuilder for #call_forwarder_ident + where + E: ::ink_env::Environment, + { + type Builder = #call_builder_ident; + + #[inline] + fn call(&self) -> &::Builder { + &self.builder + } + + #[inline] + fn call_mut(&mut self) -> &mut ::Builder { + &mut self.builder + } + } + ) + } + + /// Generates the implementation of the associated ink! trait definition. + /// + /// # Note + /// + /// The implementation mainly forwards to the associated ink! call builder + /// of the same ink! trait definition. + fn generate_ink_trait_impl(&self) -> TokenStream2 { + let span = self.trait_def.span(); + let trait_ident = self.trait_def.trait_def.ident(); + let trait_uid = self.trait_def.trait_def.unique_id(); + let trait_info_ident = self.trait_def.trait_info_ident(); + let forwarder_ident = self.ident(); + let message_impls = self.generate_ink_trait_impl_messages(); + quote_spanned!(span=> + unsafe impl ::ink_lang::TraitImplementer<#trait_uid> + for #forwarder_ident + where + E: ::ink_env::Environment, + { + } + + impl #trait_ident for #forwarder_ident + where + E: ::ink_env::Environment, + { + type Env = E; + + #[doc(hidden)] + #[allow(non_camel_case_types)] + type __ink_TraitInfo = #trait_info_ident; + + #message_impls + } + ) + } + + /// Generate the code for all ink! trait messages implemented by the trait call forwarder. + fn generate_ink_trait_impl_messages(&self) -> TokenStream2 { + let messages = self + .trait_def + .trait_def + .iter_items() + .filter_map(|(item, _)| { + item.filter_map_message() + .map(|message| self.generate_ink_trait_impl_for_message(&message)) + }); + quote! { + #( #messages )* + } + } + + /// Generate the code for a single ink! trait message implemented by the trait call forwarder. + fn generate_ink_trait_impl_for_message( + &self, + message: &ir::InkTraitMessage, + ) -> TokenStream2 { + let span = message.span(); + let trait_ident = self.trait_def.trait_def.ident(); + let forwarder_ident = self.ident(); + let message_ident = message.ident(); + let attrs = message.attrs(); + let output_ident = self.trait_def.output_ident(message.ident()); + let output_type = message.output().cloned().unwrap_or(syn::parse_quote!(())); + let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); + let input_types = message.inputs().map(|input| &input.ty).collect::>(); + let call_op = match message.receiver() { + ir::Receiver::Ref => quote! { call }, + ir::Receiver::RefMut => quote! { call_mut }, + }; + let panic_str = format!( + "encountered error while calling <{} as {}>::{}", + forwarder_ident, trait_ident, message_ident, + ); + quote_spanned!(span => + type #output_ident = #output_type; + + #( #attrs )* + #[inline] + fn #message_ident( + #( #input_bindings : #input_types ),* + ) -> Self::#output_ident { + <::Builder as #trait_ident>::#message_ident( + ::#call_op(self) + #( + , #input_bindings: #input_types + ),* + ) + .fire() + .unwrap_or_else(|err| ::core::panic!("{}: {}", #panic_str, err)) + } + ) + } +} diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 59dc05eb41..db72b98be5 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -18,6 +18,7 @@ mod long_call; mod short_call; mod trait_registry; mod call_builder; +mod call_forwarder; use heck::CamelCase as _; use crate::GenerateCode; @@ -73,6 +74,7 @@ impl GenerateCode for TraitDefinition<'_> { // let long_hand_impls = self.generate_trait_impl_longhand(); let trait_registry = self.generate_trait_registry_impl(); let trait_call_builder = self.generate_call_builder(); + let trait_call_forwarder = self.generate_call_forwarder(); quote_spanned!(span => #trait_definition const _: () = { @@ -80,6 +82,7 @@ impl GenerateCode for TraitDefinition<'_> { #trait_concretizer_impls #trait_registry #trait_call_builder + #trait_call_forwarder }; ) } From 032c423c036532d236100ac19d7ca682bc0ff96d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:46:08 +0200 Subject: [PATCH 064/493] rename message_mut field to message_is_mut --- crates/lang/codegen/src/generator/cross_calling.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index 2b30c2fba1..f1167060c9 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -50,7 +50,7 @@ pub enum EnforcedErrors { /// The selector of the called message. message_selector: [u8; 4], /// Is `true` if the `self` receiver of the ink! message is `&mut self`. - message_mut: bool, + message_is_mut: bool, }, /// The below error represents calling a constructor in a context that does /// not allow calling it. This may happen when the constructor defined in a @@ -239,7 +239,7 @@ impl CrossCalling<'_> { trait_ident, message_ident: ident.to_string(), message_selector: composed_selector, - message_mut: message.receiver().is_ref_mut(), + message_is_mut: message.receiver().is_ref_mut(), }); let output_ty = message .output() From 08f33b2df2c60a6a457171f1f0e866023ad01088 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:46:47 +0200 Subject: [PATCH 065/493] add enforced error module --- .../codegen/src/generator/enforced_error.rs | 82 +++++++++++++++++++ crates/lang/codegen/src/generator/mod.rs | 1 + 2 files changed, 83 insertions(+) create mode 100644 crates/lang/codegen/src/generator/enforced_error.rs diff --git a/crates/lang/codegen/src/generator/enforced_error.rs b/crates/lang/codegen/src/generator/enforced_error.rs new file mode 100644 index 0000000000..982f40ab66 --- /dev/null +++ b/crates/lang/codegen/src/generator/enforced_error.rs @@ -0,0 +1,82 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use impl_serde::serialize as serde_hex; +use quote::format_ident; + +/// Errors which may occur when forwarding a call is not allowed. +/// +/// We insert markers for these errors in the generated contract code. +/// This is necessary since we can't check these errors at compile time +/// of the contract. +/// `cargo-contract` checks the contract code for these error markers +/// when building a contract and fails if it finds markers. +#[derive(scale::Encode, scale::Decode)] +pub enum EnforcedErrors { + /// The below error represents calling a `&mut self` message in a context that + /// only allows for `&self` messages. This may happen under certain circumstances + /// when ink! trait implementations are involved with long-hand calling notation. + #[codec(index = 1)] + CannotCallTraitMessage { + /// The trait that defines the called message. + trait_ident: String, + /// The name of the called message. + message_ident: String, + /// The selector of the called message. + message_selector: [u8; 4], + /// Is `true` if the `self` receiver of the ink! message is `&mut self`. + message_is_mut: bool, + }, + /// The below error represents calling a constructor in a context that does + /// not allow calling it. This may happen when the constructor defined in a + /// trait is cross-called in another contract. + /// This is not allowed since the contract to which a call is forwarded must + /// already exist at the point when the call to it is made. + #[codec(index = 2)] + CannotCallTraitConstructor { + /// The trait that defines the called constructor. + trait_ident: String, + /// The name of the called constructor. + constructor_ident: String, + /// The selector of the called constructor. + constructor_selector: [u8; 4], + }, +} + +impl EnforcedErrors { + /// Create the identifier of an enforced ink! compilation error. + fn into_ident(self) -> syn::Ident { + format_ident!( + "__ink_enforce_error_{}", + serde_hex::to_hex(&scale::Encode::encode(&self), false) + ) + } + + /// Creates an enforced linker error to signal that an invalid + /// implementation of an ink! trait message has been called. + pub fn cannot_call_trait_message( + trait_ident: &syn::Ident, + message_ident: &syn::Ident, + message_selector: ir::Selector, + message_is_mut: bool, + ) -> syn::Ident { + Self::CannotCallTraitMessage { + trait_ident: trait_ident.to_string(), + message_ident: message_ident.to_string(), + message_selector: *message_selector.as_bytes(), + message_is_mut, + } + .into_ident() + } +} diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index b0406c7589..d6aae330eb 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -23,6 +23,7 @@ mod item_impls; mod metadata; mod storage; mod trait_def; +mod enforced_error; pub use self::{ chain_extension::ChainExtension, From 4cb47643f281838373764b8ee6d995eb78836f1a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:47:16 +0200 Subject: [PATCH 066/493] fix receiver expansion in ink! trait call builder and call forwarder --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 5 +++-- .../lang/codegen/src/generator/trait_def/call_forwarder.rs | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 3facb8759b..62992abcd8 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -384,9 +384,10 @@ impl CallBuilder<'_> { #( #attrs )* #[inline] fn #message_ident( - & #mut_tok #(, #input_bindings : #input_types )* + & #mut_tok self + #( , #input_bindings : #input_types )* ) -> Self::#output_ident { - ::ink_env::call::build_call::() + ::ink_env::call::build_call::() .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) .exec_input( ::ink_env::call::ExecutionInput::new( diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 8bbae1295d..8f36ceaf93 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -397,6 +397,7 @@ impl CallForwarder<'_> { ir::Receiver::Ref => quote! { call }, ir::Receiver::RefMut => quote! { call_mut }, }; + let mut_tok = message.mutates().then(|| quote! { mut }); let panic_str = format!( "encountered error while calling <{} as {}>::{}", forwarder_ident, trait_ident, message_ident, @@ -407,7 +408,8 @@ impl CallForwarder<'_> { #( #attrs )* #[inline] fn #message_ident( - #( #input_bindings : #input_types ),* + & #mut_tok self + #( , #input_bindings : #input_types )* ) -> Self::#output_ident { <::Builder as #trait_ident>::#message_ident( ::#call_op(self) From 1f872e3ed360cd198b9b026ed4265ed326e81be5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:47:50 +0200 Subject: [PATCH 067/493] update ink! trait definition codegen to expand to new structure --- .../src/generator/trait_def/definition.rs | 58 +++---------------- 1 file changed, 9 insertions(+), 49 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 5844dbf035..45b8be3305 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -24,24 +24,6 @@ use quote::{ }; impl<'a> TraitDefinition<'a> { - fn generate_for_constructor( - constructor: ir::InkTraitConstructor<'a>, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let sig = constructor.sig(); - let ident = &sig.ident; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let inputs = &sig.inputs; - quote_spanned!(span => - /// Output type of the respective trait constructor. - type #output_ident; - - #(#attrs)* - fn #ident(#inputs) -> Self::#output_ident; - ) - } - fn generate_for_message(message: ir::InkTraitMessage<'a>) -> TokenStream2 { let span = message.span(); let attrs = message.attrs(); @@ -52,7 +34,7 @@ impl<'a> TraitDefinition<'a> { syn::ReturnType::Default => quote! { () }, syn::ReturnType::Type(_, ty) => quote! { #ty }, }; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); quote_spanned!(span => /// Output type of the respective trait message. type #output_ident: ::ink_lang::ImpliesReturn<#output>; @@ -69,22 +51,8 @@ impl TraitDefinition<'_> { let attrs = self.trait_def.attrs(); let hash = self.trait_def.verify_hash(); let ident = self.trait_def.ident(); - let helper_ident = format_ident!( - "__ink_Checked{}_0x{:X}{:X}{:X}{:X}", - ident, - hash[0], - hash[1], - hash[2], - hash[3] - ); - let verify_hash_id = + let unique_trait_id = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; - let constructors = self - .trait_def - .iter_items() - .map(|(item, _)| item) - .flat_map(ir::InkTraitItem::filter_map_constructor) - .map(Self::generate_for_constructor); let messages = self .trait_def .iter_items() @@ -93,27 +61,19 @@ impl TraitDefinition<'_> { .map(Self::generate_for_message); quote_spanned!(span => #(#attrs)* - pub trait #ident: ::ink_lang::CheckedInkTrait<[(); #verify_hash_id]> { - #[doc(hidden)] - #[allow(non_camel_case_types)] - type __ink_Checksum: #helper_ident; + pub trait #ident: ::ink_lang::TraitImplementer<#unique_trait_id> { + /// The contract environment. + type Env: ::ink_env::Environment; - /// Used to map from trait to a concrete `AccountId` thin-wrapper - /// implementing the exact same trait. This defaults to - /// `ink_lang::NoConcreteImplementer` for user provided implementations. + /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] - type __ink_ConcreteImplementer; + type __ink_TraitInfo: ::ink_lang::TraitUniqueId + + ::ink_lang::TraitCallForwarder + + ::ink_lang::TraitImplementer<#unique_trait_id>; - #(#constructors)* #(#messages)* } - - #[doc(hidden)] - #[allow(non_camel_case_types)] - pub unsafe trait #helper_ident {} - - unsafe impl #helper_ident for [(); #verify_hash_id] {} ) } } From 9ef836868da4a62699cdd893b5145cf508c3cfc1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:48:04 +0200 Subject: [PATCH 068/493] remove commented out code --- crates/lang/codegen/src/generator/trait_def/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index db72b98be5..411b562642 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -71,7 +71,7 @@ impl GenerateCode for TraitDefinition<'_> { let trait_definition = self.generate_trait_definition(); let trait_concretizer = self.generate_trait_concretizer(); let trait_concretizer_impls = self.generate_trait_impl_block(); - // let long_hand_impls = self.generate_trait_impl_longhand(); + let trait_registry = self.generate_trait_registry_impl(); let trait_call_builder = self.generate_call_builder(); let trait_call_forwarder = self.generate_call_forwarder(); From 0cb9ee40524e8979869b6371091e41baaf1bfea0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:49:37 +0200 Subject: [PATCH 069/493] make use of enforced_error module --- .../codegen/src/generator/cross_calling.rs | 40 +------------------ 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index f1167060c9..c6dd4141a9 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -28,45 +28,7 @@ use quote::{ quote_spanned, }; use syn::spanned::Spanned as _; - -/// Errors which may occur when forwarding a call is not allowed. -/// -/// We insert markers for these errors in the generated contract code. -/// This is necessary since we can't check these errors at compile time -/// of the contract. -/// `cargo-contract` checks the contract code for these error markers -/// when building a contract and fails if it finds markers. -#[derive(scale::Encode, scale::Decode)] -pub enum EnforcedErrors { - /// The below error represents calling a `&mut self` message in a context that - /// only allows for `&self` messages. This may happen under certain circumstances - /// when ink! trait implementations are involved with long-hand calling notation. - #[codec(index = 1)] - CannotCallTraitMessage { - /// The trait that defines the called message. - trait_ident: String, - /// The name of the called message. - message_ident: String, - /// The selector of the called message. - message_selector: [u8; 4], - /// Is `true` if the `self` receiver of the ink! message is `&mut self`. - message_is_mut: bool, - }, - /// The below error represents calling a constructor in a context that does - /// not allow calling it. This may happen when the constructor defined in a - /// trait is cross-called in another contract. - /// This is not allowed since the contract to which a call is forwarded must - /// already exist at the point when the call to it is made. - #[codec(index = 2)] - CannotCallTraitConstructor { - /// The trait that defines the called constructor. - trait_ident: String, - /// The name of the called constructor. - constructor_ident: String, - /// The selector of the called constructor. - constructor_selector: [u8; 4], - }, -} +use super::enforced_error::EnforcedErrors; /// Generates `#[cfg(..)]` code to guard against compilation under `ink-as-dependency`. #[derive(From)] From 47fef1c2d6f6f9b98c1a95093da25aa5d522dac5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 27 May 2021 09:51:53 +0200 Subject: [PATCH 070/493] remove deprecated ink! trait codegen --- .../src/generator/trait_def/concretizer.rs | 218 ------------ .../src/generator/trait_def/long_call.rs | 329 ------------------ .../codegen/src/generator/trait_def/mod.rs | 8 - .../src/generator/trait_def/short_call.rs | 189 ---------- 4 files changed, 744 deletions(-) delete mode 100644 crates/lang/codegen/src/generator/trait_def/concretizer.rs delete mode 100644 crates/lang/codegen/src/generator/trait_def/long_call.rs delete mode 100644 crates/lang/codegen/src/generator/trait_def/short_call.rs diff --git a/crates/lang/codegen/src/generator/trait_def/concretizer.rs b/crates/lang/codegen/src/generator/trait_def/concretizer.rs deleted file mode 100644 index da388d894f..0000000000 --- a/crates/lang/codegen/src/generator/trait_def/concretizer.rs +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Generates the definition and implementations for the ink! trait definition resolver. -//! -//! This is used in order code in order to resolve an ink! trait definition to a proper -//! Rust type that can be used in the Rust type system and used as instance. This is -//! for example required in order to cross-call a trait based contract implementation or -//! to allow for contract references in arguments that implement a trait by definition -//! of the API. - -use super::TraitDefinition; -use heck::CamelCase as _; -use proc_macro2::TokenStream as TokenStream2; -use quote::{ - format_ident, - quote, - quote_spanned, -}; - -impl<'a> TraitDefinition<'a> { - pub(super) fn concretizer_ident(&self) -> syn::Ident { - let hash = self.trait_def.verify_hash(); - let ident = self.trait_def.ident(); - format_ident!( - "__ink_ConcreteImplementer{}_0x{:X}{:X}{:X}{:X}", - ident, - hash[0], - hash[1], - hash[2], - hash[3] - ) - } - - pub(super) fn generate_trait_concretizer(&self) -> TokenStream2 { - let span = self.trait_def.span(); - let hash = self.trait_def.verify_hash(); - let ident = self.trait_def.ident(); - let concrete_implementer_ident = self.concretizer_ident(); - let verify_hash_id = - u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; - let constructors_never_call = self - .trait_def - .iter_items() - .map(|(item, _)| item) - .flat_map(ir::InkTraitItem::filter_map_constructor) - .map(Self::generate_for_constructor_never_call); - let messages_never_call = self - .trait_def - .iter_items() - .map(|(item, _)| item) - .flat_map(ir::InkTraitItem::filter_map_message) - .map(Self::generate_for_message_never_call); - quote_spanned!(span => - /// A universal concrete implementer of the ink! trait definition. - #[doc(hidden)] - #[allow(non_camel_case_types)] - #[derive( - Debug, - ::scale::Encode, - ::scale::Decode, - ::ink_storage::traits::SpreadLayout, - ::ink_storage::traits::PackedLayout, - )] - #[cfg_attr( - feature = "std", - derive( - ::scale_info::TypeInfo, - ::ink_storage::traits::StorageLayout, - ) - )] - pub struct #concrete_implementer_ident - where - E: ::ink_env::Environment, - { - account_id: ::AccountId, - } - - impl ::ink_env::call::FromAccountId for #concrete_implementer_ident - where - E: ::ink_env::Environment, - { - #[inline] - fn from_account_id(account_id: ::AccountId) -> Self { - Self { account_id } - } - } - - impl ::ink_lang::ToAccountId for #concrete_implementer_ident - where - E: ::ink_env::Environment, - ::AccountId: Clone, - { - #[inline] - fn to_account_id(&self) -> ::AccountId { - self.account_id.clone() - } - } - - impl ::core::clone::Clone for #concrete_implementer_ident - where - E: ::ink_env::Environment, - ::AccountId: Clone, - { - #[inline] - fn clone(&self) -> Self { - Self { account_id: self.account_id.clone() } - } - } - - impl #ident for ::ink_lang::ConcreteImplementers - where - E: ::ink_env::Environment, - { - #[doc(hidden)] - #[allow(non_camel_case_types)] - type __ink_Checksum = [(); #verify_hash_id]; - - #[doc(hidden)] - #[allow(non_camel_case_types)] - type __ink_ConcreteImplementer = #concrete_implementer_ident; - - #(#constructors_never_call)* - #(#messages_never_call)* - } - ) - } - - fn generate_for_constructor_never_call( - constructor: ir::InkTraitConstructor<'a>, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let sig = constructor.sig(); - let ident = &sig.ident; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let input_bindings = sig - .inputs - .iter() - .enumerate() - .map(|(n, fn_arg)| { - match fn_arg { - syn::FnArg::Typed(pat_type) => { - let ident = format_ident!("__ink_binding_{}", n); - let ty = &pat_type.ty; - quote! { #ident : #ty } - } - syn::FnArg::Receiver(receiver) => quote! { #receiver }, - } - }) - .collect::>(); - let linker_error_ident = - format_ident!("{}", "__ink_enforce_error_for_constructor"); - quote_spanned!(span => - /// Output type of the respective trait constructor. - type #output_ident = ::ink_lang::NeverReturns; - - #(#attrs)* - fn #ident(#(#input_bindings),*) -> Self::#output_ident { - extern { - fn #linker_error_ident() -> !; - } - unsafe { #linker_error_ident() } - } - ) - } - - fn generate_for_message_never_call(message: ir::InkTraitMessage<'a>) -> TokenStream2 { - let span = message.span(); - let attrs = message.attrs(); - let sig = message.sig(); - let ident = &sig.ident; - let output = match &sig.output { - syn::ReturnType::Default => quote! { () }, - syn::ReturnType::Type(_, ty) => quote! { #ty }, - }; - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let input_bindings = sig - .inputs - .iter() - .enumerate() - .map(|(n, fn_arg)| { - match fn_arg { - syn::FnArg::Typed(pat_type) => { - let ident = format_ident!("__ink_binding_{}", n); - let ty = &pat_type.ty; - quote! { #ident : #ty } - } - syn::FnArg::Receiver(receiver) => quote! { #receiver }, - } - }) - .collect::>(); - let linker_error_ident = format_ident!("{}", "__ink_enforce_error_for_message"); - quote_spanned!(span => - /// Output type of the respective trait constructor. - type #output_ident = #output; - - #(#attrs)* - fn #ident(#(#input_bindings),*) -> Self::#output_ident { - extern { - fn #linker_error_ident() -> !; - } - unsafe { #linker_error_ident() } - } - ) - } -} diff --git a/crates/lang/codegen/src/generator/trait_def/long_call.rs b/crates/lang/codegen/src/generator/trait_def/long_call.rs deleted file mode 100644 index 86f58c62a0..0000000000 --- a/crates/lang/codegen/src/generator/trait_def/long_call.rs +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Generates code to implement an ink! trait definition for the concretized -//! type using the more elaborate and customizable long-hand calling notation. - -#![allow(dead_code)] - -use super::TraitDefinition; -use heck::CamelCase as _; -use impl_serde::serialize as serde_hex; -use ir::TraitItemInputsIter; -use proc_macro2::TokenStream as TokenStream2; -use quote::{ - format_ident, - quote, - quote_spanned, -}; - -/// Errors which may occur when forwarding a call is not allowed. -/// -/// We insert markers for these errors in the generated contract code. -/// This is necessary since we can't check these errors at compile time -/// of the contract. -/// `cargo-contract` checks the contract code for these error markers -/// when building a contract and fails if it finds markers. -#[derive(scale::Encode, scale::Decode)] -pub enum EnforcedErrors { - /// The below error represents calling a `&mut self` message in a context that - /// only allows for `&self` messages. This may happen under certain circumstances - /// when ink! trait implementations are involved with long-hand calling notation. - #[codec(index = 1)] - CannotCallTraitMessage { - /// The trait that defines the called message. - trait_ident: String, - /// The name of the called message. - message_ident: String, - /// The selector of the called message. - message_selector: [u8; 4], - /// Is `true` if the `self` receiver of the ink! message is `&mut self`. - message_mut: bool, - }, - /// The below error represents calling a constructor in a context that does - /// not allow calling it. This may happen when the constructor defined in a - /// trait is cross-called in another contract. - /// This is not allowed since the contract to which a call is forwarded must - /// already exist at the point when the call to it is made. - #[codec(index = 2)] - CannotCallTraitConstructor { - /// The trait that defines the called constructor. - trait_ident: String, - /// The name of the called constructor. - constructor_ident: String, - /// The selector of the called constructor. - constructor_selector: [u8; 4], - }, -} - -impl EnforcedErrors { - /// Create the identifier of an enforced ink! compilation error. - fn enforce_error_ident(&self) -> syn::Ident { - format_ident!( - "__ink_enforce_error_{}", - serde_hex::to_hex(&scale::Encode::encode(&self), false) - ) - } -} - -impl<'a> TraitDefinition<'a> { - /// Returns the identifier for the generated call forwarder utility. - fn call_forwarder_ident() -> syn::Ident { - format_ident!("__ink_CallForwarder") - } - - /// Returns the identifier for the generated `Out*` assoc. type. - fn out_assoc_type_ident(method_ident: &syn::Ident) -> syn::Ident { - format_ident!("{}Out", method_ident.to_string().to_camel_case()) - } - - /// Returns the sequence of input parameter bindings for the message. - fn input_bindings(inputs: TraitItemInputsIter) -> Vec { - inputs - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>() - } - - /// Returns the sequence of input types for the message. - fn input_types<'b>(inputs: TraitItemInputsIter<'b>) -> Vec<&'b syn::Type> { - inputs.map(|pat_type| &*pat_type.ty).collect::>() - } - - /// Create an enforced ink! message error. - fn create_enforced_message_error( - &self, - message: &ir::InkTraitMessage, - selector: ir::Selector, - ) -> syn::Ident { - let trait_ident = self.trait_def.ident(); - EnforcedErrors::CannotCallTraitMessage { - trait_ident: trait_ident.to_string(), - message_ident: message.ident().to_string(), - message_selector: selector.as_bytes().to_owned(), - message_mut: message.receiver().is_ref_mut(), - } - .enforce_error_ident() - } - - /// Create an enforced ink! message error. - fn create_enforced_constructor_error( - &self, - constructor: &ir::InkTraitConstructor, - selector: ir::Selector, - ) -> syn::Ident { - let trait_ident = self.trait_def.ident(); - EnforcedErrors::CannotCallTraitConstructor { - trait_ident: trait_ident.to_string(), - constructor_ident: constructor.ident().to_string(), - constructor_selector: selector.as_bytes().to_owned(), - } - .enforce_error_ident() - } - - /// Generate code for cross-calling an invalid ink! trait message. - /// - /// Trying to call the generated message will always yield a link-time - /// error which is caught by the `cargo-contract` CLI tool. - /// - /// # Note - /// - /// This is implemented for the call forwarder in case the mutability - /// overlaps with the message's mutability. - fn generate_ghost_message( - &self, - message: ir::InkTraitMessage, - selector: ir::Selector, - ) -> TokenStream2 { - let span = message.span(); - let ident = message.ident(); - let output_ident = Self::out_assoc_type_ident(ident); - let attrs = message.attrs(); - let mut_tok = message.mutates().then(|| quote! { mut }); - let input_bindings = Self::input_bindings(message.inputs()); - let input_types = Self::input_types(message.inputs()); - let enforced_error = self.create_enforced_message_error(&message, selector); - let output_ty = message - .output() - .cloned() - .unwrap_or_else(|| syn::parse_quote! { () }); - quote_spanned!(span=> - type #output_ident = #output_ty; - - #( #attrs )* - #[cold] - #[doc(hidden)] - fn #ident( - & #mut_tok self, - #( #input_bindings : #input_types ),* - ) -> Self::#output_ident { - extern { - fn #enforced_error() -> !; - } - unsafe { #enforced_error() } - } - ) - } - - /// Generate code for cross-calling an ink! trait message. - /// - /// # Note - /// - /// This is implemented for the call forwarder in case the mutability - /// overlaps with the message's mutability. - fn generate_proper_message( - &self, - message: ir::InkTraitMessage, - selector: ir::Selector, - ) -> TokenStream2 { - let span = message.span(); - let ident = message.ident(); - let output_ident = Self::out_assoc_type_ident(ident); - let attrs = message.attrs(); - let mut_tok = message.mutates().then(|| quote! { mut }); - let input_bindings = Self::input_bindings(message.inputs()); - let input_types = Self::input_types(message.inputs()); - let selector_bytes = selector.as_bytes(); - let arg_list = Self::generate_arg_list(input_types.iter().cloned()); - let output = message.output(); - let output_sig = output.map_or_else( - || quote! { () }, - |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, - ); - quote_spanned!(span=> - #[allow(clippy::type_complexity)] - type #output_ident = ::ink_env::call::CallBuilder< - Environment, - ::ink_env::call::utils::Set, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, - ::ink_env::call::utils::Set<#output_sig>, - >; - - #( #attrs )* - #[inline] - fn #ident( - & #mut_tok #(, #input_bindings : #input_types )* - ) -> Self::#output_ident { - ::ink_env::call::build_call::() - .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) - .exec_input( - ::ink_env::call::ExecutionInput::new( - ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) - ) - #( - .push_arg(#input_bindings) - )* - ) - .returns::<#output_sig>() - } - ) - } - - /// Generates code for a single call forwarder trait message. - /// - /// The `mutable` parameter indicates whether only read-only (`false`) or - /// write-only (`true`) messages shall be valid calls. For non valid messages - /// an invalid implementation is provided so that actually calling those - /// will result in a compiler or linker error. - fn generate_proper_or_ghost_message( - &self, - mutable: bool, - message: ir::InkTraitMessage, - selector: ir::Selector, - ) -> TokenStream2 { - if mutable == message.receiver().is_ref_mut() { - self.generate_proper_message(message, selector) - } else { - self.generate_ghost_message(message, selector) - } - } - - /// Generates code for a single call forwarder trait constructor. - /// - /// Note that constructors never need to be forwarded and that we only - /// provide their implementations to satisfy the implementation block. - /// We generally try to generate code in a way that actually calling - /// those constructors will result in a compiler or linker error. - fn generate_ghost_constructor( - &self, - constructor: ir::InkTraitConstructor, - selector: ir::Selector, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let ident = constructor.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let enforced_error = - self.create_enforced_constructor_error(&constructor, selector); - let input_bindings = Self::input_bindings(constructor.inputs()); - let input_types = Self::input_types(constructor.inputs()); - quote_spanned!(span => - type #output_ident = ::ink_lang::NeverReturns; - - #( #attrs )* - #[cold] - #[doc(hidden)] - fn #ident( - #( #input_bindings : #input_types ),* - ) -> Self::#output_ident { - extern { - fn #enforced_error() -> !; - } - unsafe { #enforced_error() } - } - ) - } - - /// Generates code for a single call forwarder trait implementation block. - /// - /// The `mutable` parameter indicates whether only read-only (`false`) or - /// write-only (`true`) messages and constructors are to be considered. - fn generate_trait_impl_longhand(&self, mutable: bool) -> TokenStream2 { - let span = self.trait_def.span(); - let attrs = self.trait_def.attrs(); - let forwarder_ident = Self::call_forwarder_ident(); - let verify_hash = self.trait_def.verify_hash(); - let checksum = u32::from_be_bytes([ - verify_hash[0], - verify_hash[1], - verify_hash[2], - verify_hash[3], - ]) as usize; - let trait_ident = self.trait_def.ident(); - let self_ident = self.concretizer_ident(); - let mut_tok = mutable.then(|| quote! { mut }); - let messages = self.trait_def.iter_items().filter_map(|(item, selector)| { - item.filter_map_message().map(|message| { - self.generate_proper_or_ghost_message(mutable, message, selector) - }) - }); - let constructors = self.trait_def.iter_items().filter_map(|(item, selector)| { - item.filter_map_constructor() - .map(|constructor| self.generate_ghost_constructor(constructor, selector)) - }); - quote_spanned!(span => - unsafe impl<'a> ::ink_lang::CheckedInkTrait<[(); #checksum]> for #forwarder_ident<&'a #mut_tok #self_ident> {} - - #( #attrs )* - impl<'a> #trait_ident for #forwarder_ident<&'a #mut_tok #self_ident> { - type __ink_Checksum = [(); #checksum]; - - #( #constructors )* - #( #messages )* - } - ) - } -} diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 411b562642..dce60d6844 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -12,10 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod concretizer; mod definition; -mod long_call; -mod short_call; mod trait_registry; mod call_builder; mod call_forwarder; @@ -69,17 +66,12 @@ impl GenerateCode for TraitDefinition<'_> { fn generate_code(&self) -> TokenStream2 { let span = self.trait_def.span(); let trait_definition = self.generate_trait_definition(); - let trait_concretizer = self.generate_trait_concretizer(); - let trait_concretizer_impls = self.generate_trait_impl_block(); - let trait_registry = self.generate_trait_registry_impl(); let trait_call_builder = self.generate_call_builder(); let trait_call_forwarder = self.generate_call_forwarder(); quote_spanned!(span => #trait_definition const _: () = { - #trait_concretizer - #trait_concretizer_impls #trait_registry #trait_call_builder #trait_call_forwarder diff --git a/crates/lang/codegen/src/generator/trait_def/short_call.rs b/crates/lang/codegen/src/generator/trait_def/short_call.rs deleted file mode 100644 index b618feb941..0000000000 --- a/crates/lang/codegen/src/generator/trait_def/short_call.rs +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Generates code to implement an ink! trait definition for the concretized -//! type using the short-hand calling notation. - -use super::TraitDefinition; -use heck::CamelCase as _; -use proc_macro2::TokenStream as TokenStream2; -use quote::{ - format_ident, - quote, - quote_spanned, -}; - -impl<'a> TraitDefinition<'a> { - /// Generates the code to allow short-hand cross-chain contract calls for messages. - /// - /// Unlike the generated code for ink! trait constructors the generated code uses - /// the long-hand calling versions under the hood. - fn generate_trait_impl_block_message( - &self, - message: ir::InkTraitMessage, - _selector: ir::Selector, - ) -> TokenStream2 { - let implementer_ident = self.concrete_implementer_ident(); - let span = message.span(); - let ident = message.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let ident_str = ident.to_string(); - let trait_ident = self.trait_def.ident(); - let error_str = format!( - "encountered error while calling <{} as {}>::{}", - implementer_ident, trait_ident, ident_str - ); - let inputs_sig = message.inputs(); - let inputs_params = message.inputs().map(|pat_type| &pat_type.pat); - let output_ty = message - .output() - .cloned() - .unwrap_or_else(|| syn::parse_quote! { () }); - let receiver = message.receiver(); - let forward_ident = match receiver { - ir::Receiver::Ref => format_ident!("call"), - ir::Receiver::RefMut => format_ident!("call_mut"), - }; - let forward_trait = match receiver { - ir::Receiver::Ref => format_ident!("ForwardCall"), - ir::Receiver::RefMut => format_ident!("ForwardCallMut"), - }; - let opt_mut = match receiver { - ir::Receiver::Ref => None, - ir::Receiver::RefMut => Some(quote! { mut }), - }; - quote_spanned!(span => - type #output_ident = #output_ty; - - #[inline] - fn #ident( #receiver #(, #inputs_sig )* ) -> Self::#output_ident { - <&#opt_mut Self as ::ink_lang::#forward_trait>::#forward_ident(self) - .#ident( #( #inputs_params ),* ) - .fire() - .expect(#error_str) - } - ) - } - - /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. - pub(super) fn generate_arg_list<'b, Args>(args: Args) -> TokenStream2 - where - Args: IntoIterator, - ::IntoIter: DoubleEndedIterator, - { - args.into_iter().fold( - quote! { ::ink_env::call::utils::EmptyArgumentList }, - |rest, arg| quote! { - ::ink_env::call::utils::ArgumentList<::ink_env::call::utils::Argument<#arg>, #rest> - } - ) - } - - /// Generates the code to allow cross-chain contract calls for trait constructors. - fn generate_trait_impl_block_constructor( - &self, - constructor: ir::InkTraitConstructor, - selector: ir::Selector, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let ident = constructor.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); - let selector_bytes = selector.as_bytes().to_owned(); - let input_bindings = constructor - .inputs() - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>(); - let input_types = constructor - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>(); - let arg_list = Self::generate_arg_list(input_types.iter().cloned()); - quote_spanned!(span => - #[allow(clippy::type_complexity)] - type #output_ident = ::ink_env::call::CreateBuilder< - Environment, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, - ::ink_env::call::utils::Unset<::ink_env::call::state::Salt>, - Self, - >; - - #( #attrs )* - #[inline] - fn #ident( - #( #input_bindings : #input_types ),* - ) -> Self::#output_ident { - ::ink_env::call::build_create::() - .exec_input( - ::ink_env::call::ExecutionInput::new( - ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) - ) - #( - .push_arg(#input_bindings) - )* - ) - } - ) - } - - /// Returns the identifier of the concrete implementer for the ink! trait. - fn concrete_implementer_ident(&self) -> syn::Ident { - let hash = self.trait_def.verify_hash(); - let ident = self.trait_def.ident(); - format_ident!( - "__ink_ConcreteImplementer{}_0x{:X}{:X}{:X}{:X}", - ident, - hash[0], - hash[1], - hash[2], - hash[3] - ) - } - - /// Generates the short-hand calling implementations for the ink! trait concretizer. - pub(super) fn generate_trait_impl_block(&self) -> TokenStream2 { - let span = self.trait_def.span(); - let attrs = self.trait_def.attrs(); - let hash = self.trait_def.verify_hash(); - let trait_ident = self.trait_def.ident(); - let self_ident = self.concrete_implementer_ident(); - let verify_hash_id = - u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; - let messages = self.trait_def.iter_items().filter_map(|(item, selector)| { - item.filter_map_message().map(|message| { - self.generate_trait_impl_block_message(message, selector) - }) - }); - let constructors = self.trait_def.iter_items().filter_map(|(item, selector)| { - item.filter_map_constructor().map(|constructor| { - self.generate_trait_impl_block_constructor(constructor, selector) - }) - }); - quote_spanned!(span => - unsafe impl ::ink_lang::CheckedInkTrait<[(); #verify_hash_id]> for #self_ident {} - - #( #attrs )* - impl #trait_ident for #self_ident { - type __ink_Checksum = [(); #verify_hash_id]; - - #( #messages )* - #( #constructors )* - } - ) - } -} From 8481341c97c36997c1d27e2e35934d445550993e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 28 May 2021 15:46:47 +0200 Subject: [PATCH 071/493] fix generated ink! trait call forwarder identifier --- crates/lang/codegen/src/generator/trait_def/call_forwarder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 8f36ceaf93..86a458c9e2 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -86,7 +86,7 @@ impl CallForwarder<'_> { /// Returns the identifier of the ink! trait call forwarder. fn ident(&self) -> syn::Ident { - self.trait_def.call_builder_ident() + self.trait_def.call_forwarder_ident() } /// Generates the struct type definition for the account wrapper type. From b96a0acb6269ddfb61863c63a15c323703fd9964 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 28 May 2021 15:47:18 +0200 Subject: [PATCH 072/493] change TraitModulePath::FULL to NAME since concat! cannot handle non-literals. --- .../codegen/src/generator/trait_def/trait_registry.rs | 10 +--------- crates/lang/src/traits.rs | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 7f8176cf3f..c4a6107ace 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -230,15 +230,7 @@ impl TraitRegistry<'_> { { const PATH: &'static ::core::primitive::str = ::core::module_path!(); - const FULL: &'static ::core::primitive::str = ::core::concat!( - // We cannot reuse `Self::PATH` here since only literals - // are allow to be passed into the `concat!` macro. - // Fortunately the Rust compiler produces a string literal - // in place of the `module_path!` macro invokation. - ::core::module_path!(), - "::", - #trait_ident, - ); + const NAME: &'static ::core::primitive::str = ::core::stringify!(#trait_ident); } impl ::ink_lang::TraitCallForwarder for #trait_info_ident diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index dda6e64742..fd8cf08ce1 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -209,10 +209,10 @@ pub trait TraitModulePath { /// invokation at the definition site of the ink! trait. const PATH: &'static str; - /// The full path and name of the ink! trait separated with `::`. + /// The name of the ink! trait. /// /// This is just for convenience. - const FULL: &'static str; + const NAME: &'static str; } /// Implemented by call builders of smart contracts. From 8468d7bf92a49e607e2d00033a0e7a573b960caa Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 4 Jun 2021 17:25:49 +0200 Subject: [PATCH 073/493] miscellaneous improvements to macro hygiene in derive macros --- crates/storage/derive/src/spread_layout.rs | 14 +++++++------- crates/storage/derive/src/storage_layout.rs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/storage/derive/src/spread_layout.rs b/crates/storage/derive/src/spread_layout.rs index d2796c78b5..b20f3e5b28 100644 --- a/crates/storage/derive/src/spread_layout.rs +++ b/crates/storage/derive/src/spread_layout.rs @@ -31,7 +31,7 @@ fn max_n(args: &[TokenStream2]) -> TokenStream2 { Some((head, rest)) => { let rest = max_n(rest); quote! { - [#head, #rest][(#head < #rest) as usize] + [#head, #rest][(#head < #rest) as ::core::primitive::usize] } } None => quote! { 0u64 }, @@ -103,8 +103,8 @@ fn spread_layout_struct_derive(s: &synstructure::Structure) -> TokenStream2 { s.gen_impl(quote! { gen impl ::ink_storage::traits::SpreadLayout for @Self { #[allow(unused_comparisons)] - const FOOTPRINT: u64 = #footprint_body; - const REQUIRES_DEEP_CLEAN_UP: bool = #requires_deep_clean_up_body; + const FOOTPRINT: ::core::primitive::u64 = #footprint_body; + const REQUIRES_DEEP_CLEAN_UP: ::core::primitive::bool = #requires_deep_clean_up_body; fn pull_spread(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> Self { #pull_body @@ -154,7 +154,7 @@ fn spread_layout_enum_derive(s: &synstructure::Structure) -> TokenStream2 { }); quote! { #pat => { - { ::push_spread(&#index, __key_ptr); } + { <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::push_spread(&#index, __key_ptr); } #( { #fields } )* @@ -169,12 +169,12 @@ fn spread_layout_enum_derive(s: &synstructure::Structure) -> TokenStream2 { s.gen_impl(quote! { gen impl ::ink_storage::traits::SpreadLayout for @Self { #[allow(unused_comparisons)] - const FOOTPRINT: u64 = 1 + #footprint_body; + const FOOTPRINT: ::core::primitive::u64 = 1 + #footprint_body; - const REQUIRES_DEEP_CLEAN_UP: bool = #requires_deep_clean_up_body; + const REQUIRES_DEEP_CLEAN_UP: ::core::primitive::bool = #requires_deep_clean_up_body; fn pull_spread(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> Self { - match ::pull_spread(__key_ptr) { + match <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::pull_spread(__key_ptr) { #pull_body _ => unreachable!("encountered invalid enum discriminant"), } diff --git a/crates/storage/derive/src/storage_layout.rs b/crates/storage/derive/src/storage_layout.rs index 7ee807e090..33ee20067b 100644 --- a/crates/storage/derive/src/storage_layout.rs +++ b/crates/storage/derive/src/storage_layout.rs @@ -22,9 +22,9 @@ fn field_layout<'a>( let ident = match field.ident.as_ref() { Some(ident) => { let ident_str = ident.to_string(); - quote! { Some(#ident_str) } + quote! { ::core::option::Option::Some(#ident_str) } } - None => quote! { None }, + None => quote! { ::core::option::Option::None }, }; let ty = &field.ty; quote! { From 42e1b60ef45b9930c65b46987f5b8bcc2f91d0e5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 4 Jun 2021 17:29:33 +0200 Subject: [PATCH 074/493] add new call builder codegen for ink! trait implementations This is the last codegen piece before the new ink! trait codegen can be tested. Note though that still some semantic analysis is missing and that the codegen might still be incorrect and malfunctioning under certain compile configurations. --- .../codegen/src/generator/call_builder.rs | 454 ++++++++++++++++++ crates/lang/codegen/src/generator/contract.rs | 2 + crates/lang/codegen/src/generator/mod.rs | 2 + 3 files changed, 458 insertions(+) create mode 100644 crates/lang/codegen/src/generator/call_builder.rs diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs new file mode 100644 index 0000000000..ed7107c364 --- /dev/null +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -0,0 +1,454 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::GenerateCode; +use derive_more::From; +use heck::CamelCase; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ + format_ident, + quote, + quote_spanned, +}; +use syn::spanned::Spanned as _; + +/// Generates code for the call builder of the ink! smart contract. +/// +/// The call builder is the entity that builds up calls for calling of other +/// smart contract on-chain in a type safe way. +/// It implements all ink! traits that the associated ink! smart contract implements +/// so that their underlying implementation directly calls the respective ink! +/// trait implementation on-chain. +/// +/// The ink! call builder of a smart contract is directly used by the storage +/// type of the smart contract itself as well by other entities that use the +/// smart contract via long-hand calling notation to incrementally build up calls. +#[derive(From)] +pub struct CallBuilder<'a> { + contract: &'a ir::Contract, +} + +impl GenerateCode for CallBuilder<'_> { + fn generate_code(&self) -> TokenStream2 { + let call_builder_struct = self.generate_struct(); + let trait_impl = self.generate_trait_impl(); + let auxiliary_trait_impls = self.generate_auxiliary_trait_impls(); + let call_forwarder_impls = self.generate_call_forwarder_impls(); + let contract_trait_impls = self.generate_contract_trait_impls(); + quote! { + const _: () = { + #call_builder_struct + #trait_impl + #auxiliary_trait_impls + #call_forwarder_impls + }; + #contract_trait_impls + } + } +} + +impl CallBuilder<'_> { + fn generate_struct(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + quote_spanned!(span=> + /// The ink! smart contract's call builder. + /// + /// Implements the underlying on-chain calling of the ink! smart contract + /// messages and trait implementations in a type safe way. + #[repr(transparent)] + #[cfg_attr(feature = "std", derive( + ::core::fmt::Debug, + ::ink_storage::traits::StorageLayout, + ))] + #[derive( + ::scale::Encode, + ::scale::Decode, + ::ink_storage::traits::SpreadLayout, + ::ink_storage::traits::PackedLayout, + )] + pub struct CallBuilder { + account_id: AccountId, + } + ) + } + + /// Generates the `CallBuilder` trait implementation for the ink! contract. + /// + /// This creates the bridge between the ink! smart contract type and the + /// associated call builder. + fn generate_trait_impl(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let ident = self.contract.module().storage().ident(); + quote_spanned!(span=> + impl ::ink_lang::TraitCallBuilder for #ident { + type Builder = CallBuilder; + + #[inline] + fn call(&self) -> &Self::Builder { + &self.builder + } + + #[inline] + fn call_mut(&mut self) -> &mut Self::Builder { + &mut self.builder + } + } + ) + } + + /// Generates some ink! specific auxiliary trait implementations for the + /// smart contract call builder type. + /// + /// These are required to properly interoperate with the call builder. + fn generate_auxiliary_trait_impls(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + quote_spanned!(span=> + impl ::ink_env::call::FromAccountId for CallBuilder { + #[inline] + fn from_account_id(account_id: AccountId) -> Self { + Self { account_id } + } + } + + impl ::ink_lang::ToAccountId for CallBuilder { + #[inline] + fn to_account_id(&self) -> AccountId { + ::clone(&self.account_id) + } + } + ) + } + + /// Generate the `TraitCallForwarder` trait implementations for the call builder + /// for every ink! trait implemented by the associated ink! smart contract. + /// + /// These call forwarder trait implementations are used to dispatch to the global + /// call builder for the respective ink! trait definition that is being called. + /// The call builder only forwards the actual calls to those global call builders + /// and does not have its own calling logic. + fn generate_call_forwarder_impls(&self) -> TokenStream2 { + self.contract + .module() + .impls() + .filter_map(|impl_block| { + // We are only interested in ink! trait implementation block. + impl_block.trait_path().map(|trait_path| { + self.generate_code_for_trait_impl(trait_path, impl_block) + }) + }) + .collect() + } + + /// Generates code required by the ink! call builder of an ink! smart contract + /// for a single ink! trait definition that the contract implements. + fn generate_code_for_trait_impl( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + let call_forwarder_impl = + self.generate_call_forwarder_for_trait_impl(trait_path, impl_block); + let implementation_marker = + self.generate_implementation_marker_for_trait_impl(trait_path, impl_block); + let ink_trait_impl = self.generate_ink_trait_impl(trait_path, impl_block); + quote! { + #call_forwarder_impl + #implementation_marker + #ink_trait_impl + } + } + + /// Generates code for a single ink! trait implementation to forward calls for + /// the associated ink! smart contract call builder. + fn generate_call_forwarder_for_trait_impl( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + let span = impl_block.span(); + let unique_trait_id = self.generate_unique_trait_id(trait_path); + quote_spanned!(span=> + #[doc(hidden)] + impl ::ink_lang::TraitCallForwarderFor<#unique_trait_id> for CallBuilder { + type Forwarder = <::__ink_TraitInfo as ::ink_lang::TraitCallForwarder>::Forwarder; + + #[inline(always)] + fn forward(&self) -> &Self::Forwarder { + // SAFETY: + // + // We convert from a shared reference to a type that thinly wraps + // only an `AccountId` to a shared reference to another type of which + // we know that it also thinly wraps an `AccountId`. + // Furthermore both types use `repr(transparent)`. + unsafe { + &*(&self.account_id as *const AccountId as *const Self::Forwarder) + } + } + + #[inline(always)] + fn forward_mut(&mut self) -> &mut Self::Forwarder { + // SAFETY: + // + // We convert from a exclusive reference to a type that thinly wraps + // only an `AccountId` to a exclusive reference to another type of which + // we know that it also thinly wraps an `AccountId`. + // Furthermore both types use `repr(transparent)`. + unsafe { + &mut *(&mut self.account_id as *mut AccountId as *mut Self::Forwarder) + } + } + + #[inline(always)] + fn build( + &self, + ) -> &::Builder { + <_ as ::ink_lang::TraitCallBuilder>::call( + >::forward(self) + ) + } + + #[inline(always)] + fn build_mut( + &mut self, + ) -> &mut ::Builder + { + <_ as ::ink_lang::TraitCallBuilder>::call_mut( + >::forward_mut(self) + ) + } + } + ) + } + + /// Unsafely implements the required trait implementation marker. + /// + /// This marker only states that the ink! trait definition has been properly implemented. + /// The marker trait is unsafe to make people think twice before manually implementing + /// ink! trait definitions. + fn generate_implementation_marker_for_trait_impl( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + let span = impl_block.span(); + let unique_trait_id = self.generate_unique_trait_id(trait_path); + quote_spanned!(span=> + #[doc(hidden)] + unsafe impl + ::ink_lang::TraitImplementer<#unique_trait_id> for CallBuilder + {} + ) + } + + /// Generates code to uniquely identify a trait by its unique ID given only its identifier. + /// + /// # Note + /// + /// As with all Rust macros identifiers can shadow each other so the given identifier + /// needs to be valid for the scope in which the returned code is generated. + fn generate_unique_trait_id(&self, trait_path: &syn::Path) -> TokenStream2 { + let span = self.contract.module().storage().span(); + quote_spanned!(span=> + { + <<::ink_lang::TraitCallForwarderRegistry + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitUniqueId>::ID + } + ) + } + + /// Generates the actual ink! trait implementation for the generated call builder. + fn generate_ink_trait_impl( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + let span = impl_block.span(); + let messages = impl_block + .iter_messages() + .map(|message| self.generate_ink_trait_impl_for_message(trait_path, message)); + quote_spanned!(span=> + impl #trait_path for CallBuilder { + type Env = Environment; + + type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry + as #trait_path>::__ink_TraitInfo; + + #( #messages )* + } + ) + } + + /// Generates the code for the ink! trait implementation of the call builder + /// of a single ink! trait message and its associated output type. + fn generate_ink_trait_impl_for_message( + &self, + trait_path: &syn::Path, + message: ir::CallableWithSelector, + ) -> TokenStream2 { + use ir::Callable as _; + let span = message.span(); + let message_ident = message.ident(); + let output_ident = self.output_ident(message_ident); + let unique_trait_id = self.generate_unique_trait_id(trait_path); + let input_bindings = message + .callable() + .inputs() + .map(|input| &input.pat) + .collect::>(); + let input_types = message + .callable() + .inputs() + .map(|input| &input.ty) + .collect::>(); + let mut_token = message + .receiver() + .is_ref_mut() + .then(|| Some(quote! { mut })); + let attrs = message.attrs(); + quote_spanned!(span=> + type #output_ident = <<< + Self + as ::ink_lang::TraitCallForwarderFor<#unique_trait_id>>::Forwarder + as ::ink_lang::TraitCallBuilder>::Builder + as #trait_path>::#output_ident; + + #[inline] + #( #attrs )* + fn #message_ident( + & #mut_token self + #( , #input_bindings: #input_types )* + ) -> Self::#output_ident { + <_ as #trait_path>::#message_ident( + >::build_mut(self) + #( , #input_bindings )* + ) + } + ) + } + + /// Returns the associated output type for an ink! trait message. + /// + /// TODO: Remove duplicated `output_ident` method before merging PR. + fn output_ident(&self, message_name: &syn::Ident) -> syn::Ident { + format_ident!("{}Output", message_name.to_string().to_camel_case()) + } + + /// Generates the code for all ink! trait implementations of the contract itself. + /// + /// # Note + /// + /// Since those implementations must live outside of an artificial `const` block + /// we need to keep this in a separate expansion step. + fn generate_contract_trait_impls(&self) -> TokenStream2 { + self.contract + .module() + .impls() + .filter_map(|impl_block| { + // We are only interested in ink! trait implementation block. + impl_block.trait_path().map(|trait_path| { + self.generate_contract_trait_impl(trait_path, impl_block) + }) + }) + .collect() + } + + /// Generates the code for a single ink! trait implementation of the contract itself. + /// + /// The generated implementation mainly forwards the calls to the previously generated + /// associated call builder that implements each respective ink! trait. + fn generate_contract_trait_impl( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let unique_trait_id = self.generate_unique_trait_id(trait_path); + let storage_ident = self.contract.module().storage().ident(); + let messages = self.generate_contract_trait_impl_messages(trait_path, impl_block); + quote_spanned!(span=> + #[doc(hidden)] + unsafe impl + ::ink_lang::TraitImplementer<#unique_trait_id> for #storage_ident + {} + + impl #trait_path for #storage_ident { + type Env = Environment; + + #[doc(hidden)] + type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry + as #trait_path>::__ink_TraitInfo; + + #messages + } + ) + } + + /// Generates the code for a all messages of a single ink! trait implementation of + /// the ink! smart contract. + fn generate_contract_trait_impl_messages( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + impl_block + .iter_messages() + .map(|message| { + self.generate_contract_trait_impl_for_message(trait_path, message) + }) + .collect() + } + + /// Generates the code for a single message of a single ink! trait implementation + /// that is implemented by the ink! smart contract. + fn generate_contract_trait_impl_for_message( + &self, + trait_path: &syn::Path, + message: ir::CallableWithSelector, + ) -> TokenStream2 { + use ir::Callable as _; + let unique_trait_id = self.generate_unique_trait_id(trait_path); + let span = message.span(); + let message_ident = message.ident(); + let output_ident = self.output_ident(message_ident); + let call_operator = match message.receiver() { + ir::Receiver::Ref => quote! { call }, + ir::Receiver::RefMut => quote! { call_mut }, + }; + let forward_operator = match message.receiver() { + ir::Receiver::Ref => quote! { forward }, + ir::Receiver::RefMut => quote! { forward_mut }, + }; + let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); + let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); + let input_types = message.inputs().map(|input| &input.ty).collect::>(); + quote_spanned!(span=> + type #output_ident = + <::Forwarder as #trait_path>::#output_ident; + + #[inline] + fn #message_ident( + & #mut_token self + #( , #input_bindings : #input_types )* + ) -> Self::#output_ident { + <_ as #trait_path>::#message_ident( + <_ as ::ink_lang::TraitCallForwarderFor<#unique_trait_id>>::#forward_operator( + ::#call_operator(self), + ) + #( , #input_bindings )* + ) + } + ) + } +} diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index 380ba156c3..adc95d066d 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -48,6 +48,7 @@ impl GenerateCode for Contract<'_> { let item_impls = self.generate_code_using::(); let cross_calling = self.generate_code_using::(); let metadata = self.generate_code_using::(); + let call_builder = self.generate_code_using::(); let non_ink_items = self .contract .module() @@ -63,6 +64,7 @@ impl GenerateCode for Contract<'_> { #dispatch #item_impls #cross_calling + #call_builder #metadata #( #non_ink_items )* } diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index d6aae330eb..87480bae61 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod call_builder; mod chain_extension; mod contract; mod cross_calling; @@ -27,6 +28,7 @@ mod enforced_error; pub use self::{ chain_extension::ChainExtension, + call_builder::CallBuilder, contract::Contract, cross_calling::{ CrossCalling, From 655230d26a6468555339cacc7b96bbea28a2dc87 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 4 Jun 2021 17:29:45 +0200 Subject: [PATCH 075/493] reordered import statements --- crates/lang/codegen/src/generator/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 87480bae61..899f8bb293 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -17,6 +17,7 @@ mod chain_extension; mod contract; mod cross_calling; mod dispatch; +mod enforced_error; mod env; mod events; mod ink_test; @@ -24,7 +25,6 @@ mod item_impls; mod metadata; mod storage; mod trait_def; -mod enforced_error; pub use self::{ chain_extension::ChainExtension, From c869374e7bfe40341c96b2cac6105399fc415f9a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 10 Jun 2021 10:09:34 +0200 Subject: [PATCH 076/493] fix clippy warnings --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- .../lang/codegen/src/generator/trait_def/call_forwarder.rs | 2 +- .../lang/codegen/src/generator/trait_def/trait_registry.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 62992abcd8..29e9ac6fb9 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -416,7 +416,7 @@ impl CallBuilder<'_> { } /// Returns the sequence of input types for the message. - fn input_types<'b>(inputs: ir::TraitItemInputsIter<'b>) -> Vec<&'b syn::Type> { + fn input_types(inputs: ir::TraitItemInputsIter) -> Vec<&syn::Type> { inputs.map(|pat_type| &*pat_type.ty).collect::>() } diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 86a458c9e2..52a7080dfb 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -390,7 +390,7 @@ impl CallForwarder<'_> { let message_ident = message.ident(); let attrs = message.attrs(); let output_ident = self.trait_def.output_ident(message.ident()); - let output_type = message.output().cloned().unwrap_or(syn::parse_quote!(())); + let output_type = message.output().cloned().unwrap_or_else(|| syn::parse_quote!(())); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); let call_op = match message.receiver() { diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index c4a6107ace..4568fba1f8 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -177,9 +177,9 @@ impl TraitRegistry<'_> { } /// Returns a pair of input bindings `__ink_bindings_N` and types. - fn input_bindings_and_types<'b>( - inputs: ir::TraitItemInputsIter<'b>, - ) -> (Vec, Vec<&'b syn::Type>) { + fn input_bindings_and_types( + inputs: ir::TraitItemInputsIter, + ) -> (Vec, Vec<&syn::Type>) { inputs .enumerate() .map(|(n, pat_type)| { From f7388b3dab583ef025295d0d265843997d1d271f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 15 Jun 2021 13:30:36 +0200 Subject: [PATCH 077/493] refactor as-ink-dependency #[cfg(..)] codegen --- .../codegen/src/generator/as_dependency.rs | 60 ++++++++++++++++++ .../codegen/src/generator/cross_calling.rs | 62 +++++++------------ crates/lang/codegen/src/generator/dispatch.rs | 9 +-- crates/lang/codegen/src/generator/events.rs | 17 ++--- .../lang/codegen/src/generator/item_impls.rs | 9 +-- crates/lang/codegen/src/generator/mod.rs | 26 ++++++-- crates/lang/codegen/src/generator/storage.rs | 13 ++-- 7 files changed, 118 insertions(+), 78 deletions(-) create mode 100644 crates/lang/codegen/src/generator/as_dependency.rs diff --git a/crates/lang/codegen/src/generator/as_dependency.rs b/crates/lang/codegen/src/generator/as_dependency.rs new file mode 100644 index 0000000000..1f0d7ca415 --- /dev/null +++ b/crates/lang/codegen/src/generator/as_dependency.rs @@ -0,0 +1,60 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::GenerateCode; +use derive_more::From; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; + +/// Generates `#[cfg(..)]` code to guard against compilation under `ink-as-dependency`. +#[derive(From)] +pub struct NotAsDependencyCfg<'a> { + contract: &'a ir::Contract, +} + +impl GenerateCode for NotAsDependencyCfg<'_> { + fn generate_code(&self) -> TokenStream2 { + if self.contract.config().is_compile_as_dependency_enabled() { + // We use `__ink_DO_NOT_COMPILE` in order to craft a `cfg` that + // never evaluates to `true` and therefore is always disabled. + return quote! { #[cfg(feature = "__ink_DO_NOT_COMPILE")] } + } + quote! { #[cfg(not(feature = "ink-as-dependency"))] } + } +} + +/// Generates `#[cfg(..)]` code to only allow compilation when `ink-as-dependency` is enabled. +/// +/// The `ink-as-dependency` can be enabled mainly by 2 different ways: +/// +/// - Enabling it in the associated `Cargo.toml` as crate feature. +/// - Note: This can be enabled by dependencies of an ink! smart contract. +/// - Enabling it in the configuration header with `#[ink::contract(compile_as_dependency = true)]`. +/// - If set here the contract will always be compiled as it is was a dependency. +#[derive(From)] +pub struct OnlyAsDependencyCfg<'a> { + contract: &'a ir::Contract, +} + +impl GenerateCode for OnlyAsDependencyCfg<'_> { + fn generate_code(&self) -> TokenStream2 { + if self.contract.config().is_compile_as_dependency_enabled() { + // We return no code since no code is required to disable compilation. + return quote! {} + } + quote! { + #[cfg(feature = "ink-as-dependency")] + } + } +} diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index 39e47922a4..e2c7415b9f 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -12,7 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::GenerateCode; +use super::enforced_error::EnforcedErrors; +use crate::{ + generator, + GenerateCode, + GenerateCodeUsing as _, +}; use derive_more::From; use heck::CamelCase as _; use impl_serde::serialize as serde_hex; @@ -28,28 +33,13 @@ use quote::{ quote_spanned, }; use syn::spanned::Spanned as _; -use super::enforced_error::EnforcedErrors; - -/// Generates `#[cfg(..)]` code to guard against compilation under `ink-as-dependency`. -#[derive(From)] -pub struct CrossCallingConflictCfg<'a> { - contract: &'a ir::Contract, -} - -impl GenerateCode for CrossCallingConflictCfg<'_> { - fn generate_code(&self) -> TokenStream2 { - if self.contract.config().is_compile_as_dependency_enabled() { - return quote! { #[cfg(feature = "__ink_DO_NOT_COMPILE")] } - } - quote! { #[cfg(not(feature = "ink-as-dependency"))] } - } -} /// Generates code for using this ink! contract as a dependency. #[derive(From)] pub struct CrossCalling<'a> { contract: &'a ir::Contract, } +impl_as_ref_for_generator!(CrossCalling); impl GenerateCode for CrossCalling<'_> { fn generate_code(&self) -> TokenStream2 { @@ -67,17 +57,6 @@ impl GenerateCode for CrossCalling<'_> { } impl CrossCalling<'_> { - /// Generates code for conditionally compiling code only if the contract - /// is compiled as dependency. - fn generate_cfg(&self) -> Option { - if self.contract.config().is_compile_as_dependency_enabled() { - return None - } - Some(quote! { - #[cfg(feature = "ink-as-dependency")] - }) - } - /// Generates code for the ink! storage struct for cross-calling purposes. /// /// # Note @@ -87,13 +66,14 @@ impl CrossCalling<'_> { /// forward all calls via ink!'s provided cross-calling infrastructure /// automatically over the chain. fn generate_storage(&self) -> TokenStream2 { - let cfg = self.generate_cfg(); + let only_as_dependency = + self.generate_code_using::(); let storage = self.contract.module().storage(); let span = storage.span(); let ident = storage.ident(); let attrs = storage.attrs(); quote_spanned!(span => - #cfg + #only_as_dependency #( #attrs )* #[derive( Clone, @@ -120,10 +100,11 @@ impl CrossCalling<'_> { /// generated ink! storage struct for cross-calling work out-of-the-box /// for the cross-calling infrastructure. fn generate_standard_impls(&self) -> TokenStream2 { - let cfg = self.generate_cfg(); + let only_as_dependency = + self.generate_code_using::(); let ident = self.contract.module().storage().ident(); quote! { - #cfg + #only_as_dependency const _: () = { impl ::ink_env::call::FromAccountId for #ident { #[inline] @@ -528,9 +509,10 @@ impl CrossCalling<'_> { let storage_ident = self.contract.module().storage().ident(); let impl_blocks_ref = self.generate_call_forwarder_impl_blocks(false); let impl_blocks_refmut = self.generate_call_forwarder_impl_blocks(true); - let cfg = self.generate_cfg(); + let only_as_dependency = + self.generate_code_using::(); quote! { - #cfg + #only_as_dependency const _: () = { impl<'a> ::ink_lang::ForwardCall for &'a #storage_ident { type Forwarder = #forwarder_ident<&'a #storage_ident>; @@ -672,7 +654,8 @@ impl CrossCalling<'_> { fn generate_trait_impl_block(&self, impl_block: &ir::ItemImpl) -> TokenStream2 { assert!(impl_block.trait_path().is_some()); - let cfg = self.generate_cfg(); + let only_as_dependency = + self.generate_code_using::(); let span = impl_block.span(); let attrs = impl_block.attrs(); let trait_path = impl_block @@ -704,10 +687,10 @@ impl CrossCalling<'_> { ); let checksum = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; quote_spanned!(span => - #cfg + #only_as_dependency unsafe impl ::ink_lang::CheckedInkTrait<[(); #checksum]> for #self_type {} - #cfg + #only_as_dependency #( #attrs )* impl #trait_path for #self_type { type __ink_Checksum = [(); #checksum]; @@ -814,7 +797,8 @@ impl CrossCalling<'_> { fn generate_inherent_impl_block(&self, impl_block: &ir::ItemImpl) -> TokenStream2 { assert!(impl_block.trait_path().is_none()); - let cfg = self.generate_cfg(); + let only_as_dependency = + self.generate_code_using::(); let span = impl_block.span(); let attrs = impl_block.attrs(); let self_type = impl_block.self_type(); @@ -825,7 +809,7 @@ impl CrossCalling<'_> { Self::generate_inherent_impl_block_constructor(constructor) }); quote_spanned!(span => - #cfg + #only_as_dependency #( #attrs )* impl #self_type { #( #messages )* diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index a78fd27613..0156e1ac78 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -47,17 +47,12 @@ use syn::spanned::Spanned as _; pub struct Dispatch<'a> { contract: &'a ir::Contract, } - -impl AsRef for Dispatch<'_> { - fn as_ref(&self) -> &ir::Contract { - self.contract - } -} +impl_as_ref_for_generator!(Dispatch); impl GenerateCode for Dispatch<'_> { fn generate_code(&self) -> TokenStream2 { let no_cross_calling_cfg = - self.generate_code_using::(); + self.generate_code_using::(); let entry_points = self.generate_entry_points(); let dispatch_using_mode = self.generate_dispatch_using_mode(); let dispatch_trait_impl_namespaces = self.generate_trait_impl_namespaces(); diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index 61ed755612..dc248fb329 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -33,12 +33,7 @@ use syn::spanned::Spanned as _; pub struct Events<'a> { contract: &'a ir::Contract, } - -impl AsRef for Events<'_> { - fn as_ref(&self) -> &ir::Contract { - self.contract - } -} +impl_as_ref_for_generator!(Events); impl GenerateCode for Events<'_> { fn generate_code(&self) -> TokenStream2 { @@ -67,7 +62,7 @@ impl<'a> Events<'a> { fn generate_emit_event_trait_impl(&self) -> TokenStream2 { let storage_ident = &self.contract.module().storage().ident(); let no_cross_calling_cfg = - self.generate_code_using::(); + self.generate_code_using::(); quote! { const _: () = { #no_cross_calling_cfg @@ -92,7 +87,7 @@ impl<'a> Events<'a> { fn generate_event_base(&self) -> TokenStream2 { let storage_ident = &self.contract.module().storage().ident(); let no_cross_calling_cfg = - self.generate_code_using::(); + self.generate_code_using::(); let event_idents = self .contract .module() @@ -202,7 +197,7 @@ impl<'a> Events<'a> { /// Generates the guard code that protects against having too many topics defined on an ink! event. fn generate_topic_guards(&'a self) -> impl Iterator + 'a { let no_cross_calling_cfg = - self.generate_code_using::(); + self.generate_code_using::(); self.contract.module().events().map(move |event| { let span = event.span(); let topics_guard = self.generate_topics_guard(event); @@ -216,7 +211,7 @@ impl<'a> Events<'a> { /// Generates the `Topics` trait implementations for the user defined events. fn generate_topics_impls(&'a self) -> impl Iterator + 'a { let no_cross_calling_cfg = - self.generate_code_using::(); + self.generate_code_using::(); let contract_ident = self.contract.module().storage().ident(); self.contract.module().events().map(move |event| { let span = event.span(); @@ -293,7 +288,7 @@ impl<'a> Events<'a> { /// Generates all the user defined event struct definitions. fn generate_event_structs(&'a self) -> impl Iterator + 'a { let no_cross_calling_cfg = - self.generate_code_using::(); + self.generate_code_using::(); self.contract.module().events().map(move |event| { let span = event.span(); let ident = event.ident(); diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 601f132ed4..50911518a7 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -34,12 +34,7 @@ use syn::spanned::Spanned as _; pub struct ItemImpls<'a> { contract: &'a ir::Contract, } - -impl AsRef for ItemImpls<'_> { - fn as_ref(&self) -> &ir::Contract { - self.contract - } -} +impl_as_ref_for_generator!(ItemImpls); impl GenerateCode for ItemImpls<'_> { fn generate_code(&self) -> TokenStream2 { @@ -49,7 +44,7 @@ impl GenerateCode for ItemImpls<'_> { .impls() .map(|item_impl| self.generate_item_impl(item_impl)); let no_cross_calling_cfg = - self.generate_code_using::(); + self.generate_code_using::(); quote! { #no_cross_calling_cfg const _: () = { diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 899f8bb293..d80168f317 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -12,6 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +/// Implements `AsRef` for a code generator type. +/// +/// Code generators always have a shared `contract` reference to the contract. +/// They need to implement this trait in order to use other code generators. +macro_rules! impl_as_ref_for_generator { + ( $generator_name:ident ) => { + impl ::core::convert::AsRef for $generator_name<'_> { + fn as_ref(&self) -> &ir::Contract { + self.contract + } + } + }; +} + +mod as_dependency; mod call_builder; mod chain_extension; mod contract; @@ -27,13 +42,14 @@ mod storage; mod trait_def; pub use self::{ - chain_extension::ChainExtension, + as_dependency::{ + NotAsDependencyCfg, + OnlyAsDependencyCfg, + }, call_builder::CallBuilder, + chain_extension::ChainExtension, contract::Contract, - cross_calling::{ - CrossCalling, - CrossCallingConflictCfg, - }, + cross_calling::CrossCalling, dispatch::Dispatch, env::Env, events::Events, diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index 74c830c4f7..66b35f7b36 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -30,12 +30,7 @@ use syn::spanned::Spanned as _; pub struct Storage<'a> { contract: &'a ir::Contract, } - -impl<'a> AsRef for Storage<'_> { - fn as_ref(&self) -> &ir::Contract { - self.contract - } -} +impl_as_ref_for_generator!(Storage); impl GenerateCode for Storage<'_> { fn generate_code(&self) -> TokenStream2 { @@ -48,7 +43,7 @@ impl GenerateCode for Storage<'_> { } else { None }; - let cfg = self.generate_code_using::(); + let cfg = self.generate_code_using::(); quote_spanned!(storage_span => #access_env_impls #storage_struct @@ -70,7 +65,7 @@ impl GenerateCode for Storage<'_> { impl Storage<'_> { fn generate_access_env_trait_impls(&self) -> TokenStream2 { let storage_ident = &self.contract.module().storage().ident(); - let cfg = self.generate_code_using::(); + let cfg = self.generate_code_using::(); quote! { #cfg const _: () = { @@ -100,7 +95,7 @@ impl Storage<'_> { let ident = &storage.ident(); let attrs = &storage.attrs(); let fields = storage.fields(); - let cfg = self.generate_code_using::(); + let cfg = self.generate_code_using::(); quote_spanned!( span => #cfg #(#attrs)* From ed3c972d4f8bc655a9ec124b671e98af7e0e2818 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 30 Aug 2021 15:56:29 +0200 Subject: [PATCH 078/493] add codegen utilities to expand into hex-encoded literals --- crates/lang/codegen/src/lib.rs | 1 + crates/lang/codegen/src/literal.rs | 115 +++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 crates/lang/codegen/src/literal.rs diff --git a/crates/lang/codegen/src/lib.rs b/crates/lang/codegen/src/lib.rs index 09a4bece29..d6febdf99f 100644 --- a/crates/lang/codegen/src/lib.rs +++ b/crates/lang/codegen/src/lib.rs @@ -14,6 +14,7 @@ mod generator; mod traits; +mod literal; use self::traits::{ GenerateCode, diff --git a/crates/lang/codegen/src/literal.rs b/crates/lang/codegen/src/literal.rs new file mode 100644 index 0000000000..7fda3b7055 --- /dev/null +++ b/crates/lang/codegen/src/literal.rs @@ -0,0 +1,115 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Used to convert literal values into their hex representations for code generation. +pub trait HexLiteral { + /// Shared implementation details. + /// + /// # Note + /// + /// Users shall not use this trait method directly hence it is hidden. + #[doc(hidden)] + fn hex_impl_(self, fmt: &str) -> syn::Lit; + + /// Converts the given value into a hex represented literal with type suffix. + fn hex_suffixed(self) -> syn::Lit; + + /// Converts the given value into a hex represented literal without type suffix. + fn hex_unsuffixed(self) -> syn::Lit; + + /// Converts the given value into a hex represented literal with type suffix. + /// + /// The resulting hex encoded literal is padded with zeros. + fn hex_padded_suffixed(self) -> syn::Lit; + + /// Converts the given value into a hex represented literal without type suffix. + /// + /// The resulting hex encoded literal is padded with zeros. + fn hex_padded_unsuffixed(self) -> syn::Lit; +} + +macro_rules! generate_hex_literal_impls { + ( $( ($ty:ty, $name:literal, $fmt_suffixed:literal, $fmt_unsuffixed:literal) ),* $(,)? ) => { + $( + impl HexLiteral for $ty { + #[inline] + fn hex_impl_(self, fmt: &str) -> syn::Lit { + ::syn::Lit::new( + <::proc_macro2::Literal as ::core::str::FromStr>::from_str(fmt).unwrap_or_else( + |err| ::core::panic!("cannot parse {} into a {} hex represented literal: {}", self, $name, err), + ) + ) + } + + fn hex_suffixed(self) -> syn::Lit { + self.hex_impl_(&::std::format!("0x{:X}_{}", self, $name)) + } + + fn hex_unsuffixed(self) -> syn::Lit { + self.hex_impl_(&::std::format!("0x{:X}", self)) + } + + fn hex_padded_suffixed(self) -> syn::Lit { + self.hex_impl_(&::std::format!($fmt_suffixed, self, $name)) + } + + fn hex_padded_unsuffixed(self) -> syn::Lit { + self.hex_impl_(&::std::format!($fmt_unsuffixed, self)) + } + } + )* + }; +} +#[rustfmt::skip] +generate_hex_literal_impls!( + (::core::primitive::i8 , "i8", "0x{:02X}_{}", "0x{:02X}"), + (::core::primitive::u8 , "u8", "0x{:02X}_{}", "0x{:02X}"), + (::core::primitive::i16, "i16", "0x{:04X}_{}", "0x{:04X}"), + (::core::primitive::u16, "u16", "0x{:04X}_{}", "0x{:04X}"), + (::core::primitive::i32, "i32", "0x{:08X}_{}", "0x{:08X}"), + (::core::primitive::u32, "u32", "0x{:08X}_{}", "0x{:08X}"), + (::core::primitive::i64, "i64", "0x{:016X}_{}", "0x{:016X}"), + (::core::primitive::u64, "u64", "0x{:016X}_{}", "0x{:016X}"), + (::core::primitive::i128, "i128", "0x{:032X}_{}", "0x{:032X}"), + (::core::primitive::u128, "u128", "0x{:032X}_{}", "0x{:032X}"), +); + +#[cfg(test)] +mod tests { + use super::HexLiteral as _; + use quote::quote; + + fn assert_quote(given: syn::Lit, expected: &str) { + assert_eq!(quote!(#given).to_string(), expected); + } + + #[test] + fn simple() { + let value = 0x42_i32; + assert_eq!(quote!(#value).to_string(), "66i32"); + assert_quote(value.hex_suffixed(), "0x42_i32"); + assert_quote(value.hex_unsuffixed(), "0x42"); + assert_quote(value.hex_padded_suffixed(), "0x00000042_i32"); + assert_quote(value.hex_padded_unsuffixed(), "0x00000042"); + } + + #[test] + fn code_cafe() { + let value = 0xC0DE_CAFE_u32; + assert_quote(value.hex_suffixed(), "0xC0DECAFE_u32"); + assert_quote(value.hex_padded_suffixed(), "0xC0DECAFE_u32"); + assert_quote(value.hex_unsuffixed(), "0xC0DECAFE"); + assert_quote(value.hex_padded_unsuffixed(), "0xC0DECAFE"); + } +} From 9c0c09744cac385a2db5a459a1ba4b2cbe97d10e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 31 Aug 2021 14:06:18 +0200 Subject: [PATCH 079/493] improve new hex literal module --- crates/lang/codegen/src/literal.rs | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/lang/codegen/src/literal.rs b/crates/lang/codegen/src/literal.rs index 7fda3b7055..896645aa94 100644 --- a/crates/lang/codegen/src/literal.rs +++ b/crates/lang/codegen/src/literal.rs @@ -12,6 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod private { + /// Used to prevent external direct usage of `HexLiteral::hex_impl_`. + pub struct Sealed; +} + /// Used to convert literal values into their hex representations for code generation. pub trait HexLiteral { /// Shared implementation details. @@ -20,7 +25,7 @@ pub trait HexLiteral { /// /// Users shall not use this trait method directly hence it is hidden. #[doc(hidden)] - fn hex_impl_(self, fmt: &str) -> syn::Lit; + fn hex_impl_(self, fmt: ::core::fmt::Arguments, sealed: private::Sealed) -> syn::Lit; /// Converts the given value into a hex represented literal with type suffix. fn hex_suffixed(self) -> syn::Lit; @@ -43,29 +48,29 @@ macro_rules! generate_hex_literal_impls { ( $( ($ty:ty, $name:literal, $fmt_suffixed:literal, $fmt_unsuffixed:literal) ),* $(,)? ) => { $( impl HexLiteral for $ty { - #[inline] - fn hex_impl_(self, fmt: &str) -> syn::Lit { + fn hex_impl_(self, fmt: ::core::fmt::Arguments, _sealed: private::Sealed) -> syn::Lit { + let formatted = ::std::format!("{}", fmt); ::syn::Lit::new( - <::proc_macro2::Literal as ::core::str::FromStr>::from_str(fmt).unwrap_or_else( + <::proc_macro2::Literal as ::core::str::FromStr>::from_str(&formatted).unwrap_or_else( |err| ::core::panic!("cannot parse {} into a {} hex represented literal: {}", self, $name, err), ) ) } fn hex_suffixed(self) -> syn::Lit { - self.hex_impl_(&::std::format!("0x{:X}_{}", self, $name)) + self.hex_impl_(::core::format_args!("0x{:X}_{}", self, $name), private::Sealed) } fn hex_unsuffixed(self) -> syn::Lit { - self.hex_impl_(&::std::format!("0x{:X}", self)) + self.hex_impl_(::core::format_args!("0x{:X}", self), private::Sealed) } fn hex_padded_suffixed(self) -> syn::Lit { - self.hex_impl_(&::std::format!($fmt_suffixed, self, $name)) + self.hex_impl_(::core::format_args!($fmt_suffixed, self, $name), private::Sealed) } fn hex_padded_unsuffixed(self) -> syn::Lit { - self.hex_impl_(&::std::format!($fmt_unsuffixed, self)) + self.hex_impl_(::core::format_args!($fmt_unsuffixed, self), private::Sealed) } } )* From 65220590911080559073ed5d9abdcadcde9c93f4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 2 Sep 2021 20:37:41 +0200 Subject: [PATCH 080/493] add hex-literal expansion for usize and isize --- crates/lang/codegen/src/literal.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/lang/codegen/src/literal.rs b/crates/lang/codegen/src/literal.rs index 896645aa94..0d100d20bc 100644 --- a/crates/lang/codegen/src/literal.rs +++ b/crates/lang/codegen/src/literal.rs @@ -89,6 +89,21 @@ generate_hex_literal_impls!( (::core::primitive::i128, "i128", "0x{:032X}_{}", "0x{:032X}"), (::core::primitive::u128, "u128", "0x{:032X}_{}", "0x{:032X}"), ); +#[cfg(target_pointer_width = "16")] +generate_hex_literal_impls!( + (::core::primitive::usize , "usize", "0x{:04X}_{}", "0x{:04X}"), + (::core::primitive::isize , "isize", "0x{:04X}_{}", "0x{:04X}"), +); +#[cfg(target_pointer_width = "32")] +generate_hex_literal_impls!( + (::core::primitive::usize , "usize", "0x{:08X}_{}", "0x{:08X}"), + (::core::primitive::isize , "isize", "0x{:08X}_{}", "0x{:08X}"), +); +#[cfg(target_pointer_width = "64")] +generate_hex_literal_impls!( + (::core::primitive::usize , "usize", "0x{:16X}_{}", "0x{:16X}"), + (::core::primitive::isize , "isize", "0x{:16X}_{}", "0x{:16X}"), +); #[cfg(test)] mod tests { From d2408d6f33cfe7d65e0ccd840543bda14d74cf86 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 3 Sep 2021 18:44:30 +0200 Subject: [PATCH 081/493] improve codegen hygiene for dispatch code --- crates/lang/codegen/src/generator/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index ac937b7f04..bceac1ebce 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -672,7 +672,7 @@ impl Dispatch<'_> { impl ::scale::Decode for __ink_ConstructorDispatchEnum { fn decode(input: &mut I) -> ::core::result::Result { - match <[u8; 4] as ::scale::Decode>::decode(input)? { + match <[::core::primitive::u8; 4] as ::scale::Decode>::decode(input)? { #( #decode_message )* _invalid => Err(::scale::Error::from("encountered unknown ink! constructor selector")) } From 4bc450eb0da412dcd59cdbfe5524964b61497287 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 3 Sep 2021 18:45:09 +0200 Subject: [PATCH 082/493] move literal.rs into lang_ir crate --- crates/lang/codegen/src/lib.rs | 1 - crates/lang/ir/src/lib.rs | 1 + crates/lang/{codegen => ir}/src/literal.rs | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename crates/lang/{codegen => ir}/src/literal.rs (100%) diff --git a/crates/lang/codegen/src/lib.rs b/crates/lang/codegen/src/lib.rs index d6febdf99f..09a4bece29 100644 --- a/crates/lang/codegen/src/lib.rs +++ b/crates/lang/codegen/src/lib.rs @@ -14,7 +14,6 @@ mod generator; mod traits; -mod literal; use self::traits::{ GenerateCode, diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index 95409ef79b..ebd9e5c330 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -32,6 +32,7 @@ mod error; mod ast; mod ir; +mod literal; pub use self::ir::{ Callable, diff --git a/crates/lang/codegen/src/literal.rs b/crates/lang/ir/src/literal.rs similarity index 100% rename from crates/lang/codegen/src/literal.rs rename to crates/lang/ir/src/literal.rs From 6b5f44f9c7b21cb48e248e2fe51f30548cdc46cd Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 3 Sep 2021 18:45:23 +0200 Subject: [PATCH 083/493] add hex_lit utility method to Selector type --- crates/lang/ir/src/ir/selector.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 72ee9771f2..9c06179bbc 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -13,7 +13,7 @@ // limitations under the License. use super::blake2::blake2b_256; -use crate::Namespace; +use crate::{Namespace, literal::HexLiteral}; /// A function selector. /// @@ -130,6 +130,17 @@ impl Selector { pub fn unique_id(self) -> usize { u32::from_le_bytes(self.bytes) as usize } + + /// Returns the 4 bytes that make up the selector as hex encoded bytes. + pub fn hex_lits(self) -> [syn::Lit; 4] { + let selector_bytes = self.as_bytes(); + [ + selector_bytes[0].hex_padded_suffixed(), + selector_bytes[1].hex_padded_suffixed(), + selector_bytes[2].hex_padded_suffixed(), + selector_bytes[3].hex_padded_suffixed(), + ] + } } impl From<[u8; 4]> for Selector { From b1924673ffb10536b05ccfd072e3a9aece3355cd Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 3 Sep 2021 18:45:39 +0200 Subject: [PATCH 084/493] make use of Selector::hex_lit utility method in metadata codegen --- crates/lang/codegen/src/generator/metadata.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index a234632082..161428a932 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -139,7 +139,7 @@ impl Metadata<'_> { let attrs = constructor.attrs(); let docs = Self::extract_doc_comments(attrs); let selector = constructor.composed_selector(); - let selector_bytes = selector.as_bytes(); + let selector_bytes = selector.hex_lits(); let constructor = constructor.callable(); let ident = constructor.ident(); let ident_lit = ident.to_string(); @@ -231,7 +231,7 @@ impl Metadata<'_> { let attrs = message.attrs(); let docs = Self::extract_doc_comments(attrs); let selector = message.composed_selector(); - let selector_bytes = selector.as_bytes(); + let selector_bytes = selector.hex_lits(); let is_payable = message.is_payable(); let message = message.callable(); let mutates = message.receiver().is_ref_mut(); @@ -272,7 +272,7 @@ impl Metadata<'_> { match ret_ty { None => { quote! { - ::ink_metadata::ReturnTypeSpec::new(None) + ::ink_metadata::ReturnTypeSpec::new(::core::option::Option::None) } } Some(ty) => { From 5cbccdebf34ec0103979c3e4ae416a452fc82aae Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 3 Sep 2021 18:52:26 +0200 Subject: [PATCH 085/493] replace to_string calls with stringify! invocations --- crates/lang/codegen/src/generator/metadata.rs | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index 161428a932..a2ba456d13 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -142,17 +142,15 @@ impl Metadata<'_> { let selector_bytes = selector.hex_lits(); let constructor = constructor.callable(); let ident = constructor.ident(); - let ident_lit = ident.to_string(); let args = constructor .inputs() .map(|arg| Self::generate_message_param(arg)); let constr = match trait_ident { Some(trait_ident) => { - let trait_ident_lit = trait_ident.to_string(); - quote_spanned!(span => from_trait_and_name(#trait_ident_lit, #ident_lit)) + quote_spanned!(span => from_trait_and_name(::core::stringify!(#trait_ident), ::core::stringify!(#ident))) } None => { - quote_spanned!(span => from_name(#ident_lit)) + quote_spanned!(span => from_name(::core::stringify!(#ident))) } }; quote_spanned!(span => @@ -175,10 +173,9 @@ impl Metadata<'_> { syn::Pat::Ident(ident) => &ident.ident, _ => unreachable!("encountered unexpected non identifier in ink! parameter"), }; - let ident_lit = ident.to_string(); let type_spec = Self::generate_type_spec(&pat_type.ty); quote! { - ::ink_metadata::MessageParamSpec::new(#ident_lit) + ::ink_metadata::MessageParamSpec::new(::core::stringify!(#ident)) .of_type(#type_spec) .done() } @@ -236,18 +233,16 @@ impl Metadata<'_> { let message = message.callable(); let mutates = message.receiver().is_ref_mut(); let ident = message.ident(); - let ident_lit = ident.to_string(); let args = message .inputs() .map(|arg| Self::generate_message_param(arg)); let ret_ty = Self::generate_return_type(message.output()); let constr = match trait_ident { Some(trait_ident) => { - let trait_ident_lit = trait_ident.to_string(); - quote_spanned!(span => from_trait_and_name(#trait_ident_lit, #ident_lit)) + quote_spanned!(span => from_trait_and_name(::core::stringify!(#trait_ident), ::core::stringify!(#ident))) } None => { - quote_spanned!(span => from_name(#ident_lit)) + quote_spanned!(span => from_name(::core::stringify!(#ident))) } }; quote_spanned!(span => @@ -289,11 +284,10 @@ impl Metadata<'_> { self.contract.module().events().map(|event| { let span = event.span(); let ident = event.ident(); - let ident_lit = ident.to_string(); let docs = Self::extract_doc_comments(event.attrs()); let args = Self::generate_event_args(event); quote_spanned!(span => - ::ink_metadata::EventSpec::new(#ident_lit) + ::ink_metadata::EventSpec::new(::core::stringify!(#ident)) .args([ #( #args, )* ]) @@ -310,13 +304,12 @@ impl Metadata<'_> { event.fields().map(|event_field| { let span = event_field.span(); let ident = event_field.ident(); - let ident_lit = ident.map(ToString::to_string); let is_topic = event_field.is_topic; let attrs = event_field.attrs(); let docs = Self::extract_doc_comments(&attrs); let ty = Self::generate_type_spec(event_field.ty()); quote_spanned!(span => - ::ink_metadata::EventParamSpec::new(#ident_lit) + ::ink_metadata::EventParamSpec::new(::core::stringify!(#ident)) .of_type(#ty) .indexed(#is_topic) .docs([ From dd6e5f95f1a412799bb78beebf4eeb4480d85138 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 5 Sep 2021 13:50:26 +0200 Subject: [PATCH 086/493] implement minor simplifications in ink! codegen --- crates/lang/codegen/src/generator/dispatch.rs | 4 ++-- crates/lang/codegen/src/generator/ink_test.rs | 2 +- crates/lang/codegen/src/generator/item_impls.rs | 10 ++-------- crates/lang/codegen/src/generator/storage.rs | 11 +++++------ 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index bceac1ebce..499ad80f84 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -446,7 +446,7 @@ impl Dispatch<'_> { let variant_types = cws.callable().inputs().map(|arg| &arg.ty); quote! { [ #( #selector_bytes ),* ] => { - Ok(Self::#variant_ident( + ::core::result::Result::Ok(Self::#variant_ident( #( <#variant_types as ::scale::Decode>::decode(input)? ),* @@ -674,7 +674,7 @@ impl Dispatch<'_> { fn decode(input: &mut I) -> ::core::result::Result { match <[::core::primitive::u8; 4] as ::scale::Decode>::decode(input)? { #( #decode_message )* - _invalid => Err(::scale::Error::from("encountered unknown ink! constructor selector")) + _invalid => ::core::result::Result::Err(::scale::Error::from("encountered unknown ink! constructor selector")) } } } diff --git a/crates/lang/codegen/src/generator/ink_test.rs b/crates/lang/codegen/src/generator/ink_test.rs index 16fa2d0660..fd05b31712 100644 --- a/crates/lang/codegen/src/generator/ink_test.rs +++ b/crates/lang/codegen/src/generator/ink_test.rs @@ -50,7 +50,7 @@ impl GenerateCode for InkTest<'_> { let _: () = { #fn_block }; - Ok(()) + ::core::result::Result::Ok(()) } }) .expect(#expect_msg); diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 50911518a7..53c17cceaf 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -87,10 +87,7 @@ impl ItemImpls<'_> { ir::Visibility::Inherited => None, ir::Visibility::Public(vis_public) => Some(vis_public), }; - let receiver = match message.receiver() { - ir::Receiver::RefMut => quote! { &mut self }, - ir::Receiver::Ref => quote! { &self }, - }; + let receiver = message.receiver(); let ident = message.ident(); let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); let inputs = message.inputs(); @@ -188,10 +185,7 @@ impl ItemImpls<'_> { ir::Visibility::Inherited => None, ir::Visibility::Public(vis_public) => Some(vis_public), }; - let receiver = match message.receiver() { - ir::Receiver::RefMut => quote! { &mut self }, - ir::Receiver::Ref => quote! { &self }, - }; + let receiver = message.receiver(); let ident = message.ident(); let inputs = message.inputs(); let output_arrow = message.output().map(|_| quote! { -> }); diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index 6f3f4b0e6c..a0df601500 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -37,12 +37,11 @@ impl GenerateCode for Storage<'_> { let storage_span = self.contract.module().storage().span(); let access_env_impls = self.generate_access_env_trait_impls(); let storage_struct = self.generate_storage_struct(); - let use_emit_event = if self.contract.module().events().next().is_some() { - // Required to allow for `self.env().emit_event(..)` in messages and constructors. - Some(quote! { use ::ink_lang::EmitEvent as _; }) - } else { - None - }; + let use_emit_event = + self.contract.module().events().next().is_some().then(|| { + // Required to allow for `self.env().emit_event(..)` in messages and constructors. + quote! { use ::ink_lang::EmitEvent as _; } + }); let cfg = self.generate_code_using::(); quote_spanned!(storage_span => #access_env_impls From acba03f3a61a897a5dce5c515726a6af5a62f2be Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 5 Sep 2021 13:50:50 +0200 Subject: [PATCH 087/493] disable outdated cross_calling codegen --- crates/lang/codegen/src/generator/contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index adc95d066d..b1342c49c1 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -46,7 +46,7 @@ impl GenerateCode for Contract<'_> { let events = self.generate_code_using::(); let dispatch = self.generate_code_using::(); let item_impls = self.generate_code_using::(); - let cross_calling = self.generate_code_using::(); + // let cross_calling = self.generate_code_using::(); let metadata = self.generate_code_using::(); let call_builder = self.generate_code_using::(); let non_ink_items = self @@ -63,7 +63,7 @@ impl GenerateCode for Contract<'_> { #events #dispatch #item_impls - #cross_calling + // #cross_calling #call_builder #metadata #( #non_ink_items )* From 38ef960bf5e64bdc64e03b0eaeec1c4cf83d7518 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 5 Sep 2021 13:51:26 +0200 Subject: [PATCH 088/493] fix outdated impl item codegen to produce fewer compile errors This is only a temporary fix until the new codegen has been fully implemented. --- crates/lang/codegen/src/generator/item_impls.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 53c17cceaf..497d9258b9 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -66,7 +66,7 @@ impl ItemImpls<'_> { ir::Visibility::Public(vis_public) => Some(vis_public), }; let ident = constructor.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); let inputs = constructor.inputs(); let statements = constructor.statements(); quote_spanned!(span => @@ -89,7 +89,7 @@ impl ItemImpls<'_> { }; let receiver = message.receiver(); let ident = message.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); let inputs = message.inputs(); let output = message .output() From 3879417d14bcc31c00ccaacdc09d9f807eb6d5e0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 5 Sep 2021 13:53:37 +0200 Subject: [PATCH 089/493] apply clippy suggestions --- crates/lang/ir/src/ir/selector.rs | 2 +- crates/lang/ir/src/ir/trait_def/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 9c06179bbc..5a0b901e03 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -54,7 +54,7 @@ impl<'a> TraitPrefix<'a> { /// Returns a shared reference to the Rust identifier of the trait. pub fn trait_ident(&self) -> &'a syn::Ident { - &self.trait_ident + self.trait_ident } } diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index cc606a7e4b..c04a07a61e 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -477,7 +477,7 @@ impl InkTrait { .as_ref() .map(InkAttribute::namespace) .flatten() - .unwrap_or_else(Default::default); + .unwrap_or_default(); let ident = &item_trait.ident; let trait_prefix = TraitPrefix::new(ident, &namespace); for callable in IterInkTraitItemsRaw::from_raw(item_trait) { From 4fa0467f0fb867bd2db33cb8c5861679edc96b24 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 6 Sep 2021 23:08:13 +0200 Subject: [PATCH 090/493] update parity-scale-codec version 2.1 -> 2.2 --- crates/lang/Cargo.toml | 2 +- crates/lang/codegen/Cargo.toml | 2 +- crates/lang/macro/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index d9195981a0..7be59d1597 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -22,7 +22,7 @@ ink_metadata = { version = "3.0.0-rc4", path = "../metadata", default-features = ink_prelude = { version = "3.0.0-rc4", path = "../prelude", default-features = false } ink_lang_macro = { version = "3.0.0-rc4", path = "macro", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2.2", default-features = false, features = ["derive", "full"] } derive_more = { version = "0.99", default-features = false, features = ["from"] } static_assertions = "1.1" diff --git a/crates/lang/codegen/Cargo.toml b/crates/lang/codegen/Cargo.toml index 6a009cb164..0ba6e85b37 100644 --- a/crates/lang/codegen/Cargo.toml +++ b/crates/lang/codegen/Cargo.toml @@ -28,7 +28,7 @@ either = { version = "1.5", default-features = false } regex = "1.3" blake2 = "0.9" heck = "0.3.1" -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2.2", default-features = false, features = ["derive", "full"] } impl-serde = "0.3.1" [features] diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index b551e3bbd5..f62d6bcb0f 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -19,7 +19,7 @@ ink_lang_ir = { version = "3.0.0-rc4", path = "../ir", default-features = false ink_lang_codegen = { version = "3.0.0-rc4", path = "../codegen", default-features = false } ink_primitives = { version = "3.0.0-rc4", path = "../../primitives/", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2.2", default-features = false, features = ["derive"] } syn = "1" proc-macro2 = "1" From e289d28947b83f18febe87326b70356cbcd620fb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 6 Sep 2021 23:33:50 +0200 Subject: [PATCH 091/493] use hex-lits where possible in dispatch codegen --- crates/lang/codegen/src/generator/dispatch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 499ad80f84..90b18a20ba 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -196,7 +196,7 @@ impl Dispatch<'_> { let callable = cws.callable(); let callable_span = callable.span(); let selector = cws.composed_selector(); - let (selector_bytes, selector_id) = (selector.as_bytes(), selector.unique_id()); + let (selector_bytes, selector_id) = (selector.hex_lits(), selector.unique_id()); let input_types = callable .inputs() .map(|pat_type| &pat_type.ty) @@ -441,7 +441,7 @@ impl Dispatch<'_> { where C: ir::Callable, { - let selector_bytes = cws.composed_selector().as_bytes().to_owned(); + let selector_bytes = cws.composed_selector().hex_lits(); let variant_ident = self.generate_dispatch_variant_ident(cws); let variant_types = cws.callable().inputs().map(|arg| &arg.ty); quote! { From 3738bb5f99e73d9ac827a57a319d47e05702a6a8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 6 Sep 2021 23:34:21 +0200 Subject: [PATCH 092/493] improve macro hygiene in dispatch codegen --- crates/lang/codegen/src/generator/dispatch.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 90b18a20ba..252d066b8f 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -579,9 +579,13 @@ impl Dispatch<'_> { impl ::scale::Decode for __ink_MessageDispatchEnum { fn decode(input: &mut I) -> ::core::result::Result { - match <[u8; 4] as ::scale::Decode>::decode(input)? { + match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { #( #decode_message )* - _invalid => Err(::scale::Error::from("encountered unknown ink! message selector")) + _invalid => ::core::result::Result::Err( + <::scale::Error as ::core::convert::From<'static ::core::primtive::str>>::from( + "encountered unknown ink! message selector" + ) + ) } } } @@ -672,9 +676,13 @@ impl Dispatch<'_> { impl ::scale::Decode for __ink_ConstructorDispatchEnum { fn decode(input: &mut I) -> ::core::result::Result { - match <[::core::primitive::u8; 4] as ::scale::Decode>::decode(input)? { + match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { #( #decode_message )* - _invalid => ::core::result::Result::Err(::scale::Error::from("encountered unknown ink! constructor selector")) + _invalid => ::core::result::Result::Err( + <::scale::Error as ::core::convert::From<&'static ::core::primtive::str>>::from( + "encountered unknown ink! constructor selector" + ) + ) } } } From af3fac6e21bb85326f92f7515d3c1ef605460745 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 6 Sep 2021 23:53:38 +0200 Subject: [PATCH 093/493] re-enable cross-calling codegen partially --- crates/lang/codegen/src/generator/contract.rs | 4 ++-- crates/lang/codegen/src/generator/cross_calling.rs | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index b1342c49c1..adc95d066d 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -46,7 +46,7 @@ impl GenerateCode for Contract<'_> { let events = self.generate_code_using::(); let dispatch = self.generate_code_using::(); let item_impls = self.generate_code_using::(); - // let cross_calling = self.generate_code_using::(); + let cross_calling = self.generate_code_using::(); let metadata = self.generate_code_using::(); let call_builder = self.generate_code_using::(); let non_ink_items = self @@ -63,7 +63,7 @@ impl GenerateCode for Contract<'_> { #events #dispatch #item_impls - // #cross_calling + #cross_calling #call_builder #metadata #( #non_ink_items )* diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index 81499ce9cc..cd865e59d0 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -45,12 +45,12 @@ impl GenerateCode for CrossCalling<'_> { fn generate_code(&self) -> TokenStream2 { let storage = self.generate_storage(); let standard_impls = self.generate_standard_impls(); - let call_forwarder = self.generate_call_forwarders(); + // let call_forwarder = self.generate_call_forwarders(); let impl_blocks = self.generate_impl_blocks(); quote! { #storage #standard_impls - #call_forwarder + // #call_forwarder #impl_blocks } } @@ -150,9 +150,9 @@ impl CrossCalling<'_> { ) } - /// Returns the identifier for the generated `Out*` assoc. type. + /// Returns the identifier for the generated `Output*` assoc. type. fn out_assoc_type_ident(method_ident: &Ident) -> syn::Ident { - format_ident!("{}Out", method_ident.to_string().to_camel_case()) + format_ident!("{}Output", method_ident.to_string().to_camel_case()) } fn generate_call_forwarder_trait_ghost_message( @@ -305,7 +305,7 @@ impl CrossCalling<'_> { let span = constructor.span(); let attrs = constructor.attrs(); let ident = constructor.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); let composed_selector = constructor.composed_selector().as_bytes().to_owned(); let trait_ident = constructor .item_impl() @@ -552,7 +552,7 @@ impl CrossCalling<'_> { let storage_ident_str = self.contract.module().storage().ident().to_string(); let span = message.span(); let ident = message.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); let ident_str = ident.to_string(); let trait_path = message .item_impl() @@ -610,7 +610,7 @@ impl CrossCalling<'_> { let span = constructor.span(); let attrs = constructor.attrs(); let ident = constructor.ident(); - let output_ident = format_ident!("{}Out", ident.to_string().to_camel_case()); + let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); let composed_selector = constructor.composed_selector().as_bytes().to_owned(); let input_bindings = constructor .inputs() From 7a1e4e65029c6433035a88476dc923daf6eb412d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 10:47:43 +0200 Subject: [PATCH 094/493] silence some warnings of deprecated code that is still enabled --- crates/lang/codegen/src/generator/cross_calling.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index cd865e59d0..0ee3c8502b 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![allow(dead_code)] + use super::enforced_error::EnforcedErrors; use crate::{ generator, From 9af39225e870b93947d95007b8976abf3d042382 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 10:59:48 +0200 Subject: [PATCH 095/493] improve macro codegen hygiene --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 29e9ac6fb9..a42a20e25c 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -290,7 +290,7 @@ impl CallBuilder<'_> { { #[inline] fn to_account_id(&self) -> ::AccountId { - self.account_id.clone() + <::AccountId as ::core::clone::Clone>::clone(&self.account_id) } } ) From bf0acf9aefbdf3f56615e90b848a73adc9557e24 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 11:00:24 +0200 Subject: [PATCH 096/493] simplify macro codegen using stringify! macro --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 3 +-- crates/lang/codegen/src/generator/trait_def/call_forwarder.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index a42a20e25c..5580e11d13 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -232,7 +232,6 @@ impl CallBuilder<'_> { fn generate_auxiliary_trait_impls(&self) -> TokenStream2 { let span = self.span(); let call_builder_ident = self.ident(); - let call_builder_name = call_builder_ident.to_string(); quote_spanned!(span=> /// We require this manual impl since the derive produces incorrect trait bounds. impl ::core::clone::Clone for #call_builder_ident @@ -255,7 +254,7 @@ impl CallBuilder<'_> { ::AccountId: ::core::fmt::Debug, { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - f.debug_struct(#call_builder_name) + f.debug_struct(::core::stringify!(#call_builder_ident)) .field("account_id", &self.account_id) .finish() } diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 52a7080dfb..663949e7aa 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -228,7 +228,6 @@ impl CallForwarder<'_> { fn generate_auxiliary_trait_impls(&self) -> TokenStream2 { let span = self.span(); let call_forwarder_ident = self.ident(); - let call_forwarder_name = call_forwarder_ident.to_string(); quote_spanned!(span=> impl ::core::clone::Clone for #call_forwarder_ident where @@ -250,7 +249,7 @@ impl CallForwarder<'_> { ::AccountId: ::core::fmt::Debug, { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - f.debug_struct(#call_forwarder_name) + f.debug_struct(::core::stringify!(#call_forwarder_ident)) .field("account_id", &self.builder.account_id) .finish() } From 09d608bdcce1f6faf8a10001ceb403b9818850b5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 12:16:35 +0200 Subject: [PATCH 097/493] add SAFETY comment for codegen of unsafe impl --- crates/lang/codegen/src/generator/call_builder.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index ed7107c364..7f576b5b13 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -244,6 +244,11 @@ impl CallBuilder<'_> { let span = impl_block.span(); let unique_trait_id = self.generate_unique_trait_id(trait_path); quote_spanned!(span=> + // SAFETY: + // + // The trait is unsafe to implement in order to prevent users doing a manual + // implementation themselves. Generally it is safe to implement only by the ink! + // provided macros with correct unique trait ID. #[doc(hidden)] unsafe impl ::ink_lang::TraitImplementer<#unique_trait_id> for CallBuilder From d3bfa8677292bd3a48c71f58b31c0c41aca64474 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 12:18:15 +0200 Subject: [PATCH 098/493] simplify codegen implementation slightly --- .../codegen/src/generator/cross_calling.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index 0ee3c8502b..c670151a75 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -588,10 +588,11 @@ impl CrossCalling<'_> { ir::Receiver::Ref => None, ir::Receiver::RefMut => Some(quote! { mut }), }; - let opt_pub = match message.item_impl().trait_path() { - None => Some(quote! { pub }), - Some(_) => None, - }; + let opt_pub = message + .item_impl() + .trait_path() + .is_none() + .then(|| quote! { pub }); quote_spanned!(span => type #output_ident = #output_ty; @@ -782,10 +783,11 @@ impl CrossCalling<'_> { ir::Receiver::Ref => None, ir::Receiver::RefMut => Some(quote! { mut }), }; - let opt_pub = match message.item_impl().trait_path() { - None => Some(quote! { pub }), - Some(_) => None, - }; + let opt_pub = message + .item_impl() + .trait_path() + .is_none() + .then(|| quote! { pub }); quote_spanned!(span => #[inline] #opt_pub fn #ident( #receiver #(, #inputs_sig )* ) #output_sig { From 72bda5da56b84f4974bd179547d852bdcc522226 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 12:18:51 +0200 Subject: [PATCH 099/493] fix minor macro hygiene issue --- crates/lang/codegen/src/generator/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 252d066b8f..e99c8ef60f 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -120,7 +120,7 @@ impl Dispatch<'_> { #[allow(unused_parens)] fn dispatch_using_mode( mode: ::ink_lang::DispatchMode - ) -> core::result::Result<(), ::ink_lang::DispatchError> { + ) -> ::core::result::Result<(), ::ink_lang::DispatchError> { match mode { ::ink_lang::DispatchMode::Instantiate => { <<#storage_ident as ::ink_lang::ConstructorDispatcher>::Type as ::ink_lang::Execute>::execute( From e98fc1853dae1ab22959aabf6e090cf44a0f1638 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 12:19:26 +0200 Subject: [PATCH 100/493] use hex formatted integer literals where possible in codegen --- .../codegen/src/generator/cross_calling.rs | 8 +-- crates/lang/codegen/src/generator/dispatch.rs | 51 +++++++++---------- .../src/generator/trait_def/call_builder.rs | 2 +- .../src/generator/trait_def/trait_registry.rs | 3 +- crates/lang/ir/src/ir/selector.rs | 7 ++- crates/lang/ir/src/lib.rs | 1 + 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index c670151a75..9ce9b4421d 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -222,7 +222,7 @@ impl CrossCalling<'_> { let span = message.span(); let ident = message.ident(); let output_ident = Self::out_assoc_type_ident(ident); - let composed_selector = message.composed_selector().as_bytes().to_owned(); + let composed_selector = message.composed_selector().hex_lits(); let attrs = message.attrs(); let input_bindings = message .inputs() @@ -409,7 +409,7 @@ impl CrossCalling<'_> { ) -> TokenStream2 { let span = message.span(); let ident = message.ident(); - let composed_selector = message.composed_selector().as_bytes().to_owned(); + let composed_selector = message.composed_selector().hex_lits(); let attrs = message.attrs(); let input_bindings = message .inputs() @@ -614,7 +614,7 @@ impl CrossCalling<'_> { let attrs = constructor.attrs(); let ident = constructor.ident(); let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); - let composed_selector = constructor.composed_selector().as_bytes().to_owned(); + let composed_selector = constructor.composed_selector().hex_lits(); let input_bindings = constructor .inputs() .enumerate() @@ -715,7 +715,7 @@ impl CrossCalling<'_> { let span = constructor.span(); let attrs = constructor.attrs(); let ident = constructor.ident(); - let composed_selector = constructor.composed_selector().as_bytes().to_owned(); + let composed_selector = constructor.composed_selector().hex_lits(); let input_bindings = constructor .inputs() .enumerate() diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index e99c8ef60f..b680326fb3 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -18,7 +18,10 @@ use crate::{ GenerateCodeUsing as _, }; use derive_more::From; -use ir::Callable as _; +use ir::{ + Callable as _, + HexLiteral as _, +}; use proc_macro2::{ Ident, TokenStream as TokenStream2, @@ -143,8 +146,8 @@ impl Dispatch<'_> { /// Returns the generated ink! namespace identifier for the given callable kind. fn dispatch_trait_impl_namespace(kind: ir::CallableKind) -> Ident { match kind { - ir::CallableKind::Constructor => format_ident!("__ink_Constr"), - ir::CallableKind::Message => format_ident!("__ink_Msg"), + ir::CallableKind::Constructor => format_ident!("__ink_ConstructorInfo"), + ir::CallableKind::Message => format_ident!("__ink_MessageInfo"), } } @@ -165,10 +168,7 @@ impl Dispatch<'_> { // where `N` is the unique identifier of the associated message // selector. #[doc(hidden)] - pub struct #message_namespace { - // We need to wrap inner because of Rust's orphan rules. - marker: core::marker::PhantomData S>, - } + pub struct #message_namespace {} // Namespace for constructors. // @@ -178,10 +178,7 @@ impl Dispatch<'_> { // where `N` is the unique identifier of the associated constructor // selector. #[doc(hidden)] - pub struct #constructor_namespace { - // We need to wrap inner because of Rust's orphan rules. - marker: core::marker::PhantomData S>, - } + pub struct #constructor_namespace {} } } @@ -196,7 +193,7 @@ impl Dispatch<'_> { let callable = cws.callable(); let callable_span = callable.span(); let selector = cws.composed_selector(); - let (selector_bytes, selector_id) = (selector.hex_lits(), selector.unique_id()); + let (selector_bytes, selector_id) = (selector.hex_lits(), selector.into_be_u32().hex_padded_suffixed()); let input_types = callable .inputs() .map(|pat_type| &pat_type.ty) @@ -212,19 +209,19 @@ impl Dispatch<'_> { quote! { #( #input_types )* } }; let fn_input_impl = quote_spanned!(callable.inputs_span() => - impl ::ink_lang::FnInput for #namespace<[(); #selector_id]> { + impl ::ink_lang::FnInput for #namespace::<#selector_id> { type Input = #input_types_tuple; } ); let fn_selector_impl = quote_spanned!(callable_span => - impl ::ink_lang::FnSelector for #namespace<[(); #selector_id]> { + impl ::ink_lang::FnSelector for #namespace::<#selector_id> { const SELECTOR: ::ink_env::call::Selector = ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]); } ); let fn_state_impl = quote_spanned!(callable_span => - impl ::ink_lang::FnState for #namespace<[(); #selector_id]> { + impl ::ink_lang::FnState for #namespace::<#selector_id> { type State = #storage_ident; } ); @@ -296,7 +293,7 @@ impl Dispatch<'_> { let message = cws.callable(); let message_span = message.span(); let selector = cws.composed_selector(); - let selector_id = selector.unique_id(); + let selector_id = selector.into_be_u32().hex_padded_suffixed(); let output_tokens = message .output() .map(quote::ToTokens::to_token_stream) @@ -306,7 +303,7 @@ impl Dispatch<'_> { let message_ident = message.ident(); let namespace = Self::dispatch_trait_impl_namespace(ir::CallableKind::Message); let fn_output_impl = quote_spanned!(message.output().span() => - impl ::ink_lang::FnOutput for #namespace<[(); #selector_id]> { + impl ::ink_lang::FnOutput for #namespace::<#selector_id> { #[allow(unused_parens)] type Output = #output_tokens; } @@ -328,7 +325,7 @@ impl Dispatch<'_> { ) }); let message_impl = quote_spanned!(message_span => - impl ::ink_lang::#message_trait_ident for #namespace<[(); #selector_id]> { + impl ::ink_lang::#message_trait_ident for #namespace::<#selector_id> { const CALLABLE: fn( &#mut_token ::State, ::Input @@ -352,7 +349,7 @@ impl Dispatch<'_> { let constructor = cws.callable(); let constructor_span = constructor.span(); let selector = cws.composed_selector(); - let selector_id = selector.unique_id(); + let selector_id = selector.into_be_u32().hex_padded_suffixed(); let storage_ident = self.contract.module().storage().ident(); let constructor_ident = constructor.ident(); let namespace = @@ -366,7 +363,7 @@ impl Dispatch<'_> { ) }); let constructor_impl = quote_spanned!(constructor_span => - impl ::ink_lang::Constructor for #namespace<[(); #selector_id]> { + impl ::ink_lang::Constructor for #namespace::<#selector_id> { const CALLABLE: fn( ::Input ) -> ::State = |#inputs_as_tuple_or_wildcard| { @@ -419,7 +416,7 @@ impl Dispatch<'_> { ir::CallableKind::Constructor => "Constructor", }; quote::format_ident!( - "__ink_{}_0x{:02x}{:02x}{:02x}{:02x}", + "__ink_{}_0x{:02X}{:02X}{:02X}{:02X}", prefix, selector_bytes[0], selector_bytes[1], @@ -519,7 +516,7 @@ impl Dispatch<'_> { (None, quote! { MessageRef }, quote! { execute_message }) } }; - let selector_id = cws.composed_selector().unique_id(); + let selector_id = cws.composed_selector().into_be_u32().hex_padded_suffixed(); let namespace = Self::dispatch_trait_impl_namespace(ir::CallableKind::Message); // If all ink! messages deny payment we can move the payment check to before // the message dispatch which is more efficient. @@ -530,11 +527,11 @@ impl Dispatch<'_> { .is_dynamic_storage_allocator_enabled(); quote! { Self::#ident(#(#arg_pats),*) => { - ::ink_lang::#exec_fn::<<#storage_ident as ::ink_lang::ContractEnv>::Env, #namespace<[(); #selector_id]>, _>( + ::ink_lang::#exec_fn::<<#storage_ident as ::ink_lang::ContractEnv>::Env, #namespace::<#selector_id>, _>( ::ink_lang::AcceptsPayments(#accepts_payments), ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), move |state: &#mut_mod #storage_ident| { - <#namespace<[(); #selector_id]> as ::ink_lang::#msg_trait>::CALLABLE( + <#namespace::<#selector_id> as ::ink_lang::#msg_trait>::CALLABLE( state, #arg_inputs ) } @@ -619,7 +616,7 @@ impl Dispatch<'_> { } else { quote! { ( #(#arg_pats),* ) } }; - let selector_id = cws.composed_selector().unique_id(); + let selector_id = cws.composed_selector().into_be_u32().hex_padded_suffixed(); let namespace = Self::dispatch_trait_impl_namespace(ir::CallableKind::Constructor); let is_dynamic_storage_allocation_enabled = self @@ -628,10 +625,10 @@ impl Dispatch<'_> { .is_dynamic_storage_allocator_enabled(); quote! { Self::#ident(#(#arg_pats),*) => { - ::ink_lang::execute_constructor::<#namespace<[(); #selector_id]>, _>( + ::ink_lang::execute_constructor::<#namespace::<#selector_id>, _>( ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), move || { - <#namespace<[(); #selector_id]> as ::ink_lang::Constructor>::CALLABLE( + <#namespace::<#selector_id> as ::ink_lang::Constructor>::CALLABLE( #arg_inputs ) } diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 5580e11d13..d487e4d9e7 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -364,7 +364,7 @@ impl CallBuilder<'_> { || quote! { () }, |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, ); - let selector_bytes = selector.as_bytes(); + let selector_bytes = selector.hex_lits(); let input_bindings = Self::input_bindings(message.inputs()); let input_types = Self::input_types(message.inputs()); let arg_list = Self::generate_argument_list_for(input_types.iter().cloned()); diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 4568fba1f8..aa6215b258 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -25,6 +25,7 @@ use crate::{ traits::GenerateCode, }; use derive_more::From; +use ir::HexLiteral; use proc_macro2::{ Span, TokenStream as TokenStream2, @@ -200,7 +201,7 @@ impl TraitRegistry<'_> { fn generate_trait_info_object(&self) -> TokenStream2 { let span = self.span(); let trait_ident = self.trait_ident(); - let unique_id = self.trait_def.trait_def.unique_id(); + let unique_id = self.trait_def.trait_def.unique_id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let trait_call_forwarder = self.trait_def.call_forwarder_ident(); quote_spanned!(span => diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 5a0b901e03..49a5efe10f 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -128,7 +128,12 @@ impl Selector { /// Returns a unique identifier as `usize`. pub fn unique_id(self) -> usize { - u32::from_le_bytes(self.bytes) as usize + self.into_be_u32() as usize + } + + /// Returns the big-endian `u32` representation of the selector bytes. + pub fn into_be_u32(self) -> u32 { + u32::from_be_bytes(self.bytes) } /// Returns the 4 bytes that make up the selector as hex encoded bytes. diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index ebd9e5c330..b613e91f34 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -34,6 +34,7 @@ mod ast; mod ir; mod literal; +pub use self::literal::HexLiteral; pub use self::ir::{ Callable, CallableKind, From dc22700705df8da6c18a4df14370476620bd7c60 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 12:31:39 +0200 Subject: [PATCH 101/493] fix minor core path codegen bug --- crates/lang/codegen/src/generator/dispatch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index b680326fb3..b565076e51 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -579,7 +579,7 @@ impl Dispatch<'_> { match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { #( #decode_message )* _invalid => ::core::result::Result::Err( - <::scale::Error as ::core::convert::From<'static ::core::primtive::str>>::from( + <::scale::Error as ::core::convert::From<'static ::core::primitive::str>>::from( "encountered unknown ink! message selector" ) ) @@ -676,7 +676,7 @@ impl Dispatch<'_> { match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { #( #decode_message )* _invalid => ::core::result::Result::Err( - <::scale::Error as ::core::convert::From<&'static ::core::primtive::str>>::from( + <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( "encountered unknown ink! constructor selector" ) ) From a0f1cad3c75d1f0d66564a08846af211478b287f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 14:19:30 +0200 Subject: [PATCH 102/493] fix warning for unneeded extern #[no_mangle] fn --- crates/lang/codegen/src/generator/trait_def/trait_registry.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index aa6215b258..6e32a56628 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -169,7 +169,6 @@ impl TraitRegistry<'_> { /// We enforce linking errors in case this is ever actually called. /// These linker errors are properly resolved by the cargo-contract tool. extern "C" { - #[no_mangle] fn #linker_error_ident() -> !; } unsafe { #linker_error_ident() } From fd28b60e1b9375b15cf99b28f5f8371fd6f8ff03 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 15:24:45 +0200 Subject: [PATCH 103/493] generate hex encoded integer identifiers in more places in codegen --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 3 ++- .../lang/codegen/src/generator/trait_def/call_forwarder.rs | 3 ++- crates/lang/codegen/src/generator/trait_def/definition.rs | 5 ++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index d487e4d9e7..244abaecf4 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -15,6 +15,7 @@ use super::TraitDefinition; use crate::traits::GenerateCode; use derive_more::From; +use ir::HexLiteral; use proc_macro2::{ Span, TokenStream as TokenStream2, @@ -307,7 +308,7 @@ impl CallBuilder<'_> { fn generate_ink_trait_impl(&self) -> TokenStream2 { let span = self.trait_def.span(); let trait_ident = self.trait_def.trait_def.ident(); - let trait_uid = self.trait_def.trait_def.unique_id(); + let trait_uid = self.trait_def.trait_def.unique_id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let builder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 663949e7aa..e617ede6c3 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -15,6 +15,7 @@ use super::TraitDefinition; use crate::traits::GenerateCode; use derive_more::From; +use ir::HexLiteral; use proc_macro2::{ Span, TokenStream as TokenStream2, @@ -336,7 +337,7 @@ impl CallForwarder<'_> { fn generate_ink_trait_impl(&self) -> TokenStream2 { let span = self.trait_def.span(); let trait_ident = self.trait_def.trait_def.ident(); - let trait_uid = self.trait_def.trait_def.unique_id(); + let trait_uid = self.trait_def.trait_def.unique_id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let forwarder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 45b8be3305..7be8a962b7 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -16,6 +16,7 @@ use super::TraitDefinition; use heck::CamelCase as _; +use ir::HexLiteral; use proc_macro2::TokenStream as TokenStream2; use quote::{ format_ident, @@ -49,10 +50,8 @@ impl TraitDefinition<'_> { pub(super) fn generate_trait_definition(&self) -> TokenStream2 { let span = self.trait_def.span(); let attrs = self.trait_def.attrs(); - let hash = self.trait_def.verify_hash(); let ident = self.trait_def.ident(); - let unique_trait_id = - u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; + let unique_trait_id = self.trait_def.unique_id().hex_padded_suffixed(); let messages = self .trait_def .iter_items() From 16f9c30efbce98a9d258cbd75e856a8430f8967c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 15:25:04 +0200 Subject: [PATCH 104/493] disable outdated cross-calling codegen impl blocks --- crates/lang/codegen/src/generator/cross_calling.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs index 9ce9b4421d..8efffbc833 100644 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ b/crates/lang/codegen/src/generator/cross_calling.rs @@ -48,12 +48,12 @@ impl GenerateCode for CrossCalling<'_> { let storage = self.generate_storage(); let standard_impls = self.generate_standard_impls(); // let call_forwarder = self.generate_call_forwarders(); - let impl_blocks = self.generate_impl_blocks(); + // let impl_blocks = self.generate_impl_blocks(); quote! { #storage #standard_impls // #call_forwarder - #impl_blocks + // #impl_blocks } } } From 788a2ef610f0181823f2ce8eb62baf9b9b82fd54 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 16:07:53 +0200 Subject: [PATCH 105/493] remove Flip::new trait definition constructor The new dynamic impl calling infrastructure no longer supports constructors. --- examples/trait-flipper/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/examples/trait-flipper/lib.rs b/examples/trait-flipper/lib.rs index 8bc0347b30..7576ff1ee1 100644 --- a/examples/trait-flipper/lib.rs +++ b/examples/trait-flipper/lib.rs @@ -4,10 +4,6 @@ use ink_lang as ink; #[ink::trait_definition] pub trait Flip { - /// Creates a new flipper smart contract initialized with the given value. - #[ink(constructor)] - fn new(init_value: bool) -> Self; - /// Flips the current value of the Flipper's boolean. #[ink(message)] fn flip(&mut self); @@ -35,11 +31,6 @@ pub mod flipper { } impl Flip for Flipper { - #[ink(constructor)] - fn new(init_value: bool) -> Self { - Self { value: init_value } - } - #[ink(message)] fn flip(&mut self) { self.value = !self.value; From 45af41a2df2f4d927ccaf5c2b8fad63d8ea29803 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 16:08:58 +0200 Subject: [PATCH 106/493] fix trait flipper default constructor --- examples/trait-flipper/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/trait-flipper/lib.rs b/examples/trait-flipper/lib.rs index 7576ff1ee1..dd1c0b5f91 100644 --- a/examples/trait-flipper/lib.rs +++ b/examples/trait-flipper/lib.rs @@ -26,7 +26,7 @@ pub mod flipper { /// Creates a new flipper smart contract initialized to `false`. #[ink(constructor)] pub fn default() -> Self { - Self::new(Default::default()) + Self { value: Default::default() } } } From 46e122be8c95f2cba86631b214cec7e7c3b637d8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 21:46:26 +0200 Subject: [PATCH 107/493] fix codegen error with missing & --- crates/lang/codegen/src/generator/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index b565076e51..67e3908bb4 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -579,7 +579,7 @@ impl Dispatch<'_> { match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { #( #decode_message )* _invalid => ::core::result::Result::Err( - <::scale::Error as ::core::convert::From<'static ::core::primitive::str>>::from( + <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( "encountered unknown ink! message selector" ) ) From cc2abe0b8b29f3ea31dee45cdd0f52f2cb168237 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 22:07:23 +0200 Subject: [PATCH 108/493] remove superflous comma from new call_builder codegen --- crates/lang/codegen/src/generator/call_builder.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 7f576b5b13..6c8ab07ddf 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -210,18 +210,15 @@ impl CallBuilder<'_> { } #[inline(always)] - fn build( - &self, - ) -> &::Builder { + fn build(&self) -> &::Builder { <_ as ::ink_lang::TraitCallBuilder>::call( >::forward(self) ) } #[inline(always)] - fn build_mut( - &mut self, - ) -> &mut ::Builder + fn build_mut(&mut self) + -> &mut ::Builder { <_ as ::ink_lang::TraitCallBuilder>::call_mut( >::forward_mut(self) From fa19f0f109f3fa246cfe22afb435274d63012f9f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 7 Sep 2021 23:09:10 +0200 Subject: [PATCH 109/493] fix bug in new call_builder codegen (build_cmd) --- crates/lang/codegen/src/generator/call_builder.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 6c8ab07ddf..df9e086190 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -318,6 +318,10 @@ impl CallBuilder<'_> { .receiver() .is_ref_mut() .then(|| Some(quote! { mut })); + let build_cmd = match message.receiver() { + ir::Receiver::Ref => quote! { build }, + ir::Receiver::RefMut => quote! { build_mut }, + }; let attrs = message.attrs(); quote_spanned!(span=> type #output_ident = <<< @@ -333,7 +337,7 @@ impl CallBuilder<'_> { #( , #input_bindings: #input_types )* ) -> Self::#output_ident { <_ as #trait_path>::#message_ident( - >::build_mut(self) + >::#build_cmd(self) #( , #input_bindings )* ) } From 44613b874cab2c23916f2573ec5d3591ff128e57 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 8 Sep 2021 12:21:27 +0200 Subject: [PATCH 110/493] improve macro hygiene in storage codegen --- crates/lang/codegen/src/generator/storage.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index a0df601500..11007eee9a 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -72,7 +72,7 @@ impl Storage<'_> { type EnvAccess = ::ink_lang::EnvAccess<'a, <#storage_ident as ::ink_lang::ContractEnv>::Env>; fn env(self) -> Self::EnvAccess { - Default::default() + ::default() } } @@ -80,7 +80,7 @@ impl Storage<'_> { type EnvAccess = ::ink_lang::EnvAccess<'static, <#storage_ident as ::ink_lang::ContractEnv>::Env>; fn env() -> Self::EnvAccess { - Default::default() + ::default() } } }; From bc7b1a219781f3d08affccb902e6813aa90548a2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 18:57:32 +0200 Subject: [PATCH 111/493] improve span of contract trait impls that forward to call forwarder --- crates/lang/codegen/src/generator/call_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index df9e086190..b8d0c2f716 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -379,7 +379,7 @@ impl CallBuilder<'_> { trait_path: &syn::Path, impl_block: &ir::ItemImpl, ) -> TokenStream2 { - let span = self.contract.module().storage().span(); + let span = impl_block.span(); let unique_trait_id = self.generate_unique_trait_id(trait_path); let storage_ident = self.contract.module().storage().ident(); let messages = self.generate_contract_trait_impl_messages(trait_path, impl_block); From 9a03418d5abf19414e9db5194c8384a6dfdca556 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 18:58:46 +0200 Subject: [PATCH 112/493] move CallBuilder ident generation into a function This allows to more easily refactor the call builder ident later. --- .../codegen/src/generator/call_builder.rs | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index b8d0c2f716..0c49571cbb 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -59,8 +59,21 @@ impl GenerateCode for CallBuilder<'_> { } impl CallBuilder<'_> { + /// Returns the identifier of the generated ink! call builder struct. + /// + /// # Note + /// + /// This identifier must not be used outside of the generated `const` + /// block in which the call builder type is going to be defined. + /// In order to refer to the call builder of an ink! smart contract + /// use the [`ink_lang::TraitCallBuilder`] trait implementation. + fn call_builder_ident() -> syn::Ident { + format_ident!("CallBuilder") + } + fn generate_struct(&self) -> TokenStream2 { let span = self.contract.module().storage().span(); + let cb_ident = Self::call_builder_ident(); quote_spanned!(span=> /// The ink! smart contract's call builder. /// @@ -77,7 +90,7 @@ impl CallBuilder<'_> { ::ink_storage::traits::SpreadLayout, ::ink_storage::traits::PackedLayout, )] - pub struct CallBuilder { + pub struct #cb_ident { account_id: AccountId, } ) @@ -113,15 +126,16 @@ impl CallBuilder<'_> { /// These are required to properly interoperate with the call builder. fn generate_auxiliary_trait_impls(&self) -> TokenStream2 { let span = self.contract.module().storage().span(); + let cb_ident = Self::call_builder_ident(); quote_spanned!(span=> - impl ::ink_env::call::FromAccountId for CallBuilder { + impl ::ink_env::call::FromAccountId for #cb_ident { #[inline] fn from_account_id(account_id: AccountId) -> Self { Self { account_id } } } - impl ::ink_lang::ToAccountId for CallBuilder { + impl ::ink_lang::ToAccountId for #cb_ident { #[inline] fn to_account_id(&self) -> AccountId { ::clone(&self.account_id) @@ -177,10 +191,11 @@ impl CallBuilder<'_> { impl_block: &ir::ItemImpl, ) -> TokenStream2 { let span = impl_block.span(); + let cb_ident = Self::call_builder_ident(); let unique_trait_id = self.generate_unique_trait_id(trait_path); quote_spanned!(span=> #[doc(hidden)] - impl ::ink_lang::TraitCallForwarderFor<#unique_trait_id> for CallBuilder { + impl ::ink_lang::TraitCallForwarderFor<#unique_trait_id> for #cb_ident { type Forwarder = <::__ink_TraitInfo as ::ink_lang::TraitCallForwarder>::Forwarder; #[inline(always)] @@ -239,6 +254,7 @@ impl CallBuilder<'_> { impl_block: &ir::ItemImpl, ) -> TokenStream2 { let span = impl_block.span(); + let cb_ident = Self::call_builder_ident(); let unique_trait_id = self.generate_unique_trait_id(trait_path); quote_spanned!(span=> // SAFETY: @@ -248,7 +264,7 @@ impl CallBuilder<'_> { // provided macros with correct unique trait ID. #[doc(hidden)] unsafe impl - ::ink_lang::TraitImplementer<#unique_trait_id> for CallBuilder + ::ink_lang::TraitImplementer<#unique_trait_id> for #cb_ident {} ) } @@ -277,11 +293,12 @@ impl CallBuilder<'_> { impl_block: &ir::ItemImpl, ) -> TokenStream2 { let span = impl_block.span(); + let cb_ident = Self::call_builder_ident(); let messages = impl_block .iter_messages() .map(|message| self.generate_ink_trait_impl_for_message(trait_path, message)); quote_spanned!(span=> - impl #trait_path for CallBuilder { + impl #trait_path for #cb_ident { type Env = Environment; type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry From a5e57c8277d7f8a37a677929a7dc45e9679099ef Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 19:00:55 +0200 Subject: [PATCH 113/493] fix docs of generate_contract_trait_impl_message --- crates/lang/codegen/src/generator/call_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 0c49571cbb..ecb6cf058b 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -418,7 +418,7 @@ impl CallBuilder<'_> { ) } - /// Generates the code for a all messages of a single ink! trait implementation of + /// Generates the code for all messages of a single ink! trait implementation of /// the ink! smart contract. fn generate_contract_trait_impl_messages( &self, From 158c84044a12a541b53c6251f87c0dcaf00d78cf Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 19:44:45 +0200 Subject: [PATCH 114/493] move generate_argument_list generator into its own module It is going to be used from inherent impl call builder generators as well. --- crates/lang/codegen/src/generator/arg_list.rs | 34 +++++++++++++++++++ crates/lang/codegen/src/generator/mod.rs | 2 ++ .../src/generator/trait_def/call_builder.rs | 21 ++---------- 3 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 crates/lang/codegen/src/generator/arg_list.rs diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs new file mode 100644 index 0000000000..6fbab18e5d --- /dev/null +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -0,0 +1,34 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use quote::{quote, quote_spanned}; +use proc_macro2::TokenStream as TokenStream2; + +/// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. +pub fn generate_argument_list<'b, Args>(args: Args) -> TokenStream2 +where + Args: IntoIterator, + ::IntoIter: Iterator, +{ + use syn::spanned::Spanned as _; + args.into_iter().fold( + quote! { ::ink_env::call::utils::EmptyArgumentList }, + |rest, arg| { + let span = arg.span(); + quote_spanned!(span=> + ::ink_env::call::utils::ArgumentList<::ink_env::call::utils::Argument<#arg>, #rest> + ) + } + ) +} diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index d80168f317..5d87993a8a 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -26,6 +26,7 @@ macro_rules! impl_as_ref_for_generator { }; } +mod arg_list; mod as_dependency; mod call_builder; mod chain_extension; @@ -42,6 +43,7 @@ mod storage; mod trait_def; pub use self::{ + arg_list::generate_argument_list, as_dependency::{ NotAsDependencyCfg, OnlyAsDependencyCfg, diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 244abaecf4..96d97b9aa5 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -21,6 +21,7 @@ use proc_macro2::{ TokenStream as TokenStream2, }; use quote::{format_ident, quote, quote_spanned}; +use crate::generator; impl<'a> TraitDefinition<'a> { /// Generates code for the global trait call builder for an ink! trait. @@ -368,7 +369,7 @@ impl CallBuilder<'_> { let selector_bytes = selector.hex_lits(); let input_bindings = Self::input_bindings(message.inputs()); let input_types = Self::input_types(message.inputs()); - let arg_list = Self::generate_argument_list_for(input_types.iter().cloned()); + let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = message.mutates().then(|| quote! { mut }); quote_spanned!(span => #[allow(clippy::type_complexity)] @@ -419,22 +420,4 @@ impl CallBuilder<'_> { fn input_types(inputs: ir::TraitItemInputsIter) -> Vec<&syn::Type> { inputs.map(|pat_type| &*pat_type.ty).collect::>() } - - /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. - fn generate_argument_list_for<'b, Args>(args: Args) -> TokenStream2 - where - Args: IntoIterator, - ::IntoIter: DoubleEndedIterator, - { - use syn::spanned::Spanned as _; - args.into_iter().fold( - quote! { ::ink_env::call::utils::EmptyArgumentList }, - |rest, arg| { - let span = arg.span(); - quote_spanned!(span=> - ::ink_env::call::utils::ArgumentList<::ink_env::call::utils::Argument<#arg>, #rest> - ) - } - ) - } } From 6bdf9e52cf4bc74395f1a89505e55536a8b7b124 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 20:26:32 +0200 Subject: [PATCH 115/493] move input_bindings utility method into arg_list generator module --- crates/lang/codegen/src/generator/arg_list.rs | 19 +++++++++++++- .../src/generator/trait_def/call_builder.rs | 26 +++++++------------ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 6fbab18e5d..8e6d6235bf 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -12,8 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -use quote::{quote, quote_spanned}; use proc_macro2::TokenStream as TokenStream2; +use quote::{ + format_ident, + quote, + quote_spanned, +}; + +/// Returns the sequence of artificial input parameter bindings for the message. +/// +/// # Note +/// +/// This returns `__ink_binding_N` for every message input where `N` is the number +/// of the input from first to last. +pub fn input_bindings(inputs: ir::InputsIter) -> Vec { + inputs + .enumerate() + .map(|(n, _)| format_ident!("__ink_binding_{}", n)) + .collect::>() +} /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. pub fn generate_argument_list<'b, Args>(args: Args) -> TokenStream2 diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 96d97b9aa5..6294f27826 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -13,15 +13,20 @@ // limitations under the License. use super::TraitDefinition; -use crate::traits::GenerateCode; +use crate::{ + generator, + traits::GenerateCode, +}; use derive_more::From; use ir::HexLiteral; use proc_macro2::{ Span, TokenStream as TokenStream2, }; -use quote::{format_ident, quote, quote_spanned}; -use crate::generator; +use quote::{ + quote, + quote_spanned, +}; impl<'a> TraitDefinition<'a> { /// Generates code for the global trait call builder for an ink! trait. @@ -367,7 +372,7 @@ impl CallBuilder<'_> { |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, ); let selector_bytes = selector.hex_lits(); - let input_bindings = Self::input_bindings(message.inputs()); + let input_bindings = generator::input_bindings(message.inputs()); let input_types = Self::input_types(message.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = message.mutates().then(|| quote! { mut }); @@ -403,19 +408,6 @@ impl CallBuilder<'_> { ) } - /// Returns the sequence of artificial input parameter bindings for the message. - /// - /// # Note - /// - /// This returns `__ink_binding_N` for every message input where `N` is the number - /// of the input from first to last. - fn input_bindings(inputs: ir::TraitItemInputsIter) -> Vec { - inputs - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>() - } - /// Returns the sequence of input types for the message. fn input_types(inputs: ir::TraitItemInputsIter) -> Vec<&syn::Type> { inputs.map(|pat_type| &*pat_type.ty).collect::>() From 885dca99e9fb1bc773ca6a5432eee25b3f77e686 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 20:27:24 +0200 Subject: [PATCH 116/493] deduplicate InputsIter and TraitItemInputsIter They are now the same type. This heavily simplifies utility functions operating on both, e.g. input_bindings. --- crates/lang/ir/src/ir/item_impl/callable.rs | 17 +++++++---- crates/lang/ir/src/ir/mod.rs | 1 - crates/lang/ir/src/ir/trait_def/mod.rs | 1 - crates/lang/ir/src/ir/trait_def/trait_item.rs | 30 ++----------------- crates/lang/ir/src/lib.rs | 1 - 5 files changed, 14 insertions(+), 36 deletions(-) diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index 88fee67b7b..7781472335 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -475,19 +475,24 @@ pub struct InputsIter<'a> { iter: syn::punctuated::Iter<'a, syn::FnArg>, } -impl<'a> From<&'a ir::Message> for InputsIter<'a> { - fn from(message: &'a ir::Message) -> Self { +impl<'a> InputsIter<'a> { + /// Creates a new inputs iterator over the given `syn` punctuation. + pub(crate) fn new

(inputs: &'a syn::punctuated::Punctuated) -> Self { Self { - iter: message.item.sig.inputs.iter(), + iter: inputs.iter(), } } } +impl<'a> From<&'a ir::Message> for InputsIter<'a> { + fn from(message: &'a ir::Message) -> Self { + Self::new(&message.item.sig.inputs) + } +} + impl<'a> From<&'a ir::Constructor> for InputsIter<'a> { fn from(constructor: &'a ir::Constructor) -> Self { - Self { - iter: constructor.item.sig.inputs.iter(), - } + Self::new(&constructor.item.sig.inputs) } } diff --git a/crates/lang/ir/src/ir/mod.rs b/crates/lang/ir/src/ir/mod.rs index d62e9cd6fa..5140748976 100644 --- a/crates/lang/ir/src/ir/mod.rs +++ b/crates/lang/ir/src/ir/mod.rs @@ -87,6 +87,5 @@ pub use self::{ InkTraitItem, InkTraitMessage, IterInkTraitItems, - InputsIter as TraitItemInputsIter, }, }; diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index c04a07a61e..b686d7d040 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -25,7 +25,6 @@ pub use self::{ InkTraitConstructor, InkTraitItem, InkTraitMessage, - InputsIter, }, }; use super::attrs::InkAttribute; diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/trait_item.rs index d790beb94b..44c23b6b57 100644 --- a/crates/lang/ir/src/ir/trait_def/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/trait_item.rs @@ -15,6 +15,7 @@ use super::super::InkAttribute; use crate::{ ir, + InputsIter, Receiver, }; use proc_macro2::Span; @@ -258,39 +259,14 @@ impl<'a> InkTraitMessage<'a> { } } -/// Iterator over the input parameters of an ink! message or constructor. -/// -/// Does not yield the self receiver of ink! messages. -pub struct InputsIter<'a> { - iter: syn::punctuated::Iter<'a, syn::FnArg>, -} - impl<'a> From<&'a InkTraitMessage<'a>> for InputsIter<'a> { fn from(message: &'a InkTraitMessage) -> Self { - Self { - iter: message.item.sig.inputs.iter(), - } + Self::new(&message.item.sig.inputs) } } impl<'a> From<&'a InkTraitConstructor<'a>> for InputsIter<'a> { fn from(constructor: &'a InkTraitConstructor) -> Self { - Self { - iter: constructor.item.sig.inputs.iter(), - } - } -} - -impl<'a> Iterator for InputsIter<'a> { - type Item = &'a syn::PatType; - - fn next(&mut self) -> Option { - 'repeat: loop { - match self.iter.next() { - None => return None, - Some(syn::FnArg::Typed(pat_typed)) => return Some(pat_typed), - Some(syn::FnArg::Receiver(_)) => continue 'repeat, - } - } + Self::new(&constructor.item.sig.inputs) } } diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index b613e91f34..16cfdb2076 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -67,6 +67,5 @@ pub use self::ir::{ Receiver, Selector, Storage, - TraitItemInputsIter, Visibility, }; From 23dffadae9c48c85375a57dc000d1dc2cd3e8aa2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 20:28:25 +0200 Subject: [PATCH 117/493] make use of deduplicated InputItems types in generator crate --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- crates/lang/codegen/src/generator/trait_def/trait_registry.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 6294f27826..fd4da9e7e1 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -409,7 +409,7 @@ impl CallBuilder<'_> { } /// Returns the sequence of input types for the message. - fn input_types(inputs: ir::TraitItemInputsIter) -> Vec<&syn::Type> { + fn input_types(inputs: ir::InputsIter) -> Vec<&syn::Type> { inputs.map(|pat_type| &*pat_type.ty).collect::>() } } diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 6e32a56628..3563878c18 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -178,7 +178,7 @@ impl TraitRegistry<'_> { /// Returns a pair of input bindings `__ink_bindings_N` and types. fn input_bindings_and_types( - inputs: ir::TraitItemInputsIter, + inputs: ir::InputsIter, ) -> (Vec, Vec<&syn::Type>) { inputs .enumerate() From 3d7d638fef7db62118020f66add5ed8185bb3883 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 20:28:41 +0200 Subject: [PATCH 118/493] add missing input_bindings import --- crates/lang/codegen/src/generator/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 5d87993a8a..f2ef6557fc 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -43,7 +43,7 @@ mod storage; mod trait_def; pub use self::{ - arg_list::generate_argument_list, + arg_list::{input_bindings, generate_argument_list}, as_dependency::{ NotAsDependencyCfg, OnlyAsDependencyCfg, From 0728a6de341431509d5206235564e1e34c69b6cb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 20:28:50 +0200 Subject: [PATCH 119/493] apply rustfmt suggestion --- .../src/generator/trait_def/call_builder.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index fd4da9e7e1..e67fd0df22 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -343,14 +343,15 @@ impl CallBuilder<'_> { /// Generate the code for all ink! trait messages implemented by the trait call builder. fn generate_ink_trait_impl_messages(&self) -> TokenStream2 { - let messages = self - .trait_def - .trait_def - .iter_items() - .filter_map(|(item, selector)| { - item.filter_map_message() - .map(|message| self.generate_ink_trait_impl_for_message(&message, selector)) - }); + let messages = + self.trait_def + .trait_def + .iter_items() + .filter_map(|(item, selector)| { + item.filter_map_message().map(|message| { + self.generate_ink_trait_impl_for_message(&message, selector) + }) + }); quote! { #( #messages )* } From d83996e0e5e3196d4661c02970f1ad10b30156a3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 21:21:05 +0200 Subject: [PATCH 120/493] move input_types utility function into arg_list utility module --- crates/lang/codegen/src/generator/arg_list.rs | 5 +++++ .../lang/codegen/src/generator/trait_def/call_builder.rs | 7 +------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 8e6d6235bf..3936b499fc 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -32,6 +32,11 @@ pub fn input_bindings(inputs: ir::InputsIter) -> Vec { .collect::>() } +/// Returns the sequence of input types for the message. +pub fn input_types(inputs: ir::InputsIter) -> Vec<&syn::Type> { + inputs.map(|pat_type| &*pat_type.ty).collect::>() +} + /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. pub fn generate_argument_list<'b, Args>(args: Args) -> TokenStream2 where diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index e67fd0df22..6bc10dbba0 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -374,7 +374,7 @@ impl CallBuilder<'_> { ); let selector_bytes = selector.hex_lits(); let input_bindings = generator::input_bindings(message.inputs()); - let input_types = Self::input_types(message.inputs()); + let input_types = generator::input_types(message.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = message.mutates().then(|| quote! { mut }); quote_spanned!(span => @@ -408,9 +408,4 @@ impl CallBuilder<'_> { } ) } - - /// Returns the sequence of input types for the message. - fn input_types(inputs: ir::InputsIter) -> Vec<&syn::Type> { - inputs.map(|pat_type| &*pat_type.ty).collect::>() - } } From cf3aafa4867303f9656fb835910058b63c47d544 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 21:22:20 +0200 Subject: [PATCH 121/493] move output_ident utility fn into arg_list utility module --- crates/lang/codegen/src/generator/arg_list.rs | 6 ++++++ crates/lang/codegen/src/generator/call_builder.rs | 10 ++++++---- crates/lang/codegen/src/generator/mod.rs | 7 ++++++- .../codegen/src/generator/trait_def/call_builder.rs | 2 +- .../src/generator/trait_def/call_forwarder.rs | 4 ++-- crates/lang/codegen/src/generator/trait_def/mod.rs | 6 ------ .../src/generator/trait_def/trait_registry.rs | 12 ++---------- 7 files changed, 23 insertions(+), 24 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 3936b499fc..b406fe838c 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -18,6 +18,12 @@ use quote::{ quote, quote_spanned, }; +use heck::CamelCase; + +/// Returns the associated output type for an ink! trait message. +pub fn output_ident(message_name: &syn::Ident) -> syn::Ident { + format_ident!("{}Output", message_name.to_string().to_camel_case()) +} /// Returns the sequence of artificial input parameter bindings for the message. /// diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index ecb6cf058b..2dc6bd39a1 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::GenerateCode; +use crate::{ + generator, + GenerateCode, +}; use derive_more::From; -use heck::CamelCase; use proc_macro2::TokenStream as TokenStream2; use quote::{ format_ident, @@ -319,7 +321,7 @@ impl CallBuilder<'_> { use ir::Callable as _; let span = message.span(); let message_ident = message.ident(); - let output_ident = self.output_ident(message_ident); + let output_ident = generator::output_ident(message_ident); let unique_trait_id = self.generate_unique_trait_id(trait_path); let input_bindings = message .callable() @@ -444,7 +446,7 @@ impl CallBuilder<'_> { let unique_trait_id = self.generate_unique_trait_id(trait_path); let span = message.span(); let message_ident = message.ident(); - let output_ident = self.output_ident(message_ident); + let output_ident = generator::output_ident(message_ident); let call_operator = match message.receiver() { ir::Receiver::Ref => quote! { call }, ir::Receiver::RefMut => quote! { call_mut }, diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index f2ef6557fc..fd17666856 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -43,7 +43,12 @@ mod storage; mod trait_def; pub use self::{ - arg_list::{input_bindings, generate_argument_list}, + arg_list::{ + generate_argument_list, + input_bindings, + input_types, + output_ident, + }, as_dependency::{ NotAsDependencyCfg, OnlyAsDependencyCfg, diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 6bc10dbba0..2ca0e6222c 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -366,7 +366,7 @@ impl CallBuilder<'_> { let span = message.span(); let message_ident = message.ident(); let attrs = message.attrs(); - let output_ident = self.trait_def.output_ident(message.ident()); + let output_ident = generator::output_ident(message_ident); let output = message.output(); let output_sig = output.map_or_else( || quote! { () }, diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index e617ede6c3..0058d036c9 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -13,7 +13,7 @@ // limitations under the License. use super::TraitDefinition; -use crate::traits::GenerateCode; +use crate::{generator, traits::GenerateCode}; use derive_more::From; use ir::HexLiteral; use proc_macro2::{ @@ -389,7 +389,7 @@ impl CallForwarder<'_> { let forwarder_ident = self.ident(); let message_ident = message.ident(); let attrs = message.attrs(); - let output_ident = self.trait_def.output_ident(message.ident()); + let output_ident = generator::output_ident(message_ident); let output_type = message.output().cloned().unwrap_or_else(|| syn::parse_quote!(())); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index dce60d6844..d30580cc12 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -17,7 +17,6 @@ mod trait_registry; mod call_builder; mod call_forwarder; -use heck::CamelCase as _; use crate::GenerateCode; use derive_more::From; use proc_macro2::{Span, TokenStream as TokenStream2}; @@ -55,11 +54,6 @@ impl<'a> TraitDefinition<'a> { fn span(&self) -> Span { self.trait_def.span() } - - /// Returns the associated output type for an ink! trait message. - fn output_ident(&self, message_name: &syn::Ident) -> syn::Ident { - format_ident!("{}Output", message_name.to_string().to_camel_case()) - } } impl GenerateCode for TraitDefinition<'_> { diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 3563878c18..0d8058ddcb 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -20,10 +20,7 @@ //! types for the trait's respective call builder and call forwarder. use super::TraitDefinition; -use crate::{ - generator::enforced_error::EnforcedErrors, - traits::GenerateCode, -}; +use crate::{generator::{self, enforced_error::EnforcedErrors}, traits::GenerateCode}; use derive_more::From; use ir::HexLiteral; use proc_macro2::{ @@ -80,11 +77,6 @@ impl TraitRegistry<'_> { self.trait_def.trait_def.ident() } - /// Returns the associated output type for an ink! trait message. - fn output_ident(&self, message_name: &syn::Ident) -> syn::Ident { - self.trait_def.output_ident(message_name) - } - /// Generates the global trait registry implementation for the ink! trait. /// /// This makes it possible to refer back to the global call forwarder and @@ -148,7 +140,7 @@ impl TraitRegistry<'_> { let span = message.span(); let ident = message.ident(); let attrs = message.attrs(); - let output_ident = self.output_ident(message.ident()); + let output_ident = generator::output_ident(message.ident()); let (input_bindings, input_types) = Self::input_bindings_and_types(message.inputs()); let linker_error_ident = EnforcedErrors::cannot_call_trait_message( From 6863c95c7e4d12840416eff30bdfed0d99cece62 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 22:15:08 +0200 Subject: [PATCH 122/493] generate call builder code for inherent contract messages --- .../codegen/src/generator/call_builder.rs | 105 +++++++++++++++++- 1 file changed, 103 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 2dc6bd39a1..b8f53c6178 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -17,6 +17,7 @@ use crate::{ GenerateCode, }; use derive_more::From; +use ir::Callable; use proc_macro2::TokenStream as TokenStream2; use quote::{ format_ident, @@ -46,14 +47,16 @@ impl GenerateCode for CallBuilder<'_> { let call_builder_struct = self.generate_struct(); let trait_impl = self.generate_trait_impl(); let auxiliary_trait_impls = self.generate_auxiliary_trait_impls(); - let call_forwarder_impls = self.generate_call_forwarder_impls(); + let call_builder_impls = self.generate_call_forwarder_impls(); + let call_builder_inherent_impls = self.generate_call_builder_inherent_impls(); let contract_trait_impls = self.generate_contract_trait_impls(); quote! { const _: () = { #call_builder_struct #trait_impl #auxiliary_trait_impls - #call_forwarder_impls + #call_builder_impls + #call_builder_inherent_impls }; #contract_trait_impls } @@ -363,8 +366,106 @@ impl CallBuilder<'_> { ) } + /// Generate call builder code for all ink! inherent ink! impl blocks. /// Returns the associated output type for an ink! trait message. /// + /// # Note + /// + /// This does not provide implementations for ink! constructors as they + /// do not have a short-hand notations as their messages counterparts. + fn generate_call_builder_inherent_impls(&self) -> TokenStream2 { + self.contract + .module() + .impls() + .filter_map(|impl_block| { + impl_block + .trait_path() + .is_none() + .then(|| self.generate_call_builder_inherent_impl(impl_block)) + }) + .collect() + } + + /// Generate call builder code for a single inherent ink! impl block. + /// + /// # Note + /// + /// Unlike as with ink! trait impl blocks we do not have to generate + /// associate `*Output` types, ink! trait validators impl blocks or + /// trait forwarder implementations. Instead we build the calls directly. + fn generate_call_builder_inherent_impl( + &self, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + let span = impl_block.span(); + let cb_ident = Self::call_builder_ident(); + let messages = impl_block + .iter_messages() + .map(|message| self.generate_call_builder_inherent_impl_for_message(message)); + quote_spanned!(span=> + impl #cb_ident { + #( #messages )* + } + ) + } + + /// Generate call builder code for a single inherent ink! message. + /// + /// # Note + /// + /// Unlike with ink! trait messages the call builder implements the call + /// building directly and does not forward to a trait call builder. + fn generate_call_builder_inherent_impl_for_message( + &self, + message: ir::CallableWithSelector, + ) -> TokenStream2 { + let span = message.span(); + let callable = message.callable(); + let message_ident = message.ident(); + let attrs = message.attrs(); + let output = message.output(); + let output_sig = output.map_or_else( + || quote! { () }, + |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, + ); + let output_span = output.span(); + let selector = message.composed_selector(); + let selector_bytes = selector.hex_lits(); + let input_bindings = generator::input_bindings(callable.inputs()); + let input_types = generator::input_types(message.inputs()); + let arg_list = generator::generate_argument_list(input_types.iter().cloned()); + let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); + let output_type = quote_spanned!(output_span=> + ::ink_env::call::CallBuilder< + Self::Env, + ::ink_env::call::utils::Set< ::AccountId >, + ::ink_env::call::utils::Unset< ::core::primitive::u64 >, + ::ink_env::call::utils::Unset< ::Balance >, + ::ink_env::call::utils::Set< ::ink_env::call::ExecutionInput<#arg_list> >, + ::ink_env::call::utils::Set<#output_sig>, + > + ); + quote_spanned!(span=> + #( #attrs )* + #[allow(clippy::type_complexity)] + #[inline] + pub fn #message_ident( + & #mut_tok self + #( , #input_bindings : #input_types )* + ) -> #output_type { + ::ink_env::call::build_call::() + .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) + .exec_input( + ::ink_env::call::ExecutionInput::new( + ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) + ) + #( + .push_arg(#input_bindings) + )* + ) + .returns::<#output_sig>() + } + ) /// TODO: Remove duplicated `output_ident` method before merging PR. fn output_ident(&self, message_name: &syn::Ident) -> syn::Ident { format_ident!("{}Output", message_name.to_string().to_camel_case()) From a126c040d5ec83b291223941523e3b76928e5a98 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 10 Sep 2021 22:15:29 +0200 Subject: [PATCH 123/493] remove left-overs from refactorings that git got wrong --- crates/lang/codegen/src/generator/call_builder.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index b8f53c6178..73326bb9ed 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -367,7 +367,6 @@ impl CallBuilder<'_> { } /// Generate call builder code for all ink! inherent ink! impl blocks. - /// Returns the associated output type for an ink! trait message. /// /// # Note /// @@ -466,9 +465,6 @@ impl CallBuilder<'_> { .returns::<#output_sig>() } ) - /// TODO: Remove duplicated `output_ident` method before merging PR. - fn output_ident(&self, message_name: &syn::Ident) -> syn::Ident { - format_ident!("{}Output", message_name.to_string().to_camel_case()) } /// Generates the code for all ink! trait implementations of the contract itself. From 5de5e61df3cfb603c9e7ff6e14ad4e3fc24cafbb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 17:09:23 +0200 Subject: [PATCH 124/493] reorder let bindings in fn --- crates/lang/codegen/src/generator/call_builder.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 73326bb9ed..000a9a8da6 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -422,18 +422,18 @@ impl CallBuilder<'_> { let callable = message.callable(); let message_ident = message.ident(); let attrs = message.attrs(); - let output = message.output(); - let output_sig = output.map_or_else( - || quote! { () }, - |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, - ); - let output_span = output.span(); let selector = message.composed_selector(); let selector_bytes = selector.hex_lits(); let input_bindings = generator::input_bindings(callable.inputs()); let input_types = generator::input_types(message.inputs()); let arg_list = generator::generate_argument_list(input_types.iter().cloned()); let mut_tok = callable.receiver().is_ref_mut().then(|| quote! { mut }); + let output = message.output(); + let output_sig = output.map_or_else( + || quote! { () }, + |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, + ); + let output_span = output.span(); let output_type = quote_spanned!(output_span=> ::ink_env::call::CallBuilder< Self::Env, From c057c996a0adc755f58f7ac43882ffb814fbda0c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 17:09:57 +0200 Subject: [PATCH 125/493] properly generate user provided attributes in generate_contract_trait_impl --- crates/lang/codegen/src/generator/call_builder.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 000a9a8da6..22230ab688 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -496,6 +496,7 @@ impl CallBuilder<'_> { impl_block: &ir::ItemImpl, ) -> TokenStream2 { let span = impl_block.span(); + let attrs = impl_block.attrs(); let unique_trait_id = self.generate_unique_trait_id(trait_path); let storage_ident = self.contract.module().storage().ident(); let messages = self.generate_contract_trait_impl_messages(trait_path, impl_block); @@ -505,6 +506,7 @@ impl CallBuilder<'_> { ::ink_lang::TraitImplementer<#unique_trait_id> for #storage_ident {} + #( #attrs )* impl #trait_path for #storage_ident { type Env = Environment; From b380c919b6840207f68772f887dec69c304013af Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 17:10:22 +0200 Subject: [PATCH 126/493] use call_builder_ident utility fn in generate_trait_impl --- crates/lang/codegen/src/generator/call_builder.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 22230ab688..3cd4e119dc 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -107,10 +107,11 @@ impl CallBuilder<'_> { /// associated call builder. fn generate_trait_impl(&self) -> TokenStream2 { let span = self.contract.module().storage().span(); - let ident = self.contract.module().storage().ident(); + let storage_ident = self.contract.module().storage().ident(); + let cb_ident = Self::call_builder_ident(); quote_spanned!(span=> - impl ::ink_lang::TraitCallBuilder for #ident { - type Builder = CallBuilder; + impl ::ink_lang::TraitCallBuilder for #storage_ident { + type Builder = #cb_ident; #[inline] fn call(&self) -> &Self::Builder { From 8f3bc5852e34691d4d6c762ba423dabf7606d7c5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 17:10:42 +0200 Subject: [PATCH 127/493] update docs of generate_contract_trait_impls --- crates/lang/codegen/src/generator/call_builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 3cd4e119dc..09442a6dc6 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -472,8 +472,8 @@ impl CallBuilder<'_> { /// /// # Note /// - /// Since those implementations must live outside of an artificial `const` block - /// we need to keep this in a separate expansion step. + /// The generated implementations must live outside of an artificial `const` block + /// in order to properly show their documentation using `rustdoc`. fn generate_contract_trait_impls(&self) -> TokenStream2 { self.contract .module() From c00f0378f74d11031e236becf3061da195cfbb61 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 17:11:05 +0200 Subject: [PATCH 128/493] add codegen for inherent impls for contract struct (cross-calling) --- .../codegen/src/generator/call_builder.rs | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 09442a6dc6..241b80799c 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -50,6 +50,7 @@ impl GenerateCode for CallBuilder<'_> { let call_builder_impls = self.generate_call_forwarder_impls(); let call_builder_inherent_impls = self.generate_call_builder_inherent_impls(); let contract_trait_impls = self.generate_contract_trait_impls(); + let contract_inherent_impls = self.generate_contract_inherent_impls(); quote! { const _: () = { #call_builder_struct @@ -59,6 +60,7 @@ impl GenerateCode for CallBuilder<'_> { #call_builder_inherent_impls }; #contract_trait_impls + #contract_inherent_impls } } } @@ -576,4 +578,138 @@ impl CallBuilder<'_> { } ) } + + /// Generates the code for all ink! inherent implementations of the contract itself. + /// + /// # Note + /// + /// The generated implementations must live outside of an artificial `const` block + /// in order to properly show their documentation using `rustdoc`. + fn generate_contract_inherent_impls(&self) -> TokenStream2 { + self.contract + .module() + .impls() + .filter_map(|impl_block| { + // We are only interested in ink! trait implementation block. + impl_block + .trait_path() + .is_none() + .then(|| self.generate_contract_inherent_impl(impl_block)) + }) + .collect() + } + + /// Generates the code for a single ink! inherent implementation of the contract itself. + /// + /// # Note + /// + /// This produces the short-hand calling notation for the inherent contract implementation. + /// The generated code simply forwards its calling logic to the associated call builder. + fn generate_contract_inherent_impl(&self, impl_block: &ir::ItemImpl) -> TokenStream2 { + let span = impl_block.span(); + let attrs = impl_block.attrs(); + let storage_ident = self.contract.module().storage().ident(); + let messages = impl_block + .iter_messages() + .map(|message| self.generate_contract_inherent_impl_for_message(message)); + let constructors = impl_block.iter_constructors().map(|constructor| { + self.generate_contract_inherent_impl_for_constructor(constructor) + }); + quote_spanned!(span=> + #( #attrs )* + impl #storage_ident { + #( #constructors )* + #( #messages )* + } + ) + } + + /// Generates the code for a single ink! inherent message of the contract itself. + /// + /// # Note + /// + /// This produces the short-hand calling notation for the inherent contract message. + /// The generated code simply forwards its calling logic to the associated call builder. + fn generate_contract_inherent_impl_for_message( + &self, + message: ir::CallableWithSelector, + ) -> TokenStream2 { + use ir::Callable as _; + let span = message.span(); + let attrs = message.attrs(); + let storage_ident = self.contract.module().storage().ident(); + let message_ident = message.ident(); + let call_operator = match message.receiver() { + ir::Receiver::Ref => quote! { call }, + ir::Receiver::RefMut => quote! { call_mut }, + }; + let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); + let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); + let input_types = message.inputs().map(|input| &input.ty).collect::>(); + let output_type = message.output().map(|ty| quote! { -> #ty }); + quote_spanned!(span=> + #( #attrs )* + #[inline] + fn #message_ident( + & #mut_token self + #( , #input_bindings : #input_types )* + ) #output_type { + ::#call_operator(self) + .#message_ident( #( #input_bindings ),* ) + .fire() + .unwrap_or_else(|error| ::core::panic!( + "encountered error while calling {}::{}: {}", + ::core::stringify!(#storage_ident), + ::core::stringify!(#message_ident), + error, + )) + } + ) + } + + /// Generates the code for a single ink! inherent constructor of the contract itself. + /// + /// # Note + /// + /// Unlike with ink! messages this does not forward to the call builder since constructor + /// calls in ink! do not have a short-hand notation and therefore this implements the + /// long-hand calling notation code directly. + fn generate_contract_inherent_impl_for_constructor( + &self, + constructor: ir::CallableWithSelector, + ) -> TokenStream2 { + let span = constructor.span(); + let attrs = constructor.attrs(); + let constructor_ident = constructor.ident(); + let selector_bytes = constructor.composed_selector().hex_lits(); + let input_bindings = generator::input_bindings(constructor.inputs()); + let input_types = generator::input_types(constructor.inputs()); + let arg_list = generator::generate_argument_list(input_types.iter().cloned()); + quote_spanned!(span => + #( #attrs )* + #[inline] + #[allow(clippy::type_complexity)] + pub fn #constructor_ident( + #( #input_bindings : #input_types ),* + ) -> ::ink_env::call::CreateBuilder< + Environment, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, + ::ink_env::call::utils::Unset<::ink_env::call::state::Salt>, + Self, + > { + ::ink_env::call::build_create::() + .exec_input( + ::ink_env::call::ExecutionInput::new( + ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) + ) + #( + .push_arg(#input_bindings) + )* + ) + } + ) + } } From 839e7c42fabff080b2145abd223a0a0c43ee8771 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 17:16:25 +0200 Subject: [PATCH 129/493] generate public message fns in call builder --- crates/lang/codegen/src/generator/call_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 241b80799c..621b6e6bb7 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -650,7 +650,7 @@ impl CallBuilder<'_> { quote_spanned!(span=> #( #attrs )* #[inline] - fn #message_ident( + pub fn #message_ident( & #mut_token self #( , #input_bindings : #input_types )* ) #output_type { From 919f86be532114d1ddea42fea3568fd64669aa5a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 17:59:54 +0200 Subject: [PATCH 130/493] move generate_unique_trait_id utility fn into arg_list utility module --- crates/lang/codegen/src/generator/arg_list.rs | 18 ++++++++++++- .../codegen/src/generator/call_builder.rs | 27 ++++--------------- crates/lang/codegen/src/generator/mod.rs | 1 + 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index b406fe838c..0be4ef8ccd 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{ format_ident, quote, @@ -60,3 +60,19 @@ where } ) } + +/// Generates code to uniquely identify a trait by its unique ID given only its identifier. +/// +/// # Note +/// +/// As with all Rust macros identifiers can shadow each other so the given identifier +/// needs to be valid for the scope in which the returned code is generated. +pub fn generate_unique_trait_id(span: Span, trait_path: &syn::Path) -> TokenStream2 { + quote_spanned!(span=> + { + <<::ink_lang::TraitCallForwarderRegistry + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitUniqueId>::ID + } + ) +} diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 621b6e6bb7..623b4f1376 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -200,7 +200,7 @@ impl CallBuilder<'_> { ) -> TokenStream2 { let span = impl_block.span(); let cb_ident = Self::call_builder_ident(); - let unique_trait_id = self.generate_unique_trait_id(trait_path); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); quote_spanned!(span=> #[doc(hidden)] impl ::ink_lang::TraitCallForwarderFor<#unique_trait_id> for #cb_ident { @@ -263,7 +263,7 @@ impl CallBuilder<'_> { ) -> TokenStream2 { let span = impl_block.span(); let cb_ident = Self::call_builder_ident(); - let unique_trait_id = self.generate_unique_trait_id(trait_path); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); quote_spanned!(span=> // SAFETY: // @@ -277,23 +277,6 @@ impl CallBuilder<'_> { ) } - /// Generates code to uniquely identify a trait by its unique ID given only its identifier. - /// - /// # Note - /// - /// As with all Rust macros identifiers can shadow each other so the given identifier - /// needs to be valid for the scope in which the returned code is generated. - fn generate_unique_trait_id(&self, trait_path: &syn::Path) -> TokenStream2 { - let span = self.contract.module().storage().span(); - quote_spanned!(span=> - { - <<::ink_lang::TraitCallForwarderRegistry - as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitUniqueId>::ID - } - ) - } - /// Generates the actual ink! trait implementation for the generated call builder. fn generate_ink_trait_impl( &self, @@ -328,7 +311,7 @@ impl CallBuilder<'_> { let span = message.span(); let message_ident = message.ident(); let output_ident = generator::output_ident(message_ident); - let unique_trait_id = self.generate_unique_trait_id(trait_path); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); let input_bindings = message .callable() .inputs() @@ -500,7 +483,7 @@ impl CallBuilder<'_> { ) -> TokenStream2 { let span = impl_block.span(); let attrs = impl_block.attrs(); - let unique_trait_id = self.generate_unique_trait_id(trait_path); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); let storage_ident = self.contract.module().storage().ident(); let messages = self.generate_contract_trait_impl_messages(trait_path, impl_block); quote_spanned!(span=> @@ -545,8 +528,8 @@ impl CallBuilder<'_> { message: ir::CallableWithSelector, ) -> TokenStream2 { use ir::Callable as _; - let unique_trait_id = self.generate_unique_trait_id(trait_path); let span = message.span(); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); let message_ident = message.ident(); let output_ident = generator::output_ident(message_ident); let call_operator = match message.receiver() { diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index fd17666856..daa0edf0e0 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -44,6 +44,7 @@ mod trait_def; pub use self::{ arg_list::{ + generate_unique_trait_id, generate_argument_list, input_bindings, input_types, From 1a62029c72b798b72038bcbb719a10d8ae4538f4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 18:00:15 +0200 Subject: [PATCH 131/493] remove deprecated cross-calling codegen --- crates/lang/codegen/src/generator/contract.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index adc95d066d..44dfd02a55 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -46,7 +46,6 @@ impl GenerateCode for Contract<'_> { let events = self.generate_code_using::(); let dispatch = self.generate_code_using::(); let item_impls = self.generate_code_using::(); - let cross_calling = self.generate_code_using::(); let metadata = self.generate_code_using::(); let call_builder = self.generate_code_using::(); let non_ink_items = self @@ -63,7 +62,6 @@ impl GenerateCode for Contract<'_> { #events #dispatch #item_impls - #cross_calling #call_builder #metadata #( #non_ink_items )* From 8c52f604ff4384a5eaae8304ac2d8ce5c46644e2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 18:00:38 +0200 Subject: [PATCH 132/493] import Env, EmitEvent and StaticEnv without names in codegen --- crates/lang/codegen/src/generator/item_impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 497d9258b9..3c715a8c1f 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -48,7 +48,7 @@ impl GenerateCode for ItemImpls<'_> { quote! { #no_cross_calling_cfg const _: () = { - use ::ink_lang::{Env, EmitEvent, StaticEnv}; + use ::ink_lang::{Env as _, EmitEvent as _, StaticEnv as _}; #( #item_impls )* }; From 5bba245ffdbecc11e1ffd2da83f8af4725e1f67d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 18:00:57 +0200 Subject: [PATCH 133/493] modernize old item_impls.rs codegen module to use new codegen --- .../lang/codegen/src/generator/item_impls.rs | 63 ++++--------------- 1 file changed, 11 insertions(+), 52 deletions(-) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 3c715a8c1f..457554228d 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -57,28 +57,6 @@ impl GenerateCode for ItemImpls<'_> { } impl ItemImpls<'_> { - /// Generates the code for the given ink! constructor within a trait implementation block. - fn generate_trait_constructor(constructor: &ir::Constructor) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let vis = match constructor.visibility() { - ir::Visibility::Inherited => None, - ir::Visibility::Public(vis_public) => Some(vis_public), - }; - let ident = constructor.ident(); - let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); - let inputs = constructor.inputs(); - let statements = constructor.statements(); - quote_spanned!(span => - type #output_ident = Self; - - #( #attrs )* - #vis fn #ident( #( #inputs ),* ) -> Self::#output_ident { - #( #statements )* - } - ) - } - /// Generates the code for the given ink! message within a trait implementation block. fn generate_trait_message(message: &ir::Message) -> TokenStream2 { let span = message.span(); @@ -113,47 +91,28 @@ impl ItemImpls<'_> { let messages = item_impl .iter_messages() .map(|cws| Self::generate_trait_message(cws.callable())); - let constructors = item_impl - .iter_constructors() - .map(|cws| Self::generate_trait_constructor(cws.callable())); - let other_items = item_impl - .items() - .iter() - .filter_map(ir::ImplItem::filter_map_other_item) - .map(ToTokens::to_token_stream); let trait_path = item_impl .trait_path() .expect("encountered missing trait path for trait impl block"); - let trait_ident = item_impl - .trait_ident() - .expect("encountered missing trait identifier for trait impl block"); let self_type = item_impl.self_type(); - let hash = ir::InkTrait::compute_verify_hash( - trait_ident, - item_impl.iter_constructors().map(|constructor| { - let ident = constructor.ident().clone(); - let len_inputs = constructor.inputs().count(); - (ident, len_inputs) - }), - item_impl.iter_messages().map(|message| { - let ident = message.ident().clone(); - let len_inputs = message.inputs().count() + 1; - let is_mut = message.receiver().is_ref_mut(); - (ident, len_inputs, is_mut) - }), + let unique_trait_id = generator::generate_unique_trait_id( + span, + trait_path, ); - let checksum = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; quote_spanned!(span => - unsafe impl ::ink_lang::CheckedInkTrait<[(); #checksum]> for #self_type {} + #[doc(hidden)] + unsafe impl + ::ink_lang::TraitImplementer<#unique_trait_id> for #self_type + {} #( #attrs )* impl #trait_path for #self_type { - type __ink_Checksum = [(); #checksum]; - type __ink_ConcreteImplementer = ::ink_lang::NoConcreteImplementer; + type Env = Environment; + + type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry + as #trait_path>::__ink_TraitInfo; - #( #constructors )* #( #messages )* - #( #other_items )* } ) } From 39b80578f2a52f5faa04396d07c09f3c01328298 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 18:03:14 +0200 Subject: [PATCH 134/493] be more explicit with associated type usage in codegen --- crates/lang/codegen/src/generator/storage.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index 11007eee9a..aa6e7d1619 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -72,7 +72,7 @@ impl Storage<'_> { type EnvAccess = ::ink_lang::EnvAccess<'a, <#storage_ident as ::ink_lang::ContractEnv>::Env>; fn env(self) -> Self::EnvAccess { - ::default() + <::EnvAccess as ::core::default::Default>::default() } } @@ -80,7 +80,7 @@ impl Storage<'_> { type EnvAccess = ::ink_lang::EnvAccess<'static, <#storage_ident as ::ink_lang::ContractEnv>::Env>; fn env() -> Self::EnvAccess { - ::default() + <::EnvAccess as ::core::default::Default>::default() } } }; From 2182c48bd3b0eacc5268fc58bf82c70724f1c965 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 12 Sep 2021 18:17:34 +0200 Subject: [PATCH 135/493] use Environment instead of Self::Env in inherent generated impls --- crates/lang/codegen/src/generator/call_builder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/call_builder.rs index 623b4f1376..8491e62a7f 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/call_builder.rs @@ -422,10 +422,10 @@ impl CallBuilder<'_> { let output_span = output.span(); let output_type = quote_spanned!(output_span=> ::ink_env::call::CallBuilder< - Self::Env, - ::ink_env::call::utils::Set< ::AccountId >, + Environment, + ::ink_env::call::utils::Set< ::AccountId >, ::ink_env::call::utils::Unset< ::core::primitive::u64 >, - ::ink_env::call::utils::Unset< ::Balance >, + ::ink_env::call::utils::Unset< ::Balance >, ::ink_env::call::utils::Set< ::ink_env::call::ExecutionInput<#arg_list> >, ::ink_env::call::utils::Set<#output_sig>, > @@ -438,7 +438,7 @@ impl CallBuilder<'_> { & #mut_tok self #( , #input_bindings : #input_types )* ) -> #output_type { - ::ink_env::call::build_call::() + ::ink_env::call::build_call::() .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) .exec_input( ::ink_env::call::ExecutionInput::new( From 5b5572f3f56078e38c034a4c86ce5cf4c122bca4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 00:51:37 +0200 Subject: [PATCH 136/493] add ink_lang::ContractRef utility codegen type This is going to be used as a base for all generated cross-calling contract types. The reason is that it is hard to type-safely reference some generated type but it is easy to refer to a generic external one when the generic parameter is already given. We will use the ink! storage struct as the generic parameter to solve the ink-as-dependency storage struct type generation using this utility type. --- crates/lang/src/contract_ref.rs | 167 ++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 crates/lang/src/contract_ref.rs diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs new file mode 100644 index 0000000000..17954f03a7 --- /dev/null +++ b/crates/lang/src/contract_ref.rs @@ -0,0 +1,167 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::marker::PhantomData; + +/// Trait to inform about the name of an ink! smart contract. +pub trait ContractName { + /// The name of the ink! smart contract. + const NAME: &'static str; +} + +/// A generic ink! smart contract reference. +/// +/// This utility struct is generic over the ink! environment `E` +/// as well as over the concrete smart contract `T`. +/// +/// This is used by the ink! codegen in order to implement various +/// implementations for calling smart contract instances of contract +/// `T` using environment `E` on-chain. +pub struct ContractRef +where + E: ink_env::Environment, +{ + account_id: ::AccountId, + __marker: PhantomData T>, +} + +impl core::fmt::Debug for ContractRef +where + E: ink_env::Environment, + ::AccountId: core::fmt::Debug, + T: ContractName, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let name = ::NAME; + f.debug_struct("ContractRef") + .field("name", &name) + .field("account_id", &self.account_id) + .finish() + } +} + +impl Copy for ContractRef +where + E: ink_env::Environment, + ::AccountId: Copy, +{ +} + +impl Clone for ContractRef +where + E: ink_env::Environment, + ::AccountId: Clone, +{ + #[inline] + fn clone(&self) -> Self { + Self { + account_id: self.account_id.clone(), + __marker: PhantomData, + } + } +} + +impl scale::Encode for ContractRef +where + E: ink_env::Environment, + ::AccountId: scale::Encode, +{ + #[inline] + fn size_hint(&self) -> usize { + <::AccountId as scale::Encode>::size_hint( + &self.account_id, + ) + } + + #[inline] + fn encode_to(&self, dest: &mut O) { + <::AccountId as scale::Encode>::encode_to( + &self.account_id, + dest, + ) + } +} + +impl scale::Decode for ContractRef +where + E: ink_env::Environment, + ::AccountId: scale::Decode, +{ + #[inline] + fn decode(input: &mut I) -> Result { + <::AccountId as scale::Decode>::decode(input) + .map(>::from_account_id) + } +} + +impl ink_env::call::FromAccountId for ContractRef +where + E: ink_env::Environment, +{ + #[inline] + fn from_account_id(account_id: ::AccountId) -> Self { + Self { + account_id, + __marker: PhantomData, + } + } +} + +impl crate::ToAccountId for ContractRef +where + E: ink_env::Environment, + ::AccountId: Clone, +{ + #[inline] + fn to_account_id(&self) -> ::AccountId { + <::AccountId as core::clone::Clone>::clone( + &self.account_id, + ) + } +} + +impl core::hash::Hash for ContractRef +where + E: ink_env::Environment, + ::AccountId: core::hash::Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: core::hash::Hasher, + { + <::AccountId as core::hash::Hash>::hash( + &self.account_id, + state, + ) + } +} + +impl core::cmp::PartialEq for ContractRef +where + E: ink_env::Environment, + ::AccountId: core::cmp::PartialEq, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.account_id == other.account_id + } +} + +impl core::cmp::Eq for ContractRef +where + E: ink_env::Environment, + ::AccountId: Eq, +{ +} From 272b72795fca1a1d1017681def4e5d3c7e8ecfb3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 00:52:08 +0200 Subject: [PATCH 137/493] re-export ContractRef and ContractName from ink_lang crate ContractName is a utility trait used to improve Debug output of ContractRef. --- crates/lang/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index f82ad254dd..b43c7193c3 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -22,8 +22,13 @@ mod env_access; mod error; mod events; mod traits; +mod contract_ref; pub use self::{ + contract_ref::{ + ContractRef, + ContractName, + }, chain_extension::{ ChainExtensionInstance, IsResultType, From e09a742e1a113a95f1697a4684cbd5d9c680dee0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 15:29:35 +0200 Subject: [PATCH 138/493] add SpreadLayout and PackedLayout impls for generic ContractRef --- crates/lang/src/contract_ref.rs | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index 17954f03a7..9c5bd18a37 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -165,3 +165,48 @@ where ::AccountId: Eq, { } + +impl ink_storage::traits::SpreadLayout for ContractRef +where + E: ink_env::Environment, + ::AccountId: ink_storage::traits::SpreadLayout, +{ + const FOOTPRINT: u64 = 1; + const REQUIRES_DEEP_CLEAN_UP: bool = false; + + #[inline] + fn pull_spread(ptr: &mut ::ink_primitives::KeyPtr) -> Self { + Self { + account_id: <::AccountId + as ink_storage::traits::SpreadLayout>::pull_spread(ptr), + __marker: PhantomData, + } + } + + #[inline] + fn push_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + <::AccountId + as ink_storage::traits::SpreadLayout>::push_spread(&self.account_id, ptr) + } + + #[inline] + fn clear_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + <::AccountId + as ink_storage::traits::SpreadLayout>::clear_spread(&self.account_id, ptr) + } +} + +impl ink_storage::traits::PackedLayout for ContractRef +where + E: ink_env::Environment, + ::AccountId: ink_storage::traits::PackedLayout, +{ + #[inline(always)] + fn pull_packed(&mut self, _at: &ink_primitives::Key) {} + + #[inline(always)] + fn push_packed(&self, _at: &ink_primitives::Key) {} + + #[inline(always)] + fn clear_packed(&self, _at: &ink_primitives::Key) {} +} From a0ad24e318deb74c2d025b06fa72d5d7b10faf48 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 17:09:35 +0200 Subject: [PATCH 139/493] rename ContractRef to CallBuilderBase --- crates/lang/src/contract_ref.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index 9c5bd18a37..a1c4d603e9 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -20,15 +20,15 @@ pub trait ContractName { const NAME: &'static str; } -/// A generic ink! smart contract reference. +/// A generic ink! smart contract call builder. /// /// This utility struct is generic over the ink! environment `E` -/// as well as over the concrete smart contract `T`. +/// as well as over a `T`, usually a concrete smart contract. /// /// This is used by the ink! codegen in order to implement various /// implementations for calling smart contract instances of contract /// `T` using environment `E` on-chain. -pub struct ContractRef +pub struct CallBuilderBase where E: ink_env::Environment, { @@ -36,7 +36,7 @@ where __marker: PhantomData T>, } -impl core::fmt::Debug for ContractRef +impl core::fmt::Debug for CallBuilderBase where E: ink_env::Environment, ::AccountId: core::fmt::Debug, @@ -51,14 +51,14 @@ where } } -impl Copy for ContractRef +impl Copy for CallBuilderBase where E: ink_env::Environment, ::AccountId: Copy, { } -impl Clone for ContractRef +impl Clone for CallBuilderBase where E: ink_env::Environment, ::AccountId: Clone, @@ -72,7 +72,7 @@ where } } -impl scale::Encode for ContractRef +impl scale::Encode for CallBuilderBase where E: ink_env::Environment, ::AccountId: scale::Encode, @@ -93,7 +93,7 @@ where } } -impl scale::Decode for ContractRef +impl scale::Decode for CallBuilderBase where E: ink_env::Environment, ::AccountId: scale::Decode, @@ -105,7 +105,7 @@ where } } -impl ink_env::call::FromAccountId for ContractRef +impl ink_env::call::FromAccountId for CallBuilderBase where E: ink_env::Environment, { @@ -118,7 +118,7 @@ where } } -impl crate::ToAccountId for ContractRef +impl crate::ToAccountId for CallBuilderBase where E: ink_env::Environment, ::AccountId: Clone, @@ -131,7 +131,7 @@ where } } -impl core::hash::Hash for ContractRef +impl core::hash::Hash for CallBuilderBase where E: ink_env::Environment, ::AccountId: core::hash::Hash, @@ -148,7 +148,7 @@ where } } -impl core::cmp::PartialEq for ContractRef +impl core::cmp::PartialEq for CallBuilderBase where E: ink_env::Environment, ::AccountId: core::cmp::PartialEq, @@ -159,14 +159,14 @@ where } } -impl core::cmp::Eq for ContractRef +impl core::cmp::Eq for CallBuilderBase where E: ink_env::Environment, ::AccountId: Eq, { } -impl ink_storage::traits::SpreadLayout for ContractRef +impl ink_storage::traits::SpreadLayout for CallBuilderBase where E: ink_env::Environment, ::AccountId: ink_storage::traits::SpreadLayout, @@ -196,7 +196,7 @@ where } } -impl ink_storage::traits::PackedLayout for ContractRef +impl ink_storage::traits::PackedLayout for CallBuilderBase where E: ink_env::Environment, ::AccountId: ink_storage::traits::PackedLayout, From ad88a63ad99067f43e0e58e31b2fc8deaec6a5a6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 17:10:02 +0200 Subject: [PATCH 140/493] add CallForwarderBase based on CallBuilderBase --- crates/lang/src/contract_ref.rs | 189 ++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index a1c4d603e9..2934d0b0f6 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -210,3 +210,192 @@ where #[inline(always)] fn clear_packed(&self, _at: &ink_primitives::Key) {} } + +/// A generic ink! smart contract call forwader. +/// +/// A call forwarder is a thin wrapper arround a call builder +/// that forwards the long-hand calls to the builder and directly +/// serves as the interface for the short-hand calls and constructors. +/// +/// This utility struct is generic over the ink! environment `E` +/// as well as over a `T`, usually a concrete smart contract. +/// +/// This is used by the ink! codegen in order to implement various +/// implementations for calling smart contract instances of contract +/// `T` using environment `E` on-chain. +#[repr(transparent)] +pub struct CallForwarderBase +where + E: ink_env::Environment, +{ + call_builder: CallBuilderBase, +} + +impl core::fmt::Debug for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: core::fmt::Debug, + T: ContractName, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CallForwarderBase") + .field("call_builder", &self.call_builder) + .finish() + } +} + +impl Copy for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: Copy, +{ +} + +impl Clone for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: Clone, +{ + #[inline] + fn clone(&self) -> Self { + Self { + call_builder: as Clone>::clone(&self.call_builder), + } + } +} + +impl scale::Encode for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: scale::Encode, +{ + #[inline] + fn size_hint(&self) -> usize { + as scale::Encode>::size_hint(&self.call_builder) + } + + #[inline] + fn encode_to(&self, dest: &mut O) { + as scale::Encode>::encode_to(&self.call_builder, dest) + } +} + +impl scale::Decode for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: scale::Decode, +{ + #[inline] + fn decode(input: &mut I) -> Result { + as scale::Decode>::decode(input) + .map(|call_builder| Self { call_builder }) + } +} + +impl ink_env::call::FromAccountId for CallForwarderBase +where + E: ink_env::Environment, +{ + #[inline] + fn from_account_id(account_id: ::AccountId) -> Self { + Self { + call_builder: + as ink_env::call::FromAccountId>::from_account_id(account_id) + } + } +} + +impl crate::ToAccountId for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: Clone, +{ + #[inline] + fn to_account_id(&self) -> ::AccountId { + as crate::ToAccountId>::to_account_id( + &self.call_builder, + ) + } +} + +impl core::hash::Hash for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: core::hash::Hash, +{ + #[inline] + fn hash(&self, state: &mut H) + where + H: core::hash::Hasher, + { + as core::hash::Hash>::hash(&self.call_builder, state) + } +} + +impl core::cmp::PartialEq for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: core::cmp::PartialEq, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.call_builder == other.call_builder + } +} + +impl core::cmp::Eq for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: Eq, +{ +} + +impl ink_storage::traits::SpreadLayout for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: ink_storage::traits::SpreadLayout, +{ + const FOOTPRINT: u64 = 1; + const REQUIRES_DEEP_CLEAN_UP: bool = false; + + #[inline] + fn pull_spread(ptr: &mut ::ink_primitives::KeyPtr) -> Self { + Self { + call_builder: + as ink_storage::traits::SpreadLayout>::pull_spread( + ptr, + ), + } + } + + #[inline] + fn push_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + as ink_storage::traits::SpreadLayout>::push_spread( + &self.call_builder, + ptr, + ) + } + + #[inline] + fn clear_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { + as ink_storage::traits::SpreadLayout>::clear_spread( + &self.call_builder, + ptr, + ) + } +} + +impl ink_storage::traits::PackedLayout for CallForwarderBase +where + E: ink_env::Environment, + ::AccountId: ink_storage::traits::PackedLayout, +{ + #[inline(always)] + fn pull_packed(&mut self, _at: &ink_primitives::Key) {} + + #[inline(always)] + fn push_packed(&self, _at: &ink_primitives::Key) {} + + #[inline(always)] + fn clear_packed(&self, _at: &ink_primitives::Key) {} +} From 5f2db9acf5cef42929415399bebfb1a38e318b37 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 17:10:19 +0200 Subject: [PATCH 141/493] re-export new CallBuilderBase and CallForwarderBase types from ink_lang --- crates/lang/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index b43c7193c3..ab483c5902 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -26,7 +26,8 @@ mod contract_ref; pub use self::{ contract_ref::{ - ContractRef, + CallBuilderBase, + CallForwarderBase, ContractName, }, chain_extension::{ From 7f65aec0dafa956853d70ef210da98a5c31b8c1a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 17:40:18 +0200 Subject: [PATCH 142/493] call TraitCallBuilder impl for CallForwarderBase --- crates/lang/src/contract_ref.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index 2934d0b0f6..cdea60ab56 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -231,6 +231,24 @@ where call_builder: CallBuilderBase, } +impl crate::TraitCallBuilder for CallForwarderBase +where + E: ink_env::Environment, +{ + type Builder = CallBuilderBase; + + #[inline] + fn call(&self) -> &Self::Builder { + &self.call_builder + } + + #[inline] + fn call_mut(&mut self) -> &mut Self::Builder { + &mut self.call_builder + } + +} + impl core::fmt::Debug for CallForwarderBase where E: ink_env::Environment, From 64089304bf8817fdcc9d36a0c56fb93874201889 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 13 Sep 2021 19:40:41 +0200 Subject: [PATCH 143/493] add repr(transparent) to CallBuilderBase --- crates/lang/src/contract_ref.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index cdea60ab56..cd32bed9ed 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -28,6 +28,7 @@ pub trait ContractName { /// This is used by the ink! codegen in order to implement various /// implementations for calling smart contract instances of contract /// `T` using environment `E` on-chain. +#[repr(transparent)] pub struct CallBuilderBase where E: ink_env::Environment, From cd1ebfdc647c7bfc1011db58614cfe5acf426352 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 19:59:05 +0200 Subject: [PATCH 144/493] fix bug that trait registry __ink_TraitInfo referred to trait call forwarder --- crates/lang/codegen/src/generator/trait_def/trait_registry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 0d8058ddcb..80f2f51a63 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -94,7 +94,7 @@ impl TraitRegistry<'_> { fn generate_registry_impl(&self) -> TokenStream2 { let span = self.span(); let name = self.trait_ident(); - let trait_info_ident = self.trait_def.call_forwarder_ident(); + let trait_info_ident = self.trait_def.trait_info_ident(); let messages = self.generate_registry_messages(); quote_spanned!(span=> impl #name for ::ink_lang::TraitCallForwarderRegistry From f4b16a72a55fa9e46849ecb817b78c65efe3581c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 20:34:01 +0200 Subject: [PATCH 145/493] rename CallForwarderBase-> ContractRef and replace ::std -> ::core --- crates/lang/src/contract_ref.rs | 32 ++++++++++++++++---------------- crates/lang/src/lib.rs | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index cd32bed9ed..e0cfaa46a4 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -43,7 +43,7 @@ where ::AccountId: core::fmt::Debug, T: ContractName, { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let name = ::NAME; f.debug_struct("ContractRef") .field("name", &name) @@ -225,14 +225,14 @@ where /// implementations for calling smart contract instances of contract /// `T` using environment `E` on-chain. #[repr(transparent)] -pub struct CallForwarderBase +pub struct ContractRef where E: ink_env::Environment, { call_builder: CallBuilderBase, } -impl crate::TraitCallBuilder for CallForwarderBase +impl crate::TraitCallBuilder for ContractRef where E: ink_env::Environment, { @@ -250,27 +250,27 @@ where } -impl core::fmt::Debug for CallForwarderBase +impl core::fmt::Debug for ContractRef where E: ink_env::Environment, ::AccountId: core::fmt::Debug, T: ContractName, { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("CallForwarderBase") .field("call_builder", &self.call_builder) .finish() } } -impl Copy for CallForwarderBase +impl Copy for ContractRef where E: ink_env::Environment, ::AccountId: Copy, { } -impl Clone for CallForwarderBase +impl Clone for ContractRef where E: ink_env::Environment, ::AccountId: Clone, @@ -283,7 +283,7 @@ where } } -impl scale::Encode for CallForwarderBase +impl scale::Encode for ContractRef where E: ink_env::Environment, ::AccountId: scale::Encode, @@ -299,7 +299,7 @@ where } } -impl scale::Decode for CallForwarderBase +impl scale::Decode for ContractRef where E: ink_env::Environment, ::AccountId: scale::Decode, @@ -311,7 +311,7 @@ where } } -impl ink_env::call::FromAccountId for CallForwarderBase +impl ink_env::call::FromAccountId for ContractRef where E: ink_env::Environment, { @@ -324,7 +324,7 @@ where } } -impl crate::ToAccountId for CallForwarderBase +impl crate::ToAccountId for ContractRef where E: ink_env::Environment, ::AccountId: Clone, @@ -337,7 +337,7 @@ where } } -impl core::hash::Hash for CallForwarderBase +impl core::hash::Hash for ContractRef where E: ink_env::Environment, ::AccountId: core::hash::Hash, @@ -351,7 +351,7 @@ where } } -impl core::cmp::PartialEq for CallForwarderBase +impl core::cmp::PartialEq for ContractRef where E: ink_env::Environment, ::AccountId: core::cmp::PartialEq, @@ -362,14 +362,14 @@ where } } -impl core::cmp::Eq for CallForwarderBase +impl core::cmp::Eq for ContractRef where E: ink_env::Environment, ::AccountId: Eq, { } -impl ink_storage::traits::SpreadLayout for CallForwarderBase +impl ink_storage::traits::SpreadLayout for ContractRef where E: ink_env::Environment, ::AccountId: ink_storage::traits::SpreadLayout, @@ -404,7 +404,7 @@ where } } -impl ink_storage::traits::PackedLayout for CallForwarderBase +impl ink_storage::traits::PackedLayout for ContractRef where E: ink_env::Environment, ::AccountId: ink_storage::traits::PackedLayout, diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index ab483c5902..a3f7f65317 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -27,7 +27,7 @@ mod contract_ref; pub use self::{ contract_ref::{ CallBuilderBase, - CallForwarderBase, + ContractRef, ContractName, }, chain_extension::{ From ef39f509283d3c681db1a8d07f399b458da05b31 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 20:34:19 +0200 Subject: [PATCH 146/493] add ink_lang::ContractReference --- crates/lang/src/contract_ref.rs | 6 ++++++ crates/lang/src/lib.rs | 1 + 2 files changed, 7 insertions(+) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index e0cfaa46a4..e38ba18707 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -14,6 +14,12 @@ use core::marker::PhantomData; +/// Used to refer to the generated contract reference from the given contract storage struct. +pub trait ContractReference { + /// The generated contract reference type. + type Type; +} + /// Trait to inform about the name of an ink! smart contract. pub trait ContractName { /// The name of the ink! smart contract. diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index a3f7f65317..911bf3b6f1 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -27,6 +27,7 @@ mod contract_ref; pub use self::{ contract_ref::{ CallBuilderBase, + ContractReference, ContractRef, ContractName, }, From 578242db9f6ef7ef701a52336bb24372751525fa Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 21:18:53 +0200 Subject: [PATCH 147/493] add ::ink_lang::ContractCallBuilder connector trait --- crates/lang/src/contract_ref.rs | 9 +++++++++ crates/lang/src/lib.rs | 15 ++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index e38ba18707..e4600c66b5 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -20,6 +20,15 @@ pub trait ContractReference { type Type; } +/// Used to refer to the generated contract call builder. +/// +/// The generated contract call builder implements the long-hand calling API +/// for all inherent or trait ink! messages. +pub trait ContractCallBuilder { + /// The generated contract call builder type. + type Type; +} + /// Trait to inform about the name of an ink! smart contract. pub trait ContractName { /// The name of the ink! smart contract. diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 911bf3b6f1..711559b243 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -16,21 +16,15 @@ mod chain_extension; mod contract; +mod contract_ref; mod cross_calling; mod dispatcher; mod env_access; mod error; mod events; mod traits; -mod contract_ref; pub use self::{ - contract_ref::{ - CallBuilderBase, - ContractReference, - ContractRef, - ContractName, - }, chain_extension::{ ChainExtensionInstance, IsResultType, @@ -39,6 +33,13 @@ pub use self::{ DispatchMode, DispatchUsingMode, }, + contract_ref::{ + CallBuilderBase, + ContractCallBuilder, + ContractName, + ContractRef, + ContractReference, + }, cross_calling::{ ForwardCall, ForwardCallMut, From 69e0eb03d2e3576869e9e9461d17d0713ff74186 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 21:19:01 +0200 Subject: [PATCH 148/493] apply rustfmt --- crates/lang/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 711559b243..bf549534bd 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -72,7 +72,6 @@ pub use self::{ EmitEvent, }, traits::{ - TraitImplementer, Constructor, FnInput, FnOutput, @@ -84,10 +83,11 @@ pub use self::{ NoConcreteImplementer, TraitCallBuilder, TraitCallForwarder, - TraitCallForwarderRegistry, - TraitUniqueId, TraitCallForwarderFor, + TraitCallForwarderRegistry, + TraitImplementer, TraitModulePath, + TraitUniqueId, True, }, }; From df0d455da79df206118383139dd83e2c8306ac4f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 21:19:19 +0200 Subject: [PATCH 149/493] add codegen for ::ink_lang::ContractName --- crates/lang/codegen/src/generator/storage.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index aa6e7d1619..d211e43c68 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -107,6 +107,12 @@ impl Storage<'_> { pub struct #ident { #( #fields ),* } + + const _: () = { + impl ::ink_lang::ContractName for #ident { + const NAME: &'static str = ::core::stringify!(#ident); + } + }; ) } } From e5d0eadb453db9c06088c379c5734ba543dd2235 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 21:20:00 +0200 Subject: [PATCH 150/493] move call_builder.rs into as_dependency module --- .../{ => as_dependency}/call_builder.rs | 279 +------------ .../generator/as_dependency/contract_ref.rs | 369 ++++++++++++++++++ .../mod.rs} | 41 +- crates/lang/codegen/src/generator/contract.rs | 4 +- crates/lang/codegen/src/generator/mod.rs | 3 +- 5 files changed, 418 insertions(+), 278 deletions(-) rename crates/lang/codegen/src/generator/{ => as_dependency}/call_builder.rs (59%) create mode 100644 crates/lang/codegen/src/generator/as_dependency/contract_ref.rs rename crates/lang/codegen/src/generator/{as_dependency.rs => as_dependency/mod.rs} (68%) diff --git a/crates/lang/codegen/src/generator/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs similarity index 59% rename from crates/lang/codegen/src/generator/call_builder.rs rename to crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 8491e62a7f..116a09a498 100644 --- a/crates/lang/codegen/src/generator/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -45,22 +45,16 @@ pub struct CallBuilder<'a> { impl GenerateCode for CallBuilder<'_> { fn generate_code(&self) -> TokenStream2 { let call_builder_struct = self.generate_struct(); - let trait_impl = self.generate_trait_impl(); let auxiliary_trait_impls = self.generate_auxiliary_trait_impls(); let call_builder_impls = self.generate_call_forwarder_impls(); let call_builder_inherent_impls = self.generate_call_builder_inherent_impls(); - let contract_trait_impls = self.generate_contract_trait_impls(); - let contract_inherent_impls = self.generate_contract_inherent_impls(); quote! { const _: () = { #call_builder_struct - #trait_impl #auxiliary_trait_impls #call_builder_impls #call_builder_inherent_impls }; - #contract_trait_impls - #contract_inherent_impls } } } @@ -80,6 +74,7 @@ impl CallBuilder<'_> { fn generate_struct(&self) -> TokenStream2 { let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); let cb_ident = Self::call_builder_ident(); quote_spanned!(span=> /// The ink! smart contract's call builder. @@ -100,31 +95,12 @@ impl CallBuilder<'_> { pub struct #cb_ident { account_id: AccountId, } - ) - } - /// Generates the `CallBuilder` trait implementation for the ink! contract. - /// - /// This creates the bridge between the ink! smart contract type and the - /// associated call builder. - fn generate_trait_impl(&self) -> TokenStream2 { - let span = self.contract.module().storage().span(); - let storage_ident = self.contract.module().storage().ident(); - let cb_ident = Self::call_builder_ident(); - quote_spanned!(span=> - impl ::ink_lang::TraitCallBuilder for #storage_ident { - type Builder = #cb_ident; - - #[inline] - fn call(&self) -> &Self::Builder { - &self.builder - } - - #[inline] - fn call_mut(&mut self) -> &mut Self::Builder { - &mut self.builder + const _: () = { + impl ::ink_lang::ContractCallBuilder for #storage_ident { + type Type = #cb_ident; } - } + }; ) } @@ -204,7 +180,7 @@ impl CallBuilder<'_> { quote_spanned!(span=> #[doc(hidden)] impl ::ink_lang::TraitCallForwarderFor<#unique_trait_id> for #cb_ident { - type Forwarder = <::__ink_TraitInfo as ::ink_lang::TraitCallForwarder>::Forwarder; + type Forwarder = <::__ink_TraitInfo as ::ink_lang::TraitCallForwarder>::Forwarder; #[inline(always)] fn forward(&self) -> &Self::Forwarder { @@ -452,247 +428,4 @@ impl CallBuilder<'_> { } ) } - - /// Generates the code for all ink! trait implementations of the contract itself. - /// - /// # Note - /// - /// The generated implementations must live outside of an artificial `const` block - /// in order to properly show their documentation using `rustdoc`. - fn generate_contract_trait_impls(&self) -> TokenStream2 { - self.contract - .module() - .impls() - .filter_map(|impl_block| { - // We are only interested in ink! trait implementation block. - impl_block.trait_path().map(|trait_path| { - self.generate_contract_trait_impl(trait_path, impl_block) - }) - }) - .collect() - } - - /// Generates the code for a single ink! trait implementation of the contract itself. - /// - /// The generated implementation mainly forwards the calls to the previously generated - /// associated call builder that implements each respective ink! trait. - fn generate_contract_trait_impl( - &self, - trait_path: &syn::Path, - impl_block: &ir::ItemImpl, - ) -> TokenStream2 { - let span = impl_block.span(); - let attrs = impl_block.attrs(); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); - let storage_ident = self.contract.module().storage().ident(); - let messages = self.generate_contract_trait_impl_messages(trait_path, impl_block); - quote_spanned!(span=> - #[doc(hidden)] - unsafe impl - ::ink_lang::TraitImplementer<#unique_trait_id> for #storage_ident - {} - - #( #attrs )* - impl #trait_path for #storage_ident { - type Env = Environment; - - #[doc(hidden)] - type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry - as #trait_path>::__ink_TraitInfo; - - #messages - } - ) - } - - /// Generates the code for all messages of a single ink! trait implementation of - /// the ink! smart contract. - fn generate_contract_trait_impl_messages( - &self, - trait_path: &syn::Path, - impl_block: &ir::ItemImpl, - ) -> TokenStream2 { - impl_block - .iter_messages() - .map(|message| { - self.generate_contract_trait_impl_for_message(trait_path, message) - }) - .collect() - } - - /// Generates the code for a single message of a single ink! trait implementation - /// that is implemented by the ink! smart contract. - fn generate_contract_trait_impl_for_message( - &self, - trait_path: &syn::Path, - message: ir::CallableWithSelector, - ) -> TokenStream2 { - use ir::Callable as _; - let span = message.span(); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); - let message_ident = message.ident(); - let output_ident = generator::output_ident(message_ident); - let call_operator = match message.receiver() { - ir::Receiver::Ref => quote! { call }, - ir::Receiver::RefMut => quote! { call_mut }, - }; - let forward_operator = match message.receiver() { - ir::Receiver::Ref => quote! { forward }, - ir::Receiver::RefMut => quote! { forward_mut }, - }; - let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); - let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); - let input_types = message.inputs().map(|input| &input.ty).collect::>(); - quote_spanned!(span=> - type #output_ident = - <::Forwarder as #trait_path>::#output_ident; - - #[inline] - fn #message_ident( - & #mut_token self - #( , #input_bindings : #input_types )* - ) -> Self::#output_ident { - <_ as #trait_path>::#message_ident( - <_ as ::ink_lang::TraitCallForwarderFor<#unique_trait_id>>::#forward_operator( - ::#call_operator(self), - ) - #( , #input_bindings )* - ) - } - ) - } - - /// Generates the code for all ink! inherent implementations of the contract itself. - /// - /// # Note - /// - /// The generated implementations must live outside of an artificial `const` block - /// in order to properly show their documentation using `rustdoc`. - fn generate_contract_inherent_impls(&self) -> TokenStream2 { - self.contract - .module() - .impls() - .filter_map(|impl_block| { - // We are only interested in ink! trait implementation block. - impl_block - .trait_path() - .is_none() - .then(|| self.generate_contract_inherent_impl(impl_block)) - }) - .collect() - } - - /// Generates the code for a single ink! inherent implementation of the contract itself. - /// - /// # Note - /// - /// This produces the short-hand calling notation for the inherent contract implementation. - /// The generated code simply forwards its calling logic to the associated call builder. - fn generate_contract_inherent_impl(&self, impl_block: &ir::ItemImpl) -> TokenStream2 { - let span = impl_block.span(); - let attrs = impl_block.attrs(); - let storage_ident = self.contract.module().storage().ident(); - let messages = impl_block - .iter_messages() - .map(|message| self.generate_contract_inherent_impl_for_message(message)); - let constructors = impl_block.iter_constructors().map(|constructor| { - self.generate_contract_inherent_impl_for_constructor(constructor) - }); - quote_spanned!(span=> - #( #attrs )* - impl #storage_ident { - #( #constructors )* - #( #messages )* - } - ) - } - - /// Generates the code for a single ink! inherent message of the contract itself. - /// - /// # Note - /// - /// This produces the short-hand calling notation for the inherent contract message. - /// The generated code simply forwards its calling logic to the associated call builder. - fn generate_contract_inherent_impl_for_message( - &self, - message: ir::CallableWithSelector, - ) -> TokenStream2 { - use ir::Callable as _; - let span = message.span(); - let attrs = message.attrs(); - let storage_ident = self.contract.module().storage().ident(); - let message_ident = message.ident(); - let call_operator = match message.receiver() { - ir::Receiver::Ref => quote! { call }, - ir::Receiver::RefMut => quote! { call_mut }, - }; - let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); - let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); - let input_types = message.inputs().map(|input| &input.ty).collect::>(); - let output_type = message.output().map(|ty| quote! { -> #ty }); - quote_spanned!(span=> - #( #attrs )* - #[inline] - pub fn #message_ident( - & #mut_token self - #( , #input_bindings : #input_types )* - ) #output_type { - ::#call_operator(self) - .#message_ident( #( #input_bindings ),* ) - .fire() - .unwrap_or_else(|error| ::core::panic!( - "encountered error while calling {}::{}: {}", - ::core::stringify!(#storage_ident), - ::core::stringify!(#message_ident), - error, - )) - } - ) - } - - /// Generates the code for a single ink! inherent constructor of the contract itself. - /// - /// # Note - /// - /// Unlike with ink! messages this does not forward to the call builder since constructor - /// calls in ink! do not have a short-hand notation and therefore this implements the - /// long-hand calling notation code directly. - fn generate_contract_inherent_impl_for_constructor( - &self, - constructor: ir::CallableWithSelector, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let constructor_ident = constructor.ident(); - let selector_bytes = constructor.composed_selector().hex_lits(); - let input_bindings = generator::input_bindings(constructor.inputs()); - let input_types = generator::input_types(constructor.inputs()); - let arg_list = generator::generate_argument_list(input_types.iter().cloned()); - quote_spanned!(span => - #( #attrs )* - #[inline] - #[allow(clippy::type_complexity)] - pub fn #constructor_ident( - #( #input_bindings : #input_types ),* - ) -> ::ink_env::call::CreateBuilder< - Environment, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, - ::ink_env::call::utils::Unset<::ink_env::call::state::Salt>, - Self, - > { - ::ink_env::call::build_create::() - .exec_input( - ::ink_env::call::ExecutionInput::new( - ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) - ) - #( - .push_arg(#input_bindings) - )* - ) - } - ) - } } diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs new file mode 100644 index 0000000000..d0a3b4003e --- /dev/null +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -0,0 +1,369 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + generator, + GenerateCode, +}; +use derive_more::From; +use ir::Callable; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ + quote, + quote_spanned, +}; +use syn::spanned::Spanned as _; + +/// Generates code for the contract reference of the ink! smart contract. +/// +/// The call builder is the entity that builds up calls for calling of other +/// smart contract on-chain in a type safe way. +/// It implements all ink! traits that the associated ink! smart contract implements +/// so that their underlying implementation directly calls the respective ink! +/// trait implementation on-chain. +/// +/// The ink! call builder of a smart contract is directly used by the storage +/// type of the smart contract itself as well by other entities that use the +/// smart contract via long-hand calling notation to incrementally build up calls. +#[derive(From)] +pub struct ContractRef<'a> { + contract: &'a ir::Contract, +} + +impl GenerateCode for ContractRef<'_> { + fn generate_code(&self) -> TokenStream2 { + let contract_ref = self.generate_struct(); + let contract_ref_trait_impls = self.generate_contract_trait_impls(); + let contract_ref_inherent_impls = self.generate_contract_inherent_impls(); + let call_builder_trait_impl = self.generate_call_builder_trait_impl(); + quote! { + #contract_ref + #contract_ref_trait_impls + #contract_ref_inherent_impls + #call_builder_trait_impl + } + } +} + +impl ContractRef<'_> { + /// Generates the identifier of the contract reference struct. + fn generate_contract_ref_ident(&self) -> syn::Ident { + quote::format_ident!("{}Ref", self.contract.module().storage().ident()) + } + + /// Generates the code for the struct representing the contract reference. + /// + /// The generated struct is the type onto which everything is implemented. + /// It is also the type that is going to be used by other smart contract + /// dynamically depending on the smart contract. It mirrors the smart contract + /// API but is just a typed thin-wrapper around an `AccountId`. + fn generate_struct(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let ref_ident = self.generate_contract_ref_ident(); + quote_spanned!(span=> + #[derive( + ::ink_storage::traits::SpreadLayout, + ::ink_storage::traits::PackedLayout, + ::scale::Encode, + ::scale::Decode, + ::core::clone::Clone, + ::core::marker::Copy, + ::core::hash::Hash, + ::core::cmp::PartialEq, + ::core::cmp::Eq, + ::core::fmt::Debug, + )] + pub struct #ref_ident { + inner: ::ink_lang::ContractRef<#storage_ident, Environment>, + } + + const _: () = { + impl ::ink_lang::ContractReference for #storage_ident { + type Type = #ref_ident; + } + }; + ) + } + + /// Generates the `CallBuilder` trait implementation for the contract reference. + /// + /// This creates the bridge between the ink! smart contract type and the + /// associated call builder. + fn generate_call_builder_trait_impl(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let ref_ident = self.generate_contract_ref_ident(); + let storage_ident = self.contract.module().storage().ident(); + quote_spanned!(span=> + const _: () = { + impl ::ink_lang::TraitCallBuilder for #ref_ident { + type Builder = <#storage_ident as ::ink_lang::ContractCallBuilder>::Type; + + #[inline] + fn call(&self) -> &Self::Builder { + &self.inner + } + + #[inline] + fn call_mut(&mut self) -> &mut Self::Builder { + &mut self.inner + } + } + }; + ) + } + + /// Generates the code for all ink! trait implementations of the contract itself. + /// + /// # Note + /// + /// The generated implementations must live outside of an artificial `const` block + /// in order to properly show their documentation using `rustdoc`. + fn generate_contract_trait_impls(&self) -> TokenStream2 { + self.contract + .module() + .impls() + .filter_map(|impl_block| { + // We are only interested in ink! trait implementation block. + impl_block.trait_path().map(|trait_path| { + self.generate_contract_trait_impl(trait_path, impl_block) + }) + }) + .collect() + } + + /// Generates the code for a single ink! trait implementation of the contract itself. + /// + /// The generated implementation mainly forwards the calls to the previously generated + /// associated call builder that implements each respective ink! trait. + fn generate_contract_trait_impl( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + let span = impl_block.span(); + let attrs = impl_block.attrs(); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); + let forwarder_ident = self.generate_contract_ref_ident(); + let messages = self.generate_contract_trait_impl_messages(trait_path, impl_block); + quote_spanned!(span=> + #[doc(hidden)] + unsafe impl + ::ink_lang::TraitImplementer<#unique_trait_id> for #forwarder_ident + {} + + #( #attrs )* + impl #trait_path for #forwarder_ident { + type Env = Environment; + + #[doc(hidden)] + type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry + as #trait_path>::__ink_TraitInfo; + + #messages + } + ) + } + + /// Generates the code for all messages of a single ink! trait implementation of + /// the ink! smart contract. + fn generate_contract_trait_impl_messages( + &self, + trait_path: &syn::Path, + impl_block: &ir::ItemImpl, + ) -> TokenStream2 { + impl_block + .iter_messages() + .map(|message| { + self.generate_contract_trait_impl_for_message(trait_path, message) + }) + .collect() + } + + /// Generates the code for a single message of a single ink! trait implementation + /// that is implemented by the ink! smart contract. + fn generate_contract_trait_impl_for_message( + &self, + trait_path: &syn::Path, + message: ir::CallableWithSelector, + ) -> TokenStream2 { + use ir::Callable as _; + let span = message.span(); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); + let message_ident = message.ident(); + let output_ident = generator::output_ident(message_ident); + let call_operator = match message.receiver() { + ir::Receiver::Ref => quote! { call }, + ir::Receiver::RefMut => quote! { call_mut }, + }; + let forward_operator = match message.receiver() { + ir::Receiver::Ref => quote! { forward }, + ir::Receiver::RefMut => quote! { forward_mut }, + }; + let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); + let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); + let input_types = message.inputs().map(|input| &input.ty).collect::>(); + quote_spanned!(span=> + type #output_ident = + <::Forwarder as #trait_path>::#output_ident; + + #[inline] + fn #message_ident( + & #mut_token self + #( , #input_bindings : #input_types )* + ) -> Self::#output_ident { + <_ as #trait_path>::#message_ident( + <_ as ::ink_lang::TraitCallForwarderFor<#unique_trait_id>>::#forward_operator( + ::#call_operator(self), + ) + #( , #input_bindings )* + ) + } + ) + } + + /// Generates the code for all ink! inherent implementations of the contract itself. + /// + /// # Note + /// + /// The generated implementations must live outside of an artificial `const` block + /// in order to properly show their documentation using `rustdoc`. + fn generate_contract_inherent_impls(&self) -> TokenStream2 { + self.contract + .module() + .impls() + .filter_map(|impl_block| { + // We are only interested in ink! trait implementation block. + impl_block + .trait_path() + .is_none() + .then(|| self.generate_contract_inherent_impl(impl_block)) + }) + .collect() + } + + /// Generates the code for a single ink! inherent implementation of the contract itself. + /// + /// # Note + /// + /// This produces the short-hand calling notation for the inherent contract implementation. + /// The generated code simply forwards its calling logic to the associated call builder. + fn generate_contract_inherent_impl(&self, impl_block: &ir::ItemImpl) -> TokenStream2 { + let span = impl_block.span(); + let attrs = impl_block.attrs(); + let forwarder_ident = self.generate_contract_ref_ident(); + let messages = impl_block + .iter_messages() + .map(|message| self.generate_contract_inherent_impl_for_message(message)); + let constructors = impl_block.iter_constructors().map(|constructor| { + self.generate_contract_inherent_impl_for_constructor(constructor) + }); + quote_spanned!(span=> + #( #attrs )* + impl #forwarder_ident { + #( #constructors )* + #( #messages )* + } + ) + } + + /// Generates the code for a single ink! inherent message of the contract itself. + /// + /// # Note + /// + /// This produces the short-hand calling notation for the inherent contract message. + /// The generated code simply forwards its calling logic to the associated call builder. + fn generate_contract_inherent_impl_for_message( + &self, + message: ir::CallableWithSelector, + ) -> TokenStream2 { + use ir::Callable as _; + let span = message.span(); + let attrs = message.attrs(); + let storage_ident = self.contract.module().storage().ident(); + let message_ident = message.ident(); + let call_operator = match message.receiver() { + ir::Receiver::Ref => quote! { call }, + ir::Receiver::RefMut => quote! { call_mut }, + }; + let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); + let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); + let input_types = message.inputs().map(|input| &input.ty).collect::>(); + let output_type = message.output().map(|ty| quote! { -> #ty }); + quote_spanned!(span=> + #( #attrs )* + #[inline] + pub fn #message_ident( + & #mut_token self + #( , #input_bindings : #input_types )* + ) #output_type { + ::#call_operator(self) + .#message_ident( #( #input_bindings ),* ) + .fire() + .unwrap_or_else(|error| ::core::panic!( + "encountered error while calling {}::{}: {}", + ::core::stringify!(#storage_ident), + ::core::stringify!(#message_ident), + error, + )) + } + ) + } + + /// Generates the code for a single ink! inherent constructor of the contract itself. + /// + /// # Note + /// + /// Unlike with ink! messages this does not forward to the call builder since constructor + /// calls in ink! do not have a short-hand notation and therefore this implements the + /// long-hand calling notation code directly. + fn generate_contract_inherent_impl_for_constructor( + &self, + constructor: ir::CallableWithSelector, + ) -> TokenStream2 { + let span = constructor.span(); + let attrs = constructor.attrs(); + let constructor_ident = constructor.ident(); + let selector_bytes = constructor.composed_selector().hex_lits(); + let input_bindings = generator::input_bindings(constructor.inputs()); + let input_types = generator::input_types(constructor.inputs()); + let arg_list = generator::generate_argument_list(input_types.iter().cloned()); + quote_spanned!(span => + #( #attrs )* + #[inline] + #[allow(clippy::type_complexity)] + pub fn #constructor_ident( + #( #input_bindings : #input_types ),* + ) -> ::ink_env::call::CreateBuilder< + Environment, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Unset, + ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, + ::ink_env::call::utils::Unset<::ink_env::call::state::Salt>, + Self, + > { + ::ink_env::call::build_create::() + .exec_input( + ::ink_env::call::ExecutionInput::new( + ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) + ) + #( + .push_arg(#input_bindings) + )* + ) + } + ) + } +} diff --git a/crates/lang/codegen/src/generator/as_dependency.rs b/crates/lang/codegen/src/generator/as_dependency/mod.rs similarity index 68% rename from crates/lang/codegen/src/generator/as_dependency.rs rename to crates/lang/codegen/src/generator/as_dependency/mod.rs index 1f0d7ca415..2c6da30819 100644 --- a/crates/lang/codegen/src/generator/as_dependency.rs +++ b/crates/lang/codegen/src/generator/as_dependency/mod.rs @@ -12,7 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::GenerateCode; +mod call_builder; +mod contract_ref; + +use self::{ + call_builder::CallBuilder, + contract_ref::ContractRef, +}; +use crate::{ + traits::GenerateCodeUsing, + GenerateCode, +}; use derive_more::From; use proc_macro2::TokenStream as TokenStream2; use quote::quote; @@ -58,3 +68,32 @@ impl GenerateCode for OnlyAsDependencyCfg<'_> { } } } + +/// Generates code for generating a contract reference. +/// +/// Contract references are used to dynamically depend on a smart contract. +/// The contract reference is just a typed thin-wrapper around an `AccountId` +/// that implements an API mirrored by the smart contract. +#[derive(From)] +pub struct ContractReference<'a> { + /// The contract to generate code for. + contract: &'a ir::Contract, +} + +impl AsRef for ContractReference<'_> { + fn as_ref(&self) -> &ir::Contract { + self.contract + } +} + +impl GenerateCode for ContractReference<'_> { + /// Generates ink! contract code. + fn generate_code(&self) -> TokenStream2 { + let call_builder = self.generate_code_using::(); + let call_forwarder = self.generate_code_using::(); + quote! { + #call_builder + #call_forwarder + } + } +} diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index 44dfd02a55..a094a1b6b3 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -47,7 +47,7 @@ impl GenerateCode for Contract<'_> { let dispatch = self.generate_code_using::(); let item_impls = self.generate_code_using::(); let metadata = self.generate_code_using::(); - let call_builder = self.generate_code_using::(); + let contract_reference = self.generate_code_using::(); let non_ink_items = self .contract .module() @@ -62,7 +62,7 @@ impl GenerateCode for Contract<'_> { #events #dispatch #item_impls - #call_builder + #contract_reference #metadata #( #non_ink_items )* } diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index daa0edf0e0..ce57f45b44 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -28,7 +28,6 @@ macro_rules! impl_as_ref_for_generator { mod arg_list; mod as_dependency; -mod call_builder; mod chain_extension; mod contract; mod cross_calling; @@ -53,8 +52,8 @@ pub use self::{ as_dependency::{ NotAsDependencyCfg, OnlyAsDependencyCfg, + ContractReference, }, - call_builder::CallBuilder, chain_extension::ChainExtension, contract::Contract, cross_calling::CrossCalling, From 42908d6e38a0b1f48e2084255b2f8741aa89be8a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 23:32:39 +0200 Subject: [PATCH 151/493] fix codegen for ghost trait registry impls --- .../src/generator/trait_def/trait_registry.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 80f2f51a63..2388e3f1cf 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -20,7 +20,13 @@ //! types for the trait's respective call builder and call forwarder. use super::TraitDefinition; -use crate::{generator::{self, enforced_error::EnforcedErrors}, traits::GenerateCode}; +use crate::{ + generator::{ + self, + enforced_error::EnforcedErrors, + }, + traits::GenerateCode, +}; use derive_more::From; use ir::HexLiteral; use proc_macro2::{ @@ -32,6 +38,7 @@ use quote::{ quote, quote_spanned, }; +use syn::parse_quote; impl<'a> TraitDefinition<'a> { /// Generates the code for the global trait registry implementation. @@ -141,6 +148,11 @@ impl TraitRegistry<'_> { let ident = message.ident(); let attrs = message.attrs(); let output_ident = generator::output_ident(message.ident()); + let output_type = message + .output() + .cloned() + .unwrap_or_else(|| parse_quote! { () }); + let mut_token = message.receiver().is_ref_mut().then(|| quote! { mut }); let (input_bindings, input_types) = Self::input_bindings_and_types(message.inputs()); let linker_error_ident = EnforcedErrors::cannot_call_trait_message( @@ -150,13 +162,14 @@ impl TraitRegistry<'_> { message.mutates(), ); quote_spanned!(span => - type #output_ident = ::ink_lang::NeverReturns; + type #output_ident = #output_type; #( #attrs )* #[cold] #[doc(hidden)] fn #ident( - #( #input_bindings : #input_types ),* + & #mut_token self + #( , #input_bindings : #input_types )* ) -> Self::#output_ident { /// We enforce linking errors in case this is ever actually called. /// These linker errors are properly resolved by the cargo-contract tool. From 09eb777c0e38b056266c2808076433e38317095e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 23:33:12 +0200 Subject: [PATCH 152/493] fix self.contract usage -> self.account_id --- crates/lang/codegen/src/generator/as_dependency/call_builder.rs | 2 +- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 116a09a498..bb45d78bd4 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -415,7 +415,7 @@ impl CallBuilder<'_> { #( , #input_bindings : #input_types )* ) -> #output_type { ::ink_env::call::build_call::() - .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) + .callee(self.account_id) .exec_input( ::ink_env::call::ExecutionInput::new( ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 2ca0e6222c..ae703cc7f5 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -395,7 +395,7 @@ impl CallBuilder<'_> { #( , #input_bindings : #input_types )* ) -> Self::#output_ident { ::ink_env::call::build_call::() - .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) + .callee(self.account_id) .exec_input( ::ink_env::call::ExecutionInput::new( ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) From b885f9f46c86296daad6d5ec4e96994e66f3f436 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 23:33:41 +0200 Subject: [PATCH 153/493] add auxiliary trait impls to Ref struct codegen --- .../generator/as_dependency/contract_ref.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index d0a3b4003e..fafc53dc49 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -47,11 +47,13 @@ impl GenerateCode for ContractRef<'_> { let contract_ref_trait_impls = self.generate_contract_trait_impls(); let contract_ref_inherent_impls = self.generate_contract_inherent_impls(); let call_builder_trait_impl = self.generate_call_builder_trait_impl(); + let auxiliary_trait_impls = self.generate_auxiliary_trait_impls(); quote! { #contract_ref #contract_ref_trait_impls #contract_ref_inherent_impls #call_builder_trait_impl + #auxiliary_trait_impls } } } @@ -97,6 +99,35 @@ impl ContractRef<'_> { ) } + /// Generates some ink! specific auxiliary trait implementations for the + /// smart contract reference type. + /// + /// These are required to properly interoperate with the contract reference. + fn generate_auxiliary_trait_impls(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let ref_ident = self.generate_contract_ref_ident(); + quote_spanned!(span=> + impl ::ink_env::call::FromAccountId for #ref_ident { + #[inline] + fn from_account_id(account_id: AccountId) -> Self { + Self { inner: <<#storage_ident + as ::ink_lang::ContractCallBuilder>::Type + as ::ink_env::call::FromAccountId>::from_account_id(account_id) + } + } + } + + impl ::ink_lang::ToAccountId for #ref_ident { + #[inline] + fn to_account_id(&self) -> AccountId { + <<#storage_ident as ::ink_lang::ContractCallBuilder>::Type + as ::ink_lang::ToAccountId>::to_account_id(&self.inner) + } + } + ) + } + /// Generates the `CallBuilder` trait implementation for the contract reference. /// /// This creates the bridge between the ink! smart contract type and the From 83078322aaf15d96d1b2a14a2eef115da050f656 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 23:34:00 +0200 Subject: [PATCH 154/493] sync codegen of CallBuilder and Ref struct types --- .../codegen/src/generator/as_dependency/call_builder.rs | 7 +++++-- .../codegen/src/generator/as_dependency/contract_ref.rs | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index bb45d78bd4..2a8a4f6e92 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -87,10 +87,13 @@ impl CallBuilder<'_> { ::ink_storage::traits::StorageLayout, ))] #[derive( - ::scale::Encode, - ::scale::Decode, ::ink_storage::traits::SpreadLayout, ::ink_storage::traits::PackedLayout, + ::scale::Encode, + ::scale::Decode, + ::core::hash::Hash, + ::core::cmp::PartialEq, + ::core::cmp::Eq, )] pub struct #cb_ident { account_id: AccountId, diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index fafc53dc49..2192f5c286 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -75,20 +75,21 @@ impl ContractRef<'_> { let storage_ident = self.contract.module().storage().ident(); let ref_ident = self.generate_contract_ref_ident(); quote_spanned!(span=> + #[cfg_attr(feature = "std", derive( + ::core::fmt::Debug, + ::ink_storage::traits::StorageLayout, + ))] #[derive( ::ink_storage::traits::SpreadLayout, ::ink_storage::traits::PackedLayout, ::scale::Encode, ::scale::Decode, - ::core::clone::Clone, - ::core::marker::Copy, ::core::hash::Hash, ::core::cmp::PartialEq, ::core::cmp::Eq, - ::core::fmt::Debug, )] pub struct #ref_ident { - inner: ::ink_lang::ContractRef<#storage_ident, Environment>, + inner: <#storage_ident as ::ink_lang::ContractCallBuilder>::Type, } const _: () = { From 6a0d341d66f0b88f379bd7c9c08cd7f8fadbaaee Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 23:35:39 +0200 Subject: [PATCH 155/493] use Debug instead of Display for printing ink_env::Error Ideally we implement Display for ink_env::Error. --- crates/lang/codegen/src/generator/as_dependency/contract_ref.rs | 2 +- crates/lang/codegen/src/generator/trait_def/call_forwarder.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 2192f5c286..f7a910dc40 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -344,7 +344,7 @@ impl ContractRef<'_> { .#message_ident( #( #input_bindings ),* ) .fire() .unwrap_or_else(|error| ::core::panic!( - "encountered error while calling {}::{}: {}", + "encountered error while calling {}::{}: {:?}", ::core::stringify!(#storage_ident), ::core::stringify!(#message_ident), error, diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 0058d036c9..fdf2b7966d 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -418,7 +418,7 @@ impl CallForwarder<'_> { ),* ) .fire() - .unwrap_or_else(|err| ::core::panic!("{}: {}", #panic_str, err)) + .unwrap_or_else(|err| ::core::panic!("{}: {:?}", #panic_str, err)) } ) } From fc16996d1714e586e9ce45cd90acf3dbb6b5ae57 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 23:45:32 +0200 Subject: [PATCH 156/493] fix remaining codegen bugs --- crates/lang/codegen/src/generator/as_dependency/call_builder.rs | 2 +- crates/lang/codegen/src/generator/storage.rs | 2 +- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 2a8a4f6e92..719be5dc17 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -418,7 +418,7 @@ impl CallBuilder<'_> { #( , #input_bindings : #input_types )* ) -> #output_type { ::ink_env::call::build_call::() - .callee(self.account_id) + .callee(::ink_lang::ToAccountId::to_account_id(self)) .exec_input( ::ink_env::call::ExecutionInput::new( ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index d211e43c68..7499a6464d 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -80,7 +80,7 @@ impl Storage<'_> { type EnvAccess = ::ink_lang::EnvAccess<'static, <#storage_ident as ::ink_lang::ContractEnv>::Env>; fn env() -> Self::EnvAccess { - <::EnvAccess as ::core::default::Default>::default() + <::EnvAccess as ::core::default::Default>::default() } } }; diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index ae703cc7f5..4ff1865a83 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -395,7 +395,7 @@ impl CallBuilder<'_> { #( , #input_bindings : #input_types )* ) -> Self::#output_ident { ::ink_env::call::build_call::() - .callee(self.account_id) + .callee(::ink_lang::ToAccountId::to_account_id(self)) .exec_input( ::ink_env::call::ExecutionInput::new( ::ink_env::call::Selector::new([ #( #selector_bytes ),* ]) From dc33222916fc2524048a3889e7a0c245e4ca7159 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 14 Sep 2021 23:53:53 +0200 Subject: [PATCH 157/493] apply rustfmt --- crates/lang/src/contract_ref.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index e4600c66b5..8d88ad088d 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -262,7 +262,6 @@ where fn call_mut(&mut self) -> &mut Self::Builder { &mut self.call_builder } - } impl core::fmt::Debug for ContractRef From 7c28b7e73ba62d0b6795dca6ed7e74cb687570a3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 00:04:31 +0200 Subject: [PATCH 158/493] update and fix trait-incrementer example contract --- examples/trait-incrementer/Cargo.toml | 14 ++++---- examples/trait-incrementer/lib.rs | 46 +++++++++++++++------------ 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/examples/trait-incrementer/Cargo.toml b/examples/trait-incrementer/Cargo.toml index 60340d84f9..cc7acea14d 100644 --- a/examples/trait-incrementer/Cargo.toml +++ b/examples/trait-incrementer/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "flipper" +name = "trait-incrementer" version = "3.0.0-rc3" authors = ["Parity Technologies "] edition = "2018" [dependencies] -ink_primitives = { version = "3.0.0-rc3", path = "../../crates/primitives", default-features = false } -ink_metadata = { version = "3.0.0-rc3", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } -ink_env = { version = "3.0.0-rc3", path = "../../crates/env", default-features = false } -ink_storage = { version = "3.0.0-rc3", path = "../../crates/storage", default-features = false } -ink_lang = { version = "3.0.0-rc3", path = "../../crates/lang", default-features = false } +ink_primitives = { version = "3.0.0-rc4", path = "../../crates/primitives", default-features = false } +ink_metadata = { version = "3.0.0-rc4", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } +ink_env = { version = "3.0.0-rc4", path = "../../crates/env", default-features = false } +ink_storage = { version = "3.0.0-rc4", path = "../../crates/storage", default-features = false } +ink_lang = { version = "3.0.0-rc4", path = "../../crates/lang", default-features = false } scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } @@ -18,7 +18,7 @@ scale-info = { version = "0.6", default-features = false, features = ["derive"], funty = "=1.1.0" [lib] -name = "flipper" +name = "trait_incrementer" path = "lib.rs" crate-type = ["cdylib"] diff --git a/examples/trait-incrementer/lib.rs b/examples/trait-incrementer/lib.rs index 49308eeca1..340d240a0a 100644 --- a/examples/trait-incrementer/lib.rs +++ b/examples/trait-incrementer/lib.rs @@ -51,16 +51,22 @@ pub mod incrementer { pub fn new() -> Self { Self { value: Default::default() } } + + /// Increases the value of the incrementer by the given delta. + #[ink(message)] + pub fn inc_by(&mut self, delta: u64) { + self.value += delta; + } } impl Increment for Incrementer { #[ink(message)] fn inc(&mut self) { - self.value += 1; + self.inc_by(1) } #[ink(message)] - fn get(&self) -> bool { + fn get(&self) -> u64 { self.value } } @@ -72,24 +78,24 @@ pub mod incrementer { } } - // #[cfg(test)] - // mod tests { - // use super::*; + #[cfg(test)] + mod tests { + use super::*; - // #[test] - // fn default_works() { - // let flipper = Flipper::default(); - // assert_eq!(flipper.get(), false); - // } + #[test] + fn default_works() { + let incrementer = Incrementer::new(); + assert_eq!(incrementer.get(), 0); + } - // #[test] - // fn it_works() { - // let mut flipper = Flipper::new(false); - // // Can call using universal call syntax using the trait. - // assert_eq!(::get(&flipper), false); - // ::flip(&mut flipper); - // // Normal call syntax possible to as long as the trait is in scope. - // assert_eq!(flipper.get(), true); - // } - // } + #[test] + fn it_works() { + let mut incrementer = Incrementer::new(); + // Can call using universal call syntax using the trait. + assert_eq!(::get(&incrementer), 0); + ::inc(&mut incrementer); + // Normal call syntax possible to as long as the trait is in scope. + assert_eq!(incrementer.get(), 1); + } + } } From dc7894500277e340a453fca11ff61dd51b7e9d68 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 00:06:08 +0200 Subject: [PATCH 159/493] apply rustfmt --- examples/trait-incrementer/lib.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/trait-incrementer/lib.rs b/examples/trait-incrementer/lib.rs index 340d240a0a..9e5dc05d00 100644 --- a/examples/trait-incrementer/lib.rs +++ b/examples/trait-incrementer/lib.rs @@ -38,7 +38,10 @@ pub trait Reset { #[ink::contract] pub mod incrementer { - use super::{Increment, Reset}; + use super::{ + Increment, + Reset, + }; #[ink(storage)] pub struct Incrementer { @@ -49,7 +52,9 @@ pub mod incrementer { /// Creates a new incrementer smart contract initialized with `0`. #[ink(constructor)] pub fn new() -> Self { - Self { value: Default::default() } + Self { + value: Default::default(), + } } /// Increases the value of the incrementer by the given delta. From d3f2f81b7d1eac8914e85319363252254f0be93c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 00:10:30 +0200 Subject: [PATCH 160/493] update trait-incrementer contract example Cargo.toml --- examples/trait-incrementer/Cargo.toml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/examples/trait-incrementer/Cargo.toml b/examples/trait-incrementer/Cargo.toml index cc7acea14d..ded9335080 100644 --- a/examples/trait-incrementer/Cargo.toml +++ b/examples/trait-incrementer/Cargo.toml @@ -5,18 +5,15 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -ink_primitives = { version = "3.0.0-rc4", path = "../../crates/primitives", default-features = false } -ink_metadata = { version = "3.0.0-rc4", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } -ink_env = { version = "3.0.0-rc4", path = "../../crates/env", default-features = false } -ink_storage = { version = "3.0.0-rc4", path = "../../crates/storage", default-features = false } -ink_lang = { version = "3.0.0-rc4", path = "../../crates/lang", default-features = false } +ink_primitives = { version = "3.0.0-rc5", path = "../../crates/primitives", default-features = false } +ink_metadata = { version = "3.0.0-rc5", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } +ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = false } +ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } +ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } -# Should be removed once bitvecto-rs/bitvec#105 is resolved -funty = "=1.1.0" - [lib] name = "trait_incrementer" path = "lib.rs" From d1b04287bf46eda2b6c696b31211730cd3563b3e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 00:38:01 +0200 Subject: [PATCH 161/493] apply rustfmt --- crates/lang/codegen/src/generator/arg_list.rs | 7 +- crates/lang/codegen/src/generator/contract.rs | 3 +- crates/lang/codegen/src/generator/dispatch.rs | 5 +- .../lang/codegen/src/generator/item_impls.rs | 5 +- crates/lang/codegen/src/generator/mod.rs | 4 +- .../src/generator/trait_def/call_forwarder.rs | 10 ++- .../codegen/src/generator/trait_def/mod.rs | 9 ++- crates/lang/ir/src/ir/selector.rs | 5 +- crates/lang/ir/src/lib.rs | 70 ++++++++++--------- crates/lang/ir/src/literal.rs | 12 ++-- 10 files changed, 74 insertions(+), 56 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 0be4ef8ccd..2f9f8e96a6 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -12,13 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -use proc_macro2::{Span, TokenStream as TokenStream2}; +use heck::CamelCase; +use proc_macro2::{ + Span, + TokenStream as TokenStream2, +}; use quote::{ format_ident, quote, quote_spanned, }; -use heck::CamelCase; /// Returns the associated output type for an ink! trait message. pub fn output_ident(message_name: &syn::Ident) -> syn::Ident { diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index a094a1b6b3..eb0f7e18ad 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -47,7 +47,8 @@ impl GenerateCode for Contract<'_> { let dispatch = self.generate_code_using::(); let item_impls = self.generate_code_using::(); let metadata = self.generate_code_using::(); - let contract_reference = self.generate_code_using::(); + let contract_reference = + self.generate_code_using::(); let non_ink_items = self .contract .module() diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 67e3908bb4..d6a6f3f9f6 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -193,7 +193,10 @@ impl Dispatch<'_> { let callable = cws.callable(); let callable_span = callable.span(); let selector = cws.composed_selector(); - let (selector_bytes, selector_id) = (selector.hex_lits(), selector.into_be_u32().hex_padded_suffixed()); + let (selector_bytes, selector_id) = ( + selector.hex_lits(), + selector.into_be_u32().hex_padded_suffixed(), + ); let input_types = callable .inputs() .map(|pat_type| &pat_type.ty) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 457554228d..1505453c79 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -95,10 +95,7 @@ impl ItemImpls<'_> { .trait_path() .expect("encountered missing trait path for trait impl block"); let self_type = item_impl.self_type(); - let unique_trait_id = generator::generate_unique_trait_id( - span, - trait_path, - ); + let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); quote_spanned!(span => #[doc(hidden)] unsafe impl diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index ce57f45b44..10bdec4c9a 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -43,16 +43,16 @@ mod trait_def; pub use self::{ arg_list::{ - generate_unique_trait_id, generate_argument_list, + generate_unique_trait_id, input_bindings, input_types, output_ident, }, as_dependency::{ + ContractReference, NotAsDependencyCfg, OnlyAsDependencyCfg, - ContractReference, }, chain_extension::ChainExtension, contract::Contract, diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index fdf2b7966d..8d07f0ba32 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -13,7 +13,10 @@ // limitations under the License. use super::TraitDefinition; -use crate::{generator, traits::GenerateCode}; +use crate::{ + generator, + traits::GenerateCode, +}; use derive_more::From; use ir::HexLiteral; use proc_macro2::{ @@ -390,7 +393,10 @@ impl CallForwarder<'_> { let message_ident = message.ident(); let attrs = message.attrs(); let output_ident = generator::output_ident(message_ident); - let output_type = message.output().cloned().unwrap_or_else(|| syn::parse_quote!(())); + let output_type = message + .output() + .cloned() + .unwrap_or_else(|| syn::parse_quote!(())); let input_bindings = message.inputs().map(|input| &input.pat).collect::>(); let input_types = message.inputs().map(|input| &input.ty).collect::>(); let call_op = match message.receiver() { diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index d30580cc12..5ca3c52666 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -12,14 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod definition; -mod trait_registry; mod call_builder; mod call_forwarder; +mod definition; +mod trait_registry; use crate::GenerateCode; use derive_more::From; -use proc_macro2::{Span, TokenStream as TokenStream2}; +use proc_macro2::{ + Span, + TokenStream as TokenStream2, +}; use quote::{ format_ident, quote_spanned, diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 49a5efe10f..195f107b2f 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -13,7 +13,10 @@ // limitations under the License. use super::blake2::blake2b_256; -use crate::{Namespace, literal::HexLiteral}; +use crate::{ + literal::HexLiteral, + Namespace, +}; /// A function selector. /// diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index 16cfdb2076..e8da7d1b1a 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -34,38 +34,40 @@ mod ast; mod ir; mod literal; -pub use self::literal::HexLiteral; -pub use self::ir::{ - Callable, - CallableKind, - CallableWithSelector, - ChainExtension, - ChainExtensionMethod, - Config, - Constructor, - Contract, - Event, - ExtensionId, - ImplItem, - InkItem, - InkTest, - InkTrait, - InkTraitConstructor, - InkTraitItem, - InkTraitMessage, - InputsIter, - Item, - ItemImpl, - ItemMod, - IterConstructors, - IterEvents, - IterInkTraitItems, - IterItemImpls, - IterMessages, - Message, - Namespace, - Receiver, - Selector, - Storage, - Visibility, +pub use self::{ + ir::{ + Callable, + CallableKind, + CallableWithSelector, + ChainExtension, + ChainExtensionMethod, + Config, + Constructor, + Contract, + Event, + ExtensionId, + ImplItem, + InkItem, + InkTest, + InkTrait, + InkTraitConstructor, + InkTraitItem, + InkTraitMessage, + InputsIter, + Item, + ItemImpl, + ItemMod, + IterConstructors, + IterEvents, + IterInkTraitItems, + IterItemImpls, + IterMessages, + Message, + Namespace, + Receiver, + Selector, + Storage, + Visibility, + }, + literal::HexLiteral, }; diff --git a/crates/lang/ir/src/literal.rs b/crates/lang/ir/src/literal.rs index 0d100d20bc..b4735977b9 100644 --- a/crates/lang/ir/src/literal.rs +++ b/crates/lang/ir/src/literal.rs @@ -91,18 +91,18 @@ generate_hex_literal_impls!( ); #[cfg(target_pointer_width = "16")] generate_hex_literal_impls!( - (::core::primitive::usize , "usize", "0x{:04X}_{}", "0x{:04X}"), - (::core::primitive::isize , "isize", "0x{:04X}_{}", "0x{:04X}"), + (::core::primitive::usize, "usize", "0x{:04X}_{}", "0x{:04X}"), + (::core::primitive::isize, "isize", "0x{:04X}_{}", "0x{:04X}"), ); #[cfg(target_pointer_width = "32")] generate_hex_literal_impls!( - (::core::primitive::usize , "usize", "0x{:08X}_{}", "0x{:08X}"), - (::core::primitive::isize , "isize", "0x{:08X}_{}", "0x{:08X}"), + (::core::primitive::usize, "usize", "0x{:08X}_{}", "0x{:08X}"), + (::core::primitive::isize, "isize", "0x{:08X}_{}", "0x{:08X}"), ); #[cfg(target_pointer_width = "64")] generate_hex_literal_impls!( - (::core::primitive::usize , "usize", "0x{:16X}_{}", "0x{:16X}"), - (::core::primitive::isize , "isize", "0x{:16X}_{}", "0x{:16X}"), + (::core::primitive::usize, "usize", "0x{:16X}_{}", "0x{:16X}"), + (::core::primitive::isize, "isize", "0x{:16X}_{}", "0x{:16X}"), ); #[cfg(test)] From a78193957ca04e3d236a44fdc4d90065a7e3ce33 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 11:12:00 +0200 Subject: [PATCH 162/493] fix spelling issues --- .config/cargo_spellcheck.dic | 6 ++++-- .../src/generator/as_dependency/call_builder.rs | 8 ++++---- .../codegen/src/generator/trait_def/call_builder.rs | 12 ++++++------ .../src/generator/trait_def/call_forwarder.rs | 8 ++++---- .../src/generator/trait_def/trait_registry.rs | 4 ++-- crates/lang/ir/src/ir/selector.rs | 8 ++++---- crates/lang/ir/src/ir/trait_def/mod.rs | 2 +- crates/lang/src/contract_ref.rs | 2 +- crates/lang/src/traits.rs | 4 ++-- 9 files changed, 28 insertions(+), 26 deletions(-) diff --git a/.config/cargo_spellcheck.dic b/.config/cargo_spellcheck.dic index 63a06223f3..3e6cda7fe0 100644 --- a/.config/cargo_spellcheck.dic +++ b/.config/cargo_spellcheck.dic @@ -1,4 +1,4 @@ -90 +100 ABI AST @@ -34,7 +34,7 @@ defrag defragmentation deploy dereferencing -deserializes +deserialize/S dispatchable encodable evaluable @@ -91,3 +91,5 @@ runtime/S struct/S vec/S vector/S +implementer/S +deduplicated diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 719be5dc17..32a929b493 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -331,7 +331,7 @@ impl CallBuilder<'_> { ) } - /// Generate call builder code for all ink! inherent ink! impl blocks. + /// Generate call builder code for all ink! inherent ink! implementation blocks. /// /// # Note /// @@ -350,12 +350,12 @@ impl CallBuilder<'_> { .collect() } - /// Generate call builder code for a single inherent ink! impl block. + /// Generate call builder code for a single inherent ink! implementation block. /// /// # Note /// - /// Unlike as with ink! trait impl blocks we do not have to generate - /// associate `*Output` types, ink! trait validators impl blocks or + /// Unlike as with ink! trait implementation blocks we do not have to generate + /// associate `*Output` types, ink! trait validating implementation blocks or /// trait forwarder implementations. Instead we build the calls directly. fn generate_call_builder_inherent_impl( &self, diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 4ff1865a83..9acf060147 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -93,15 +93,15 @@ impl CallBuilder<'_> { /// Generates the struct type definition for the account wrapper type. /// /// This type is going to implement the trait so that invoking its trait - /// methods will perform contract calls via SEAL's contract execution - /// abstraction. + /// methods will perform contract calls via contract's pallet contract + /// execution abstraction. /// /// # Note /// /// Unlike the layout specific traits it is possible to derive the SCALE /// `Encode` and `Decode` traits since they generate trait bounds per field /// instead of per generic parameter which is exactly what we need here. - /// However, it should be noted that this is not Rust default behaviour. + /// However, it should be noted that this is not Rust default behavior. fn generate_struct_definition(&self) -> TokenStream2 { let span = self.span(); let call_builder_ident = self.ident(); @@ -168,7 +168,7 @@ impl CallBuilder<'_> { let span = self.span(); let call_builder_ident = self.ident(); quote_spanned!(span=> - /// We require this manual impl since the derive produces incorrect trait bounds. + /// We require this manual implementation since the derive produces incorrect trait bounds. impl ::ink_storage::traits::SpreadLayout for #call_builder_ident where @@ -211,7 +211,7 @@ impl CallBuilder<'_> { let span = self.span(); let call_builder_ident = self.ident(); quote_spanned!(span=> - /// We require this manual impl since the derive produces incorrect trait bounds. + /// We require this manual implementation since the derive produces incorrect trait bounds. impl ::ink_storage::traits::PackedLayout for #call_builder_ident where @@ -254,7 +254,7 @@ impl CallBuilder<'_> { } } - /// We require this manual impl since the derive produces incorrect trait bounds. + /// We require this manual implementation since the derive produces incorrect trait bounds. impl ::core::fmt::Debug for #call_builder_ident where E: ::ink_env::Environment, diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 8d07f0ba32..14d7569904 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -96,15 +96,15 @@ impl CallForwarder<'_> { /// Generates the struct type definition for the account wrapper type. /// /// This type is going to implement the trait so that invoking its trait - /// methods will perform contract calls via SEAL's contract execution - /// abstraction. + /// methods will perform contract calls via contract's pallet contract + /// execution abstraction. /// /// # Note /// /// Unlike the layout specific traits it is possible to derive the SCALE /// `Encode` and `Decode` traits since they generate trait bounds per field /// instead of per generic parameter which is exactly what we need here. - /// However, it should be noted that this is not Rust default behaviour. + /// However, it should be noted that this is not Rust default behavior. fn generate_struct_definition(&self) -> TokenStream2 { let span = self.span(); let call_forwarder_ident = self.ident(); @@ -296,7 +296,7 @@ impl CallForwarder<'_> { ) } - /// Generate the trait impl for `CallBuilder` for the ink! trait call forwarder. + /// Generate the trait implementation for `CallBuilder` for the ink! trait call forwarder. /// /// # Note /// diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 2388e3f1cf..58a7286df9 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -96,7 +96,7 @@ impl TraitRegistry<'_> { /// call forwarder and call builder types as such for the ink! trait. /// /// This is done by the fact that ink! implements all ink! traits by the - /// ink_lang::TraitCallForwarderRegistry type and uses the __ink_ConcreteImplementer + /// [`ink_lang::TraitCallForwarderRegistry`] type and uses the `__ink_ConcreteImplementer` /// associated type to refer back to the actual call forwarder and call builder types. fn generate_registry_impl(&self) -> TokenStream2 { let span = self.span(); @@ -197,7 +197,7 @@ impl TraitRegistry<'_> { /// Phantom type that implements the following traits for every ink! trait: /// - /// - `ink_lang::TraitImplementer` (unsafe impl) + /// - `ink_lang::TraitImplementer` (unsafe implementation) /// - `ink_lang::TraitUniqueId` /// - `ink_lang::TraitCallForwarder` /// diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 195f107b2f..c112ea6c22 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -92,7 +92,7 @@ impl Selector { /// For inherent implementation blocks, when `trait_prefix` is `None` the composed /// selector is computed as follows: /// - /// 1. Apply `BLAKE2` 256-bit hash `H` on the bytes of the ascii representation of + /// 1. Apply `BLAKE2` 256-bit hash `H` on the bytes of the ASCII representation of /// the `fn_ident` identifier. /// 1. The first 4 bytes of `H` make up the selector. /// @@ -101,9 +101,9 @@ impl Selector { /// For trait implementation blocks, when `trait_prefix` is /// `Some((namespace, trait_ident))` the composed selector is computed as follows: /// - /// 1. Compute the ascii byte representation of `fn_ident` and call it `F`. - /// 1. Compute the ascii byte representation of `namespace` and call it `N`. - /// 1. Compute the ascii byte representation of `trait_ident` and call it `T`. + /// 1. Compute the ASCII byte representation of `fn_ident` and call it `F`. + /// 1. Compute the ASCII byte representation of `namespace` and call it `N`. + /// 1. Compute the ASCII byte representation of `trait_ident` and call it `T`. /// 1. Concatenate `N`, `T` and `F` using `::` as separator and call it `C`. /// 1. Apply the `BLAKE2` 256-bit hash `H` of `C`. /// 1. The first 4 bytes of `H` make up the selector. diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index b686d7d040..38a0928efc 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -241,7 +241,7 @@ impl InkTrait { /// - associated constants (`const`) /// - associated types (`type`) /// - macros definitions or usages - /// - unknown token sequences (verbatims) + /// - unknown token sequences (verbatim) /// - methods with default implementations /// - If the trait contains methods which do not respect the ink! trait definition requirements: /// - All trait methods need to be declared as either `#[ink(message)]` or `#[ink(constructor)]` diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index 8d88ad088d..0d9301ce26 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -229,7 +229,7 @@ where /// A generic ink! smart contract call forwader. /// -/// A call forwarder is a thin wrapper arround a call builder +/// A call forwarder is a thin wrapper around a call builder /// that forwards the long-hand calls to the builder and directly /// serves as the interface for the short-hand calls and constructors. /// diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 28f03c5c59..cf21ab31ea 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -123,7 +123,7 @@ pub trait MessageMut: FnInput + FnOutput + FnSelector + FnState { pub trait True {} /// This type is known to ink! to implement all defined ink! trait definitions. -/// This property can be guaranteed by `#[ink::trait_definition]` proc. macro. +/// This property can be guaranteed by `#[ink::trait_definition]` procedural macro. /// /// By the introduction of an new internal and hidden associated type called /// `__ink_DynamicCallForwarder` for all ink! trait definitions it is possible @@ -206,7 +206,7 @@ pub trait TraitModulePath { /// The module path of the ink! trait definition. /// /// This is equivalent to Rust's builtin `module_path!` macro - /// invokation at the definition site of the ink! trait. + /// invocation at the definition site of the ink! trait. const PATH: &'static str; /// The name of the ink! trait. From 61d936c78a437a55f6130c98d4167e11ec301b62 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 11:20:13 +0200 Subject: [PATCH 163/493] fix spelling issue --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 9acf060147..fc880e98a8 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -240,7 +240,7 @@ impl CallBuilder<'_> { let span = self.span(); let call_builder_ident = self.ident(); quote_spanned!(span=> - /// We require this manual impl since the derive produces incorrect trait bounds. + /// We require this manual implementation since the derive produces incorrect trait bounds. impl ::core::clone::Clone for #call_builder_ident where E: ::ink_env::Environment, From b86e20da8c8d713e0d1baa364cca0aa720830f26 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 11:20:24 +0200 Subject: [PATCH 164/493] fix flipper-as-dependency UI test --- .../macro/tests/ui/pass/08-flipper-as-dependency-trait.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs index 59514a4ea7..b434a64157 100644 --- a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs +++ b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs @@ -4,9 +4,6 @@ use ink_lang as ink; mod flipper { #[ink_lang::trait_definition] pub trait FlipperTrait { - #[ink(constructor)] - fn new() -> Self; - #[ink(message)] fn flip(&mut self); @@ -19,12 +16,14 @@ mod flipper { value: bool, } - impl FlipperTrait for Flipper { + impl Flipper { #[ink(constructor)] fn new() -> Self { Self::default() } + } + impl FlipperTrait for Flipper { #[ink(message)] fn flip(&mut self) { self.value = !self.value; From 62dbc79a7044a595f8a0182a7d5ab7c13994fb4d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 11:30:47 +0200 Subject: [PATCH 165/493] apply some clippy suggestions --- crates/env/src/backend.rs | 7 +------ crates/storage/src/collections/bitvec/bits256.rs | 10 +--------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/crates/env/src/backend.rs b/crates/env/src/backend.rs index f4525b977f..c901135a32 100644 --- a/crates/env/src/backend.rs +++ b/crates/env/src/backend.rs @@ -33,16 +33,11 @@ use crate::{ use ink_primitives::Key; /// The flags to indicate further information about the end of a contract execution. +#[derive(Default)] pub struct ReturnFlags { value: u32, } -impl Default for ReturnFlags { - fn default() -> Self { - Self { value: 0 } - } -} - impl ReturnFlags { /// Sets the bit to indicate that the execution is going to be reverted. pub fn set_reverted(mut self, has_reverted: bool) -> Self { diff --git a/crates/storage/src/collections/bitvec/bits256.rs b/crates/storage/src/collections/bitvec/bits256.rs index 7d5ef96bb5..f93b98803b 100644 --- a/crates/storage/src/collections/bitvec/bits256.rs +++ b/crates/storage/src/collections/bitvec/bits256.rs @@ -21,20 +21,12 @@ use super::{ }; /// A chunk of 256 bits. -#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub struct Bits256 { bits: [Bits64; 4], } -impl Default for Bits256 { - fn default() -> Self { - Self { - bits: Default::default(), - } - } -} - /// Iterator over the valid bits of a pack of 256 bits. #[derive(Debug, Copy, Clone)] pub struct Iter<'a> { From 5eb1f2cff40276972db1089b98c970890d719349 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 11:31:07 +0200 Subject: [PATCH 166/493] fix flipper-as-dependency-trait UI test (again) --- .../lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs index b434a64157..6e8a4c584d 100644 --- a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs +++ b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs @@ -18,7 +18,7 @@ mod flipper { impl Flipper { #[ink(constructor)] - fn new() -> Self { + pub fn new() -> Self { Self::default() } } From 5da0f11c8e80d9fc1a2a6e5eec96c9d96fe6e12f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 12:49:56 +0200 Subject: [PATCH 167/493] generate code for ink! storage struct and impls even with ink-as-dependency This is useful since the ink! storage structs and its impls can also be used as dependency to fully embed a smart contract into another. --- crates/lang/codegen/src/generator/events.rs | 24 +------------------ .../lang/codegen/src/generator/item_impls.rs | 4 ---- crates/lang/codegen/src/generator/storage.rs | 18 ++++---------- 3 files changed, 5 insertions(+), 41 deletions(-) diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index dc248fb329..245adf9485 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -12,11 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - generator, - GenerateCode, - GenerateCodeUsing as _, -}; +use crate::GenerateCode; use derive_more::From; use proc_macro2::{ Span, @@ -61,11 +57,8 @@ impl<'a> Events<'a> { /// them first into the automatically generated base trait of the contract. fn generate_emit_event_trait_impl(&self) -> TokenStream2 { let storage_ident = &self.contract.module().storage().ident(); - let no_cross_calling_cfg = - self.generate_code_using::(); quote! { const _: () = { - #no_cross_calling_cfg impl<'a> ::ink_lang::EmitEvent<#storage_ident> for ::ink_lang::EnvAccess<'a, Environment> { fn emit_event(self, event: E) where @@ -86,8 +79,6 @@ impl<'a> Events<'a> { /// serialized and emitted to apply their unique event discriminant (ID). fn generate_event_base(&self) -> TokenStream2 { let storage_ident = &self.contract.module().storage().ident(); - let no_cross_calling_cfg = - self.generate_code_using::(); let event_idents = self .contract .module() @@ -97,13 +88,11 @@ impl<'a> Events<'a> { let base_event_ident = proc_macro2::Ident::new("__ink_EventBase", Span::call_site()); quote! { - #no_cross_calling_cfg #[derive(::scale::Encode, ::scale::Decode)] pub enum #base_event_ident { #( #event_idents(#event_idents), )* } - #no_cross_calling_cfg const _: () = { impl ::ink_lang::BaseEvent for #storage_ident { type Type = #base_event_ident; @@ -111,7 +100,6 @@ impl<'a> Events<'a> { }; #( - #no_cross_calling_cfg const _: () = { impl From<#event_idents> for #base_event_ident { fn from(event: #event_idents) -> Self { @@ -127,7 +115,6 @@ impl<'a> Events<'a> { const AMOUNT: usize = 0; } - #no_cross_calling_cfg impl ::ink_env::Topics for #base_event_ident { type RemainingTopics = __ink_UndefinedAmountOfTopics; @@ -196,13 +183,10 @@ impl<'a> Events<'a> { /// Generates the guard code that protects against having too many topics defined on an ink! event. fn generate_topic_guards(&'a self) -> impl Iterator + 'a { - let no_cross_calling_cfg = - self.generate_code_using::(); self.contract.module().events().map(move |event| { let span = event.span(); let topics_guard = self.generate_topics_guard(event); quote_spanned!(span => - #no_cross_calling_cfg #topics_guard ) }) @@ -210,8 +194,6 @@ impl<'a> Events<'a> { /// Generates the `Topics` trait implementations for the user defined events. fn generate_topics_impls(&'a self) -> impl Iterator + 'a { - let no_cross_calling_cfg = - self.generate_code_using::(); let contract_ident = self.contract.module().storage().ident(); self.contract.module().events().map(move |event| { let span = event.span(); @@ -258,7 +240,6 @@ impl<'a> Events<'a> { n => quote_spanned!(span=> [::ink_env::topics::state::HasRemainingTopics; #n]), }; quote_spanned!(span => - #no_cross_calling_cfg const _: () = { impl ::ink_env::Topics for #event_ident { type RemainingTopics = #remaining_topics_ty; @@ -287,8 +268,6 @@ impl<'a> Events<'a> { /// Generates all the user defined event struct definitions. fn generate_event_structs(&'a self) -> impl Iterator + 'a { - let no_cross_calling_cfg = - self.generate_code_using::(); self.contract.module().events().map(move |event| { let span = event.span(); let ident = event.ident(); @@ -305,7 +284,6 @@ impl<'a> Events<'a> { ) }); quote_spanned!(span => - #no_cross_calling_cfg #( #attrs )* #[derive(scale::Encode, scale::Decode)] pub struct #ident { diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 1505453c79..f69592f8a6 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -15,7 +15,6 @@ use crate::{ generator, GenerateCode, - GenerateCodeUsing as _, }; use derive_more::From; use heck::CamelCase as _; @@ -43,10 +42,7 @@ impl GenerateCode for ItemImpls<'_> { .module() .impls() .map(|item_impl| self.generate_item_impl(item_impl)); - let no_cross_calling_cfg = - self.generate_code_using::(); quote! { - #no_cross_calling_cfg const _: () = { use ::ink_lang::{Env as _, EmitEvent as _, StaticEnv as _}; diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index 7499a6464d..7bf239168f 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -12,11 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - generator, - GenerateCode, - GenerateCodeUsing, -}; +use crate::GenerateCode; use derive_more::From; use proc_macro2::TokenStream as TokenStream2; use quote::{ @@ -42,12 +38,10 @@ impl GenerateCode for Storage<'_> { // Required to allow for `self.env().emit_event(..)` in messages and constructors. quote! { use ::ink_lang::EmitEvent as _; } }); - let cfg = self.generate_code_using::(); quote_spanned!(storage_span => #access_env_impls #storage_struct - #cfg const _: () = { // Used to make `self.env()` available in message code. #[allow(unused_imports)] @@ -64,9 +58,7 @@ impl GenerateCode for Storage<'_> { impl Storage<'_> { fn generate_access_env_trait_impls(&self) -> TokenStream2 { let storage_ident = &self.contract.module().storage().ident(); - let cfg = self.generate_code_using::(); quote! { - #cfg const _: () = { impl<'a> ::ink_lang::Env for &'a #storage_ident { type EnvAccess = ::ink_lang::EnvAccess<'a, <#storage_ident as ::ink_lang::ContractEnv>::Env>; @@ -91,19 +83,17 @@ impl Storage<'_> { fn generate_storage_struct(&self) -> TokenStream2 { let storage = self.contract.module().storage(); let span = storage.span(); - let ident = &storage.ident(); - let attrs = &storage.attrs(); + let ident = storage.ident(); + let attrs = storage.attrs(); let fields = storage.fields(); - let cfg = self.generate_code_using::(); quote_spanned!( span => - #cfg #(#attrs)* #[cfg_attr( feature = "std", derive(::ink_storage::traits::StorageLayout) )] #[derive(::ink_storage::traits::SpreadLayout)] - #[cfg_attr(test, derive(Debug))] + #[cfg_attr(test, derive(::core::fmt::Debug))] pub struct #ident { #( #fields ),* } From 088cab23ff9a594229f27eff442b9ecaba65e261 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 13:06:01 +0200 Subject: [PATCH 168/493] fix storage_derive UI tests --- .../storage/derive/src/tests/spread_layout.rs | 56 +++++++++---------- .../derive/src/tests/storage_layout.rs | 24 ++++---- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/crates/storage/derive/src/tests/spread_layout.rs b/crates/storage/derive/src/tests/spread_layout.rs index 0cb9d2729b..286a509e64 100644 --- a/crates/storage/derive/src/tests/spread_layout.rs +++ b/crates/storage/derive/src/tests/spread_layout.rs @@ -32,9 +32,9 @@ fn unit_struct_works() { const _: () = { impl ::ink_storage::traits::SpreadLayout for UnitStruct { #[allow(unused_comparisons)] - const FOOTPRINT: u64 = [0u64, 0u64][(0u64 < 0u64) as usize]; + const FOOTPRINT: ::core::primitive::u64 = [0u64, 0u64][(0u64 < 0u64) as ::core::primitive::usize]; - const REQUIRES_DEEP_CLEAN_UP : bool = (false || false ); + const REQUIRES_DEEP_CLEAN_UP : ::core::primitive::bool = (false || false ); fn pull_spread(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> Self { UnitStruct @@ -71,7 +71,7 @@ fn struct_works() { const _: () = { impl ::ink_storage::traits::SpreadLayout for NamedFields { #[allow(unused_comparisons)] - const FOOTPRINT: u64 = [ + const FOOTPRINT: ::core::primitive::u64 = [ (((0u64 + ::FOOTPRINT) + <[u8; 32] as ::ink_storage::traits::SpreadLayout>::FOOTPRINT) + as ::ink_storage::traits::SpreadLayout>::FOOTPRINT), @@ -80,10 +80,10 @@ fn struct_works() { + ::FOOTPRINT) + <[u8; 32] as ::ink_storage::traits::SpreadLayout>::FOOTPRINT) + as ::ink_storage::traits::SpreadLayout>::FOOTPRINT) - < 0u64) as usize + < 0u64) as ::core::primitive::usize ]; - const REQUIRES_DEEP_CLEAN_UP : bool = ( + const REQUIRES_DEEP_CLEAN_UP : ::core::primitive::bool = ( false || ( ( ( @@ -181,7 +181,7 @@ fn enum_works() { const _: () = { impl ::ink_storage::traits::SpreadLayout for MixedEnum { #[allow(unused_comparisons)] - const FOOTPRINT : u64 = 1 + [ + const FOOTPRINT : ::core::primitive::u64 = 1 + [ 0u64 , [ ( @@ -211,7 +211,7 @@ fn enum_works() { + <(bool, i32) as ::ink_storage::traits::SpreadLayout>::FOOTPRINT ) < 0u64 - ) as usize + ) as ::core::primitive::usize ] ][ ( @@ -241,9 +241,9 @@ fn enum_works() { + <(bool, i32) as ::ink_storage::traits::SpreadLayout>::FOOTPRINT ) < 0u64 - ) as usize + ) as ::core::primitive::usize ] - ) as usize + ) as ::core::primitive::usize ] ][ ( @@ -274,7 +274,7 @@ fn enum_works() { + <(bool, i32) as ::ink_storage::traits::SpreadLayout>::FOOTPRINT ) < 0u64 - ) as usize + ) as ::core::primitive::usize ] ][ ( @@ -304,14 +304,14 @@ fn enum_works() { + <(bool, i32) as ::ink_storage::traits::SpreadLayout>::FOOTPRINT ) < 0u64 - ) as usize + ) as ::core::primitive::usize ] - ) as usize + ) as ::core::primitive::usize ] - ) as usize + ) as ::core::primitive::usize ]; - const REQUIRES_DEEP_CLEAN_UP : bool = ( + const REQUIRES_DEEP_CLEAN_UP : ::core::primitive::bool = ( ( (false || false) || ( @@ -332,7 +332,7 @@ fn enum_works() { ); fn pull_spread(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> Self { - match ::pull_spread(__key_ptr) + match <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::pull_spread(__key_ptr) { 0u8 => MixedEnum::A, 1u8 => MixedEnum::B( @@ -350,7 +350,7 @@ fn enum_works() { match self { MixedEnum::A => { { - ::push_spread( + <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::push_spread( &0u8, __key_ptr ); @@ -358,7 +358,7 @@ fn enum_works() { } MixedEnum::B(__binding_0, __binding_1,) => { { - ::push_spread( + <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::push_spread( &1u8, __key_ptr ); @@ -381,7 +381,7 @@ fn enum_works() { b: __binding_1, } => { { - ::push_spread( + <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::push_spread( &2u8, __key_ptr ); } @@ -459,16 +459,16 @@ fn generic_struct_works() { T2: ::ink_storage::traits::SpreadLayout { #[allow(unused_comparisons)] - const FOOTPRINT: u64 = [ + const FOOTPRINT: ::core::primitive::u64 = [ ((0u64 + ::FOOTPRINT) + <(T1, T2) as ::ink_storage::traits::SpreadLayout>::FOOTPRINT), 0u64 ][(((0u64 + ::FOOTPRINT) + <(T1, T2) as ::ink_storage::traits::SpreadLayout>::FOOTPRINT) - < 0u64) as usize + < 0u64) as ::core::primitive::usize ]; - const REQUIRES_DEEP_CLEAN_UP : bool = ( + const REQUIRES_DEEP_CLEAN_UP : ::core::primitive::bool = ( false || ( ( false @@ -555,7 +555,7 @@ fn generic_enum_works() { T2: ::ink_storage::traits::SpreadLayout { #[allow(unused_comparisons)] - const FOOTPRINT: u64 = 1 + [ + const FOOTPRINT: ::core::primitive::u64 = 1 + [ ((0u64 + ::FOOTPRINT) + ::FOOTPRINT), [ @@ -565,7 +565,7 @@ fn generic_enum_works() { ][(((0u64 + ::FOOTPRINT) + ::FOOTPRINT) - < 0u64) as usize] + < 0u64) as ::core::primitive::usize] ][(((0u64 + ::FOOTPRINT) + ::FOOTPRINT) < [ @@ -575,10 +575,10 @@ fn generic_enum_works() { ][(((0u64 + ::FOOTPRINT) + ::FOOTPRINT) - < 0u64) as usize]) as usize + < 0u64) as ::core::primitive::usize]) as ::core::primitive::usize ]; - const REQUIRES_DEEP_CLEAN_UP : bool = ( + const REQUIRES_DEEP_CLEAN_UP : ::core::primitive::bool = ( ( false || ( ( @@ -598,7 +598,7 @@ fn generic_enum_works() { ); fn pull_spread(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> Self { - match ::pull_spread(__key_ptr) + match <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::pull_spread(__key_ptr) { 0u8 => GenericEnum::Tuple( ::pull_spread(__key_ptr), @@ -616,7 +616,7 @@ fn generic_enum_works() { match self { GenericEnum::Tuple(__binding_0, __binding_1,) => { { - ::push_spread(&0u8, __key_ptr); + <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::push_spread(&0u8, __key_ptr); } { ::ink_storage::traits::SpreadLayout::push_spread( @@ -636,7 +636,7 @@ fn generic_enum_works() { b: __binding_1, } => { { - ::push_spread(&1u8, __key_ptr); + <::core::primitive::u8 as ::ink_storage::traits::SpreadLayout>::push_spread(&1u8, __key_ptr); } { ::ink_storage::traits::SpreadLayout::push_spread( diff --git a/crates/storage/derive/src/tests/storage_layout.rs b/crates/storage/derive/src/tests/storage_layout.rs index d52e4905ec..2a71f50482 100644 --- a/crates/storage/derive/src/tests/storage_layout.rs +++ b/crates/storage/derive/src/tests/storage_layout.rs @@ -47,15 +47,15 @@ fn tuple_struct_works() { ::ink_metadata::layout::Layout::Struct( ::ink_metadata::layout::StructLayout::new(vec![ ::ink_metadata::layout::FieldLayout::new( - None, + ::core::option::Option::None, ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - None, + ::core::option::Option::None, ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - None, + ::core::option::Option::None, ::layout(__key_ptr), ), ]) @@ -84,15 +84,15 @@ fn named_fields_struct_works() { ::ink_metadata::layout::Layout::Struct( ::ink_metadata::layout::StructLayout::new(vec![ ::ink_metadata::layout::FieldLayout::new( - Some("a"), + ::core::option::Option::Some("a"), ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - Some("b"), + ::core::option::Option::Some("b"), ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - Some("c"), + ::core::option::Option::Some("c"), ::layout(__key_ptr), ), ]) @@ -191,15 +191,15 @@ fn mixed_enum_works() { ::ink_metadata::layout::Discriminant::from(1usize), ::ink_metadata::layout::StructLayout::new(vec![ ::ink_metadata::layout::FieldLayout::new( - None, + ::core::option::Option::None, ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - None, + ::core::option::Option::None, ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - None, + ::core::option::Option::None, ::layout(__key_ptr), ), ]), @@ -212,15 +212,15 @@ fn mixed_enum_works() { ::ink_metadata::layout::Discriminant::from(2usize), ::ink_metadata::layout::StructLayout::new(vec![ ::ink_metadata::layout::FieldLayout::new( - Some("a"), + ::core::option::Option::Some("a"), ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - Some("b"), + ::core::option::Option::Some("b"), ::layout(__key_ptr), ), ::ink_metadata::layout::FieldLayout::new( - Some("c"), + ::core::option::Option::Some("c"), ::layout(__key_ptr), ), ]), From b8e3dc72ad6ba5ed0a8d304fd7bbced2427d18e8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 13:06:25 +0200 Subject: [PATCH 169/493] fix some ink_lang derive UI tests --- .../fail/M-04-message-returns-non-codec.stderr | 18 ++++++++++++++++-- .../ui/pass/08-flipper-as-dependency-trait.rs | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.stderr index 017f0cd2f0..712a3111c8 100644 --- a/crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.stderr @@ -6,7 +6,21 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodec` note: required by a bound in `ink_lang::FnOutput::Output` - --> $DIR/traits.rs:79:18 + --> $DIR/traits.rs:80:18 | -79 | type Output: scale::Encode + 'static; +80 | type Output: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `ink_lang::FnOutput::Output` + +error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied + --> $DIR/M-04-message-returns-non-codec.rs:18:9 + | +6 | pub struct NonCodec; + | -------------------- doesn't satisfy `_: message_returns_non_codec::_::_parity_scale_codec::Decode` +... +18 | / pub fn returns_non_codec_type(&self) -> NonCodec { +19 | | NonCodec +20 | | } + | |_________^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NonCodec: message_returns_non_codec::_::_parity_scale_codec::Decode` diff --git a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs index 6e8a4c584d..2bd30c4bac 100644 --- a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs +++ b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs @@ -19,7 +19,7 @@ mod flipper { impl Flipper { #[ink(constructor)] pub fn new() -> Self { - Self::default() + Self { value: Default::default() } } } From 5ca48479573a212e92c627bf2a0e30f8d740ec92 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 13:43:49 +0200 Subject: [PATCH 170/493] fix trait definition CallForwarder codegen with input parameters --- crates/lang/codegen/src/generator/trait_def/call_forwarder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 14d7569904..9467c7b592 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -420,8 +420,8 @@ impl CallForwarder<'_> { <::Builder as #trait_ident>::#message_ident( ::#call_op(self) #( - , #input_bindings: #input_types - ),* + , #input_bindings + )* ) .fire() .unwrap_or_else(|err| ::core::panic!("{}: {:?}", #panic_str, err)) From 26766b172bc825704fd23d25bad73a5ee7cdcf0d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 13:44:05 +0200 Subject: [PATCH 171/493] fix some UI and doc tests --- crates/lang/macro/src/lib.rs | 35 ++++++++++++++++++++--------------- crates/lang/src/env_access.rs | 4 ++-- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/crates/lang/macro/src/lib.rs b/crates/lang/macro/src/lib.rs index 9455616d7a..3defdbb136 100644 --- a/crates/lang/macro/src/lib.rs +++ b/crates/lang/macro/src/lib.rs @@ -529,18 +529,19 @@ pub fn contract(attr: TokenStream, item: TokenStream) -> TokenStream { /// ``` /// use ink_lang as ink; /// # type Balance = ::Balance; +/// # type AccountId = ::AccountId; /// /// #[ink::trait_definition] /// pub trait Erc20 { -/// /// Constructs a new ERC-20 compliant smart contract using the initial supply. -/// #[ink(constructor)] -/// fn new(initial_supply: Balance) -> Self; -/// /// /// Returns the total supply of the ERC-20 smart contract. /// #[ink(message)] /// fn total_supply(&self) -> Balance; /// -/// // etc. +/// /// Transfers balance from the caller to the given address. +/// #[ink(message)] +/// fn transfer(&mut self, amount: Balance, to: AccountId) -> bool; +/// +/// // etc ... /// } /// ``` /// @@ -556,34 +557,38 @@ pub fn contract(attr: TokenStream, item: TokenStream) -> TokenStream { /// # // We somehow cannot put the trait in the doc-test crate root due to bugs. /// # #[ink_lang::trait_definition] /// # pub trait Erc20 { -/// # /// Constructors a new ERC-20 compliant smart contract using the initial supply. -/// # #[ink(constructor)] -/// # fn new(initial_supply: Balance) -> Self; +/// # /// Returns the total supply of the ERC-20 smart contract. +/// # #[ink(message)] +/// # fn total_supply(&self) -> Balance; /// # -/// # /// Returns the total supply of the ERC-20 smart contract. -/// # #[ink(message)] -/// # fn total_supply(&self) -> Balance; +/// # /// Transfers balance from the caller to the given address. +/// # #[ink(message)] +/// # fn transfer(&mut self, amount: Balance, to: AccountId) -> bool; /// # } /// # /// #[ink(storage)] /// pub struct BaseErc20 { /// total_supply: Balance, -/// // etc .. /// } /// -/// impl Erc20 for BaseErc20 { +/// impl BaseErc20 { /// #[ink(constructor)] -/// fn new(initial_supply: Balance) -> Self { +/// pub fn new(initial_supply: Balance) -> Self { /// Self { total_supply: initial_supply } /// } +/// } /// +/// impl Erc20 for BaseErc20 { /// /// Returns the total supply of the ERC-20 smart contract. /// #[ink(message)] /// fn total_supply(&self) -> Balance { /// self.total_supply /// } /// -/// // etc .. +/// #[ink(message)] +/// fn transfer(&mut self, amount: Balance, to: AccountId) -> bool { +/// todo!(); +/// } /// } /// } /// ``` diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs index 66924b9f20..6432016475 100644 --- a/crates/lang/src/env_access.rs +++ b/crates/lang/src/env_access.rs @@ -640,7 +640,7 @@ where /// DefaultEnvironment, /// call::{build_create, Selector, ExecutionInput} /// }; - /// use other_contract::OtherContract; + /// use other_contract::OtherContractRef; /// # /// # #[ink(storage)] /// # pub struct MyContract { } @@ -655,7 +655,7 @@ where /// /// Instantiates another contract. /// #[ink(message)] /// pub fn instantiate_contract(&self) -> AccountId { - /// let create_params = build_create::() + /// let create_params = build_create::() /// .code_hash(Hash::from([0x42; 32])) /// .gas_limit(4000) /// .endowment(25) From 4c4f135f448bcebc1bf4d75da4e5ec31eb4e91d6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 13:48:12 +0200 Subject: [PATCH 172/493] slightly fix trait-erc20 example A lot of remaining issue still exist with the example. --- examples/trait-erc20/lib.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/trait-erc20/lib.rs b/examples/trait-erc20/lib.rs index a7a737dc43..c0e584917a 100644 --- a/examples/trait-erc20/lib.rs +++ b/examples/trait-erc20/lib.rs @@ -35,10 +35,6 @@ mod erc20 { /// Trait implemented by all ERC-20 respecting smart contracts. #[ink::trait_definition] pub trait BaseErc20 { - /// Creates a new ERC-20 contract with the specified initial supply. - #[ink(constructor)] - fn new(initial_supply: Balance) -> Self; - /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance; @@ -105,10 +101,10 @@ mod erc20 { value: Balance, } - impl BaseErc20 for Erc20 { + impl Erc20 { /// Creates a new ERC-20 contract with the specified initial supply. #[ink(constructor)] - fn new(initial_supply: Balance) -> Self { + pub fn new(initial_supply: Balance) -> Self { let caller = Self::env().caller(); let mut balances = StorageHashMap::new(); balances.insert(caller, initial_supply); @@ -124,7 +120,9 @@ mod erc20 { }); instance } + } + impl BaseErc20 for Erc20 { /// Returns the total token supply. #[ink(message)] fn total_supply(&self) -> Balance { From debd08c850c78517354a1d1ad0ea530333bc4b04 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 13:57:16 +0200 Subject: [PATCH 173/493] remove old and deprecated cross-calling codegen --- .../codegen/src/generator/cross_calling.rs | 836 ------------------ crates/lang/codegen/src/generator/mod.rs | 2 - 2 files changed, 838 deletions(-) delete mode 100644 crates/lang/codegen/src/generator/cross_calling.rs diff --git a/crates/lang/codegen/src/generator/cross_calling.rs b/crates/lang/codegen/src/generator/cross_calling.rs deleted file mode 100644 index 8efffbc833..0000000000 --- a/crates/lang/codegen/src/generator/cross_calling.rs +++ /dev/null @@ -1,836 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![allow(dead_code)] - -use super::enforced_error::EnforcedErrors; -use crate::{ - generator, - GenerateCode, - GenerateCodeUsing as _, -}; -use derive_more::From; -use heck::CamelCase as _; -use impl_serde::serialize as serde_hex; -use ir::Callable; -use itertools::Itertools as _; -use proc_macro2::{ - Ident, - TokenStream as TokenStream2, -}; -use quote::{ - format_ident, - quote, - quote_spanned, -}; -use syn::spanned::Spanned as _; - -/// Generates code for using this ink! contract as a dependency. -#[derive(From)] -pub struct CrossCalling<'a> { - contract: &'a ir::Contract, -} -impl_as_ref_for_generator!(CrossCalling); - -impl GenerateCode for CrossCalling<'_> { - fn generate_code(&self) -> TokenStream2 { - let storage = self.generate_storage(); - let standard_impls = self.generate_standard_impls(); - // let call_forwarder = self.generate_call_forwarders(); - // let impl_blocks = self.generate_impl_blocks(); - quote! { - #storage - #standard_impls - // #call_forwarder - // #impl_blocks - } - } -} - -impl CrossCalling<'_> { - /// Generates code for the ink! storage struct for cross-calling purposes. - /// - /// # Note - /// - /// This always consists of a single `AccountId` and can be viewed as a - /// reference to a live smart contract instance of the same type. It will - /// forward all calls via ink!'s provided cross-calling infrastructure - /// automatically over the chain. - fn generate_storage(&self) -> TokenStream2 { - let only_as_dependency = - self.generate_code_using::(); - let storage = self.contract.module().storage(); - let span = storage.span(); - let ident = storage.ident(); - let attrs = storage.attrs(); - quote_spanned!(span => - #only_as_dependency - #( #attrs )* - #[derive( - Clone, - Debug, - ::scale::Encode, - ::scale::Decode, - ::ink_storage::traits::SpreadLayout, - ::ink_storage::traits::PackedLayout, - )] - #[cfg_attr( - feature = "std", - derive( - ::scale_info::TypeInfo, - ::ink_storage::traits::StorageLayout, - ) - )] - pub struct #ident { - account_id: AccountId, - } - ) - } - - /// Generates code for the trait implementations required to make the - /// generated ink! storage struct for cross-calling work out-of-the-box - /// for the cross-calling infrastructure. - fn generate_standard_impls(&self) -> TokenStream2 { - let only_as_dependency = - self.generate_code_using::(); - let ident = self.contract.module().storage().ident(); - quote! { - #only_as_dependency - const _: () = { - impl ::ink_env::call::FromAccountId for #ident { - #[inline] - fn from_account_id(account_id: AccountId) -> Self { - Self { account_id } - } - } - - impl ::ink_lang::ToAccountId for #ident { - #[inline] - fn to_account_id(&self) -> AccountId { - self.account_id - } - } - }; - } - } - - /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. - fn generate_arg_list<'a, Args>(args: Args) -> TokenStream2 - where - Args: IntoIterator, - ::IntoIter: DoubleEndedIterator, - { - args.into_iter().fold( - quote! { ::ink_env::call::utils::EmptyArgumentList }, - |rest, arg| quote! { - ::ink_env::call::utils::ArgumentList<::ink_env::call::utils::Argument<#arg>, #rest> - } - ) - } - - /// Returns the identifier for the generated call forwarder utility. - fn call_forwarder_ident() -> Ident { - format_ident!("__ink_CallForwarder") - } - - /// Create the identifier of an enforced ink! compilation error. - fn enforce_error_ident(error: EnforcedErrors) -> syn::Ident { - format_ident!( - "__ink_enforce_error_{}", - serde_hex::to_hex(&scale::Encode::encode(&error), false) - ) - } - - /// Returns the identifier for the generated `Output*` assoc. type. - fn out_assoc_type_ident(method_ident: &Ident) -> syn::Ident { - format_ident!("{}Output", method_ident.to_string().to_camel_case()) - } - - fn generate_call_forwarder_trait_ghost_message( - message: ir::CallableWithSelector, - ) -> TokenStream2 { - let span = message.span(); - let ident = message.ident(); - let output_ident = Self::out_assoc_type_ident(ident); - let composed_selector = message.composed_selector().as_bytes().to_owned(); - let attrs = message.attrs(); - let input_bindings = message - .inputs() - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>(); - let input_types = message - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>(); - let trait_ident = message - .item_impl() - .trait_ident() - .expect("trait identifier must exist") - .to_string(); - let linker_error_ident = - Self::enforce_error_ident(EnforcedErrors::CannotCallTraitMessage { - trait_ident, - message_ident: ident.to_string(), - message_selector: composed_selector, - message_is_mut: message.receiver().is_ref_mut(), - }); - let output_ty = message - .output() - .cloned() - .unwrap_or_else(|| syn::parse_quote! { () }); - let pub_tok = match message.item_impl().trait_path() { - Some(_) => None, - None => Some(quote! { pub }), - }; - let mut_tok = match message.receiver() { - ir::Receiver::Ref => None, - ir::Receiver::RefMut => Some(quote! { mut }), - }; - quote_spanned!(span=> - type #output_ident = #output_ty; - - #( #attrs )* - #[cold] - #[doc(hidden)] - #pub_tok fn #ident( - & #mut_tok self, - #( #input_bindings : #input_types ),* - ) -> Self::#output_ident { - extern { - fn #linker_error_ident() -> !; - } - unsafe { #linker_error_ident() } - } - ) - } - - fn generate_call_forwarder_trait_proper_message( - message: ir::CallableWithSelector, - ) -> TokenStream2 { - let span = message.span(); - let ident = message.ident(); - let output_ident = Self::out_assoc_type_ident(ident); - let composed_selector = message.composed_selector().hex_lits(); - let attrs = message.attrs(); - let input_bindings = message - .inputs() - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>(); - let input_types = message - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>(); - let arg_list = Self::generate_arg_list(input_types.iter().cloned()); - let output = message.output(); - let output_sig = output.map_or_else( - || quote! { () }, - |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, - ); - let pub_tok = match message.item_impl().trait_path() { - Some(_) => None, - None => Some(quote! { pub }), - }; - let mut_tok = match message.receiver() { - ir::Receiver::Ref => None, - ir::Receiver::RefMut => Some(quote! { mut }), - }; - quote_spanned!(span=> - #[allow(clippy::type_complexity)] - type #output_ident = ::ink_env::call::CallBuilder< - Environment, - ::ink_env::call::utils::Set, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, - ::ink_env::call::utils::Set<#output_sig>, - >; - - #( #attrs )* - #[inline] - #pub_tok fn #ident( - & #mut_tok #(, #input_bindings : #input_types )* - ) -> Self::#output_ident { - ::ink_env::call::build_call::() - .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) - .exec_input( - ::ink_env::call::ExecutionInput::new( - ::ink_env::call::Selector::new([ #( #composed_selector ),* ]) - ) - #( - .push_arg(#input_bindings) - )* - ) - .returns::<#output_sig>() - } - ) - } - - /// Generates code for a single call forwarder trait message. - /// - /// The `mutable` parameter indicates whether only read-only (`false`) or - /// write-only (`true`) messages shall be valid calls. For non valid messages - /// an invalid implementation is provided so that actually calling those - /// will result in a compiler or linker error. - fn generate_call_forwarder_trait_message( - mutable: bool, - message: ir::CallableWithSelector, - ) -> TokenStream2 { - if mutable == message.receiver().is_ref_mut() { - Self::generate_call_forwarder_trait_proper_message(message) - } else { - Self::generate_call_forwarder_trait_ghost_message(message) - } - } - - /// Generates code for a single call forwarder trait constructor. - /// - /// Note that constructors never need to be forwarded and that we only - /// provide their implementations to satisfy the implementation block. - /// We generally try to generate code in a way that actually calling - /// those constructors will result in a compiler or linker error. - fn generate_call_forwarder_trait_constructor( - constructor: ir::CallableWithSelector, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let ident = constructor.ident(); - let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); - let composed_selector = constructor.composed_selector().as_bytes().to_owned(); - let trait_ident = constructor - .item_impl() - .trait_ident() - .expect("trait identifier must exist") - .to_string(); - let linker_error = EnforcedErrors::CannotCallTraitConstructor { - trait_ident, - constructor_ident: ident.to_string(), - constructor_selector: composed_selector, - }; - let linker_error_ident = format_ident!( - "__ink_enforce_error_{}", - serde_hex::to_hex(&scale::Encode::encode(&linker_error), false) - ); - let input_bindings = constructor - .inputs() - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>(); - let input_types = constructor - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>(); - quote_spanned!(span => - type #output_ident = ::ink_lang::NeverReturns; - - #( #attrs )* - #[cold] - #[doc(hidden)] - fn #ident( - #( #input_bindings : #input_types ),* - ) -> Self::#output_ident { - extern { - fn #linker_error_ident() -> !; - } - unsafe { #linker_error_ident() } - } - ) - } - - /// Generates code for a single call forwarder trait implementation block. - /// - /// The `mutable` parameter indicates whether only read-only (`false`) or - /// write-only (`true`) messages and constructors are to be considered. - fn generate_call_forwarder_trait_impl_block( - &self, - mutable: bool, - item_impl: &ir::ItemImpl, - ) -> TokenStream2 { - assert!(item_impl.trait_path().is_some()); - let span = item_impl.span(); - let attrs = item_impl.attrs(); - let forwarder_ident = Self::call_forwarder_ident(); - let storage_ident = self.contract.module().storage().ident(); - let mut_tok = if mutable { Some(quote! { mut }) } else { None }; - let constructors = item_impl.iter_constructors().map(|constructor| { - Self::generate_call_forwarder_trait_constructor(constructor) - }); - let messages = item_impl - .iter_messages() - .map(|message| Self::generate_call_forwarder_trait_message(mutable, message)); - let trait_path = item_impl - .trait_path() - .expect("encountered missing trait path for trait impl block"); - let trait_ident = item_impl - .trait_ident() - .expect("encountered missing trait identifier for trait impl block"); - let hash = ir::InkTrait::compute_verify_hash( - trait_ident, - item_impl.iter_constructors().map(|constructor| { - let ident = constructor.ident().clone(); - let len_inputs = constructor.inputs().count(); - (ident, len_inputs) - }), - item_impl.iter_messages().map(|message| { - let ident = message.ident().clone(); - let len_inputs = message.inputs().count() + 1; - let is_mut = message.receiver().is_ref_mut(); - (ident, len_inputs, is_mut) - }), - ); - let checksum = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; - quote_spanned!(span => - unsafe impl<'a> ::ink_lang::CheckedInkTrait<[(); #checksum]> for #forwarder_ident<&'a #mut_tok #storage_ident> {} - - #( #attrs )* - impl<'a> #trait_path for #forwarder_ident<&'a #mut_tok #storage_ident> { - type __ink_Checksum = [(); #checksum]; - - #( #constructors )* - #( #messages )* - } - ) - } - - fn generate_call_forwarder_inherent_message( - message: ir::CallableWithSelector, - ) -> TokenStream2 { - let span = message.span(); - let ident = message.ident(); - let composed_selector = message.composed_selector().hex_lits(); - let attrs = message.attrs(); - let input_bindings = message - .inputs() - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>(); - let input_types = message - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>(); - let arg_list = Self::generate_arg_list(input_types.iter().cloned()); - let output = message.output(); - let output_sig = output.map_or_else( - || quote! { () }, - |output| quote! { ::ink_env::call::utils::ReturnType<#output> }, - ); - let pub_tok = match message.item_impl().trait_path() { - Some(_) => None, - None => Some(quote! { pub }), - }; - quote_spanned!(span=> - #( #attrs )* - #[inline] - #[allow(clippy::type_complexity)] - #pub_tok fn #ident( - self, - #( #input_bindings : #input_types ),* - ) -> ::ink_env::call::CallBuilder< - Environment, - ::ink_env::call::utils::Set, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, - ::ink_env::call::utils::Set<#output_sig>, - > { - ::ink_env::call::build_call::() - .callee(::ink_lang::ToAccountId::to_account_id(self.contract)) - .exec_input( - ::ink_env::call::ExecutionInput::new( - ::ink_env::call::Selector::new([ #( #composed_selector ),* ]) - ) - #( - .push_arg(#input_bindings) - )* - ) - .returns::<#output_sig>() - } - ) - } - - /// Generates code for a single call forwarder inherent implementation block. - /// - /// The `mutable` parameter indicates whether only read-only (`false`) or - /// write-only (`true`) messages and constructors are to be considered. - fn generate_call_forwarder_inherent_impl_block( - &self, - mutable: bool, - item_impl: &ir::ItemImpl, - ) -> TokenStream2 { - assert!(item_impl.trait_path().is_none()); - let span = item_impl.span(); - let attrs = item_impl.attrs(); - let forwarder_ident = Self::call_forwarder_ident(); - let storage_ident = self.contract.module().storage().ident(); - let mut_tok = if mutable { Some(quote! { mut }) } else { None }; - let messages = item_impl - .iter_messages() - .filter(|message| mutable == message.receiver().is_ref_mut()) - .map(Self::generate_call_forwarder_inherent_message); - quote_spanned!(span => - #( #attrs )* - impl<'a> #forwarder_ident<&'a #mut_tok #storage_ident> { - #( #messages )* - } - ) - } - - /// Generates code for the call forwarder implementation blocks. - /// - /// The `mutable` parameter indicates whether only read-only (`false`) or - /// write-only (`true`) messages and constructors are to be considered. - fn generate_call_forwarder_impl_blocks(&self, mutable: bool) -> TokenStream2 { - let impl_blocks = self.contract.module().impls().map(|item_impl| { - match item_impl.trait_path() { - Some(_) => { - self.generate_call_forwarder_trait_impl_block(mutable, item_impl) - } - None => { - self.generate_call_forwarder_inherent_impl_block(mutable, item_impl) - } - } - }); - quote! { #( #impl_blocks )* } - } - - /// Generates code for the call forwarder utility struct. - fn generate_call_forwarders(&self) -> TokenStream2 { - let forwarder_ident = Self::call_forwarder_ident(); - let storage_ident = self.contract.module().storage().ident(); - let impl_blocks_ref = self.generate_call_forwarder_impl_blocks(false); - let impl_blocks_refmut = self.generate_call_forwarder_impl_blocks(true); - let only_as_dependency = - self.generate_code_using::(); - quote! { - #only_as_dependency - const _: () = { - impl<'a> ::ink_lang::ForwardCall for &'a #storage_ident { - type Forwarder = #forwarder_ident<&'a #storage_ident>; - - #[inline] - fn call(self) -> Self::Forwarder { - #forwarder_ident { contract: self } - } - } - - impl<'a> ::ink_lang::ForwardCallMut for &'a mut #storage_ident { - type Forwarder = #forwarder_ident<&'a mut #storage_ident>; - - #[inline] - fn call_mut(self) -> Self::Forwarder { - #forwarder_ident { contract: self } - } - } - - // Forwards contract messages to the chain. - #[doc(hidden)] - pub struct #forwarder_ident { - contract: T, - } - - #impl_blocks_ref - #impl_blocks_refmut - }; - } - } - - /// Generates the code to allow short-hand cross-chain contract calls for messages. - fn generate_trait_impl_block_message( - &self, - message: ir::CallableWithSelector, - ) -> TokenStream2 { - let storage_ident_str = self.contract.module().storage().ident().to_string(); - let span = message.span(); - let ident = message.ident(); - let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); - let ident_str = ident.to_string(); - let trait_path = message - .item_impl() - .trait_path() - .expect("encountered missing trait path for trait impl block") - .segments - .iter() - .map(|path_segment| &path_segment.ident) - .map(ToString::to_string) - .join("::"); - let error_str = format!( - "encountered error while calling <{} as {}>::{}", - storage_ident_str, trait_path, ident_str - ); - let inputs_sig = message.inputs(); - let inputs_params = message.inputs().map(|pat_type| &pat_type.pat); - let output_ty = message - .output() - .cloned() - .unwrap_or_else(|| syn::parse_quote! { () }); - let receiver = message.receiver(); - let forward_ident = match receiver { - ir::Receiver::Ref => format_ident!("call"), - ir::Receiver::RefMut => format_ident!("call_mut"), - }; - let forward_trait = match receiver { - ir::Receiver::Ref => format_ident!("ForwardCall"), - ir::Receiver::RefMut => format_ident!("ForwardCallMut"), - }; - let opt_mut = match receiver { - ir::Receiver::Ref => None, - ir::Receiver::RefMut => Some(quote! { mut }), - }; - let opt_pub = message - .item_impl() - .trait_path() - .is_none() - .then(|| quote! { pub }); - quote_spanned!(span => - type #output_ident = #output_ty; - - #[inline] - #opt_pub fn #ident( #receiver #(, #inputs_sig )* ) -> Self::#output_ident { - <&#opt_mut Self as ::ink_lang::#forward_trait>::#forward_ident(self) - .#ident( #( #inputs_params ),* ) - .fire() - .expect(#error_str) - } - ) - } - - /// Generates the code to allow cross-chain contract calls for trait constructors. - fn generate_trait_impl_block_constructor( - constructor: ir::CallableWithSelector, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let ident = constructor.ident(); - let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); - let composed_selector = constructor.composed_selector().hex_lits(); - let input_bindings = constructor - .inputs() - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>(); - let input_types = constructor - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>(); - let arg_list = Self::generate_arg_list(input_types.iter().cloned()); - quote_spanned!(span => - #[allow(clippy::type_complexity)] - type #output_ident = ::ink_env::call::CreateBuilder< - Environment, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, - ::ink_env::call::utils::Unset<::ink_env::call::state::Salt>, - Self, - >; - - #( #attrs )* - #[inline] - fn #ident( - #( #input_bindings : #input_types ),* - ) -> Self::#output_ident { - ::ink_env::call::build_create::() - .exec_input( - ::ink_env::call::ExecutionInput::new( - ::ink_env::call::Selector::new([ #( #composed_selector ),* ]) - ) - #( - .push_arg(#input_bindings) - )* - ) - } - ) - } - - fn generate_trait_impl_block(&self, impl_block: &ir::ItemImpl) -> TokenStream2 { - assert!(impl_block.trait_path().is_some()); - let only_as_dependency = - self.generate_code_using::(); - let span = impl_block.span(); - let attrs = impl_block.attrs(); - let trait_path = impl_block - .trait_path() - .expect("encountered missing trait path"); - let trait_ident = impl_block - .trait_ident() - .expect("encountered missing trait identifier"); - let self_type = impl_block.self_type(); - let messages = impl_block - .iter_messages() - .map(|message| self.generate_trait_impl_block_message(message)); - let constructors = impl_block - .iter_constructors() - .map(Self::generate_trait_impl_block_constructor); - let hash = ir::InkTrait::compute_verify_hash( - trait_ident, - impl_block.iter_constructors().map(|constructor| { - let ident = constructor.ident().clone(); - let len_inputs = constructor.inputs().count(); - (ident, len_inputs) - }), - impl_block.iter_messages().map(|message| { - let ident = message.ident().clone(); - let len_inputs = message.inputs().count() + 1; - let is_mut = message.receiver().is_ref_mut(); - (ident, len_inputs, is_mut) - }), - ); - let checksum = u32::from_be_bytes([hash[0], hash[1], hash[2], hash[3]]) as usize; - quote_spanned!(span => - #only_as_dependency - unsafe impl ::ink_lang::CheckedInkTrait<[(); #checksum]> for #self_type {} - - #only_as_dependency - #( #attrs )* - impl #trait_path for #self_type { - type __ink_Checksum = [(); #checksum]; - - #( #messages )* - #( #constructors )* - } - ) - } - - /// Generates the code to allow short-hand cross-chain contract calls for constructors. - /// - /// # Note - /// - /// For constructors this is the only way they are able to be called. - fn generate_inherent_impl_block_constructor( - constructor: ir::CallableWithSelector, - ) -> TokenStream2 { - let span = constructor.span(); - let attrs = constructor.attrs(); - let ident = constructor.ident(); - let composed_selector = constructor.composed_selector().hex_lits(); - let input_bindings = constructor - .inputs() - .enumerate() - .map(|(n, _)| format_ident!("__ink_binding_{}", n)) - .collect::>(); - let input_types = constructor - .inputs() - .map(|pat_type| &*pat_type.ty) - .collect::>(); - let arg_list = Self::generate_arg_list(input_types.iter().cloned()); - quote_spanned!(span => - #( #attrs )* - #[inline] - #[allow(clippy::type_complexity)] - pub fn #ident( - #( #input_bindings : #input_types ),* - ) -> ::ink_env::call::CreateBuilder< - Environment, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Unset, - ::ink_env::call::utils::Set<::ink_env::call::ExecutionInput<#arg_list>>, - ::ink_env::call::utils::Unset<::ink_env::call::state::Salt>, - Self, - > { - ::ink_env::call::build_create::() - .exec_input( - ::ink_env::call::ExecutionInput::new( - ::ink_env::call::Selector::new([ #( #composed_selector ),* ]) - ) - #( - .push_arg(#input_bindings) - )* - ) - } - ) - } - - /// Generates the code to allow short-hand cross-chain contract calls for messages. - fn generate_inherent_impl_block_message( - &self, - message: ir::CallableWithSelector, - ) -> TokenStream2 { - let storage_ident_str = self.contract.module().storage().ident().to_string(); - let span = message.span(); - let ident = message.ident(); - let ident_str = ident.to_string(); - let error_str = format!( - "encountered error while calling {}::{}", - storage_ident_str, ident_str - ); - let inputs_sig = message.inputs(); - let inputs_params = message.inputs().map(|pat_type| &pat_type.pat); - let output_sig = message.output().map(|output| quote! { -> #output }); - let receiver = message.receiver(); - let forward_ident = match receiver { - ir::Receiver::Ref => format_ident!("call"), - ir::Receiver::RefMut => format_ident!("call_mut"), - }; - let forward_trait = match receiver { - ir::Receiver::Ref => format_ident!("ForwardCall"), - ir::Receiver::RefMut => format_ident!("ForwardCallMut"), - }; - let opt_mut = match receiver { - ir::Receiver::Ref => None, - ir::Receiver::RefMut => Some(quote! { mut }), - }; - let opt_pub = message - .item_impl() - .trait_path() - .is_none() - .then(|| quote! { pub }); - quote_spanned!(span => - #[inline] - #opt_pub fn #ident( #receiver #(, #inputs_sig )* ) #output_sig { - <&#opt_mut Self as ::ink_lang::#forward_trait>::#forward_ident(self) - .#ident( #( #inputs_params ),* ) - .fire() - .expect(#error_str) - } - ) - } - - fn generate_inherent_impl_block(&self, impl_block: &ir::ItemImpl) -> TokenStream2 { - assert!(impl_block.trait_path().is_none()); - let only_as_dependency = - self.generate_code_using::(); - let span = impl_block.span(); - let attrs = impl_block.attrs(); - let self_type = impl_block.self_type(); - let messages = impl_block - .iter_messages() - .map(|message| self.generate_inherent_impl_block_message(message)); - let constructors = impl_block.iter_constructors().map(|constructor| { - Self::generate_inherent_impl_block_constructor(constructor) - }); - quote_spanned!(span => - #only_as_dependency - #( #attrs )* - impl #self_type { - #( #messages )* - #( #constructors )* - } - ) - } - - fn generate_impl_blocks(&self) -> TokenStream2 { - let impl_blocks = self.contract.module().impls().map(|impl_block| { - match impl_block.trait_path() { - Some(_) => self.generate_trait_impl_block(impl_block), - None => self.generate_inherent_impl_block(impl_block), - } - }); - quote! { - #( #impl_blocks )* - } - } -} diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 10bdec4c9a..0dbb5fdc68 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -30,7 +30,6 @@ mod arg_list; mod as_dependency; mod chain_extension; mod contract; -mod cross_calling; mod dispatch; mod enforced_error; mod env; @@ -56,7 +55,6 @@ pub use self::{ }, chain_extension::ChainExtension, contract::Contract, - cross_calling::CrossCalling, dispatch::Dispatch, env::Env, events::Events, From a82d5a098120b83b4a835aba43d9c120b21c2505 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 14:13:38 +0200 Subject: [PATCH 174/493] remote todo!() in doc tests invalidating rustfmt config --- crates/lang/macro/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/macro/src/lib.rs b/crates/lang/macro/src/lib.rs index 3defdbb136..c06db9fd43 100644 --- a/crates/lang/macro/src/lib.rs +++ b/crates/lang/macro/src/lib.rs @@ -587,7 +587,7 @@ pub fn contract(attr: TokenStream, item: TokenStream) -> TokenStream { /// /// #[ink(message)] /// fn transfer(&mut self, amount: Balance, to: AccountId) -> bool { -/// todo!(); +/// unimplemented!() /// } /// } /// } From 3f9089a63b1d21ab3d9197e15b7cf96566f5add4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 21:05:10 +0200 Subject: [PATCH 175/493] remove Env assoc type from ink! traits and instead depend on ContractEnv super trait This makes more sense as a contract implementing ink! traits will always be defined for the same environment. The previous design invalidly allowed too much flexibility and provided the option to implement different ink! traits with different ink! environments. --- .../codegen/src/generator/as_dependency/call_builder.rs | 6 ++++-- .../codegen/src/generator/as_dependency/contract_ref.rs | 6 ++++-- crates/lang/codegen/src/generator/item_impls.rs | 2 -- .../lang/codegen/src/generator/trait_def/call_builder.rs | 7 ++++++- .../codegen/src/generator/trait_def/call_forwarder.rs | 7 ++++++- crates/lang/codegen/src/generator/trait_def/definition.rs | 8 ++++---- .../codegen/src/generator/trait_def/trait_registry.rs | 2 -- crates/lang/src/traits.rs | 7 +++++++ 8 files changed, 31 insertions(+), 14 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 32a929b493..80b15fefee 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -103,6 +103,10 @@ impl CallBuilder<'_> { impl ::ink_lang::ContractCallBuilder for #storage_ident { type Type = #cb_ident; } + + impl ::ink_lang::ContractEnv for #cb_ident { + type Env = <#storage_ident as ::ink_lang::ContractEnv>::Env; + } }; ) } @@ -269,8 +273,6 @@ impl CallBuilder<'_> { .map(|message| self.generate_ink_trait_impl_for_message(trait_path, message)); quote_spanned!(span=> impl #trait_path for #cb_ident { - type Env = Environment; - type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry as #trait_path>::__ink_TraitInfo; diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index f7a910dc40..d630afea82 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -96,6 +96,10 @@ impl ContractRef<'_> { impl ::ink_lang::ContractReference for #storage_ident { type Type = #ref_ident; } + + impl ::ink_lang::ContractEnv for #ref_ident { + type Env = <#storage_ident as ::ink_lang::ContractEnv>::Env; + } }; ) } @@ -197,8 +201,6 @@ impl ContractRef<'_> { #( #attrs )* impl #trait_path for #forwarder_ident { - type Env = Environment; - #[doc(hidden)] type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry as #trait_path>::__ink_TraitInfo; diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index f69592f8a6..8e1c3d59b1 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -100,8 +100,6 @@ impl ItemImpls<'_> { #( #attrs )* impl #trait_path for #self_type { - type Env = Environment; - type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry as #trait_path>::__ink_TraitInfo; diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index fc880e98a8..069a118fbd 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -326,12 +326,17 @@ impl CallBuilder<'_> { { } - impl #trait_ident for #builder_ident + impl ::ink_lang::ContractEnv for #builder_ident where E: ::ink_env::Environment, { type Env = E; + } + impl #trait_ident for #builder_ident + where + E: ::ink_env::Environment, + { #[doc(hidden)] #[allow(non_camel_case_types)] type __ink_TraitInfo = #trait_info_ident; diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 9467c7b592..55e159d380 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -352,12 +352,17 @@ impl CallForwarder<'_> { { } - impl #trait_ident for #forwarder_ident + impl ::ink_lang::ContractEnv for #forwarder_ident where E: ::ink_env::Environment, { type Env = E; + } + impl #trait_ident for #forwarder_ident + where + E: ::ink_env::Environment, + { #[doc(hidden)] #[allow(non_camel_case_types)] type __ink_TraitInfo = #trait_info_ident; diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 7be8a962b7..2a74bda498 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -60,10 +60,10 @@ impl TraitDefinition<'_> { .map(Self::generate_for_message); quote_spanned!(span => #(#attrs)* - pub trait #ident: ::ink_lang::TraitImplementer<#unique_trait_id> { - /// The contract environment. - type Env: ::ink_env::Environment; - + pub trait #ident: + ::ink_lang::ContractEnv + + ::ink_lang::TraitImplementer<#unique_trait_id> + { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 58a7286df9..33a71cfee5 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -108,8 +108,6 @@ impl TraitRegistry<'_> { where E: ::ink_env::Environment, { - type Env = E; - /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index cf21ab31ea..1503b163cf 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -153,6 +153,13 @@ pub struct TraitCallForwarderRegistry { marker: PhantomData E>, } +impl crate::ContractEnv for TraitCallForwarderRegistry +where + E: ink_env::Environment, +{ + type Env = E; +} + unsafe impl TraitImplementer for TraitCallForwarderRegistry {} /// The default type that ink! trait definition implementations use for the From 5633a9297001e7d2fb4e435e15be792053241cd8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 15 Sep 2021 21:10:55 +0200 Subject: [PATCH 176/493] apply rustfmt --- .../macro/tests/ui/pass/08-flipper-as-dependency-trait.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs index 2bd30c4bac..f8afea65aa 100644 --- a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs +++ b/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs @@ -19,7 +19,9 @@ mod flipper { impl Flipper { #[ink(constructor)] pub fn new() -> Self { - Self { value: Default::default() } + Self { + value: Default::default(), + } } } From bf58a36bbc465766bb27cb156302edffb6cc8a50 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 12:26:56 +0200 Subject: [PATCH 177/493] allow to specify #[ink(selector = N)] where N is a u32 integer literal --- crates/lang/ir/src/ir/attrs.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 1f4d8759c8..2c3324275c 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -794,6 +794,21 @@ impl TryFrom for AttributeFrag { match &meta { syn::Meta::NameValue(name_value) => { if name_value.path.is_ident("selector") { + if let syn::Lit::Int(lit_int) = &name_value.lit { + let selector_u32 = lit_int.base10_parse::() + .map_err(|error| { + format_err_spanned!( + lit_int, + "selector value out of range. selector must be a valid `u32` integer: {}", + error + ) + })?; + let selector = Selector::from_bytes(selector_u32.to_be_bytes()); + return Ok(AttributeFrag { + ast: meta, + arg: AttributeArg::Selector(selector), + }) + } if let syn::Lit::Str(lit_str) = &name_value.lit { let regex = Regex::new(r"0x([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})") .map_err(|_| { From c740beef8f9ae8dc24b0056cda364ec8b068b40c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 12:27:19 +0200 Subject: [PATCH 178/493] disallow empty ink! trait definitions --- crates/lang/ir/src/ir/trait_def/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index 38a0928efc..1faaa10722 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -68,6 +68,12 @@ impl TryFrom for InkTrait { &mut message_selectors, &mut constructor_selectors, )?; + if message_selectors.is_empty() { + return Err(format_err!( + item_trait.span(), + "encountered invalid empty ink! trait definition" + )) + } Ok(Self { item: item_trait, message_selectors, From 60e3c21ee81f700dc07e2236dc1b3b5fc8e69ee5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 12:27:39 +0200 Subject: [PATCH 179/493] disallow ink! constructors in ink! trait definitions --- crates/lang/ir/src/ir/trait_def/mod.rs | 57 +++++--------------------- 1 file changed, 11 insertions(+), 46 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index 1faaa10722..ad452373ff 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -284,7 +284,7 @@ impl InkTrait { )) } syn::TraitItem::Method(method_trait_item) => { - Self::analyse_methods(method_trait_item)?; + Self::analyse_trait_method(method_trait_item)?; } unknown => { return Err(format_err_spanned!( @@ -306,7 +306,7 @@ impl InkTrait { /// - If the method is variadic or has generic parameters. /// - If the method does not respect the properties of either an /// ink! message or ink! constructor. - fn analyse_methods(method: &syn::TraitItemMethod) -> Result<()> { + fn analyse_trait_method(method: &syn::TraitItemMethod) -> Result<()> { if let Some(default_impl) = &method.default { return Err(format_err_spanned!( default_impl, @@ -353,10 +353,10 @@ impl InkTrait { Ok(Some(ink_attr)) => { match ink_attr.first().kind() { ir::AttributeArg::Message => { - Self::analyse_message(method)?; + Self::analyse_trait_message(method)?; } ir::AttributeArg::Constructor => { - Self::analyse_constructor(method)?; + Self::analyse_trait_constructor(method)?; } _unsupported => { return Err(format_err_spanned!( @@ -377,47 +377,12 @@ impl InkTrait { Ok(()) } - /// Analyses the properties of an ink! constructor. - /// - /// # Errors - /// - /// - If the constructor has a `self` receiver as first argument. - /// - If the constructor has no `Self` return type. - fn analyse_constructor(constructor: &syn::TraitItemMethod) -> Result<()> { - InkTraitConstructor::extract_attributes(constructor.span(), &constructor.attrs)?; - if let Some(receiver) = constructor.sig.receiver() { - return Err(format_err_spanned!( - receiver, - "ink! constructors must not have a `self` receiver", - )) - } - match &constructor.sig.output { - syn::ReturnType::Default => { - return Err(format_err_spanned!( - constructor.sig, - "ink! constructors must return Self" - )) - } - syn::ReturnType::Type(_, ty) => { - match &**ty { - syn::Type::Path(type_path) => { - if !type_path.path.is_ident("Self") { - return Err(format_err_spanned!( - type_path.path, - "ink! constructors must return Self" - )) - } - } - unknown => { - return Err(format_err_spanned!( - unknown, - "ink! constructors must return Self" - )) - } - } - } - } - Ok(()) + /// Constructors are generally not allowed in ink! trait definitions. + fn analyse_trait_constructor(constructor: &syn::TraitItemMethod) -> Result<()> { + return Err(format_err!( + constructor.span(), + "ink! trait definitions must not have constructors", + )) } /// Analyses the properties of an ink! message. @@ -425,7 +390,7 @@ impl InkTrait { /// # Errors /// /// - If the message has no `&self` or `&mut self` receiver. - fn analyse_message(message: &syn::TraitItemMethod) -> Result<()> { + fn analyse_trait_message(message: &syn::TraitItemMethod) -> Result<()> { InkTraitMessage::extract_attributes(message.span(), &message.attrs)?; match message.sig.receiver() { None | Some(syn::FnArg::Typed(_)) => { From b8c6c5001409cb464b92c6f52bc04de702d78cc0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 12:28:22 +0200 Subject: [PATCH 180/493] add some ink! trait definition UI tests --- crates/lang/macro/tests/compile_tests.rs | 15 +++++++++ .../ui/trait_def/fail/empty_definition.rs | 6 ++++ .../ui/trait_def/fail/empty_definition.stderr | 5 +++ .../ui/trait_def/fail/invalid_payable_1.rs | 9 ++++++ .../trait_def/fail/invalid_payable_1.stderr | 5 +++ .../ui/trait_def/fail/invalid_payable_2.rs | 9 ++++++ .../trait_def/fail/invalid_payable_2.stderr | 5 +++ .../ui/trait_def/fail/invalid_selector_1.rs | 9 ++++++ .../trait_def/fail/invalid_selector_1.stderr | 5 +++ .../ui/trait_def/fail/invalid_selector_2.rs | 9 ++++++ .../trait_def/fail/invalid_selector_2.stderr | 5 +++ .../trait_def/fail/overlapping_selectors.rs | 11 +++++++ .../fail/overlapping_selectors.stderr | 11 +++++++ .../ui/trait_def/fail/with_assoc_const.rs | 11 +++++++ .../ui/trait_def/fail/with_assoc_const.stderr | 5 +++ .../ui/trait_def/fail/with_assoc_type.rs | 11 +++++++ .../ui/trait_def/fail/with_assoc_type.stderr | 5 +++ .../ui/trait_def/fail/with_constructor.rs | 9 ++++++ .../ui/trait_def/fail/with_constructor.stderr | 6 ++++ .../ui/trait_def/pass/custom_selector.rs | 21 +++++++++++++ .../ui/trait_def/pass/invalid_selector_3.rs | 9 ++++++ .../tests/ui/trait_def/pass/many_inputs.rs | 31 +++++++++++++++++++ .../tests/ui/trait_def/pass/many_outputs.rs | 31 +++++++++++++++++++ .../ui/trait_def/pass/payable_message.rs | 11 +++++++ .../ui/trait_def/pass/simple_definition.rs | 11 +++++++ 25 files changed, 265 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/empty_definition.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/empty_definition.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/with_constructor.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/with_constructor.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/many_inputs.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/many_outputs.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 93548b31a6..55b44a4677 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -60,4 +60,19 @@ fn compile_tests() { t.compile_fail("tests/ui/fail/S-06-event-as-storage.rs"); t.pass("tests/ui/chain_extension/E-01-simple.rs"); + + t.pass("tests/ui/trait_def/pass/simple_definition.rs"); + t.pass("tests/ui/trait_def/pass/many_inputs.rs"); + t.pass("tests/ui/trait_def/pass/many_outputs.rs"); + t.pass("tests/ui/trait_def/pass/payable_message.rs"); + t.pass("tests/ui/trait_def/pass/custom_selector.rs"); + t.compile_fail("tests/ui/trait_def/fail/empty_definition.rs"); + t.compile_fail("tests/ui/trait_def/fail/with_constructor.rs"); + t.compile_fail("tests/ui/trait_def/fail/overlapping_selectors.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_selector_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_selector_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_payable_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_payable_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/with_assoc_type.rs"); + t.compile_fail("tests/ui/trait_def/fail/with_assoc_const.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.rs b/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.rs new file mode 100644 index 0000000000..f1157d58e7 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.rs @@ -0,0 +1,6 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait EmptyDefinition {} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.stderr b/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.stderr new file mode 100644 index 0000000000..5289ee7699 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.stderr @@ -0,0 +1,5 @@ +error: encountered invalid empty ink! trait definition + --> $DIR/empty_definition.rs:4:1 + | +4 | pub trait EmptyDefinition {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.rs new file mode 100644 index 0000000000..367e22efa3 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait InvalidPayable { + #[ink(message, payable = false)] + fn invalid_payable(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.stderr new file mode 100644 index 0000000000..7c4cecdee3 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.stderr @@ -0,0 +1,5 @@ +error: unknown ink! attribute argument (name = value) + --> $DIR/invalid_payable_1.rs:5:20 + | +5 | #[ink(message, payable = false)] + | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.rs new file mode 100644 index 0000000000..95693e4462 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait InvalidPayable { + #[ink(message, payable = true)] + fn invalid_payable(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.stderr new file mode 100644 index 0000000000..25eec3ed87 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.stderr @@ -0,0 +1,5 @@ +error: unknown ink! attribute argument (name = value) + --> $DIR/invalid_payable_2.rs:5:20 + | +5 | #[ink(message, payable = true)] + | ^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.rs new file mode 100644 index 0000000000..ba7f6a04a0 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait InvalidSelector { + #[ink(message, selector = true)] + fn invalid_selector(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.stderr new file mode 100644 index 0000000000..b2198e4dfb --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.stderr @@ -0,0 +1,5 @@ +error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE] + --> $DIR/invalid_selector_1.rs:5:20 + | +5 | #[ink(message, selector = true)] + | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.rs new file mode 100644 index 0000000000..10d7fbe811 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait InvalidSelector { + #[ink(message, selector)] + fn invalid_selector(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.stderr new file mode 100644 index 0000000000..78f8cae889 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.stderr @@ -0,0 +1,5 @@ +error: unknown ink! attribute (path) + --> $DIR/invalid_selector_2.rs:5:20 + | +5 | #[ink(message, selector)] + | ^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.rs b/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.rs new file mode 100644 index 0000000000..3e06d25745 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait OverlappingSelectors { + #[ink(message, selector = 1)] + fn selector1(&self); + #[ink(message, selector = 1)] + fn selector2(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.stderr b/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.stderr new file mode 100644 index 0000000000..9e0f937f1b --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.stderr @@ -0,0 +1,11 @@ +error: encountered duplicate selector ([0, 0, 0, 1]) in the same ink! trait definition + --> $DIR/overlapping_selectors.rs:8:8 + | +8 | fn selector2(&self); + | ^^^^^^^^^ + +error: first ink! trait constructor or message with same selector found here + --> $DIR/overlapping_selectors.rs:6:8 + | +6 | fn selector1(&self); + | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.rs b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.rs new file mode 100644 index 0000000000..81a648d614 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait WithAssocType { + const INVALID_CONST: bool; + + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.stderr b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.stderr new file mode 100644 index 0000000000..f02424f83e --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.stderr @@ -0,0 +1,5 @@ +error: associated constants in ink! trait definitions are not supported, yet + --> $DIR/with_assoc_const.rs:5:5 + | +5 | const INVALID_CONST: bool; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.rs b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.rs new file mode 100644 index 0000000000..3c6458cb44 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait WithAssocType { + type InvalidAssocType; + + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.stderr b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.stderr new file mode 100644 index 0000000000..e2f9260ff1 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.stderr @@ -0,0 +1,5 @@ +error: associated types in ink! trait definitions are not supported, yet + --> $DIR/with_assoc_type.rs:5:5 + | +5 | type InvalidAssocType; + | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.rs b/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.rs new file mode 100644 index 0000000000..66626fd260 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait WithConstructor { + #[ink(constructor)] + fn new() -> Self; +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.stderr b/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.stderr new file mode 100644 index 0000000000..87807e8d59 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.stderr @@ -0,0 +1,6 @@ +error: ink! trait definitions must not have constructors + --> $DIR/with_constructor.rs:5:5 + | +5 | / #[ink(constructor)] +6 | | fn new() -> Self; + | |_____________________^ diff --git a/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs b/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs new file mode 100644 index 0000000000..5df92e1f74 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs @@ -0,0 +1,21 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait CustomSelector { + #[ink(message, selector = "0x00000001")] + fn selector1(&self); + #[ink(message, selector = "0x00000002")] + fn selector1_mut(&mut self); + + #[ink(message, selector = 3)] + fn selector2(&self); + #[ink(message, selector = 4)] + fn selector2_mut(&mut self); + + #[ink(message, selector = 0x0000_0005)] + fn selector3(&self); + #[ink(message, selector = 0x0000_0006)] + fn selector3_mut(&mut self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs b/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs new file mode 100644 index 0000000000..7e0e8a801b --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait InvalidSelector { + #[ink(message, selector = 0xC0DECAFE)] + fn invalid_selector(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/many_inputs.rs b/crates/lang/macro/tests/ui/trait_def/pass/many_inputs.rs new file mode 100644 index 0000000000..da988352ab --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/many_inputs.rs @@ -0,0 +1,31 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait ManyInputs { + #[ink(message)] + fn input0(&self); + #[ink(message)] + fn input0_mut(&mut self); + + #[ink(message)] + fn input1(&self, a: i8); + #[ink(message)] + fn input1_mut(&mut self, a: i8); + + #[ink(message)] + fn input2(&self, a: i8, b: i16); + #[ink(message)] + fn input2_mut(&mut self, a: i8, b: i16); + + #[ink(message)] + fn input3(&self, a: i8, b: i16, c: i32); + #[ink(message)] + fn input3_mut(&mut self, a: i8, b: i16, c: i32); + + #[ink(message)] + fn input4(&self, a: i8, b: i16, c: i32, d: i64); + #[ink(message)] + fn input4_mut(&mut self, a: i8, b: i16, c: i32, d: i64); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/many_outputs.rs b/crates/lang/macro/tests/ui/trait_def/pass/many_outputs.rs new file mode 100644 index 0000000000..4f3cafb15d --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/many_outputs.rs @@ -0,0 +1,31 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait ManyOutputs { + #[ink(message)] + fn output0(&self); + #[ink(message)] + fn output0_mut(&mut self); + + #[ink(message)] + fn output1(&self) -> i8; + #[ink(message)] + fn output1_mut(&mut self) -> i8; + + #[ink(message)] + fn output2(&self) -> (i8, i16); + #[ink(message)] + fn output2_mut(&mut self) -> (i8, i16); + + #[ink(message)] + fn output3(&self) -> (i8, i16, i32); + #[ink(message)] + fn output3_mut(&mut self) -> (i8, i16, i32); + + #[ink(message)] + fn output4(&self) -> (i8, i16, i32, i64); + #[ink(message)] + fn output4_mut(&mut self) -> (i8, i16, i32, i64); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs new file mode 100644 index 0000000000..8eccff66f3 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait PayableDefinition { + #[ink(message, payable)] + fn payable(&self); + #[ink(message, payable)] + fn payable_mut(&mut self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs b/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs new file mode 100644 index 0000000000..c2ac026d63 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait SimpleDefinition { + #[ink(message)] + fn simple(&self); + #[ink(message)] + fn simple_mut(&mut self); +} + +fn main() {} From 039c880faeeb2e884df4890aefa71ebe93c19843 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 12:38:12 +0200 Subject: [PATCH 181/493] fix ink_lang_ir unit tests --- crates/lang/ir/src/ir/attrs.rs | 2 +- crates/lang/ir/src/ir/trait_def/tests.rs | 174 +---------------------- 2 files changed, 8 insertions(+), 168 deletions(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 2c3324275c..6a37a24098 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -1153,7 +1153,7 @@ mod tests { fn selector_invalid_type() { assert_attribute_try_from( syn::parse_quote! { - #[ink(selector = 42)] + #[ink(selector = true)] }, Err("expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]"), ); diff --git a/crates/lang/ir/src/ir/trait_def/tests.rs b/crates/lang/ir/src/ir/trait_def/tests.rs index c067eb7f5d..91c188be90 100644 --- a/crates/lang/ir/src/ir/trait_def/tests.rs +++ b/crates/lang/ir/src/ir/trait_def/tests.rs @@ -269,59 +269,6 @@ fn trait_def_containing_method_with_unsupported_ink_attribute_is_denied() { ); } -#[test] -fn trait_def_containing_invalid_constructor_is_denied() { - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(&self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(&mut self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(self: &Self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must not have a `self` receiver", - pub trait MyTrait { - #[ink(constructor)] - fn has_self_receiver(self: Self) -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must return Self", - pub trait MyTrait { - #[ink(constructor)] - fn does_not_return_self(); - } - ); - assert_ink_trait_eq_err!( - error: "ink! constructors must return Self", - pub trait MyTrait { - #[ink(constructor)] - fn does_not_return_self() -> i32; - } - ); -} - #[test] fn trait_def_containing_invalid_message_is_denied() { assert_ink_trait_eq_err!( @@ -347,34 +294,6 @@ fn trait_def_containing_invalid_message_is_denied() { ); } -#[test] -fn trait_def_containing_constructor_with_invalid_ink_attributes_is_denied() { - assert_ink_trait_eq_err!( - error: "encountered duplicate ink! attribute", - pub trait MyTrait { - #[ink(constructor)] - #[ink(constructor)] - fn does_not_return_self() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "encountered conflicting ink! attribute argument", - pub trait MyTrait { - #[ink(constructor)] - #[ink(message)] - fn does_not_return_self() -> Self; - } - ); - assert_ink_trait_eq_err!( - error: "encountered conflicting ink! attribute argument", - pub trait MyTrait { - #[ink(constructor)] - #[ink(payable)] - fn does_not_return_self() -> Self; - } - ); -} - #[test] fn trait_def_containing_message_with_invalid_ink_attributes_is_denied() { assert_ink_trait_eq_err!( @@ -408,8 +327,6 @@ fn trait_def_is_ok() { assert!( >::try_from(syn::parse_quote! { pub trait MyTrait { - #[ink(constructor)] - fn my_constructor() -> Self; #[ink(message)] fn my_message(&self); #[ink(message)] @@ -426,8 +343,6 @@ fn trait_def_with_namespace_is_ok() { >::try_from(syn::parse_quote! { #[ink(namespace = "my_namespace")] pub trait MyTrait { - #[ink(constructor)] - fn my_constructor() -> Self; #[ink(message)] fn my_message(&self); #[ink(message)] @@ -443,11 +358,9 @@ fn trait_def_with_selectors_ok() { assert!( >::try_from(syn::parse_quote! { pub trait MyTrait { - #[ink(constructor, selector = "0xC0DECAFE")] - fn my_constructor() -> Self; - #[ink(message, selector = "0xDEADBEEF")] + #[ink(message, selector = 0xDEADBEEF)] fn my_message(&self); - #[ink(message, selector = "0xC0FEFEED")] + #[ink(message, selector = 0xC0FEFEED)] fn my_message_mut(&mut self); } }) @@ -476,21 +389,17 @@ fn trait_def_with_everything_combined_ok() { >::try_from(syn::parse_quote! { #[ink(namespace = "my_namespace")] pub trait MyTrait { - #[ink(constructor)] - fn my_constructor_1() -> Self; - #[ink(constructor, selector = "0xC0DECAFE")] - fn my_constructor_2() -> Self; #[ink(message)] fn my_message_1(&self); #[ink(message, payable)] fn my_message_2(&self); - #[ink(message, payable, selector = "0xDEADBEEF")] + #[ink(message, payable, selector = 0xDEADBEEF)] fn my_message_3(&self); #[ink(message)] fn my_message_mut_1(&mut self); #[ink(message, payable)] fn my_message_mut_2(&mut self); - #[ink(message, payable, selector = "0xC0DEBEEF")] + #[ink(message, payable, selector = 0xC0DEBEEF)] fn my_message_mut_3(&mut self); } }) @@ -504,51 +413,18 @@ fn trait_def_with_overlapping_selectors() { error: "encountered duplicate selector ([c0, de, ca, fe]) \ in the same ink! trait definition", pub trait MyTrait { - #[ink(constructor, selector = "0xC0DECAFE")] - fn my_constructor() -> Self; - #[ink(message, selector = "0xC0DECAFE")] + #[ink(message, selector = 0xC0DECAFE)] fn my_message(&self); - #[ink(message, selector = "0xC0DECAFE")] + #[ink(message, selector = 0xC0DECAFE)] fn my_message_mut(&mut self); } ); } -#[test] -fn iter_constructors_works() { - let ink_trait = >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2() -> Self; - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self); - } - }) - .unwrap(); - let actual = ink_trait - .iter_items() - .map(|(item, _)| item) - .flat_map(|item| { - item.filter_map_constructor() - .map(|constructor| constructor.sig().ident.to_string()) - }) - .collect::>(); - let expected = vec!["constructor_1".to_string(), "constructor_2".to_string()]; - assert_eq!(actual, expected); -} - #[test] fn iter_messages_works() { let ink_trait = >::try_from(syn::parse_quote! { pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2() -> Self; #[ink(message)] fn message_1(&self); #[ink(message)] @@ -591,26 +467,6 @@ macro_rules! ink_trait { #[test] fn verify_hash_works() { - let ink_trait = ink_trait! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2(a: i32, b: i32) -> Self; - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self, a: i32, b: i32) -> i32; - } - }; - assert_verify_hash2_works_with( - ink_trait, - "__ink_trait::MyTrait::constructor_1:0,constructor_2:2::message_1:1:r,message_2:3:w" - ); -} - -#[test] -fn verify_hash_works_without_constructors() { let ink_trait = ink_trait! { pub trait MyTrait { #[ink(message)] @@ -621,22 +477,6 @@ fn verify_hash_works_without_constructors() { }; assert_verify_hash2_works_with( ink_trait, - "__ink_trait::MyTrait::message_1:1:r,message_2:3:w", - ); -} - -#[test] -fn verify_hash_works_without_messages() { - let ink_trait = ink_trait! { - pub trait MyTrait { - #[ink(constructor)] - fn constructor_1() -> Self; - #[ink(constructor)] - fn constructor_2(a: i32, b: i32) -> Self; - } - }; - assert_verify_hash2_works_with( - ink_trait, - "__ink_trait::MyTrait::constructor_1:0,constructor_2:2", + "__ink_trait::MyTrait::message_1:1:r,message_2:3:w" ); } From 6da4852ed50fb7f7a41ef1fdb2413878f2a615d7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 12:38:42 +0200 Subject: [PATCH 182/493] apply rustfmt --- crates/lang/ir/src/ir/trait_def/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/trait_def/tests.rs b/crates/lang/ir/src/ir/trait_def/tests.rs index 91c188be90..454061425c 100644 --- a/crates/lang/ir/src/ir/trait_def/tests.rs +++ b/crates/lang/ir/src/ir/trait_def/tests.rs @@ -477,6 +477,6 @@ fn verify_hash_works() { }; assert_verify_hash2_works_with( ink_trait, - "__ink_trait::MyTrait::message_1:1:r,message_2:3:w" + "__ink_trait::MyTrait::message_1:1:r,message_2:3:w", ); } From 90bacd6778ab816bac95a8ff5915d0eb12d2f094 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 13:12:34 +0200 Subject: [PATCH 183/493] return syn::LitInt instead of syn::Lit from HexLiteral methods --- crates/lang/ir/src/ir/selector.rs | 2 +- crates/lang/ir/src/literal.rs | 33 ++++++++++++++++--------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index c112ea6c22..b5e940a97e 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -140,7 +140,7 @@ impl Selector { } /// Returns the 4 bytes that make up the selector as hex encoded bytes. - pub fn hex_lits(self) -> [syn::Lit; 4] { + pub fn hex_lits(self) -> [syn::LitInt; 4] { let selector_bytes = self.as_bytes(); [ selector_bytes[0].hex_padded_suffixed(), diff --git a/crates/lang/ir/src/literal.rs b/crates/lang/ir/src/literal.rs index b4735977b9..8ed6dbcc52 100644 --- a/crates/lang/ir/src/literal.rs +++ b/crates/lang/ir/src/literal.rs @@ -25,51 +25,52 @@ pub trait HexLiteral { /// /// Users shall not use this trait method directly hence it is hidden. #[doc(hidden)] - fn hex_impl_(self, fmt: ::core::fmt::Arguments, sealed: private::Sealed) -> syn::Lit; + fn hex_impl_(self, fmt: ::core::fmt::Arguments, sealed: private::Sealed) -> syn::LitInt; /// Converts the given value into a hex represented literal with type suffix. - fn hex_suffixed(self) -> syn::Lit; + fn hex_suffixed(self) -> syn::LitInt; /// Converts the given value into a hex represented literal without type suffix. - fn hex_unsuffixed(self) -> syn::Lit; + fn hex_unsuffixed(self) -> syn::LitInt; /// Converts the given value into a hex represented literal with type suffix. /// /// The resulting hex encoded literal is padded with zeros. - fn hex_padded_suffixed(self) -> syn::Lit; + fn hex_padded_suffixed(self) -> syn::LitInt; /// Converts the given value into a hex represented literal without type suffix. /// /// The resulting hex encoded literal is padded with zeros. - fn hex_padded_unsuffixed(self) -> syn::Lit; + fn hex_padded_unsuffixed(self) -> syn::LitInt; } macro_rules! generate_hex_literal_impls { ( $( ($ty:ty, $name:literal, $fmt_suffixed:literal, $fmt_unsuffixed:literal) ),* $(,)? ) => { $( impl HexLiteral for $ty { - fn hex_impl_(self, fmt: ::core::fmt::Arguments, _sealed: private::Sealed) -> syn::Lit { + fn hex_impl_(self, fmt: ::core::fmt::Arguments, _sealed: private::Sealed) -> syn::LitInt { let formatted = ::std::format!("{}", fmt); - ::syn::Lit::new( - <::proc_macro2::Literal as ::core::str::FromStr>::from_str(&formatted).unwrap_or_else( - |err| ::core::panic!("cannot parse {} into a {} hex represented literal: {}", self, $name, err), - ) - ) + // ::syn::Lit::new( + // <::proc_macro2::Literal as ::core::str::FromStr>::from_str(&formatted).unwrap_or_else( + // |err| ::core::panic!("cannot parse {} into a {} hex represented literal: {}", self, $name, err), + // ) + // ) + ::syn::LitInt::new(&formatted, proc_macro2::Span::call_site()) } - fn hex_suffixed(self) -> syn::Lit { + fn hex_suffixed(self) -> syn::LitInt { self.hex_impl_(::core::format_args!("0x{:X}_{}", self, $name), private::Sealed) } - fn hex_unsuffixed(self) -> syn::Lit { + fn hex_unsuffixed(self) -> syn::LitInt { self.hex_impl_(::core::format_args!("0x{:X}", self), private::Sealed) } - fn hex_padded_suffixed(self) -> syn::Lit { + fn hex_padded_suffixed(self) -> syn::LitInt { self.hex_impl_(::core::format_args!($fmt_suffixed, self, $name), private::Sealed) } - fn hex_padded_unsuffixed(self) -> syn::Lit { + fn hex_padded_unsuffixed(self) -> syn::LitInt { self.hex_impl_(::core::format_args!($fmt_unsuffixed, self), private::Sealed) } } @@ -110,7 +111,7 @@ mod tests { use super::HexLiteral as _; use quote::quote; - fn assert_quote(given: syn::Lit, expected: &str) { + fn assert_quote(given: syn::LitInt, expected: &str) { assert_eq!(quote!(#given).to_string(), expected); } From 0674eda587f62b916d0b8b8e4c3acfde90b255d1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 13:37:16 +0200 Subject: [PATCH 184/493] remove ink! trait constructors from ink! IR definitions --- crates/lang/ir/src/ir/trait_def/iter.rs | 12 ------------ crates/lang/ir/src/ir/trait_def/mod.rs | 13 ------------- crates/lang/ir/src/ir/trait_def/trait_item.rs | 12 ------------ 3 files changed, 37 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def/iter.rs b/crates/lang/ir/src/ir/trait_def/iter.rs index b1734555cb..358da7d3e1 100644 --- a/crates/lang/ir/src/ir/trait_def/iter.rs +++ b/crates/lang/ir/src/ir/trait_def/iter.rs @@ -15,7 +15,6 @@ use crate::{ ir, InkTrait, - InkTraitConstructor, InkTraitItem, InkTraitMessage, Selector, @@ -52,11 +51,6 @@ impl<'a> Iterator for IterInkTraitItemsRaw<'a> { .kind() .clone(); match first_attr { - ir::AttributeArg::Constructor => { - return Some(InkTraitItem::Constructor( - InkTraitConstructor::new(method), - )) - } ir::AttributeArg::Message => { return Some(InkTraitItem::Message(InkTraitMessage::new( method, @@ -75,7 +69,6 @@ impl<'a> Iterator for IterInkTraitItemsRaw<'a> { pub struct IterInkTraitItems<'a> { iter: IterInkTraitItemsRaw<'a>, message_selectors: &'a HashMap, - constructor_selectors: &'a HashMap, } impl<'a> IterInkTraitItems<'a> { @@ -84,7 +77,6 @@ impl<'a> IterInkTraitItems<'a> { Self { iter: IterInkTraitItemsRaw::from_raw(&item_trait.item), message_selectors: &item_trait.message_selectors, - constructor_selectors: &item_trait.constructor_selectors, } } } @@ -95,10 +87,6 @@ impl<'a> Iterator for IterInkTraitItems<'a> { fn next(&mut self) -> Option { match self.iter.next() { None => None, - Some(item @ InkTraitItem::Constructor(_)) => { - let selector = self.constructor_selectors[item.ident()]; - Some((item, selector)) - } Some(item @ InkTraitItem::Message(_)) => { let selector = self.message_selectors[item.ident()]; Some((item, selector)) diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index ad452373ff..3a404c4de8 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -51,7 +51,6 @@ use syn::{ pub struct InkTrait { item: syn::ItemTrait, message_selectors: HashMap, - constructor_selectors: HashMap, } impl TryFrom for InkTrait { @@ -62,11 +61,9 @@ impl TryFrom for InkTrait { Self::analyse_properties(&item_trait)?; Self::analyse_items(&item_trait)?; let mut message_selectors = >::new(); - let mut constructor_selectors = >::new(); Self::extract_selectors( &item_trait, &mut message_selectors, - &mut constructor_selectors, )?; if message_selectors.is_empty() { return Err(format_err!( @@ -77,7 +74,6 @@ impl TryFrom for InkTrait { Ok(Self { item: item_trait, message_selectors, - constructor_selectors, }) } } @@ -428,9 +424,7 @@ impl InkTrait { fn extract_selectors( item_trait: &syn::ItemTrait, message_selectors: &mut HashMap, - constructor_selectors: &mut HashMap, ) -> Result<()> { - let mut seen_constructor_selectors = >::new(); let mut seen_message_selectors = >::new(); let (ink_attrs, _) = ir::sanitize_optional_attributes( item_trait.span(), @@ -458,13 +452,6 @@ impl InkTrait { None => Selector::compose(trait_prefix, ident), }; let (duplicate_selector, duplicate_ident) = match callable { - InkTraitItem::Constructor(_) => { - let duplicate_selector = - seen_constructor_selectors.insert(selector, ident.clone()); - let duplicate_ident = - constructor_selectors.insert(ident.clone(), selector); - (duplicate_selector, duplicate_ident) - } InkTraitItem::Message(_) => { let duplicate_selector = seen_message_selectors.insert(selector, ident.clone()); diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/trait_item.rs index 44c23b6b57..e316db828b 100644 --- a/crates/lang/ir/src/ir/trait_def/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/trait_item.rs @@ -27,7 +27,6 @@ use syn::{ /// An ink! item within an ink! trait definition. #[derive(Debug, Clone)] pub enum InkTraitItem<'a> { - Constructor(InkTraitConstructor<'a>), Message(InkTraitMessage<'a>), } @@ -35,7 +34,6 @@ impl<'a> InkTraitItem<'a> { /// Returns the Rust identifier of the ink! trait item. pub fn ident(&self) -> &syn::Ident { match self { - Self::Constructor(constructor) => constructor.ident(), Self::Message(message) => message.ident(), } } @@ -43,24 +41,14 @@ impl<'a> InkTraitItem<'a> { /// Returns the ink! attributes of the ink! trait item. pub fn ink_attrs(&self) -> InkAttribute { match self { - Self::Constructor(constructor) => constructor.ink_attrs(), Self::Message(message) => message.ink_attrs(), } } - /// Returns `Some` if the ink! trait item is a constructor. - pub fn filter_map_constructor(self) -> Option> { - match self { - Self::Constructor(ink_trait_constructor) => Some(ink_trait_constructor), - _ => None, - } - } - /// Returns `Some` if the ink! trait item is a message. pub fn filter_map_message(self) -> Option> { match self { Self::Message(ink_trait_message) => Some(ink_trait_message), - _ => None, } } } From c29e839a703af4b14660370cfddf0c03c6cec058 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 15:38:09 +0200 Subject: [PATCH 185/493] allow parameterizing ink::trait_definition macro Also change the way how verify_hash is computed. The verify_hash is no longer depending on the structure of the ink! trait definition. It only depends on the identifier as well as the optionally given namespace. This allows more fine grained control over the resulting selector of an ink! trait definition. --- .../codegen/src/generator/trait_def/mod.rs | 2 +- crates/lang/codegen/src/lib.rs | 2 +- crates/lang/ir/src/ir/mod.rs | 3 +- crates/lang/ir/src/ir/trait_def/config.rs | 103 ++++ .../ir/src/ir/trait_def/{ => item}/iter.rs | 4 +- crates/lang/ir/src/ir/trait_def/item/mod.rs | 380 ++++++++++++++ .../src/ir/trait_def/{ => item}/trait_item.rs | 0 crates/lang/ir/src/ir/trait_def/mod.rs | 488 ++---------------- crates/lang/ir/src/ir/trait_def/tests.rs | 74 ++- crates/lang/ir/src/lib.rs | 3 +- crates/lang/macro/src/trait_def.rs | 10 +- 11 files changed, 599 insertions(+), 470 deletions(-) create mode 100644 crates/lang/ir/src/ir/trait_def/config.rs rename crates/lang/ir/src/ir/trait_def/{ => item}/iter.rs (97%) create mode 100644 crates/lang/ir/src/ir/trait_def/item/mod.rs rename crates/lang/ir/src/ir/trait_def/{ => item}/trait_item.rs (100%) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 5ca3c52666..22109371e7 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -31,7 +31,7 @@ use quote::{ /// Generator to create the ink! storage struct and important trait impls. #[derive(From, Copy, Clone)] pub struct TraitDefinition<'a> { - trait_def: &'a ir::InkTrait, + trait_def: &'a ir::InkItemTrait, } impl<'a> TraitDefinition<'a> { diff --git a/crates/lang/codegen/src/lib.rs b/crates/lang/codegen/src/lib.rs index 09a4bece29..b63d07224b 100644 --- a/crates/lang/codegen/src/lib.rs +++ b/crates/lang/codegen/src/lib.rs @@ -31,7 +31,7 @@ impl<'a> CodeGenerator for &'a ir::Contract { type Generator = generator::Contract<'a>; } -impl<'a> CodeGenerator for &'a ir::InkTrait { +impl<'a> CodeGenerator for &'a ir::InkItemTrait { type Generator = generator::TraitDefinition<'a>; } diff --git a/crates/lang/ir/src/ir/mod.rs b/crates/lang/ir/src/ir/mod.rs index 5140748976..aef8fa83f6 100644 --- a/crates/lang/ir/src/ir/mod.rs +++ b/crates/lang/ir/src/ir/mod.rs @@ -82,8 +82,9 @@ pub use self::{ TraitPrefix, }, trait_def::{ - InkTrait, + InkItemTrait, InkTraitConstructor, + InkTraitDefinition, InkTraitItem, InkTraitMessage, IterInkTraitItems, diff --git a/crates/lang/ir/src/ir/trait_def/config.rs b/crates/lang/ir/src/ir/trait_def/config.rs new file mode 100644 index 0000000000..18168a8c6f --- /dev/null +++ b/crates/lang/ir/src/ir/trait_def/config.rs @@ -0,0 +1,103 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{ + ast, + error::ExtError as _, +}; +use core::convert::TryFrom; +use syn::spanned::Spanned; + +/// The ink! configuration. +#[derive(Debug, Default, PartialEq, Eq)] +pub struct TraitDefinitionConfig { + /// Captures the optional custom namespace for the ink! trait definition. + /// + /// # Note + /// + /// The namespace config parameter is used to influence the generated + /// selectors of the ink! trait messages. This is useful to disambiguate + /// ink! trait definitions with equal names. + namespace: Option, +} + +impl TraitDefinitionConfig { + /// Sets the namespace of the ink! trait definition configuration. + /// + /// # Note + /// + /// This is a test-only API. + #[cfg(test)] + pub fn with_namespace(mut self, namespace: &str) -> Self { + self.namespace = + Some(syn::LitStr::new(namespace, proc_macro2::Span::call_site())); + self + } +} + +/// Return an error to notify about duplicate ink! trait definition configuration arguments. +fn duplicate_config_err(fst: F, snd: S, name: &str) -> syn::Error +where + F: Spanned, + S: Spanned, +{ + format_err!( + snd.span(), + "encountered duplicate ink! trait definition `{}` configuration argument", + name, + ) + .into_combine(format_err!( + fst.span(), + "first `{}` configuration argument here", + name + )) +} + +impl TryFrom for TraitDefinitionConfig { + type Error = syn::Error; + + fn try_from(args: ast::AttributeArgs) -> Result { + let mut namespace: Option<(syn::LitStr, ast::MetaNameValue)> = None; + for arg in args.into_iter() { + if arg.name.is_ident("namespace") { + if let Some((_, meta_name_value)) = namespace { + return Err(duplicate_config_err(meta_name_value, arg, "namespace")) + } + if let ast::PathOrLit::Lit(syn::Lit::Str(lit_str)) = &arg.value { + namespace = Some((lit_str.clone(), arg)) + } else { + return Err(format_err_spanned!( + arg, + "expected a string literal for `namespace` ink! trait definition configuration argument", + )) + } + } else { + return Err(format_err_spanned!( + arg, + "encountered unknown or unsupported ink! trait definition configuration argument", + )) + } + } + Ok(TraitDefinitionConfig { + namespace: namespace.map(|(value, _)| value), + }) + } +} + +impl TraitDefinitionConfig { + /// Returns the namespace config argument if any as string. + pub fn namespace(&self) -> Option<&syn::LitStr> { + self.namespace.as_ref() + } +} diff --git a/crates/lang/ir/src/ir/trait_def/iter.rs b/crates/lang/ir/src/ir/trait_def/item/iter.rs similarity index 97% rename from crates/lang/ir/src/ir/trait_def/iter.rs rename to crates/lang/ir/src/ir/trait_def/item/iter.rs index 358da7d3e1..c967a19082 100644 --- a/crates/lang/ir/src/ir/trait_def/iter.rs +++ b/crates/lang/ir/src/ir/trait_def/item/iter.rs @@ -14,7 +14,7 @@ use crate::{ ir, - InkTrait, + InkItemTrait, InkTraitItem, InkTraitMessage, Selector, @@ -73,7 +73,7 @@ pub struct IterInkTraitItems<'a> { impl<'a> IterInkTraitItems<'a> { /// Creates a new iterator yielding ink! trait items. - pub(super) fn new(item_trait: &'a InkTrait) -> Self { + pub(super) fn new(item_trait: &'a InkItemTrait) -> Self { Self { iter: IterInkTraitItemsRaw::from_raw(&item_trait.item), message_selectors: &item_trait.message_selectors, diff --git a/crates/lang/ir/src/ir/trait_def/item/mod.rs b/crates/lang/ir/src/ir/trait_def/item/mod.rs new file mode 100644 index 0000000000..f183ebed15 --- /dev/null +++ b/crates/lang/ir/src/ir/trait_def/item/mod.rs @@ -0,0 +1,380 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod iter; +mod trait_item; + +use self::iter::IterInkTraitItemsRaw; +pub use self::{ + iter::IterInkTraitItems, + trait_item::{ + InkTraitConstructor, + InkTraitItem, + InkTraitMessage, + }, +}; +use super::InkAttribute; +use crate::{ + ir, + ir::idents_lint, + Selector, +}; +use core::convert::TryFrom; +use ir::TraitPrefix; +use proc_macro2::{ + Ident, + Span, +}; +use std::collections::HashMap; +use syn::{ + spanned::Spanned as _, + Result, +}; + +/// A checked ink! trait definition without its configuration. +#[derive(Debug, PartialEq, Eq)] +pub struct InkItemTrait { + item: syn::ItemTrait, + message_selectors: HashMap, +} + +impl TryFrom for InkItemTrait { + type Error = syn::Error; + + fn try_from(item_trait: syn::ItemTrait) -> core::result::Result { + idents_lint::ensure_no_ink_identifiers(&item_trait)?; + Self::analyse_properties(&item_trait)?; + Self::analyse_items(&item_trait)?; + let mut message_selectors = >::new(); + Self::extract_selectors(&item_trait, &mut message_selectors)?; + if message_selectors.is_empty() { + return Err(format_err!( + item_trait.span(), + "encountered invalid empty ink! trait definition" + )) + } + Ok(Self { + item: item_trait, + message_selectors, + }) + } +} + +impl InkItemTrait { + /// Returns span of the ink! trait definition. + pub fn span(&self) -> Span { + self.item.span() + } + + /// Returns the attributes of the ink! trait definition. + pub fn attrs(&self) -> &[syn::Attribute] { + &self.item.attrs + } + + /// Returns the identifier of the ink! trait definition. + pub fn ident(&self) -> &Ident { + &self.item.ident + } + + /// Returns an iterator yielding the ink! specific items of the ink! trait definition. + pub fn iter_items(&self) -> IterInkTraitItems { + IterInkTraitItems::new(self) + } + + /// Analyses the properties of the ink! trait definition. + /// + /// # Errors + /// + /// - If the trait has been defined as `unsafe`. + /// - If the trait is an automatically implemented trait (`auto trait`). + /// - If the trait is generic over some set of types. + /// - If the trait's visibility is not public (`pub`). + fn analyse_properties(item_trait: &syn::ItemTrait) -> Result<()> { + if let Some(unsafety) = &item_trait.unsafety { + return Err(format_err_spanned!( + unsafety, + "ink! trait definitions cannot be unsafe" + )) + } + if let Some(auto) = &item_trait.auto_token { + return Err(format_err_spanned!( + auto, + "ink! trait definitions cannot be automatically implemented traits" + )) + } + if !item_trait.generics.params.is_empty() { + return Err(format_err_spanned!( + item_trait.generics.params, + "ink! trait definitions must not be generic" + )) + } + if !matches!(item_trait.vis, syn::Visibility::Public(_)) { + return Err(format_err_spanned!( + item_trait.vis, + "ink! trait definitions must have public visibility" + )) + } + if !item_trait.supertraits.is_empty() { + return Err(format_err_spanned!( + item_trait.supertraits, + "ink! trait definitions with supertraits are not supported, yet" + )) + } + Ok(()) + } + + /// Returns `Ok` if all trait items respects the requirements for an ink! trait definition. + /// + /// # Errors + /// + /// - If the trait contains an unsupported trait item such as + /// - associated constants (`const`) + /// - associated types (`type`) + /// - macros definitions or usages + /// - unknown token sequences (verbatim) + /// - methods with default implementations + /// - If the trait contains methods which do not respect the ink! trait definition requirements: + /// - All trait methods need to be declared as either `#[ink(message)]` or `#[ink(constructor)]` + /// and need to respect their respective rules. + /// + /// # Note + /// + /// Associated types and constants might be allowed in the future. + fn analyse_items(item_trait: &syn::ItemTrait) -> Result<()> { + for trait_item in &item_trait.items { + match trait_item { + syn::TraitItem::Const(const_trait_item) => { + return Err(format_err_spanned!( + const_trait_item, + "associated constants in ink! trait definitions are not supported, yet" + )) + } + syn::TraitItem::Macro(macro_trait_item) => { + return Err(format_err_spanned!( + macro_trait_item, + "macros in ink! trait definitions are not supported" + )) + } + syn::TraitItem::Type(type_trait_item) => { + return Err(format_err_spanned!( + type_trait_item, + "associated types in ink! trait definitions are not supported, yet" + )) + } + syn::TraitItem::Verbatim(verbatim) => { + return Err(format_err_spanned!( + verbatim, + "encountered unsupported item in ink! trait definition" + )) + } + syn::TraitItem::Method(method_trait_item) => { + Self::analyse_trait_method(method_trait_item)?; + } + unknown => { + return Err(format_err_spanned!( + unknown, + "encountered unknown or unsupported item in ink! trait definition" + )) + } + } + } + Ok(()) + } + + /// Analyses an ink! method that can be either an ink! message or constructor. + /// + /// # Errors + /// + /// - If the method declared as `unsafe`, `const` or `async`. + /// - If the method has some explicit API. + /// - If the method is variadic or has generic parameters. + /// - If the method does not respect the properties of either an + /// ink! message or ink! constructor. + fn analyse_trait_method(method: &syn::TraitItemMethod) -> Result<()> { + if let Some(default_impl) = &method.default { + return Err(format_err_spanned!( + default_impl, + "ink! trait methods with default implementations are not supported" + )) + } + if let Some(constness) = &method.sig.constness { + return Err(format_err_spanned!( + constness, + "const ink! trait methods are not supported" + )) + } + if let Some(asyncness) = &method.sig.asyncness { + return Err(format_err_spanned!( + asyncness, + "async ink! trait methods are not supported" + )) + } + if let Some(unsafety) = &method.sig.unsafety { + return Err(format_err_spanned!( + unsafety, + "unsafe ink! trait methods are not supported" + )) + } + if let Some(abi) = &method.sig.abi { + return Err(format_err_spanned!( + abi, + "ink! trait methods with non default ABI are not supported" + )) + } + if let Some(variadic) = &method.sig.variadic { + return Err(format_err_spanned!( + variadic, + "variadic ink! trait methods are not supported" + )) + } + if !method.sig.generics.params.is_empty() { + return Err(format_err_spanned!( + method.sig.generics.params, + "generic ink! trait methods are not supported" + )) + } + match ir::first_ink_attribute(&method.attrs) { + Ok(Some(ink_attr)) => { + match ink_attr.first().kind() { + ir::AttributeArg::Message => { + Self::analyse_trait_message(method)?; + } + ir::AttributeArg::Constructor => { + Self::analyse_trait_constructor(method)?; + } + _unsupported => { + return Err(format_err_spanned!( + method, + "encountered unsupported ink! attribute for ink! trait method", + )) + } + } + } + Ok(None) => { + return Err(format_err_spanned!( + method, + "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method" + )) + } + Err(err) => return Err(err), + } + Ok(()) + } + + /// Constructors are generally not allowed in ink! trait definitions. + fn analyse_trait_constructor(constructor: &syn::TraitItemMethod) -> Result<()> { + return Err(format_err!( + constructor.span(), + "ink! trait definitions must not have constructors", + )) + } + + /// Analyses the properties of an ink! message. + /// + /// # Errors + /// + /// - If the message has no `&self` or `&mut self` receiver. + fn analyse_trait_message(message: &syn::TraitItemMethod) -> Result<()> { + InkTraitMessage::extract_attributes(message.span(), &message.attrs)?; + match message.sig.receiver() { + None | Some(syn::FnArg::Typed(_)) => { + return Err(format_err_spanned!( + message.sig, + "missing or malformed `&self` or `&mut self` receiver for ink! message", + )) + } + Some(syn::FnArg::Receiver(receiver)) => { + if receiver.reference.is_none() { + return Err(format_err_spanned!( + receiver, + "self receiver of ink! message must be `&self` or `&mut self`" + )) + } + } + } + Ok(()) + } + + /// Extract selectors for ink! trait constructors and messages. + /// + /// The composed or manually specified selectors are stored into the provided + /// hashtables for later look-up when querying ink! constructors or messages. + /// This way we are more flexible with regard to the underlying structures of the IR. + /// + /// In this step we assume that all sanitation checks have taken place prior so + /// instead of returning errors we simply panic upon failures. + /// + /// # Errors + /// + /// Returns an error if there are overlapping selectors for ink! constructors + /// or ink! messages. Note that overlaps between ink! constructor and message + /// selectors are allowed. + fn extract_selectors( + item_trait: &syn::ItemTrait, + message_selectors: &mut HashMap, + ) -> Result<()> { + let mut seen_message_selectors = >::new(); + let (ink_attrs, _) = ir::sanitize_optional_attributes( + item_trait.span(), + item_trait.attrs.iter().cloned(), + |arg| { + match arg.kind() { + ir::AttributeArg::Namespace(_) => Ok(()), + _ => Err(None), + } + }, + ) + .expect("encountered unexpected invalid attributes on ink! trait definition"); + let namespace = ink_attrs + .as_ref() + .map(InkAttribute::namespace) + .flatten() + .unwrap_or_default(); + let ident = &item_trait.ident; + let trait_prefix = TraitPrefix::new(ident, &namespace); + for callable in IterInkTraitItemsRaw::from_raw(item_trait) { + let ident = callable.ident(); + let ink_attrs = callable.ink_attrs(); + let selector = match ink_attrs.selector() { + Some(manual_selector) => manual_selector, + None => Selector::compose(trait_prefix, ident), + }; + let (duplicate_selector, duplicate_ident) = match callable { + InkTraitItem::Message(_) => { + let duplicate_selector = + seen_message_selectors.insert(selector, ident.clone()); + let duplicate_ident = + message_selectors.insert(ident.clone(), selector); + (duplicate_selector, duplicate_ident) + } + }; + if let Some(duplicate_selector) = duplicate_selector { + use crate::error::ExtError as _; + return Err(format_err_spanned!( + ident, + "encountered duplicate selector ({:x?}) in the same ink! trait definition", + selector.as_bytes(), + ).into_combine(format_err_spanned!( + duplicate_selector, + "first ink! trait constructor or message with same selector found here", + ))) + } + assert!( + duplicate_ident.is_none(), + "encountered unexpected overlapping ink! trait constructor or message identifier", + ); + } + Ok(()) + } +} diff --git a/crates/lang/ir/src/ir/trait_def/trait_item.rs b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs similarity index 100% rename from crates/lang/ir/src/ir/trait_def/trait_item.rs rename to crates/lang/ir/src/ir/trait_def/item/trait_item.rs diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index 3a404c4de8..a5817cd47f 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -12,470 +12,92 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod iter; -mod trait_item; +mod config; +mod item; #[cfg(test)] mod tests; -use self::iter::IterInkTraitItemsRaw; pub use self::{ - iter::IterInkTraitItems, - trait_item::{ + config::TraitDefinitionConfig, + item::{ + InkItemTrait, InkTraitConstructor, InkTraitItem, InkTraitMessage, + IterInkTraitItems, }, }; use super::attrs::InkAttribute; -use crate::{ - ir, - ir::idents_lint, - Selector, -}; use core::convert::TryFrom; -use ir::TraitPrefix; -use proc_macro2::{ - Ident, - Span, - TokenStream as TokenStream2, -}; -use std::collections::HashMap; -use syn::{ - spanned::Spanned as _, - Result, -}; +use proc_macro2::TokenStream as TokenStream2; +use syn::Result; -/// A checked ink! trait definition. +/// A checked ink! trait definition without its configuration. #[derive(Debug, PartialEq, Eq)] -pub struct InkTrait { - item: syn::ItemTrait, - message_selectors: HashMap, -} - -impl TryFrom for InkTrait { - type Error = syn::Error; - - fn try_from(item_trait: syn::ItemTrait) -> core::result::Result { - idents_lint::ensure_no_ink_identifiers(&item_trait)?; - Self::analyse_properties(&item_trait)?; - Self::analyse_items(&item_trait)?; - let mut message_selectors = >::new(); - Self::extract_selectors( - &item_trait, - &mut message_selectors, - )?; - if message_selectors.is_empty() { - return Err(format_err!( - item_trait.span(), - "encountered invalid empty ink! trait definition" - )) - } - Ok(Self { - item: item_trait, - message_selectors, - }) - } +pub struct InkTraitDefinition { + config: TraitDefinitionConfig, + item: InkItemTrait, } -impl InkTrait { - /// Returns the hash to verify that the trait definition has been checked. - pub fn compute_verify_hash( - trait_name: &Ident, - constructors: C, - messages: M, - ) -> [u8; 32] - where - // Name and number of inputs. - C: Iterator, - // Name, number of inputs and true if message may mutate storage. - M: Iterator, - { - let mut constructors = constructors - .map(|(name, len_inputs)| { - [name.to_string(), len_inputs.to_string()].join(":") - }) - .collect::>(); - let mut messages = messages - .map(|(name, len_inputs, mutability)| { - let mutability = match mutability { - true => "w", - false => "r", - }; - [ - name.to_string(), - len_inputs.to_string(), - mutability.to_string(), - ] - .join(":") - }) - .collect::>(); - constructors.sort_unstable(); - messages.sort_unstable(); - let joined_constructors = constructors.join(","); - let joined_messages = messages.join(","); - let mut buffer = vec!["__ink_trait".to_string(), trait_name.to_string()]; - if !joined_constructors.is_empty() { - buffer.push(joined_constructors); - } - if !joined_messages.is_empty() { - buffer.push(joined_messages); - } - let buffer = buffer.join("::").into_bytes(); - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&buffer).split(); - head_32.into() - } - - /// Returns the hash to verify that the trait definition has been checked. - pub fn verify_hash(&self) -> [u8; 32] { - let trait_name = self.ident(); - Self::compute_verify_hash( - trait_name, - self.iter_items() - .map(|(item, _)| item) - .flat_map(InkTraitItem::filter_map_constructor) - .map(|constructor| { - let name = constructor.sig().ident.clone(); - let len_inputs = constructor.sig().inputs.len(); - (name, len_inputs) - }), - self.iter_items() - .map(|(item, _)| item) - .flat_map(InkTraitItem::filter_map_message) - .map(|message| { - let name = message.sig().ident.clone(); - let len_inputs = message.sig().inputs.len(); - let mutability = message.mutates(); - (name, len_inputs, mutability) - }), - ) - } - - /// Returns the unique trait identifier. - pub fn unique_id(&self) -> u32 { - let [h1, h2, h3, h4, ..] = self.verify_hash(); - u32::from_be_bytes([h1, h2, h3, h4]) - } -} - -impl InkTrait { - /// Returns `Ok` if the trait matches all requirements for an ink! trait definition. - pub fn new(attr: TokenStream2, input: TokenStream2) -> Result { - if !attr.is_empty() { - return Err(format_err_spanned!( - attr, - "unexpected attribute input for ink! trait definition" - )) - } - let item_trait = syn::parse2::(input)?; - InkTrait::try_from(item_trait) - } - - /// Returns span of the ink! trait definition. - pub fn span(&self) -> Span { - self.item.span() - } - - /// Returns the attributes of the ink! trait definition. - pub fn attrs(&self) -> &[syn::Attribute] { - &self.item.attrs - } - - /// Returns the identifier of the ink! trait definition. - pub fn ident(&self) -> &Ident { - &self.item.ident +impl InkTraitDefinition { + /// Returns `Ok` if the input matches all requirements for an ink! trait definition. + pub fn new(config: TokenStream2, input: TokenStream2) -> Result { + let parsed_config = syn::parse2::(config)?; + let parsed_item = syn::parse2::(input)?; + let config = TraitDefinitionConfig::try_from(parsed_config)?; + let item = InkItemTrait::try_from(parsed_item)?; + Ok(Self { config, item }) } - /// Returns an iterator yielding the ink! specific items of the ink! trait definition. - pub fn iter_items(&self) -> IterInkTraitItems { - IterInkTraitItems::new(self) - } - - /// Analyses the properties of the ink! trait definition. - /// - /// # Errors - /// - /// - If the trait has been defined as `unsafe`. - /// - If the trait is an automatically implemented trait (`auto trait`). - /// - If the trait is generic over some set of types. - /// - If the trait's visibility is not public (`pub`). - fn analyse_properties(item_trait: &syn::ItemTrait) -> Result<()> { - if let Some(unsafety) = &item_trait.unsafety { - return Err(format_err_spanned!( - unsafety, - "ink! trait definitions cannot be unsafe" - )) - } - if let Some(auto) = &item_trait.auto_token { - return Err(format_err_spanned!( - auto, - "ink! trait definitions cannot be automatically implemented traits" - )) - } - if !item_trait.generics.params.is_empty() { - return Err(format_err_spanned!( - item_trait.generics.params, - "ink! trait definitions must not be generic" - )) - } - if !matches!(item_trait.vis, syn::Visibility::Public(_)) { - return Err(format_err_spanned!( - item_trait.vis, - "ink! trait definitions must have public visibility" - )) - } - if !item_trait.supertraits.is_empty() { - return Err(format_err_spanned!( - item_trait.supertraits, - "ink! trait definitions with supertraits are not supported, yet" - )) - } - Ok(()) - } - - /// Returns `Ok` if all trait items respects the requirements for an ink! trait definition. - /// - /// # Errors - /// - /// - If the trait contains an unsupported trait item such as - /// - associated constants (`const`) - /// - associated types (`type`) - /// - macros definitions or usages - /// - unknown token sequences (verbatim) - /// - methods with default implementations - /// - If the trait contains methods which do not respect the ink! trait definition requirements: - /// - All trait methods need to be declared as either `#[ink(message)]` or `#[ink(constructor)]` - /// and need to respect their respective rules. + /// Constructs an ink! trait definition from its raw parts. /// /// # Note /// - /// Associated types and constants might be allowed in the future. - fn analyse_items(item_trait: &syn::ItemTrait) -> Result<()> { - for trait_item in &item_trait.items { - match trait_item { - syn::TraitItem::Const(const_trait_item) => { - return Err(format_err_spanned!( - const_trait_item, - "associated constants in ink! trait definitions are not supported, yet" - )) - } - syn::TraitItem::Macro(macro_trait_item) => { - return Err(format_err_spanned!( - macro_trait_item, - "macros in ink! trait definitions are not supported" - )) - } - syn::TraitItem::Type(type_trait_item) => { - return Err(format_err_spanned!( - type_trait_item, - "associated types in ink! trait definitions are not supported, yet" - )) - } - syn::TraitItem::Verbatim(verbatim) => { - return Err(format_err_spanned!( - verbatim, - "encountered unsupported item in ink! trait definition" - )) - } - syn::TraitItem::Method(method_trait_item) => { - Self::analyse_trait_method(method_trait_item)?; - } - unknown => { - return Err(format_err_spanned!( - unknown, - "encountered unknown or unsupported item in ink! trait definition" - )) - } - } - } - Ok(()) + /// This is a test-only API. + #[cfg(test)] + pub fn from_raw_parts(config: TraitDefinitionConfig, item: InkItemTrait) -> Self { + Self { config, item } } +} - /// Analyses an ink! method that can be either an ink! message or constructor. - /// - /// # Errors - /// - /// - If the method declared as `unsafe`, `const` or `async`. - /// - If the method has some explicit API. - /// - If the method is variadic or has generic parameters. - /// - If the method does not respect the properties of either an - /// ink! message or ink! constructor. - fn analyse_trait_method(method: &syn::TraitItemMethod) -> Result<()> { - if let Some(default_impl) = &method.default { - return Err(format_err_spanned!( - default_impl, - "ink! trait methods with default implementations are not supported" - )) - } - if let Some(constness) = &method.sig.constness { - return Err(format_err_spanned!( - constness, - "const ink! trait methods are not supported" - )) - } - if let Some(asyncness) = &method.sig.asyncness { - return Err(format_err_spanned!( - asyncness, - "async ink! trait methods are not supported" - )) - } - if let Some(unsafety) = &method.sig.unsafety { - return Err(format_err_spanned!( - unsafety, - "unsafe ink! trait methods are not supported" - )) - } - if let Some(abi) = &method.sig.abi { - return Err(format_err_spanned!( - abi, - "ink! trait methods with non default ABI are not supported" - )) - } - if let Some(variadic) = &method.sig.variadic { - return Err(format_err_spanned!( - variadic, - "variadic ink! trait methods are not supported" - )) - } - if !method.sig.generics.params.is_empty() { - return Err(format_err_spanned!( - method.sig.generics.params, - "generic ink! trait methods are not supported" - )) - } - match ir::first_ink_attribute(&method.attrs) { - Ok(Some(ink_attr)) => { - match ink_attr.first().kind() { - ir::AttributeArg::Message => { - Self::analyse_trait_message(method)?; - } - ir::AttributeArg::Constructor => { - Self::analyse_trait_constructor(method)?; - } - _unsupported => { - return Err(format_err_spanned!( - method, - "encountered unsupported ink! attribute for ink! trait method", - )) - } - } - } - Ok(None) => { - return Err(format_err_spanned!( - method, - "missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method" - )) - } - Err(err) => return Err(err), - } - Ok(()) +impl InkTraitDefinition { + /// Returns the ink! trait definition config. + pub fn config(&self) -> &TraitDefinitionConfig { + &self.config } - /// Constructors are generally not allowed in ink! trait definitions. - fn analyse_trait_constructor(constructor: &syn::TraitItemMethod) -> Result<()> { - return Err(format_err!( - constructor.span(), - "ink! trait definitions must not have constructors", - )) + /// Returns the ink! trait item representing the ink! trait definition. + pub fn item(&self) -> &InkItemTrait { + &self.item } - /// Analyses the properties of an ink! message. - /// - /// # Errors - /// - /// - If the message has no `&self` or `&mut self` receiver. - fn analyse_trait_message(message: &syn::TraitItemMethod) -> Result<()> { - InkTraitMessage::extract_attributes(message.span(), &message.attrs)?; - match message.sig.receiver() { - None | Some(syn::FnArg::Typed(_)) => { - return Err(format_err_spanned!( - message.sig, - "missing or malformed `&self` or `&mut self` receiver for ink! message", - )) - } - Some(syn::FnArg::Receiver(receiver)) => { - if receiver.reference.is_none() { - return Err(format_err_spanned!( - receiver, - "self receiver of ink! message must be `&self` or `&mut self`" - )) - } + /// Returns the hash to verify that the trait definition has been checked. + pub fn verify_hash(&self) -> [u8; 32] { + let trait_ident = self.item().ident().to_string(); + let buffer = match self.config.namespace() { + Some(lit_str) => { + format!("{}::{}", lit_str.value(), trait_ident) } - } - Ok(()) + None => trait_ident, + }; + let buffer = buffer.into_bytes(); + use blake2::digest::generic_array::sequence::Split as _; + let (head_32, _rest) = + ::digest(&buffer).split(); + head_32.into() } - /// Extract selectors for ink! trait constructors and messages. - /// - /// The composed or manually specified selectors are stored into the provided - /// hashtables for later look-up when querying ink! constructors or messages. - /// This way we are more flexible with regard to the underlying structures of the IR. + /// Returns an identifier (uniquely) representing the ink! trait definition. /// - /// In this step we assume that all sanitation checks have taken place prior so - /// instead of returning errors we simply panic upon failures. - /// - /// # Errors + /// # Note /// - /// Returns an error if there are overlapping selectors for ink! constructors - /// or ink! messages. Note that overlaps between ink! constructor and message - /// selectors are allowed. - fn extract_selectors( - item_trait: &syn::ItemTrait, - message_selectors: &mut HashMap, - ) -> Result<()> { - let mut seen_message_selectors = >::new(); - let (ink_attrs, _) = ir::sanitize_optional_attributes( - item_trait.span(), - item_trait.attrs.iter().cloned(), - |arg| { - match arg.kind() { - ir::AttributeArg::Namespace(_) => Ok(()), - _ => Err(None), - } - }, - ) - .expect("encountered unexpected invalid attributes on ink! trait definition"); - let namespace = ink_attrs - .as_ref() - .map(InkAttribute::namespace) - .flatten() - .unwrap_or_default(); - let ident = &item_trait.ident; - let trait_prefix = TraitPrefix::new(ident, &namespace); - for callable in IterInkTraitItemsRaw::from_raw(item_trait) { - let ident = callable.ident(); - let ink_attrs = callable.ink_attrs(); - let selector = match ink_attrs.selector() { - Some(manual_selector) => manual_selector, - None => Selector::compose(trait_prefix, ident), - }; - let (duplicate_selector, duplicate_ident) = match callable { - InkTraitItem::Message(_) => { - let duplicate_selector = - seen_message_selectors.insert(selector, ident.clone()); - let duplicate_ident = - message_selectors.insert(ident.clone(), selector); - (duplicate_selector, duplicate_ident) - } - }; - if let Some(duplicate_selector) = duplicate_selector { - use crate::error::ExtError as _; - return Err(format_err_spanned!( - ident, - "encountered duplicate selector ({:x?}) in the same ink! trait definition", - selector.as_bytes(), - ).into_combine(format_err_spanned!( - duplicate_selector, - "first ink! trait constructor or message with same selector found here", - ))) - } - assert!( - duplicate_ident.is_none(), - "encountered unexpected overlapping ink! trait constructor or message identifier", - ); - } - Ok(()) + /// Identifiers generated by this routine might overlap with each other + /// if ink! trait definitions have equal namespaces and identifiers. + /// Users can use the `namespace` configuration parameter in order to + /// disambiguate ink! trait definitions. + pub fn id(&self) -> u32 { + let [h1, h2, h3, h4, ..] = self.verify_hash(); + u32::from_be_bytes([h1, h2, h3, h4]) } } diff --git a/crates/lang/ir/src/ir/trait_def/tests.rs b/crates/lang/ir/src/ir/trait_def/tests.rs index 454061425c..882352e064 100644 --- a/crates/lang/ir/src/ir/trait_def/tests.rs +++ b/crates/lang/ir/src/ir/trait_def/tests.rs @@ -18,7 +18,7 @@ use super::*; macro_rules! assert_ink_trait_eq_err { ( error: $err_str:literal, $($trait_def:tt)* ) => { assert_eq!( - >::try_from(syn::parse_quote! { + >::try_from(syn::parse_quote! { $( $trait_def )* }) .map_err(|err| err.to_string()), @@ -325,7 +325,7 @@ fn trait_def_containing_message_with_invalid_ink_attributes_is_denied() { #[test] fn trait_def_is_ok() { assert!( - >::try_from(syn::parse_quote! { + >::try_from(syn::parse_quote! { pub trait MyTrait { #[ink(message)] fn my_message(&self); @@ -340,7 +340,7 @@ fn trait_def_is_ok() { #[test] fn trait_def_with_namespace_is_ok() { assert!( - >::try_from(syn::parse_quote! { + >::try_from(syn::parse_quote! { #[ink(namespace = "my_namespace")] pub trait MyTrait { #[ink(message)] @@ -356,7 +356,7 @@ fn trait_def_with_namespace_is_ok() { #[test] fn trait_def_with_selectors_ok() { assert!( - >::try_from(syn::parse_quote! { + >::try_from(syn::parse_quote! { pub trait MyTrait { #[ink(message, selector = 0xDEADBEEF)] fn my_message(&self); @@ -371,7 +371,7 @@ fn trait_def_with_selectors_ok() { #[test] fn trait_def_with_payable_ok() { assert!( - >::try_from(syn::parse_quote! { + >::try_from(syn::parse_quote! { pub trait MyTrait { #[ink(message, payable)] fn my_message(&self); @@ -386,7 +386,7 @@ fn trait_def_with_payable_ok() { #[test] fn trait_def_with_everything_combined_ok() { assert!( - >::try_from(syn::parse_quote! { + >::try_from(syn::parse_quote! { #[ink(namespace = "my_namespace")] pub trait MyTrait { #[ink(message)] @@ -423,15 +423,16 @@ fn trait_def_with_overlapping_selectors() { #[test] fn iter_messages_works() { - let ink_trait = >::try_from(syn::parse_quote! { - pub trait MyTrait { - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self); - } - }) - .unwrap(); + let ink_trait = + >::try_from(syn::parse_quote! { + pub trait MyTrait { + #[ink(message)] + fn message_1(&self); + #[ink(message)] + fn message_2(&mut self); + } + }) + .unwrap(); let actual = ink_trait .iter_items() .map(|(item, _)| item) @@ -444,9 +445,14 @@ fn iter_messages_works() { assert_eq!(actual, expected); } -fn assert_verify_hash2_works_with(ink_trait: InkTrait, expected: &str) { +fn assert_verify_hash_works_with( + config: TraitDefinitionConfig, + ink_trait: InkItemTrait, + expected: &str, +) { let expected = expected.to_string().into_bytes(); - let actual = ink_trait.verify_hash(); + let trait_definition = InkTraitDefinition::from_raw_parts(config, ink_trait); + let actual = trait_definition.verify_hash(); let expected: [u8; 32] = { use blake2::digest::generic_array::sequence::Split as _; let (head_32, _rest) = @@ -458,25 +464,41 @@ fn assert_verify_hash2_works_with(ink_trait: InkTrait, expected: &str) { macro_rules! ink_trait { ( $($tt:tt)* ) => {{ - >::try_from(syn::parse_quote! { + >::try_from(syn::parse_quote! { $( $tt )* }) .unwrap() }}; } -#[test] -fn verify_hash_works() { - let ink_trait = ink_trait! { +fn dummy_trait_definition() -> InkItemTrait { + ink_trait! { pub trait MyTrait { #[ink(message)] fn message_1(&self); #[ink(message)] fn message_2(&mut self, a: i32, b: i32) -> i32; } - }; - assert_verify_hash2_works_with( - ink_trait, - "__ink_trait::MyTrait::message_1:1:r,message_2:3:w", - ); + } +} + +#[test] +fn verify_hash_works() { + let ink_trait = dummy_trait_definition(); + let config = TraitDefinitionConfig::default(); + assert_verify_hash_works_with(config, ink_trait, "MyTrait"); +} + +#[test] +fn verify_hash_works_with_empty_namespace() { + let ink_trait = dummy_trait_definition(); + let config = TraitDefinitionConfig::default().with_namespace(""); + assert_verify_hash_works_with(config, ink_trait, "::MyTrait"); +} + +#[test] +fn verify_hash_works_with_namespace() { + let ink_trait = dummy_trait_definition(); + let config = TraitDefinitionConfig::default().with_namespace("my_custom_namespace"); + assert_verify_hash_works_with(config, ink_trait, "my_custom_namespace::MyTrait"); } diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index e8da7d1b1a..a0777c6830 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -48,9 +48,10 @@ pub use self::{ ExtensionId, ImplItem, InkItem, + InkItemTrait, InkTest, - InkTrait, InkTraitConstructor, + InkTraitDefinition, InkTraitItem, InkTraitMessage, InputsIter, diff --git a/crates/lang/macro/src/trait_def.rs b/crates/lang/macro/src/trait_def.rs index d7f008c1fb..48053b76e4 100644 --- a/crates/lang/macro/src/trait_def.rs +++ b/crates/lang/macro/src/trait_def.rs @@ -16,14 +16,14 @@ use ink_lang_codegen::generate_code; use proc_macro2::TokenStream as TokenStream2; use syn::Result; -pub fn analyze(attr: TokenStream2, input: TokenStream2) -> TokenStream2 { - match analyze_or_err(attr, input) { +pub fn analyze(config: TokenStream2, input: TokenStream2) -> TokenStream2 { + match analyze_or_err(config, input) { Ok(tokens) => tokens, Err(err) => err.to_compile_error(), } } -pub fn analyze_or_err(attr: TokenStream2, input: TokenStream2) -> Result { - let trait_definition = ink_lang_ir::InkTrait::new(attr, input)?; - Ok(generate_code(&trait_definition)) +pub fn analyze_or_err(config: TokenStream2, input: TokenStream2) -> Result { + let trait_definition = ink_lang_ir::InkTraitDefinition::new(config, input)?; + Ok(generate_code(trait_definition.item())) } From 942679f35ce8eb604b65cdef9c28bec91126cbf8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 15:47:15 +0200 Subject: [PATCH 186/493] adjust ink! trait definition codegen for changes in the IR --- .../src/generator/trait_def/call_builder.rs | 20 ++++++++-------- .../src/generator/trait_def/call_forwarder.rs | 23 ++++++++++--------- .../src/generator/trait_def/definition.rs | 12 +++++----- .../codegen/src/generator/trait_def/mod.rs | 10 ++++---- .../src/generator/trait_def/trait_registry.rs | 19 +++++++-------- crates/lang/codegen/src/lib.rs | 2 +- crates/lang/ir/src/literal.rs | 6 ++++- crates/lang/macro/src/trait_def.rs | 2 +- 8 files changed, 47 insertions(+), 47 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 069a118fbd..12f85d29f5 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -313,8 +313,8 @@ impl CallBuilder<'_> { /// parameters such as gas limit and transferred balance. fn generate_ink_trait_impl(&self) -> TokenStream2 { let span = self.trait_def.span(); - let trait_ident = self.trait_def.trait_def.ident(); - let trait_uid = self.trait_def.trait_def.unique_id().hex_padded_suffixed(); + let trait_ident = self.trait_def.trait_def.item().ident(); + let trait_uid = self.trait_def.trait_def.id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let builder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); @@ -348,15 +348,13 @@ impl CallBuilder<'_> { /// Generate the code for all ink! trait messages implemented by the trait call builder. fn generate_ink_trait_impl_messages(&self) -> TokenStream2 { - let messages = - self.trait_def - .trait_def - .iter_items() - .filter_map(|(item, selector)| { - item.filter_map_message().map(|message| { - self.generate_ink_trait_impl_for_message(&message, selector) - }) - }); + let messages = self.trait_def.trait_def.item().iter_items().filter_map( + |(item, selector)| { + item.filter_map_message().map(|message| { + self.generate_ink_trait_impl_for_message(&message, selector) + }) + }, + ); quote! { #( #messages )* } diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 55e159d380..72e3915e68 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -339,8 +339,8 @@ impl CallForwarder<'_> { /// of the same ink! trait definition. fn generate_ink_trait_impl(&self) -> TokenStream2 { let span = self.trait_def.span(); - let trait_ident = self.trait_def.trait_def.ident(); - let trait_uid = self.trait_def.trait_def.unique_id().hex_padded_suffixed(); + let trait_ident = self.trait_def.trait_def.item().ident(); + let trait_uid = self.trait_def.trait_def.id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let forwarder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); @@ -374,14 +374,15 @@ impl CallForwarder<'_> { /// Generate the code for all ink! trait messages implemented by the trait call forwarder. fn generate_ink_trait_impl_messages(&self) -> TokenStream2 { - let messages = self - .trait_def - .trait_def - .iter_items() - .filter_map(|(item, _)| { - item.filter_map_message() - .map(|message| self.generate_ink_trait_impl_for_message(&message)) - }); + let messages = + self.trait_def + .trait_def + .item() + .iter_items() + .filter_map(|(item, _)| { + item.filter_map_message() + .map(|message| self.generate_ink_trait_impl_for_message(&message)) + }); quote! { #( #messages )* } @@ -393,7 +394,7 @@ impl CallForwarder<'_> { message: &ir::InkTraitMessage, ) -> TokenStream2 { let span = message.span(); - let trait_ident = self.trait_def.trait_def.ident(); + let trait_ident = self.trait_def.trait_def.item().ident(); let forwarder_ident = self.ident(); let message_ident = message.ident(); let attrs = message.attrs(); diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 2a74bda498..05680e727e 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -48,12 +48,12 @@ impl<'a> TraitDefinition<'a> { impl TraitDefinition<'_> { pub(super) fn generate_trait_definition(&self) -> TokenStream2 { - let span = self.trait_def.span(); - let attrs = self.trait_def.attrs(); - let ident = self.trait_def.ident(); - let unique_trait_id = self.trait_def.unique_id().hex_padded_suffixed(); - let messages = self - .trait_def + let item = self.trait_def.item(); + let span = item.span(); + let attrs = item.attrs(); + let ident = item.ident(); + let unique_trait_id = self.trait_def.id().hex_padded_suffixed(); + let messages = item .iter_items() .map(|(item, _)| item) .flat_map(ir::InkTraitItem::filter_map_message) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 22109371e7..6f480a6320 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -31,7 +31,7 @@ use quote::{ /// Generator to create the ink! storage struct and important trait impls. #[derive(From, Copy, Clone)] pub struct TraitDefinition<'a> { - trait_def: &'a ir::InkItemTrait, + trait_def: &'a ir::InkTraitDefinition, } impl<'a> TraitDefinition<'a> { @@ -41,11 +41,11 @@ impl<'a> TraitDefinition<'a> { /// were `$NAME` is the non-unique name of the trait and `$TRAIT_ID` /// is the hex representation of the unique 4-byte trait identifier. fn append_trait_suffix(&self, prefix: &str) -> syn::Ident { - let unique_id = self.trait_def.unique_id().to_be_bytes(); + let unique_id = self.trait_def.id().to_be_bytes(); format_ident!( "__ink_{}_{}_0x{:X}{:X}{:X}{:X}", prefix, - self.trait_def.ident(), + self.trait_def.item().ident(), unique_id[0], unique_id[1], unique_id[2], @@ -55,13 +55,13 @@ impl<'a> TraitDefinition<'a> { /// Returns the span of the underlying ink! trait definition. fn span(&self) -> Span { - self.trait_def.span() + self.trait_def.item().span() } } impl GenerateCode for TraitDefinition<'_> { fn generate_code(&self) -> TokenStream2 { - let span = self.trait_def.span(); + let span = self.trait_def.item().span(); let trait_definition = self.generate_trait_definition(); let trait_registry = self.generate_trait_registry_impl(); let trait_call_builder = self.generate_call_builder(); diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 33a71cfee5..8c93848410 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -81,7 +81,7 @@ impl TraitRegistry<'_> { /// Returns the identifier of the ink! trait definition. fn trait_ident(&self) -> &syn::Ident { - self.trait_def.trait_def.ident() + self.trait_def.trait_def.item().ident() } /// Generates the global trait registry implementation for the ink! trait. @@ -120,15 +120,12 @@ impl TraitRegistry<'_> { /// Generate the code for all ink! trait messages implemented by the trait registry. fn generate_registry_messages(&self) -> TokenStream2 { - let messages = - self.trait_def - .trait_def - .iter_items() - .filter_map(|(item, selector)| { - item.filter_map_message().map(|message| { - self.generate_registry_for_message(&message, selector) - }) - }); + let messages = self.trait_def.trait_def.item().iter_items().filter_map( + |(item, selector)| { + item.filter_map_message() + .map(|message| self.generate_registry_for_message(&message, selector)) + }, + ); quote! { #( #messages )* } @@ -203,7 +200,7 @@ impl TraitRegistry<'_> { fn generate_trait_info_object(&self) -> TokenStream2 { let span = self.span(); let trait_ident = self.trait_ident(); - let unique_id = self.trait_def.trait_def.unique_id().hex_padded_suffixed(); + let unique_id = self.trait_def.trait_def.id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let trait_call_forwarder = self.trait_def.call_forwarder_ident(); quote_spanned!(span => diff --git a/crates/lang/codegen/src/lib.rs b/crates/lang/codegen/src/lib.rs index b63d07224b..26403fd46d 100644 --- a/crates/lang/codegen/src/lib.rs +++ b/crates/lang/codegen/src/lib.rs @@ -31,7 +31,7 @@ impl<'a> CodeGenerator for &'a ir::Contract { type Generator = generator::Contract<'a>; } -impl<'a> CodeGenerator for &'a ir::InkItemTrait { +impl<'a> CodeGenerator for &'a ir::InkTraitDefinition { type Generator = generator::TraitDefinition<'a>; } diff --git a/crates/lang/ir/src/literal.rs b/crates/lang/ir/src/literal.rs index 8ed6dbcc52..8e432f4873 100644 --- a/crates/lang/ir/src/literal.rs +++ b/crates/lang/ir/src/literal.rs @@ -25,7 +25,11 @@ pub trait HexLiteral { /// /// Users shall not use this trait method directly hence it is hidden. #[doc(hidden)] - fn hex_impl_(self, fmt: ::core::fmt::Arguments, sealed: private::Sealed) -> syn::LitInt; + fn hex_impl_( + self, + fmt: ::core::fmt::Arguments, + sealed: private::Sealed, + ) -> syn::LitInt; /// Converts the given value into a hex represented literal with type suffix. fn hex_suffixed(self) -> syn::LitInt; diff --git a/crates/lang/macro/src/trait_def.rs b/crates/lang/macro/src/trait_def.rs index 48053b76e4..71869348d1 100644 --- a/crates/lang/macro/src/trait_def.rs +++ b/crates/lang/macro/src/trait_def.rs @@ -25,5 +25,5 @@ pub fn analyze(config: TokenStream2, input: TokenStream2) -> TokenStream2 { pub fn analyze_or_err(config: TokenStream2, input: TokenStream2) -> Result { let trait_definition = ink_lang_ir::InkTraitDefinition::new(config, input)?; - Ok(generate_code(trait_definition.item())) + Ok(generate_code(&trait_definition)) } From 1a1252027befabd5079d699d89eedbae44b09e68 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 15:57:18 +0200 Subject: [PATCH 187/493] disallow namespace config arguments that are no valid Rust identifiers --- crates/lang/ir/src/ir/trait_def/config.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def/config.rs b/crates/lang/ir/src/ir/trait_def/config.rs index 18168a8c6f..ba228aced9 100644 --- a/crates/lang/ir/src/ir/trait_def/config.rs +++ b/crates/lang/ir/src/ir/trait_def/config.rs @@ -75,6 +75,12 @@ impl TryFrom for TraitDefinitionConfig { return Err(duplicate_config_err(meta_name_value, arg, "namespace")) } if let ast::PathOrLit::Lit(syn::Lit::Str(lit_str)) = &arg.value { + if syn::parse_str::(&lit_str.value()).is_err() { + return Err(format_err_spanned!( + lit_str, + "encountered invalid Rust identifier for the ink! namespace configuration parameter" + )) + } namespace = Some((lit_str.clone(), arg)) } else { return Err(format_err_spanned!( From b2905c75c5a99b37a3604e3db8e4a740c7312e3e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 15:57:42 +0200 Subject: [PATCH 188/493] add namespace ink! trait definition config UI tests --- crates/lang/macro/tests/compile_tests.rs | 5 +++++ .../macro/tests/ui/trait_def/fail/invalid_namespace_1.rs | 9 +++++++++ .../tests/ui/trait_def/fail/invalid_namespace_1.stderr | 5 +++++ .../macro/tests/ui/trait_def/fail/invalid_namespace_2.rs | 9 +++++++++ .../tests/ui/trait_def/fail/invalid_namespace_2.stderr | 7 +++++++ .../macro/tests/ui/trait_def/fail/invalid_namespace_3.rs | 9 +++++++++ .../tests/ui/trait_def/fail/invalid_namespace_3.stderr | 7 +++++++ .../macro/tests/ui/trait_def/fail/invalid_namespace_4.rs | 9 +++++++++ .../tests/ui/trait_def/fail/invalid_namespace_4.stderr | 5 +++++ .../lang/macro/tests/ui/trait_def/pass/with_namespace.rs | 9 +++++++++ 10 files changed, 74 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/with_namespace.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 55b44a4677..f244768fa4 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -66,6 +66,7 @@ fn compile_tests() { t.pass("tests/ui/trait_def/pass/many_outputs.rs"); t.pass("tests/ui/trait_def/pass/payable_message.rs"); t.pass("tests/ui/trait_def/pass/custom_selector.rs"); + t.pass("tests/ui/trait_def/pass/with_namespace.rs"); t.compile_fail("tests/ui/trait_def/fail/empty_definition.rs"); t.compile_fail("tests/ui/trait_def/fail/with_constructor.rs"); t.compile_fail("tests/ui/trait_def/fail/overlapping_selectors.rs"); @@ -75,4 +76,8 @@ fn compile_tests() { t.compile_fail("tests/ui/trait_def/fail/invalid_payable_2.rs"); t.compile_fail("tests/ui/trait_def/fail/with_assoc_type.rs"); t.compile_fail("tests/ui/trait_def/fail/with_assoc_const.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_3.rs"); + t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_4.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.rs new file mode 100644 index 0000000000..b25cdce751 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition(namespace = "::invalid::rust::identifier")] +pub trait InvalidNamespace { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.stderr new file mode 100644 index 0000000000..02ccdfb125 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.stderr @@ -0,0 +1,5 @@ +error: encountered invalid Rust identifier for the ink! namespace configuration parameter + --> $DIR/invalid_namespace_1.rs:3:37 + | +3 | #[ink::trait_definition(namespace = "::invalid::rust::identifier")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.rs new file mode 100644 index 0000000000..27bf7d801e --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition(namespace)] +pub trait InvalidNamespace { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.stderr new file mode 100644 index 0000000000..4b2b2a38b9 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.stderr @@ -0,0 +1,7 @@ +error: expected `=` + --> $DIR/invalid_namespace_2.rs:3:1 + | +3 | #[ink::trait_definition(namespace)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `ink::trait_definition` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs new file mode 100644 index 0000000000..27bf7d801e --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition(namespace)] +pub trait InvalidNamespace { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr new file mode 100644 index 0000000000..4e98cc9ac9 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr @@ -0,0 +1,7 @@ +error: expected `=` + --> $DIR/invalid_namespace_3.rs:3:1 + | +3 | #[ink::trait_definition(namespace)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `ink::trait_definition` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.rs new file mode 100644 index 0000000000..6b7d789bf6 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition(namespace = true)] +pub trait InvalidNamespace { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.stderr new file mode 100644 index 0000000000..2724b2541c --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.stderr @@ -0,0 +1,5 @@ +error: expected a string literal for `namespace` ink! trait definition configuration argument + --> $DIR/invalid_namespace_4.rs:3:25 + | +3 | #[ink::trait_definition(namespace = true)] + | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/pass/with_namespace.rs b/crates/lang/macro/tests/ui/trait_def/pass/with_namespace.rs new file mode 100644 index 0000000000..3664134030 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/with_namespace.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition(namespace = "my_trait_namespace")] +pub trait WithNamespace { + #[ink(message)] + fn message(&self); +} + +fn main() {} From b4e18be3e5984f26a7ec859faeebb97e2cd60d43 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 16:21:19 +0200 Subject: [PATCH 189/493] remove deprecated UI test for ink! trait constructors --- crates/lang/macro/tests/compile_tests.rs | 1 - .../ui/fail/C-15-payable-trait-constructor.rs | 27 ------------------- .../C-15-payable-trait-constructor.stderr | 11 -------- 3 files changed, 39 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.rs delete mode 100644 crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index f244768fa4..5733fa4b2d 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -38,7 +38,6 @@ fn compile_tests() { t.compile_fail("tests/ui/fail/C-12-const-constructor.rs"); t.compile_fail("tests/ui/fail/C-13-abi-constructor.rs"); t.compile_fail("tests/ui/fail/C-14-payable-constructor.rs"); - t.compile_fail("tests/ui/fail/C-15-payable-trait-constructor.rs"); t.compile_fail("tests/ui/fail/C-16-function-arg-struct-destructuring.rs"); t.compile_fail("tests/ui/fail/H-01-invalid-dyn-alloc.rs"); diff --git a/crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.rs b/crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.rs deleted file mode 100644 index 097c40d7b9..0000000000 --- a/crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.rs +++ /dev/null @@ -1,27 +0,0 @@ -use ink_lang as ink; - -#[ink::trait_definition] -pub trait Constructor { - #[ink(constructor)] - fn constructor() -> Self; -} - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - impl Constructor for Noop { - #[ink(constructor, payable)] - fn constructor() -> Self { - Self {} - } - } - - impl Noop { - #[ink(message)] - pub fn noop(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.stderr b/crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.stderr deleted file mode 100644 index 1dda3879dc..0000000000 --- a/crates/lang/macro/tests/ui/fail/C-15-payable-trait-constructor.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: encountered conflicting ink! attribute argument - --> $DIR/C-15-payable-trait-constructor.rs:15:28 - | -15 | #[ink(constructor, payable)] - | ^^^^^^^ - -error: constructors are implicitly payable - --> $DIR/C-15-payable-trait-constructor.rs:15:28 - | -15 | #[ink(constructor, payable)] - | ^^^^^^^ From fb7a30c0aa57fc7b27a458d41665dbaaae3b8efc Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 18:21:16 +0200 Subject: [PATCH 190/493] adjust UI test --- .../tests/ui/trait_def/fail/invalid_namespace_3.rs | 2 +- .../tests/ui/trait_def/fail/invalid_namespace_3.stderr | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs index 27bf7d801e..ea773ef945 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs @@ -1,6 +1,6 @@ use ink_lang as ink; -#[ink::trait_definition(namespace)] +#[ink::trait_definition(namespace = "")] pub trait InvalidNamespace { #[ink(message)] fn message(&self); diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr index 4e98cc9ac9..628b95d3c1 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr @@ -1,7 +1,5 @@ -error: expected `=` - --> $DIR/invalid_namespace_3.rs:3:1 +error: encountered invalid Rust identifier for the ink! namespace configuration parameter + --> $DIR/invalid_namespace_3.rs:3:37 | -3 | #[ink::trait_definition(namespace)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `ink::trait_definition` (in Nightly builds, run with -Z macro-backtrace for more info) +3 | #[ink::trait_definition(namespace = "")] + | ^^ From 5ecb4b708f0a4d06d93d1288a1f3af38ae950b20 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 18:23:27 +0200 Subject: [PATCH 191/493] divide UI tests into the different macros they are testing - ink::contract - ink::chain_extension - ink::trait_definition --- crates/lang/macro/tests/compile_tests.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 5733fa4b2d..eff63a27e8 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -13,7 +13,7 @@ // limitations under the License. #[test] -fn compile_tests() { +fn contract() { let t = trybuild::TestCases::new(); t.pass("tests/ui/pass/01-noop-contract.rs"); @@ -57,9 +57,17 @@ fn compile_tests() { t.compile_fail("tests/ui/fail/S-04-non-storage-ink-impls.rs"); t.compile_fail("tests/ui/fail/S-05-storage-as-event.rs"); t.compile_fail("tests/ui/fail/S-06-event-as-storage.rs"); +} +#[test] +fn chain_extension() { + let t = trybuild::TestCases::new(); t.pass("tests/ui/chain_extension/E-01-simple.rs"); +} +#[test] +fn trait_definition() { + let t = trybuild::TestCases::new(); t.pass("tests/ui/trait_def/pass/simple_definition.rs"); t.pass("tests/ui/trait_def/pass/many_inputs.rs"); t.pass("tests/ui/trait_def/pass/many_outputs.rs"); From 823b0d8621215701d2d899604fcb9e76b6c1cc24 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 19:24:18 +0200 Subject: [PATCH 192/493] always implement Debug and Clone for CallBuilder and Ref --- .../lang/codegen/src/generator/as_dependency/call_builder.rs | 3 ++- .../lang/codegen/src/generator/as_dependency/contract_ref.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 80b15fefee..a1e99f4dc2 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -83,10 +83,10 @@ impl CallBuilder<'_> { /// messages and trait implementations in a type safe way. #[repr(transparent)] #[cfg_attr(feature = "std", derive( - ::core::fmt::Debug, ::ink_storage::traits::StorageLayout, ))] #[derive( + ::core::fmt::Debug, ::ink_storage::traits::SpreadLayout, ::ink_storage::traits::PackedLayout, ::scale::Encode, @@ -94,6 +94,7 @@ impl CallBuilder<'_> { ::core::hash::Hash, ::core::cmp::PartialEq, ::core::cmp::Eq, + ::core::clone::Clone, )] pub struct #cb_ident { account_id: AccountId, diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index d630afea82..4fabcaadb4 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -76,10 +76,10 @@ impl ContractRef<'_> { let ref_ident = self.generate_contract_ref_ident(); quote_spanned!(span=> #[cfg_attr(feature = "std", derive( - ::core::fmt::Debug, ::ink_storage::traits::StorageLayout, ))] #[derive( + ::core::fmt::Debug, ::ink_storage::traits::SpreadLayout, ::ink_storage::traits::PackedLayout, ::scale::Encode, @@ -87,6 +87,7 @@ impl ContractRef<'_> { ::core::hash::Hash, ::core::cmp::PartialEq, ::core::cmp::Eq, + ::core::clone::Clone, )] pub struct #ref_ident { inner: <#storage_ident as ::ink_lang::ContractCallBuilder>::Type, From 90189ef668e5e860dd9ff3e22487f91a7d1d274f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 19:24:39 +0200 Subject: [PATCH 193/493] add TypeInfo derives for CallBuilder and Ref --- crates/lang/codegen/src/generator/as_dependency/call_builder.rs | 1 + crates/lang/codegen/src/generator/as_dependency/contract_ref.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index a1e99f4dc2..17d2762bca 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -83,6 +83,7 @@ impl CallBuilder<'_> { /// messages and trait implementations in a type safe way. #[repr(transparent)] #[cfg_attr(feature = "std", derive( + ::scale_info::TypeInfo, ::ink_storage::traits::StorageLayout, ))] #[derive( diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 4fabcaadb4..2c1a96c900 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -76,6 +76,7 @@ impl ContractRef<'_> { let ref_ident = self.generate_contract_ref_ident(); quote_spanned!(span=> #[cfg_attr(feature = "std", derive( + ::scale_info::TypeInfo, ::ink_storage::traits::StorageLayout, ))] #[derive( From 03c192423624a8d2b922c21dcdef3cf4a64d3a79 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 19:24:53 +0200 Subject: [PATCH 194/493] adjust Delegator example contract for new codegen --- examples/delegator/accumulator/lib.rs | 3 ++- examples/delegator/adder/lib.rs | 9 ++++---- examples/delegator/lib.rs | 30 ++++++++++++++++----------- examples/delegator/subber/lib.rs | 9 ++++---- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/examples/delegator/accumulator/lib.rs b/examples/delegator/accumulator/lib.rs index 8fd207c4a8..2299689db6 100644 --- a/examples/delegator/accumulator/lib.rs +++ b/examples/delegator/accumulator/lib.rs @@ -1,6 +1,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::accumulator::Accumulator; +pub use self::accumulator::{Accumulator, AccumulatorRef}; + use ink_lang as ink; #[ink::contract] diff --git a/examples/delegator/adder/lib.rs b/examples/delegator/adder/lib.rs index 91af1fd12f..3aabddfab6 100644 --- a/examples/delegator/adder/lib.rs +++ b/examples/delegator/adder/lib.rs @@ -1,23 +1,24 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::adder::Adder; +pub use self::adder::{Adder, AdderRef}; + use ink_lang as ink; #[ink::contract] mod adder { - use accumulator::Accumulator; + use accumulator::AccumulatorRef; /// Increments the underlying `accumulator` value. #[ink(storage)] pub struct Adder { /// The `accumulator` to store the value. - accumulator: accumulator::Accumulator, + accumulator: AccumulatorRef, } impl Adder { /// Creates a new `adder` from the given `accumulator`. #[ink(constructor)] - pub fn new(accumulator: Accumulator) -> Self { + pub fn new(accumulator: AccumulatorRef) -> Self { Self { accumulator } } diff --git a/examples/delegator/lib.rs b/examples/delegator/lib.rs index 5fa7e0fbd8..6066104a5a 100644 --- a/examples/delegator/lib.rs +++ b/examples/delegator/lib.rs @@ -4,8 +4,8 @@ use ink_lang as ink; #[ink::contract] mod delegator { - use accumulator::Accumulator; - use adder::Adder; + use accumulator::AccumulatorRef; + use adder::AdderRef; use ink_storage::{ traits::{ PackedLayout, @@ -13,7 +13,7 @@ mod delegator { }, Lazy, }; - use subber::Subber; + use subber::SubberRef; /// Specifies the state of the `delegator` contract. /// @@ -54,11 +54,11 @@ mod delegator { /// Says which of `adder` or `subber` is currently in use. which: Which, /// The `accumulator` smart contract. - accumulator: Lazy, + accumulator: Lazy, /// The `adder` smart contract. - adder: Lazy, + adder: Lazy, /// The `subber` smart contract. - subber: Lazy, + subber: Lazy, } impl Delegator { @@ -73,24 +73,30 @@ mod delegator { ) -> Self { let total_balance = Self::env().balance(); let salt = version.to_le_bytes(); - let accumulator = Accumulator::new(init_value) + let accumulator = AccumulatorRef::new(init_value) .endowment(total_balance / 4) .code_hash(accumulator_code_hash) .salt_bytes(salt) .instantiate() - .expect("failed at instantiating the `Accumulator` contract"); - let adder = Adder::new(accumulator.clone()) + .unwrap_or_else(|error| { + panic!("failed at instantiating the Accumulator contract: {:?}", error) + }); + let adder = AdderRef::new(accumulator.clone()) .endowment(total_balance / 4) .code_hash(adder_code_hash) .salt_bytes(salt) .instantiate() - .expect("failed at instantiating the `Adder` contract"); - let subber = Subber::new(accumulator.clone()) + .unwrap_or_else(|error| { + panic!("failed at instantiating the Adder contract: {:?}", error) + }); + let subber = SubberRef::new(accumulator.clone()) .endowment(total_balance / 4) .code_hash(subber_code_hash) .salt_bytes(salt) .instantiate() - .expect("failed at instantiating the `Subber` contract"); + .unwrap_or_else(|error| { + panic!("failed at instantiating the Subber contract: {:?}", error) + }); Self { which: Which::Adder, accumulator: Lazy::new(accumulator), diff --git a/examples/delegator/subber/lib.rs b/examples/delegator/subber/lib.rs index 30d5424c77..9f9da4412c 100644 --- a/examples/delegator/subber/lib.rs +++ b/examples/delegator/subber/lib.rs @@ -1,23 +1,24 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::subber::Subber; +pub use self::subber::{Subber, SubberRef}; + use ink_lang as ink; #[ink::contract] mod subber { - use accumulator::Accumulator; + use accumulator::AccumulatorRef; /// Decreases the underlying `accumulator` value. #[ink(storage)] pub struct Subber { /// The `accumulator` to store the value. - accumulator: accumulator::Accumulator, + accumulator: AccumulatorRef, } impl Subber { /// Creates a new `subber` from the given `accumulator`. #[ink(constructor)] - pub fn new(accumulator: Accumulator) -> Self { + pub fn new(accumulator: AccumulatorRef) -> Self { Self { accumulator } } From 9dbe203a5baa3c9c3e52cf06b6471399694ad6d7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 19:25:09 +0200 Subject: [PATCH 195/493] apply rustfmt --- examples/delegator/accumulator/lib.rs | 5 ++++- examples/delegator/adder/lib.rs | 5 ++++- examples/delegator/lib.rs | 5 ++++- examples/delegator/subber/lib.rs | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/delegator/accumulator/lib.rs b/examples/delegator/accumulator/lib.rs index 2299689db6..fae1482a9a 100644 --- a/examples/delegator/accumulator/lib.rs +++ b/examples/delegator/accumulator/lib.rs @@ -1,6 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::accumulator::{Accumulator, AccumulatorRef}; +pub use self::accumulator::{ + Accumulator, + AccumulatorRef, +}; use ink_lang as ink; diff --git a/examples/delegator/adder/lib.rs b/examples/delegator/adder/lib.rs index 3aabddfab6..5996ed1a78 100644 --- a/examples/delegator/adder/lib.rs +++ b/examples/delegator/adder/lib.rs @@ -1,6 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::adder::{Adder, AdderRef}; +pub use self::adder::{ + Adder, + AdderRef, +}; use ink_lang as ink; diff --git a/examples/delegator/lib.rs b/examples/delegator/lib.rs index 6066104a5a..08ae5116a1 100644 --- a/examples/delegator/lib.rs +++ b/examples/delegator/lib.rs @@ -79,7 +79,10 @@ mod delegator { .salt_bytes(salt) .instantiate() .unwrap_or_else(|error| { - panic!("failed at instantiating the Accumulator contract: {:?}", error) + panic!( + "failed at instantiating the Accumulator contract: {:?}", + error + ) }); let adder = AdderRef::new(accumulator.clone()) .endowment(total_balance / 4) diff --git a/examples/delegator/subber/lib.rs b/examples/delegator/subber/lib.rs index 9f9da4412c..35180f9bbf 100644 --- a/examples/delegator/subber/lib.rs +++ b/examples/delegator/subber/lib.rs @@ -1,6 +1,9 @@ #![cfg_attr(not(feature = "std"), no_std)] -pub use self::subber::{Subber, SubberRef}; +pub use self::subber::{ + Subber, + SubberRef, +}; use ink_lang as ink; From 856513c3b17b29c960de044ecade5f96a3babe28 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 19:37:41 +0200 Subject: [PATCH 196/493] fix trait-flipper example contract --- examples/trait-flipper/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/trait-flipper/lib.rs b/examples/trait-flipper/lib.rs index dd1c0b5f91..68642b5128 100644 --- a/examples/trait-flipper/lib.rs +++ b/examples/trait-flipper/lib.rs @@ -25,7 +25,7 @@ pub mod flipper { impl Flipper { /// Creates a new flipper smart contract initialized to `false`. #[ink(constructor)] - pub fn default() -> Self { + pub fn new() -> Self { Self { value: Default::default() } } } @@ -49,7 +49,7 @@ pub mod flipper { #[ink::test] fn default_works() { - let flipper = Flipper::default(); + let flipper = Flipper::new(); assert!(!flipper.get()); } From 12c2d360cfed32353a1cd5b9803119921c98f86e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 19:40:45 +0200 Subject: [PATCH 197/493] fix trait-flipper example contract tests --- examples/trait-flipper/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/trait-flipper/lib.rs b/examples/trait-flipper/lib.rs index 68642b5128..456c060cf8 100644 --- a/examples/trait-flipper/lib.rs +++ b/examples/trait-flipper/lib.rs @@ -55,7 +55,7 @@ pub mod flipper { #[ink::test] fn it_works() { - let mut flipper = Flipper::new(false); + let mut flipper = Flipper::new(); // Can call using universal call syntax using the trait. assert!(!::get(&flipper)); ::flip(&mut flipper); From a60f51c87dba3ce2d154a5e93e57478957c27b22 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 16 Sep 2021 19:53:44 +0200 Subject: [PATCH 198/493] silence clippy warning in trait-flipper example contract --- examples/trait-flipper/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/trait-flipper/lib.rs b/examples/trait-flipper/lib.rs index 456c060cf8..bb3236a193 100644 --- a/examples/trait-flipper/lib.rs +++ b/examples/trait-flipper/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::new_without_default)] use ink_lang as ink; From 4911994972f4059fb76a97f67801b215ec0c56ac Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 17 Sep 2021 13:06:04 +0200 Subject: [PATCH 199/493] remove unneeded regex dependency from ink_lang_codegen --- crates/lang/codegen/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/lang/codegen/Cargo.toml b/crates/lang/codegen/Cargo.toml index fbde30e6cc..43b961836b 100644 --- a/crates/lang/codegen/Cargo.toml +++ b/crates/lang/codegen/Cargo.toml @@ -25,7 +25,6 @@ proc-macro2 = "1.0" derive_more = { version = "0.99", default-features = false, features = ["from"] } itertools = "0.10" either = { version = "1.5", default-features = false } -regex = "1.3" blake2 = "0.9" heck = "0.3.1" scale = { package = "parity-scale-codec", version = "2.2", default-features = false, features = ["derive", "full"] } From 3a39d884834ccf574478c4fa17aff293ebe090cd Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 17 Sep 2021 13:06:38 +0200 Subject: [PATCH 200/493] no longer allow string literal as input for #[ink(selector: u32)] --- crates/lang/ir/Cargo.toml | 1 - crates/lang/ir/src/ir/attrs.rs | 76 ++++--------------- crates/lang/ir/src/ir/item_impl/callable.rs | 2 +- crates/lang/ir/src/ir/item_impl/message.rs | 2 +- crates/lang/ir/src/ir/item_mod.rs | 12 +-- .../ui/fail/M-05-message-invalid-selector.rs | 2 +- .../fail/M-05-message-invalid-selector.stderr | 6 +- .../ui/trait_def/pass/custom_selector.rs | 13 +--- 8 files changed, 31 insertions(+), 83 deletions(-) diff --git a/crates/lang/ir/Cargo.toml b/crates/lang/ir/Cargo.toml index 79757578e4..99c4a0de68 100644 --- a/crates/lang/ir/Cargo.toml +++ b/crates/lang/ir/Cargo.toml @@ -23,7 +23,6 @@ syn = { version = "1.0", features = ["parsing", "full", "visit", "extra-traits"] proc-macro2 = "1.0" itertools = { version = "0.10", default-features = false } either = { version = "1.5", default-features = false } -regex = "1.3" blake2 = "0.9" [features] diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 6a37a24098..b2ad23d837 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -28,7 +28,6 @@ use proc_macro2::{ Ident, Span, }; -use regex::Regex; use std::collections::HashMap; use syn::spanned::Spanned; @@ -772,19 +771,6 @@ impl InkAttribute { } } -/// Returns an error to notify about non-hex digits at a position. -fn err_non_hex(meta: &syn::Meta, pos: usize) -> syn::Error { - format_err_spanned!(meta, "encountered non-hex digit at position {}", pos) -} - -/// Returns an error to notify about an invalid ink! selector. -fn invalid_selector_err_regex(meta: &syn::Meta) -> syn::Error { - format_err_spanned!( - meta, - "invalid selector - a selector must consist of four bytes in hex (e.g. `selector = \"0xCAFEBABE\"`)" - ) -} - impl TryFrom for AttributeFrag { type Error = syn::Error; @@ -809,46 +795,6 @@ impl TryFrom for AttributeFrag { arg: AttributeArg::Selector(selector), }) } - if let syn::Lit::Str(lit_str) = &name_value.lit { - let regex = Regex::new(r"0x([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})") - .map_err(|_| { - invalid_selector_err_regex(&meta) - })?; - let str = lit_str.value(); - let cap = - regex.captures(&str).ok_or_else(|| { - invalid_selector_err_regex(&meta) - })?; - if !regex.is_match(&str) { - return Err(invalid_selector_err_regex( - &meta, - )) - } - let len_digits = (str.as_bytes().len() - 2) / 2; - if len_digits != 4 { - return Err(format_err!( - name_value, - "expected 4-digit hexcode for `selector` argument, found {} digits", - len_digits, - )) - } - let selector_bytes = [ - u8::from_str_radix(&cap[1], 16) - .map_err(|_| err_non_hex(&meta, 0))?, - u8::from_str_radix(&cap[2], 16) - .map_err(|_| err_non_hex(&meta, 1))?, - u8::from_str_radix(&cap[3], 16) - .map_err(|_| err_non_hex(&meta, 2))?, - u8::from_str_radix(&cap[4], 16) - .map_err(|_| err_non_hex(&meta, 3))?, - ]; - return Ok(AttributeFrag { - ast: meta, - arg: AttributeArg::Selector(Selector::from_bytes( - selector_bytes, - )), - }) - } return Err(format_err!(name_value, "expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE]")) } if name_value.path.is_ident("namespace") { @@ -1121,7 +1067,15 @@ mod tests { fn selector_works() { assert_attribute_try_from( syn::parse_quote! { - #[ink(selector = "0xDEADBEEF")] + #[ink(selector = 42)] + }, + Ok(test::Attribute::Ink(vec![AttributeArg::Selector( + Selector::from_bytes([0, 0, 0, 42]), + )])), + ); + assert_attribute_try_from( + syn::parse_quote! { + #[ink(selector = 0xDEADBEEF)] }, Ok(test::Attribute::Ink(vec![AttributeArg::Selector( Selector::from_bytes([0xDE, 0xAD, 0xBE, 0xEF]), @@ -1130,22 +1084,22 @@ mod tests { } #[test] - fn selector_non_hexcode() { + fn selector_negative_number() { assert_attribute_try_from( syn::parse_quote! { - #[ink(selector = "0xhelloworld")] + #[ink(selector = -1)] }, - Err("invalid selector - a selector must consist of four bytes in hex (e.g. `selector = \"0xCAFEBABE\"`)"), + Err("selector value out of range. selector must be a valid `u32` integer: invalid digit found in string"), ); } #[test] - fn selector_too_long() { + fn selector_out_of_range() { assert_attribute_try_from( syn::parse_quote! { - #[ink(selector = "0xDEADBEEFC0FEBABE")] + #[ink(selector = 0xFFFF_FFFF_FFFF_FFFF)] }, - Err("expected 4-digit hexcode for `selector` argument, found 8 digits"), + Err("selector value out of range. selector must be a valid `u32` integer: number too large to fit in target type"), ); } diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index 7781472335..6150dbb254 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -616,7 +616,7 @@ mod tests { impl MyTrait for MyStorage {} }, syn::parse_quote! { - #[ink(message, selector = "0xDEADBEEF")] + #[ink(message, selector = 0xDEADBEEF)] fn my_message(&self) {} }, [0xDE, 0xAD, 0xBE, 0xEF], diff --git a/crates/lang/ir/src/ir/item_impl/message.rs b/crates/lang/ir/src/ir/item_impl/message.rs index 63eda9971f..90b44e9941 100644 --- a/crates/lang/ir/src/ir/item_impl/message.rs +++ b/crates/lang/ir/src/ir/item_impl/message.rs @@ -405,7 +405,7 @@ mod tests { true, syn::parse_quote! { #[ink(message)] - #[ink(selector = "0xDEADBEEF", payable)] + #[ink(selector = 0xDEADBEEF, payable)] pub fn my_message(&self) {} }, ), diff --git a/crates/lang/ir/src/ir/item_mod.rs b/crates/lang/ir/src/ir/item_mod.rs index e3effcd8a0..1db189fb44 100644 --- a/crates/lang/ir/src/ir/item_mod.rs +++ b/crates/lang/ir/src/ir/item_mod.rs @@ -713,12 +713,12 @@ mod tests { #[ink(constructor)] pub fn my_constructor() -> Self {} - #[ink(message, selector = "0xDEADBEEF")] + #[ink(message, selector = 0xDEADBEEF)] pub fn my_message_1(&self) {} } impl MyStorage { - #[ink(message, selector = "0xDEADBEEF")] + #[ink(message, selector = 0xDEADBEEF)] pub fn my_message_2(&self) {} } } @@ -739,7 +739,7 @@ mod tests { pub struct MyStorage {} impl MyStorage { - #[ink(constructor, selector = "0xDEADBEEF")] + #[ink(constructor, selector = 0xDEADBEEF)] pub fn my_constructor_1() -> Self {} #[ink(message)] @@ -747,7 +747,7 @@ mod tests { } impl MyStorage { - #[ink(constructor, selector = "0xDEADBEEF")] + #[ink(constructor, selector = 0xDEADBEEF)] pub fn my_constructor_2() -> Self {} } } @@ -824,10 +824,10 @@ mod tests { pub struct MyStorage {} impl MyStorage { - #[ink(constructor, selector = "0xDEADBEEF")] + #[ink(constructor, selector = 0xDEADBEEF)] pub fn my_constructor() -> Self {} - #[ink(message, selector = "0xDEADBEEF")] + #[ink(message, selector = 0xDEADBEEF)] pub fn my_message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.rs b/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.rs index bb5b7b9075..88348aa471 100644 --- a/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.rs +++ b/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.rs @@ -11,7 +11,7 @@ mod message_invalid_selector { Self {} } - #[ink(message, selector = "0x00")] + #[ink(message, selector = true)] pub fn invalid_selector(&self) {} } } diff --git a/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.stderr b/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.stderr index ac4ea433bc..d4ad9fec24 100644 --- a/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.stderr +++ b/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.stderr @@ -1,5 +1,5 @@ -error: invalid selector - a selector must consist of four bytes in hex (e.g. `selector = "0xCAFEBABE"`) +error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE] --> $DIR/M-05-message-invalid-selector.rs:14:24 | -14 | #[ink(message, selector = "0x00")] - | ^^^^^^^^^^^^^^^^^ +14 | #[ink(message, selector = true)] + | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs b/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs index 5df92e1f74..6cb9dbaff7 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs @@ -2,20 +2,15 @@ use ink_lang as ink; #[ink::trait_definition] pub trait CustomSelector { - #[ink(message, selector = "0x00000001")] + #[ink(message, selector = 1)] fn selector1(&self); - #[ink(message, selector = "0x00000002")] + #[ink(message, selector = 2)] fn selector1_mut(&mut self); - #[ink(message, selector = 3)] + #[ink(message, selector = 0x0000_0003)] fn selector2(&self); - #[ink(message, selector = 4)] + #[ink(message, selector = 0x0000_0004)] fn selector2_mut(&mut self); - - #[ink(message, selector = 0x0000_0005)] - fn selector3(&self); - #[ink(message, selector = 0x0000_0006)] - fn selector3_mut(&mut self); } fn main() {} From 7ffefeac442ab2393c1f3f148c3e82dcfa7deedd Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 17 Sep 2021 13:47:07 +0200 Subject: [PATCH 201/493] fix doc tests with new selector format --- crates/lang/macro/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/macro/src/lib.rs b/crates/lang/macro/src/lib.rs index c06db9fd43..a85908d566 100644 --- a/crates/lang/macro/src/lib.rs +++ b/crates/lang/macro/src/lib.rs @@ -356,20 +356,20 @@ use proc_macro::TokenStream; /// # } /// impl Flipper { /// #[ink(constructor)] -/// #[ink(selector = "0xDEADBEEF")] // Works on constructors as well. +/// #[ink(selector = 0xDEADBEEF)] // Works on constructors as well. /// pub fn new(initial_value: bool) -> Self { /// Flipper { value: false } /// } /// /// # /// Flips the current value. /// # #[ink(message)] -/// # #[ink(selector = "0xCAFEBABE")] // You can either specify selector out-of-line. +/// # #[ink(selector = 0xCAFEBABE)] // You can either specify selector out-of-line. /// # pub fn flip(&mut self) { /// # self.value = !self.value; /// # } /// # /// /// Returns the current value. -/// #[ink(message, selector = "0xFEEDBEEF")] // ... or specify selector inline. +/// #[ink(message, selector = 0xFEEDBEEF)] // ... or specify selector inline. /// pub fn get(&self) -> bool { /// self.value /// } From 651ffe2b38da3e9aad97cd3ec34dce4372367390 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 17 Sep 2021 20:46:33 +0200 Subject: [PATCH 202/493] add way to filter Rust documentation attributes to ink! IR --- crates/lang/ir/src/ir/attrs.rs | 12 ++++++++++++ crates/lang/ir/src/ir/mod.rs | 5 ++++- crates/lang/ir/src/lib.rs | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index b2ad23d837..80b3bce05f 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -31,6 +31,18 @@ use proc_macro2::{ use std::collections::HashMap; use syn::spanned::Spanned; +/// An extension trait for [`syn::Attribute`] in order to query for documentation. +pub trait IsDocAttribute { + /// Returns `true` if the attribute is a Rust documentation attribute. + fn is_doc_attribute(&self) -> bool; +} + +impl IsDocAttribute for syn::Attribute { + fn is_doc_attribute(&self) -> bool { + self.path.is_ident("doc") + } +} + /// Either an ink! specific attribute, or another uninterpreted attribute. #[derive(Debug, PartialEq, Eq)] pub enum Attribute { diff --git a/crates/lang/ir/src/ir/mod.rs b/crates/lang/ir/src/ir/mod.rs index aef8fa83f6..c2a455ac50 100644 --- a/crates/lang/ir/src/ir/mod.rs +++ b/crates/lang/ir/src/ir/mod.rs @@ -43,7 +43,10 @@ use self::attrs::{ InkAttribute, }; pub use self::{ - attrs::Namespace, + attrs::{ + IsDocAttribute, + Namespace, + }, chain_extension::{ ChainExtension, ChainExtensionMethod, diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index a0777c6830..7f8c4f39ac 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -55,6 +55,7 @@ pub use self::{ InkTraitItem, InkTraitMessage, InputsIter, + IsDocAttribute, Item, ItemImpl, ItemMod, From ef103c422d8fae8c14324e6e460ebb18ad07411e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 17 Sep 2021 20:46:55 +0200 Subject: [PATCH 203/493] generate docs for generated Ref type --- .../src/generator/as_dependency/contract_ref.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 2c1a96c900..e7fd0f2e99 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -23,6 +23,7 @@ use quote::{ quote, quote_spanned, }; +use ir::IsDocAttribute as _; use syn::spanned::Spanned as _; /// Generates code for the contract reference of the ink! smart contract. @@ -72,6 +73,14 @@ impl ContractRef<'_> { /// API but is just a typed thin-wrapper around an `AccountId`. fn generate_struct(&self) -> TokenStream2 { let span = self.contract.module().storage().span(); + let doc_attrs = self + .contract + .module() + .storage() + .attrs() + .iter() + .cloned() + .filter(syn::Attribute::is_doc_attribute); let storage_ident = self.contract.module().storage().ident(); let ref_ident = self.generate_contract_ref_ident(); quote_spanned!(span=> @@ -90,6 +99,7 @@ impl ContractRef<'_> { ::core::cmp::Eq, ::core::clone::Clone, )] + #( #doc_attrs )* pub struct #ref_ident { inner: <#storage_ident as ::ink_lang::ContractCallBuilder>::Type, } From d9a45d4f39c2b4ecd792389704682c75319b5ec5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 17 Sep 2021 20:47:04 +0200 Subject: [PATCH 204/493] add docs to trait-incrementer storage type --- examples/trait-incrementer/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/trait-incrementer/lib.rs b/examples/trait-incrementer/lib.rs index 9e5dc05d00..1a861a1066 100644 --- a/examples/trait-incrementer/lib.rs +++ b/examples/trait-incrementer/lib.rs @@ -43,6 +43,7 @@ pub mod incrementer { Reset, }; + /// A concrete incrementer smart contract. #[ink(storage)] pub struct Incrementer { value: u64, From 236b99b232ffb9854772d89ba6f0f0b1b5a4cdb8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 17 Sep 2021 21:01:03 +0200 Subject: [PATCH 205/493] apply rustfmt --- .../codegen/src/generator/as_dependency/contract_ref.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index e7fd0f2e99..ba0a93b3f1 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -17,13 +17,15 @@ use crate::{ GenerateCode, }; use derive_more::From; -use ir::Callable; +use ir::{ + Callable, + IsDocAttribute as _, +}; use proc_macro2::TokenStream as TokenStream2; use quote::{ quote, quote_spanned, }; -use ir::IsDocAttribute as _; use syn::spanned::Spanned as _; /// Generates code for the contract reference of the ink! smart contract. From de31c8d961f1f34078e229515eced150fcbbfeb8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 18 Sep 2021 12:38:25 +0200 Subject: [PATCH 206/493] remove super trait bound for TraitImplementer in ink! trait definitions --- .../generator/as_dependency/call_builder.rs | 29 ------------------- .../generator/as_dependency/contract_ref.rs | 6 ---- .../lang/codegen/src/generator/item_impls.rs | 11 +------ .../src/generator/trait_def/call_builder.rs | 9 ------ .../src/generator/trait_def/call_forwarder.rs | 9 ------ .../src/generator/trait_def/definition.rs | 5 +--- 6 files changed, 2 insertions(+), 67 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 17d2762bca..6190a0ddac 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -166,12 +166,9 @@ impl CallBuilder<'_> { ) -> TokenStream2 { let call_forwarder_impl = self.generate_call_forwarder_for_trait_impl(trait_path, impl_block); - let implementation_marker = - self.generate_implementation_marker_for_trait_impl(trait_path, impl_block); let ink_trait_impl = self.generate_ink_trait_impl(trait_path, impl_block); quote! { #call_forwarder_impl - #implementation_marker #ink_trait_impl } } @@ -236,32 +233,6 @@ impl CallBuilder<'_> { ) } - /// Unsafely implements the required trait implementation marker. - /// - /// This marker only states that the ink! trait definition has been properly implemented. - /// The marker trait is unsafe to make people think twice before manually implementing - /// ink! trait definitions. - fn generate_implementation_marker_for_trait_impl( - &self, - trait_path: &syn::Path, - impl_block: &ir::ItemImpl, - ) -> TokenStream2 { - let span = impl_block.span(); - let cb_ident = Self::call_builder_ident(); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); - quote_spanned!(span=> - // SAFETY: - // - // The trait is unsafe to implement in order to prevent users doing a manual - // implementation themselves. Generally it is safe to implement only by the ink! - // provided macros with correct unique trait ID. - #[doc(hidden)] - unsafe impl - ::ink_lang::TraitImplementer<#unique_trait_id> for #cb_ident - {} - ) - } - /// Generates the actual ink! trait implementation for the generated call builder. fn generate_ink_trait_impl( &self, diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index ba0a93b3f1..82a20e0130 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -204,15 +204,9 @@ impl ContractRef<'_> { ) -> TokenStream2 { let span = impl_block.span(); let attrs = impl_block.attrs(); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); let forwarder_ident = self.generate_contract_ref_ident(); let messages = self.generate_contract_trait_impl_messages(trait_path, impl_block); quote_spanned!(span=> - #[doc(hidden)] - unsafe impl - ::ink_lang::TraitImplementer<#unique_trait_id> for #forwarder_ident - {} - #( #attrs )* impl #trait_path for #forwarder_ident { #[doc(hidden)] diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 8e1c3d59b1..454299c6a8 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -12,10 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - generator, - GenerateCode, -}; +use crate::GenerateCode; use derive_more::From; use heck::CamelCase as _; use ir::Callable as _; @@ -91,13 +88,7 @@ impl ItemImpls<'_> { .trait_path() .expect("encountered missing trait path for trait impl block"); let self_type = item_impl.self_type(); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); quote_spanned!(span => - #[doc(hidden)] - unsafe impl - ::ink_lang::TraitImplementer<#unique_trait_id> for #self_type - {} - #( #attrs )* impl #trait_path for #self_type { type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 12f85d29f5..fe741237cc 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -18,7 +18,6 @@ use crate::{ traits::GenerateCode, }; use derive_more::From; -use ir::HexLiteral; use proc_macro2::{ Span, TokenStream as TokenStream2, @@ -314,18 +313,10 @@ impl CallBuilder<'_> { fn generate_ink_trait_impl(&self) -> TokenStream2 { let span = self.trait_def.span(); let trait_ident = self.trait_def.trait_def.item().ident(); - let trait_uid = self.trait_def.trait_def.id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let builder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - unsafe impl ::ink_lang::TraitImplementer<#trait_uid> - for #builder_ident - where - E: ::ink_env::Environment, - { - } - impl ::ink_lang::ContractEnv for #builder_ident where E: ::ink_env::Environment, diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 72e3915e68..fa7b24a158 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -18,7 +18,6 @@ use crate::{ traits::GenerateCode, }; use derive_more::From; -use ir::HexLiteral; use proc_macro2::{ Span, TokenStream as TokenStream2, @@ -340,18 +339,10 @@ impl CallForwarder<'_> { fn generate_ink_trait_impl(&self) -> TokenStream2 { let span = self.trait_def.span(); let trait_ident = self.trait_def.trait_def.item().ident(); - let trait_uid = self.trait_def.trait_def.id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let forwarder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - unsafe impl ::ink_lang::TraitImplementer<#trait_uid> - for #forwarder_ident - where - E: ::ink_env::Environment, - { - } - impl ::ink_lang::ContractEnv for #forwarder_ident where E: ::ink_env::Environment, diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 05680e727e..4532b51619 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -60,10 +60,7 @@ impl TraitDefinition<'_> { .map(Self::generate_for_message); quote_spanned!(span => #(#attrs)* - pub trait #ident: - ::ink_lang::ContractEnv + - ::ink_lang::TraitImplementer<#unique_trait_id> - { + pub trait #ident: ::ink_lang::ContractEnv { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] From 368cc09d9af28b6c2b915dce01455c327e857db3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 18 Sep 2021 13:12:37 +0200 Subject: [PATCH 207/493] move UI tests of ink::contract macro into their own folder --- crates/lang/macro/tests/compile_tests.rs | 74 +++++++++---------- .../fail/C-00-constructor-self-ref.rs | 0 .../fail/C-00-constructor-self-ref.stderr | 0 .../fail/C-01-constructor-self-mut.rs | 0 .../fail/C-01-constructor-self-mut.stderr | 0 .../fail/C-02-constructor-self-val.rs | 0 .../fail/C-02-constructor-self-val.stderr | 0 .../fail/C-03-constructor-missing-return.rs | 0 .../C-03-constructor-missing-return.stderr | 0 .../fail/C-04-missing-constructor.rs | 0 .../fail/C-04-missing-constructor.stderr | 0 .../fail/C-10-async-constructor.rs | 0 .../fail/C-10-async-constructor.stderr | 0 .../fail/C-11-unsafe-constructor.rs | 0 .../fail/C-11-unsafe-constructor.stderr | 0 .../fail/C-12-const-constructor.rs | 0 .../fail/C-12-const-constructor.stderr | 0 .../fail/C-13-abi-constructor.rs | 0 .../fail/C-13-abi-constructor.stderr | 0 .../fail/C-14-payable-constructor.rs | 0 .../fail/C-14-payable-constructor.stderr | 0 .../C-16-function-arg-struct-destructuring.rs | 0 ...6-function-arg-struct-destructuring.stderr | 0 .../fail/H-01-invalid-dyn-alloc.rs | 0 .../fail/H-01-invalid-dyn-alloc.stderr | 0 .../fail/H-02-invalid-as-dependency.rs | 0 .../fail/H-02-invalid-as-dependency.stderr | 0 .../fail/H-03-use-forbidden-idents.rs | 0 .../fail/H-03-use-forbidden-idents.stderr | 0 .../fail/M-01-missing-message.rs | 0 .../fail/M-01-missing-message.stderr | 0 .../fail/M-02-message-missing-self-arg.rs | 0 .../fail/M-02-message-missing-self-arg.stderr | 0 .../fail/M-03-message-returns-self.rs | 0 .../fail/M-03-message-returns-self.stderr | 0 .../fail/M-04-message-returns-non-codec.rs | 0 .../M-04-message-returns-non-codec.stderr | 0 .../fail/M-05-message-invalid-selector.rs | 0 .../fail/M-05-message-invalid-selector.stderr | 0 .../fail/M-10-method-unknown-ink-marker.rs | 0 .../M-10-method-unknown-ink-marker.stderr | 0 .../fail/S-01-missing-storage-struct.rs | 0 .../fail/S-01-missing-storage-struct.stderr | 0 .../fail/S-02-multiple-storage-structs.rs | 0 .../fail/S-02-multiple-storage-structs.stderr | 0 .../fail/S-03-struct-unknown-ink-marker.rs | 0 .../S-03-struct-unknown-ink-marker.stderr | 0 .../fail/S-04-non-storage-ink-impls.rs | 0 .../fail/S-04-non-storage-ink-impls.stderr | 0 .../fail/S-05-storage-as-event.rs | 0 .../fail/S-05-storage-as-event.stderr | 0 .../fail/S-06-event-as-storage.rs | 0 .../fail/S-06-event-as-storage.stderr | 0 .../{ => contract}/pass/01-noop-contract.rs | 0 .../pass/02-flipper-contract.rs | 0 .../pass/03-incrementer-contract.rs | 0 .../{ => contract}/pass/04-erc20-contract.rs | 0 .../{ => contract}/pass/05-erc721-contract.rs | 0 .../{ => contract}/pass/06-non-ink-items.rs | 0 .../pass/07-flipper-as-dependency.rs | 0 .../pass/08-flipper-as-dependency-trait.rs | 0 .../ui/{ => contract}/pass/09-static-env.rs | 0 .../pass/10-derive-for-storage.rs | 0 .../pass/11-alias-storage-struct-impl.rs | 0 64 files changed, 37 insertions(+), 37 deletions(-) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-00-constructor-self-ref.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-00-constructor-self-ref.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-01-constructor-self-mut.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-01-constructor-self-mut.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-02-constructor-self-val.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-02-constructor-self-val.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-03-constructor-missing-return.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-03-constructor-missing-return.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-04-missing-constructor.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-04-missing-constructor.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-10-async-constructor.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-10-async-constructor.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-11-unsafe-constructor.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-11-unsafe-constructor.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-12-const-constructor.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-12-const-constructor.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-13-abi-constructor.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-13-abi-constructor.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-14-payable-constructor.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-14-payable-constructor.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-16-function-arg-struct-destructuring.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/C-16-function-arg-struct-destructuring.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/H-01-invalid-dyn-alloc.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/H-01-invalid-dyn-alloc.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/H-02-invalid-as-dependency.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/H-02-invalid-as-dependency.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/H-03-use-forbidden-idents.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/H-03-use-forbidden-idents.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-01-missing-message.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-01-missing-message.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-02-message-missing-self-arg.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-02-message-missing-self-arg.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-03-message-returns-self.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-03-message-returns-self.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-04-message-returns-non-codec.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-04-message-returns-non-codec.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-05-message-invalid-selector.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-05-message-invalid-selector.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-10-method-unknown-ink-marker.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/M-10-method-unknown-ink-marker.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-01-missing-storage-struct.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-01-missing-storage-struct.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-02-multiple-storage-structs.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-02-multiple-storage-structs.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-03-struct-unknown-ink-marker.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-03-struct-unknown-ink-marker.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-04-non-storage-ink-impls.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-04-non-storage-ink-impls.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-05-storage-as-event.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-05-storage-as-event.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-06-event-as-storage.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/fail/S-06-event-as-storage.stderr (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/01-noop-contract.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/02-flipper-contract.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/03-incrementer-contract.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/04-erc20-contract.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/05-erc721-contract.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/06-non-ink-items.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/07-flipper-as-dependency.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/08-flipper-as-dependency-trait.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/09-static-env.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/10-derive-for-storage.rs (100%) rename crates/lang/macro/tests/ui/{ => contract}/pass/11-alias-storage-struct-impl.rs (100%) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index eff63a27e8..a2b40a76db 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -16,47 +16,47 @@ fn contract() { let t = trybuild::TestCases::new(); - t.pass("tests/ui/pass/01-noop-contract.rs"); - t.pass("tests/ui/pass/02-flipper-contract.rs"); - t.pass("tests/ui/pass/03-incrementer-contract.rs"); - t.pass("tests/ui/pass/04-erc20-contract.rs"); - t.pass("tests/ui/pass/05-erc721-contract.rs"); - t.pass("tests/ui/pass/06-non-ink-items.rs"); - t.pass("tests/ui/pass/07-flipper-as-dependency.rs"); - t.pass("tests/ui/pass/08-flipper-as-dependency-trait.rs"); - t.pass("tests/ui/pass/09-static-env.rs"); - t.pass("tests/ui/pass/10-derive-for-storage.rs"); - t.pass("tests/ui/pass/11-alias-storage-struct-impl.rs"); + t.pass("tests/ui/contract/pass/01-noop-contract.rs"); + t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); + t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); + t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); + t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); + t.pass("tests/ui/contract/pass/06-non-ink-items.rs"); + t.pass("tests/ui/contract/pass/07-flipper-as-dependency.rs"); + t.pass("tests/ui/contract/pass/08-flipper-as-dependency-trait.rs"); + t.pass("tests/ui/contract/pass/09-static-env.rs"); + t.pass("tests/ui/contract/pass/10-derive-for-storage.rs"); + t.pass("tests/ui/contract/pass/11-alias-storage-struct-impl.rs"); - t.compile_fail("tests/ui/fail/C-00-constructor-self-ref.rs"); - t.compile_fail("tests/ui/fail/C-01-constructor-self-mut.rs"); - t.compile_fail("tests/ui/fail/C-02-constructor-self-val.rs"); - t.compile_fail("tests/ui/fail/C-03-constructor-missing-return.rs"); - t.compile_fail("tests/ui/fail/C-04-missing-constructor.rs"); - t.compile_fail("tests/ui/fail/C-10-async-constructor.rs"); - t.compile_fail("tests/ui/fail/C-11-unsafe-constructor.rs"); - t.compile_fail("tests/ui/fail/C-12-const-constructor.rs"); - t.compile_fail("tests/ui/fail/C-13-abi-constructor.rs"); - t.compile_fail("tests/ui/fail/C-14-payable-constructor.rs"); - t.compile_fail("tests/ui/fail/C-16-function-arg-struct-destructuring.rs"); + t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); + t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); + t.compile_fail("tests/ui/contract/fail/C-02-constructor-self-val.rs"); + t.compile_fail("tests/ui/contract/fail/C-03-constructor-missing-return.rs"); + t.compile_fail("tests/ui/contract/fail/C-04-missing-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/C-10-async-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/C-11-unsafe-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/C-12-const-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/C-13-abi-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/C-14-payable-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs"); - t.compile_fail("tests/ui/fail/H-01-invalid-dyn-alloc.rs"); - t.compile_fail("tests/ui/fail/H-02-invalid-as-dependency.rs"); - t.compile_fail("tests/ui/fail/H-03-use-forbidden-idents.rs"); + t.compile_fail("tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs"); + t.compile_fail("tests/ui/contract/fail/H-02-invalid-as-dependency.rs"); + t.compile_fail("tests/ui/contract/fail/H-03-use-forbidden-idents.rs"); - t.compile_fail("tests/ui/fail/M-01-missing-message.rs"); - t.compile_fail("tests/ui/fail/M-02-message-missing-self-arg.rs"); - t.compile_fail("tests/ui/fail/M-03-message-returns-self.rs"); - t.compile_fail("tests/ui/fail/M-04-message-returns-non-codec.rs"); - t.compile_fail("tests/ui/fail/M-05-message-invalid-selector.rs"); - t.compile_fail("tests/ui/fail/M-10-method-unknown-ink-marker.rs"); + t.compile_fail("tests/ui/contract/fail/M-01-missing-message.rs"); + t.compile_fail("tests/ui/contract/fail/M-02-message-missing-self-arg.rs"); + t.compile_fail("tests/ui/contract/fail/M-03-message-returns-self.rs"); + t.compile_fail("tests/ui/contract/fail/M-04-message-returns-non-codec.rs"); + t.compile_fail("tests/ui/contract/fail/M-05-message-invalid-selector.rs"); + t.compile_fail("tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs"); - t.compile_fail("tests/ui/fail/S-01-missing-storage-struct.rs"); - t.compile_fail("tests/ui/fail/S-02-multiple-storage-structs.rs"); - t.compile_fail("tests/ui/fail/S-03-struct-unknown-ink-marker.rs"); - t.compile_fail("tests/ui/fail/S-04-non-storage-ink-impls.rs"); - t.compile_fail("tests/ui/fail/S-05-storage-as-event.rs"); - t.compile_fail("tests/ui/fail/S-06-event-as-storage.rs"); + t.compile_fail("tests/ui/contract/fail/S-01-missing-storage-struct.rs"); + t.compile_fail("tests/ui/contract/fail/S-02-multiple-storage-structs.rs"); + t.compile_fail("tests/ui/contract/fail/S-03-struct-unknown-ink-marker.rs"); + t.compile_fail("tests/ui/contract/fail/S-04-non-storage-ink-impls.rs"); + t.compile_fail("tests/ui/contract/fail/S-05-storage-as-event.rs"); + t.compile_fail("tests/ui/contract/fail/S-06-event-as-storage.rs"); } #[test] diff --git a/crates/lang/macro/tests/ui/fail/C-00-constructor-self-ref.rs b/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-00-constructor-self-ref.rs rename to crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.rs diff --git a/crates/lang/macro/tests/ui/fail/C-00-constructor-self-ref.stderr b/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-00-constructor-self-ref.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-01-constructor-self-mut.rs b/crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-01-constructor-self-mut.rs rename to crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.rs diff --git a/crates/lang/macro/tests/ui/fail/C-01-constructor-self-mut.stderr b/crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-01-constructor-self-mut.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-02-constructor-self-val.rs b/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-02-constructor-self-val.rs rename to crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.rs diff --git a/crates/lang/macro/tests/ui/fail/C-02-constructor-self-val.stderr b/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-02-constructor-self-val.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-03-constructor-missing-return.rs b/crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-03-constructor-missing-return.rs rename to crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.rs diff --git a/crates/lang/macro/tests/ui/fail/C-03-constructor-missing-return.stderr b/crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-03-constructor-missing-return.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-04-missing-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-04-missing-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.rs diff --git a/crates/lang/macro/tests/ui/fail/C-04-missing-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-04-missing-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-10-async-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-10-async-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.rs diff --git a/crates/lang/macro/tests/ui/fail/C-10-async-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-10-async-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-11-unsafe-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-11-unsafe-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.rs diff --git a/crates/lang/macro/tests/ui/fail/C-11-unsafe-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-11-unsafe-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-12-const-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-12-const-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.rs diff --git a/crates/lang/macro/tests/ui/fail/C-12-const-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-12-const-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-13-abi-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-13-abi-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.rs diff --git a/crates/lang/macro/tests/ui/fail/C-13-abi-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-13-abi-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-14-payable-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-14-payable-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.rs diff --git a/crates/lang/macro/tests/ui/fail/C-14-payable-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-14-payable-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.stderr diff --git a/crates/lang/macro/tests/ui/fail/C-16-function-arg-struct-destructuring.rs b/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-16-function-arg-struct-destructuring.rs rename to crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs diff --git a/crates/lang/macro/tests/ui/fail/C-16-function-arg-struct-destructuring.stderr b/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/C-16-function-arg-struct-destructuring.stderr rename to crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.stderr diff --git a/crates/lang/macro/tests/ui/fail/H-01-invalid-dyn-alloc.rs b/crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/H-01-invalid-dyn-alloc.rs rename to crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs diff --git a/crates/lang/macro/tests/ui/fail/H-01-invalid-dyn-alloc.stderr b/crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/H-01-invalid-dyn-alloc.stderr rename to crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.stderr diff --git a/crates/lang/macro/tests/ui/fail/H-02-invalid-as-dependency.rs b/crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/H-02-invalid-as-dependency.rs rename to crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.rs diff --git a/crates/lang/macro/tests/ui/fail/H-02-invalid-as-dependency.stderr b/crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/H-02-invalid-as-dependency.stderr rename to crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.stderr diff --git a/crates/lang/macro/tests/ui/fail/H-03-use-forbidden-idents.rs b/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/H-03-use-forbidden-idents.rs rename to crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.rs diff --git a/crates/lang/macro/tests/ui/fail/H-03-use-forbidden-idents.stderr b/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/H-03-use-forbidden-idents.stderr rename to crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.stderr diff --git a/crates/lang/macro/tests/ui/fail/M-01-missing-message.rs b/crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-01-missing-message.rs rename to crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.rs diff --git a/crates/lang/macro/tests/ui/fail/M-01-missing-message.stderr b/crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-01-missing-message.stderr rename to crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.stderr diff --git a/crates/lang/macro/tests/ui/fail/M-02-message-missing-self-arg.rs b/crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-02-message-missing-self-arg.rs rename to crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.rs diff --git a/crates/lang/macro/tests/ui/fail/M-02-message-missing-self-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-02-message-missing-self-arg.stderr rename to crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.stderr diff --git a/crates/lang/macro/tests/ui/fail/M-03-message-returns-self.rs b/crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-03-message-returns-self.rs rename to crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.rs diff --git a/crates/lang/macro/tests/ui/fail/M-03-message-returns-self.stderr b/crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-03-message-returns-self.stderr rename to crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.stderr diff --git a/crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.rs b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.rs rename to crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs diff --git a/crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-04-message-returns-non-codec.stderr rename to crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr diff --git a/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.rs b/crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.rs rename to crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.rs diff --git a/crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.stderr b/crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-05-message-invalid-selector.stderr rename to crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.stderr diff --git a/crates/lang/macro/tests/ui/fail/M-10-method-unknown-ink-marker.rs b/crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-10-method-unknown-ink-marker.rs rename to crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs diff --git a/crates/lang/macro/tests/ui/fail/M-10-method-unknown-ink-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/M-10-method-unknown-ink-marker.stderr rename to crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.stderr diff --git a/crates/lang/macro/tests/ui/fail/S-01-missing-storage-struct.rs b/crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-01-missing-storage-struct.rs rename to crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.rs diff --git a/crates/lang/macro/tests/ui/fail/S-01-missing-storage-struct.stderr b/crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-01-missing-storage-struct.stderr rename to crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.stderr diff --git a/crates/lang/macro/tests/ui/fail/S-02-multiple-storage-structs.rs b/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-02-multiple-storage-structs.rs rename to crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.rs diff --git a/crates/lang/macro/tests/ui/fail/S-02-multiple-storage-structs.stderr b/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-02-multiple-storage-structs.stderr rename to crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.stderr diff --git a/crates/lang/macro/tests/ui/fail/S-03-struct-unknown-ink-marker.rs b/crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-03-struct-unknown-ink-marker.rs rename to crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.rs diff --git a/crates/lang/macro/tests/ui/fail/S-03-struct-unknown-ink-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-03-struct-unknown-ink-marker.stderr rename to crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.stderr diff --git a/crates/lang/macro/tests/ui/fail/S-04-non-storage-ink-impls.rs b/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-04-non-storage-ink-impls.rs rename to crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.rs diff --git a/crates/lang/macro/tests/ui/fail/S-04-non-storage-ink-impls.stderr b/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-04-non-storage-ink-impls.stderr rename to crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr diff --git a/crates/lang/macro/tests/ui/fail/S-05-storage-as-event.rs b/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-05-storage-as-event.rs rename to crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.rs diff --git a/crates/lang/macro/tests/ui/fail/S-05-storage-as-event.stderr b/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-05-storage-as-event.stderr rename to crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.stderr diff --git a/crates/lang/macro/tests/ui/fail/S-06-event-as-storage.rs b/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.rs similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-06-event-as-storage.rs rename to crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.rs diff --git a/crates/lang/macro/tests/ui/fail/S-06-event-as-storage.stderr b/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.stderr similarity index 100% rename from crates/lang/macro/tests/ui/fail/S-06-event-as-storage.stderr rename to crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.stderr diff --git a/crates/lang/macro/tests/ui/pass/01-noop-contract.rs b/crates/lang/macro/tests/ui/contract/pass/01-noop-contract.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/01-noop-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/01-noop-contract.rs diff --git a/crates/lang/macro/tests/ui/pass/02-flipper-contract.rs b/crates/lang/macro/tests/ui/contract/pass/02-flipper-contract.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/02-flipper-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/02-flipper-contract.rs diff --git a/crates/lang/macro/tests/ui/pass/03-incrementer-contract.rs b/crates/lang/macro/tests/ui/contract/pass/03-incrementer-contract.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/03-incrementer-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/03-incrementer-contract.rs diff --git a/crates/lang/macro/tests/ui/pass/04-erc20-contract.rs b/crates/lang/macro/tests/ui/contract/pass/04-erc20-contract.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/04-erc20-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/04-erc20-contract.rs diff --git a/crates/lang/macro/tests/ui/pass/05-erc721-contract.rs b/crates/lang/macro/tests/ui/contract/pass/05-erc721-contract.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/05-erc721-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/05-erc721-contract.rs diff --git a/crates/lang/macro/tests/ui/pass/06-non-ink-items.rs b/crates/lang/macro/tests/ui/contract/pass/06-non-ink-items.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/06-non-ink-items.rs rename to crates/lang/macro/tests/ui/contract/pass/06-non-ink-items.rs diff --git a/crates/lang/macro/tests/ui/pass/07-flipper-as-dependency.rs b/crates/lang/macro/tests/ui/contract/pass/07-flipper-as-dependency.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/07-flipper-as-dependency.rs rename to crates/lang/macro/tests/ui/contract/pass/07-flipper-as-dependency.rs diff --git a/crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs b/crates/lang/macro/tests/ui/contract/pass/08-flipper-as-dependency-trait.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/08-flipper-as-dependency-trait.rs rename to crates/lang/macro/tests/ui/contract/pass/08-flipper-as-dependency-trait.rs diff --git a/crates/lang/macro/tests/ui/pass/09-static-env.rs b/crates/lang/macro/tests/ui/contract/pass/09-static-env.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/09-static-env.rs rename to crates/lang/macro/tests/ui/contract/pass/09-static-env.rs diff --git a/crates/lang/macro/tests/ui/pass/10-derive-for-storage.rs b/crates/lang/macro/tests/ui/contract/pass/10-derive-for-storage.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/10-derive-for-storage.rs rename to crates/lang/macro/tests/ui/contract/pass/10-derive-for-storage.rs diff --git a/crates/lang/macro/tests/ui/pass/11-alias-storage-struct-impl.rs b/crates/lang/macro/tests/ui/contract/pass/11-alias-storage-struct-impl.rs similarity index 100% rename from crates/lang/macro/tests/ui/pass/11-alias-storage-struct-impl.rs rename to crates/lang/macro/tests/ui/contract/pass/11-alias-storage-struct-impl.rs From 9093e36cd411098de8738b7fd8ca8232c095a178 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 18 Sep 2021 13:19:52 +0200 Subject: [PATCH 208/493] fix error message --- crates/lang/ir/src/ir/item_impl/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/item_impl/mod.rs b/crates/lang/ir/src/ir/item_impl/mod.rs index b3d16cd09e..6f8f9dc8e0 100644 --- a/crates/lang/ir/src/ir/item_impl/mod.rs +++ b/crates/lang/ir/src/ir/item_impl/mod.rs @@ -218,7 +218,7 @@ impl TryFrom for ItemImpl { if !Self::is_ink_impl_block(&item_impl)? { return Err(format_err_spanned!( item_impl, - "missing ink! annotations on 16 kB block or on any of its items" + "missing ink! annotations on implementation block or on any of its items" )) } if let Some(defaultness) = item_impl.defaultness { From d31d996a7aeb4aac61e04eb3094d03006a4034cf Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 18 Sep 2021 14:36:10 +0200 Subject: [PATCH 209/493] try to fix formatting CI with new UI test folder structure --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c84a50e259..087277360e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -287,7 +287,7 @@ fmt: script: - cargo fmt --verbose --all -- --check # For the UI tests we need to disable the license check - - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/macro/tests/ui/{pass,fail}/*.rs + - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/macro/tests/ui/**.rs #### stage: examples From cb6b96f2b596945a5a2c67c7a922640eae1685d1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 18 Sep 2021 14:57:41 +0200 Subject: [PATCH 210/493] fix UI test formatting in CI (2) --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 087277360e..6bcfe78934 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -287,7 +287,8 @@ fmt: script: - cargo fmt --verbose --all -- --check # For the UI tests we need to disable the license check - - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/macro/tests/ui/**.rs + - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/macro/tests/ui/contract/{pass,fail}/*.rs + - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/macro/tests/ui/trait_def/{pass,fail}/*.rs #### stage: examples From 5028cfb75ec2b034c86c98a3aae71096b9009bf5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 19 Sep 2021 18:54:55 +0200 Subject: [PATCH 211/493] fix contract example --- examples/contract-transfer/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/contract-transfer/lib.rs b/examples/contract-transfer/lib.rs index f42e55a54a..5c9279ad32 100644 --- a/examples/contract-transfer/lib.rs +++ b/examples/contract-transfer/lib.rs @@ -69,7 +69,7 @@ pub mod give_me { /// /// The method needs to be annotated with `payable`; only then it is /// allowed to receive value as part of the call. - #[ink(message, payable, selector = "0xCAFEBABE")] + #[ink(message, payable, selector = 0xCAFEBABE)] pub fn was_it_ten(&self) { ink_env::debug_println!( "received payment: {}", From ac3c26fd8d79f036ecb4188b913f444bd614489a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 19 Sep 2021 19:08:11 +0200 Subject: [PATCH 212/493] fix more custom selectors in contract examples --- examples/erc1155/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index 67ac9d2d55..d730346242 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -562,7 +562,7 @@ mod erc1155 { } impl super::Erc1155TokenReceiver for Contract { - #[ink(message, selector = "0xF23A6E61")] + #[ink(message, selector = 0xF23A6E61)] fn on_received( &mut self, _operator: AccountId, @@ -582,7 +582,7 @@ mod erc1155 { unimplemented!("This smart contract does not accept token transfer.") } - #[ink(message, selector = "0xBC197C81")] + #[ink(message, selector = 0xBC197C81)] fn on_batch_received( &mut self, _operator: AccountId, From fcc50de220e70d726ceb099f50d0deb577d057f2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 19 Sep 2021 23:15:01 +0200 Subject: [PATCH 213/493] silence clippy warnings --- examples/trait-incrementer/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/trait-incrementer/lib.rs b/examples/trait-incrementer/lib.rs index 1a861a1066..1860605562 100644 --- a/examples/trait-incrementer/lib.rs +++ b/examples/trait-incrementer/lib.rs @@ -13,6 +13,7 @@ // limitations under the License. #![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::new_without_default)] use ink_lang as ink; From 031f4d3b4c4b9b5c4e75763d8dc697bf9a625c28 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Sep 2021 15:28:51 +0200 Subject: [PATCH 214/493] remove unused InkTraitConstructor type definition --- crates/lang/ir/src/ir/mod.rs | 1 - crates/lang/ir/src/ir/trait_def/item/mod.rs | 1 - .../ir/src/ir/trait_def/item/trait_item.rs | 78 ------------------- crates/lang/ir/src/ir/trait_def/mod.rs | 1 - crates/lang/ir/src/lib.rs | 1 - 5 files changed, 82 deletions(-) diff --git a/crates/lang/ir/src/ir/mod.rs b/crates/lang/ir/src/ir/mod.rs index c2a455ac50..b1dbf78810 100644 --- a/crates/lang/ir/src/ir/mod.rs +++ b/crates/lang/ir/src/ir/mod.rs @@ -86,7 +86,6 @@ pub use self::{ }, trait_def::{ InkItemTrait, - InkTraitConstructor, InkTraitDefinition, InkTraitItem, InkTraitMessage, diff --git a/crates/lang/ir/src/ir/trait_def/item/mod.rs b/crates/lang/ir/src/ir/trait_def/item/mod.rs index f183ebed15..906b331a75 100644 --- a/crates/lang/ir/src/ir/trait_def/item/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/item/mod.rs @@ -19,7 +19,6 @@ use self::iter::IterInkTraitItemsRaw; pub use self::{ iter::IterInkTraitItems, trait_item::{ - InkTraitConstructor, InkTraitItem, InkTraitMessage, }, diff --git a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs index e316db828b..97a59b31ba 100644 --- a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs @@ -53,78 +53,6 @@ impl<'a> InkTraitItem<'a> { } } -/// A checked ink! constructor of an ink! trait definition. -#[derive(Debug, Clone)] -pub struct InkTraitConstructor<'a> { - item: &'a syn::TraitItemMethod, -} - -impl<'a> InkTraitConstructor<'a> { - /// Panic message in case a user encounters invalid attributes. - const INVALID_ATTRIBUTES_ERRSTR: &'static str = - "encountered invalid attributes for ink! trait constructor"; - - /// Creates a new ink! trait definition constructor. - pub(super) fn new(item: &'a syn::TraitItemMethod) -> Self { - Self { item } - } - - /// Analyses and extracts the ink! and non-ink! attributes of an ink! trait constructor. - pub(super) fn extract_attributes( - span: Span, - attrs: &[syn::Attribute], - ) -> Result<(InkAttribute, Vec)> { - let (ink_attrs, non_ink_attrs) = ir::sanitize_attributes( - span, - attrs.iter().cloned(), - &ir::AttributeArgKind::Constructor, - |arg| { - match arg.kind() { - ir::AttributeArg::Constructor | ir::AttributeArg::Selector(_) => { - Ok(()) - } - _ => Err(None), - } - }, - )?; - Ok((ink_attrs, non_ink_attrs)) - } - - /// Returns all non-ink! attributes. - pub fn attrs(&self) -> Vec { - let (_, rust_attrs) = Self::extract_attributes(self.span(), &self.item.attrs) - .expect(Self::INVALID_ATTRIBUTES_ERRSTR); - rust_attrs - } - - /// Returns all ink! attributes. - pub fn ink_attrs(&self) -> InkAttribute { - let (ink_attrs, _) = Self::extract_attributes(self.span(), &self.item.attrs) - .expect(Self::INVALID_ATTRIBUTES_ERRSTR); - ink_attrs - } - - /// Returns the original signature of the ink! constructor. - pub fn sig(&self) -> &syn::Signature { - &self.item.sig - } - - /// Returns an iterator over the inputs of the ink! trait message. - pub fn inputs(&self) -> InputsIter { - InputsIter::from(self) - } - - /// Returns the Rust identifier of the ink! constructor. - pub fn ident(&self) -> &syn::Ident { - &self.item.sig.ident - } - - /// Returns the span of the ink! constructor. - pub fn span(&self) -> Span { - self.item.span() - } -} - /// A checked ink! message of an ink! trait definition. #[derive(Debug, Clone)] pub struct InkTraitMessage<'a> { @@ -252,9 +180,3 @@ impl<'a> From<&'a InkTraitMessage<'a>> for InputsIter<'a> { Self::new(&message.item.sig.inputs) } } - -impl<'a> From<&'a InkTraitConstructor<'a>> for InputsIter<'a> { - fn from(constructor: &'a InkTraitConstructor) -> Self { - Self::new(&constructor.item.sig.inputs) - } -} diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index a5817cd47f..b2bf05d6d8 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -22,7 +22,6 @@ pub use self::{ config::TraitDefinitionConfig, item::{ InkItemTrait, - InkTraitConstructor, InkTraitItem, InkTraitMessage, IterInkTraitItems, diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index 7f8c4f39ac..6cd2db198b 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -50,7 +50,6 @@ pub use self::{ InkItem, InkItemTrait, InkTest, - InkTraitConstructor, InkTraitDefinition, InkTraitItem, InkTraitMessage, From 4b508f48498142e257120e33326803c329395d6b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Sep 2021 15:45:55 +0200 Subject: [PATCH 215/493] add ink! trait message local ID utility method This is required in order to add compile time information about ink! trait messages that can be queried by ink! trait definition implementers (smart contracts) later on. The querying is required so that the smart contract is able to verify selectors and payable properties of its implemented ink! trait messages. Also the user might safety guard against changes to the selector or payable property that can be validated by this means. --- .../lang/ir/src/ir/trait_def/item/trait_item.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs index 97a59b31ba..934842790e 100644 --- a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs @@ -144,6 +144,22 @@ impl<'a> InkTraitMessage<'a> { &self.item.sig.ident } + /// Returns a local ID unique to the ink! trait definition of the ink! trait message. + /// + /// # Note + /// + /// It is a compile error if two ink! trait messages share the same local ID. + /// Although the above scenario is very unlikely since the local ID is computed + /// solely by the identifier of the ink! message. + pub fn local_id(&self) -> u32 { + let buffer = format!("message::{}", self.ident()).into_bytes(); + use blake2::digest::generic_array::sequence::Split as _; + let (head_32, _rest) = + ::digest(&buffer).split(); + let head_32: [u8; 4] = head_32.into(); + u32::from_be_bytes(head_32) + } + /// Returns the span of the ink! message. pub fn span(&self) -> Span { self.item.span() From d14b6562798ee9759d342eca597da2edec4506f4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 20 Sep 2021 16:13:00 +0200 Subject: [PATCH 216/493] revisit ink_lang::TraitMessageInfo trait It now works given an ink! trait definition unique ID of each ink! trait message in order to store information that can be queried by ink! implementation blocks. --- crates/lang/src/traits.rs | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 1503b163cf..5df25d70d4 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -263,10 +263,10 @@ pub trait TraitCallForwarderFor { fn build_mut(&mut self) -> &mut ::Builder; } -/// Stores information per trait message. +/// Stores information for every ink! trait message of an ink! trait definition. /// -/// This information includes if the ink! trait message has been -/// annotated with `#[ink(payable)]`. +/// This information includes if the ink! trait message is payable +/// as well as its derived or manually specified selector. /// /// In the future this info trait might be extended to contain /// more information about a single ink! trait message. @@ -279,14 +279,25 @@ pub trait TraitCallForwarderFor { /// /// # Note /// -/// - The `TRAIT_ID` is the `u32` identifier uniquely identifying the -/// ink! trait. -/// - The `MSG_ID` is the `u32` identifier derived from the selector -/// that uniquely identifies the message. -pub trait TraitMessageInfo { +/// - The `TraitMessageInfo` is implemented by the +/// automatically generated ink! trait definition information object +/// associated to the ink! trait definition at hand. +/// - For every ink! trait message defined by the ink! trait definition +/// the associated ink! trait definition information object implements +/// this trait given the `TRAIT_LOCAL_MESSAGE_ID` of each ink! trait +/// message respectively. +/// - The local IDs uniquely identifying all the ink! trait messages +/// of the ink! trait definition are computed solely using the Rust +/// identifier of the ink! trait message which can be derived from +/// ink! implementation blocks in order to query the information +/// stored by this ink! trait information object trait implementation. +pub trait TraitMessageInfo { /// Is `true` if the ink! trait message has been annotated with `#[ink(payable)]`. const PAYABLE: bool; /// The unique selector of the ink! trait message. + /// + /// This might have been adjusted using `#[ink(selector = N:u32)]` at the + /// ink! trait definition site. const SELECTOR: [u8; 4]; } From 786976e93896e010396ac5900976e88b8d2f3174 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 08:51:19 +0200 Subject: [PATCH 217/493] use version 2 of parity-scale-info across the entire workspace --- crates/engine/Cargo.toml | 2 +- crates/env/Cargo.toml | 2 +- crates/lang/Cargo.toml | 2 +- crates/lang/codegen/Cargo.toml | 2 +- crates/lang/macro/Cargo.toml | 2 +- crates/primitives/Cargo.toml | 2 +- crates/storage/Cargo.toml | 2 +- crates/storage/derive/Cargo.toml | 2 +- examples/contract-terminate/Cargo.toml | 2 +- examples/contract-transfer/Cargo.toml | 2 +- examples/delegator/Cargo.toml | 2 +- examples/delegator/accumulator/Cargo.toml | 2 +- examples/delegator/adder/Cargo.toml | 2 +- examples/delegator/subber/Cargo.toml | 2 +- examples/dns/Cargo.toml | 2 +- examples/erc1155/Cargo.toml | 2 +- examples/erc20/Cargo.toml | 2 +- examples/erc721/Cargo.toml | 2 +- examples/flipper/Cargo.toml | 2 +- examples/incrementer/Cargo.toml | 2 +- examples/multisig_plain/Cargo.toml | 2 +- examples/rand-extension/Cargo.toml | 2 +- examples/trait-erc20/Cargo.toml | 2 +- examples/trait-flipper/Cargo.toml | 2 +- examples/trait-incrementer/Cargo.toml | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/crates/engine/Cargo.toml b/crates/engine/Cargo.toml index 2648622d3d..dcc9530842 100644 --- a/crates/engine/Cargo.toml +++ b/crates/engine/Cargo.toml @@ -15,7 +15,7 @@ categories = ["no-std", "embedded"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"] [dependencies] -scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } derive_more = { version = "0.99", default-features = false, features = ["from", "display"] } sha2 = { version = "0.9" } diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml index e9ec3eaeb9..6a6e0fcc83 100644 --- a/crates/env/Cargo.toml +++ b/crates/env/Cargo.toml @@ -21,7 +21,7 @@ ink_allocator = { version = "3.0.0-rc5", path = "../allocator/", default-feature ink_primitives = { version = "3.0.0-rc5", path = "../primitives/", default-features = false } ink_prelude = { version = "3.0.0-rc5", path = "../prelude/", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } derive_more = { version = "0.99", default-features = false, features = ["from", "display"] } num-traits = { version = "0.2", default-features = false, features = ["i128"] } cfg-if = "1.0" diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index 5d8809cf48..0a91a88fd4 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -22,7 +22,7 @@ ink_metadata = { version = "3.0.0-rc5", path = "../metadata", default-features = ink_prelude = { version = "3.0.0-rc5", path = "../prelude", default-features = false } ink_lang_macro = { version = "3.0.0-rc5", path = "macro", default-features = false } -scale = { package = "parity-scale-codec", version = "2.2", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } derive_more = { version = "0.99", default-features = false, features = ["from"] } static_assertions = "1.1" diff --git a/crates/lang/codegen/Cargo.toml b/crates/lang/codegen/Cargo.toml index 43b961836b..0262115943 100644 --- a/crates/lang/codegen/Cargo.toml +++ b/crates/lang/codegen/Cargo.toml @@ -27,7 +27,7 @@ itertools = "0.10" either = { version = "1.5", default-features = false } blake2 = "0.9" heck = "0.3.1" -scale = { package = "parity-scale-codec", version = "2.2", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } impl-serde = "0.3.1" [features] diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index 44894a9e62..29cc59537d 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -19,7 +19,7 @@ ink_lang_ir = { version = "3.0.0-rc5", path = "../ir", default-features = false ink_lang_codegen = { version = "3.0.0-rc5", path = "../codegen", default-features = false } ink_primitives = { version = "3.0.0-rc5", path = "../../primitives/", default-features = false } -scale = { package = "parity-scale-codec", version = "2.2", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } syn = "1" proc-macro2 = "1" diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 72c1e473f9..6939af1974 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -16,7 +16,7 @@ include = ["/Cargo.toml", "src/**/*.rs", "/README.md", "/LICENSE"] [dependencies] ink_prelude = { version = "3.0.0-rc5", path = "../prelude/", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [dev-dependencies] diff --git a/crates/storage/Cargo.toml b/crates/storage/Cargo.toml index f3c3d22ecb..864b01f50f 100644 --- a/crates/storage/Cargo.toml +++ b/crates/storage/Cargo.toml @@ -21,7 +21,7 @@ ink_primitives = { version = "3.0.0-rc5", path = "../primitives/", default-featu ink_storage_derive = { version = "3.0.0-rc5", path = "derive", default-features = false } ink_prelude = { version = "3.0.0-rc5", path = "../prelude/", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } derive_more = { version = "0.99", default-features = false, features = ["from", "display"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } cfg-if = "1.0" diff --git a/crates/storage/derive/Cargo.toml b/crates/storage/derive/Cargo.toml index 0b2ecc8490..72c57f81e5 100644 --- a/crates/storage/derive/Cargo.toml +++ b/crates/storage/derive/Cargo.toml @@ -24,7 +24,7 @@ proc-macro2 = "1.0" synstructure = "0.12.4" [dev-dependencies] -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive", "full"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } ink_env = { version = "3.0.0-rc5", path = "../../env" } ink_primitives = { version = "3.0.0-rc5", path = "../../primitives" } ink_metadata = { version = "3.0.0-rc5", path = "../../metadata" } diff --git a/examples/contract-terminate/Cargo.toml b/examples/contract-terminate/Cargo.toml index f36a4608c3..3a29788df2 100644 --- a/examples/contract-terminate/Cargo.toml +++ b/examples/contract-terminate/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/contract-transfer/Cargo.toml b/examples/contract-transfer/Cargo.toml index 8d17550e54..159fbe7fb5 100644 --- a/examples/contract-transfer/Cargo.toml +++ b/examples/contract-transfer/Cargo.toml @@ -12,7 +12,7 @@ ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-fe ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } ink_prelude = { version = "3.0.0-rc5", path = "../../crates/prelude", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/delegator/Cargo.toml b/examples/delegator/Cargo.toml index c819352265..9d6398c236 100644 --- a/examples/delegator/Cargo.toml +++ b/examples/delegator/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } adder = { version = "3.0.0-rc5", path = "adder", default-features = false, features = ["ink-as-dependency"] } subber = { version = "3.0.0-rc5", path = "subber", default-features = false, features = ["ink-as-dependency"] } diff --git a/examples/delegator/accumulator/Cargo.toml b/examples/delegator/accumulator/Cargo.toml index c203f7adbf..d311cc44fc 100644 --- a/examples/delegator/accumulator/Cargo.toml +++ b/examples/delegator/accumulator/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../../crates/env", default-feature ink_storage = { version = "3.0.0-rc5", path = "../../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/delegator/adder/Cargo.toml b/examples/delegator/adder/Cargo.toml index b8d26d7871..0f7653fb04 100644 --- a/examples/delegator/adder/Cargo.toml +++ b/examples/delegator/adder/Cargo.toml @@ -13,7 +13,7 @@ ink_lang = { version = "3.0.0-rc5", path = "../../../crates/lang", default-featu accumulator = { version = "3.0.0-rc5", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/delegator/subber/Cargo.toml b/examples/delegator/subber/Cargo.toml index ce56559368..9bab0c8df3 100644 --- a/examples/delegator/subber/Cargo.toml +++ b/examples/delegator/subber/Cargo.toml @@ -13,7 +13,7 @@ ink_lang = { version = "3.0.0-rc5", path = "../../../crates/lang", default-featu accumulator = { version = "3.0.0-rc5", path = "../accumulator", default-features = false, features = ["ink-as-dependency"] } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/dns/Cargo.toml b/examples/dns/Cargo.toml index 3274d9d44e..b993f92b64 100644 --- a/examples/dns/Cargo.toml +++ b/examples/dns/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/erc1155/Cargo.toml b/examples/erc1155/Cargo.toml index d31b3dfa1e..e319c3e702 100644 --- a/examples/erc1155/Cargo.toml +++ b/examples/erc1155/Cargo.toml @@ -12,7 +12,7 @@ ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-fe ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } ink_prelude = { version = "3.0.0-rc5", path = "../../crates/prelude", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/erc20/Cargo.toml b/examples/erc20/Cargo.toml index 4e1b596bc5..6f010abaa4 100644 --- a/examples/erc20/Cargo.toml +++ b/examples/erc20/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/erc721/Cargo.toml b/examples/erc721/Cargo.toml index c8f9987416..07e14c3a42 100644 --- a/examples/erc721/Cargo.toml +++ b/examples/erc721/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/flipper/Cargo.toml b/examples/flipper/Cargo.toml index 309736b43a..f15018b624 100644 --- a/examples/flipper/Cargo.toml +++ b/examples/flipper/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/incrementer/Cargo.toml b/examples/incrementer/Cargo.toml index 45c5cc3feb..e967be9b7b 100644 --- a/examples/incrementer/Cargo.toml +++ b/examples/incrementer/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/multisig_plain/Cargo.toml b/examples/multisig_plain/Cargo.toml index 582e34e2ae..8097d9a090 100755 --- a/examples/multisig_plain/Cargo.toml +++ b/examples/multisig_plain/Cargo.toml @@ -12,7 +12,7 @@ ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-fe ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } ink_prelude = { version = "3.0.0-rc5", path = "../../crates/prelude", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/rand-extension/Cargo.toml b/examples/rand-extension/Cargo.toml index 2f479989a7..edd4fa0abf 100755 --- a/examples/rand-extension/Cargo.toml +++ b/examples/rand-extension/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { path = "../../crates/env", default-features = false } ink_storage = { path = "../../crates/storage", default-features = false } ink_lang = { path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/trait-erc20/Cargo.toml b/examples/trait-erc20/Cargo.toml index 2f8faedcae..2921853c4f 100644 --- a/examples/trait-erc20/Cargo.toml +++ b/examples/trait-erc20/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/trait-flipper/Cargo.toml b/examples/trait-flipper/Cargo.toml index b6f1d932ca..5d2f2046ca 100644 --- a/examples/trait-flipper/Cargo.toml +++ b/examples/trait-flipper/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] diff --git a/examples/trait-incrementer/Cargo.toml b/examples/trait-incrementer/Cargo.toml index ded9335080..9f4bab4104 100644 --- a/examples/trait-incrementer/Cargo.toml +++ b/examples/trait-incrementer/Cargo.toml @@ -11,7 +11,7 @@ ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -scale = { package = "parity-scale-codec", version = "2.1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } scale-info = { version = "0.6", default-features = false, features = ["derive"], optional = true } [lib] From 2f4de5fcc04e9923aae1c9cccdef8297b29be460 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 09:37:58 +0200 Subject: [PATCH 218/493] check that argument in #[ink(namespace = "argument")] is a Rust identifier --- crates/lang/ir/src/ir/attrs.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index e85a54b940..d21f874c36 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -818,11 +818,16 @@ impl TryFrom for AttributeFrag { } if name_value.path.is_ident("namespace") { if let syn::Lit::Str(lit_str) = &name_value.lit { - let bytes = lit_str.value().into_bytes(); + let argument = lit_str.value(); + syn::parse_str::(&argument) + .map_err(|_error| format_err!( + lit_str, + "encountered invalid non-Rust identifier for namespace argument", + ))?; return Ok(AttributeFrag { ast: meta, arg: AttributeArg::Namespace( - Namespace::from(bytes), + Namespace::from(argument.into_bytes()), ), }) } @@ -1150,6 +1155,16 @@ mod tests { ); } + #[test] + fn namespace_invalid_identifier() { + assert_attribute_try_from( + syn::parse_quote! { + #[ink(namespace = "::invalid_identifier")] + }, + Err("encountered invalid non-Rust identifier for namespace argument"), + ); + } + #[test] fn namespace_invalid_type() { assert_attribute_try_from( From e3b619c73a0dcadb1e4065aa4d056ac4f45f79fc Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 09:49:47 +0200 Subject: [PATCH 219/493] add UI tests for #[ink(namespace = "..")] ink! property --- crates/lang/macro/tests/compile_tests.rs | 4 ++++ .../fail/N-01-namespace-invalid-identifier.rs | 20 +++++++++++++++++++ .../N-01-namespace-invalid-identifier.stderr | 5 +++++ .../fail/N-02-namespace-invalid-type.rs | 20 +++++++++++++++++++ .../fail/N-02-namespace-invalid-type.stderr | 5 +++++ .../fail/N-03-namespace-missing-argument.rs | 20 +++++++++++++++++++ .../N-03-namespace-missing-argument.stderr | 5 +++++ 7 files changed, 79 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index a2b40a76db..07ceaef379 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -57,6 +57,10 @@ fn contract() { t.compile_fail("tests/ui/contract/fail/S-04-non-storage-ink-impls.rs"); t.compile_fail("tests/ui/contract/fail/S-05-storage-as-event.rs"); t.compile_fail("tests/ui/contract/fail/S-06-event-as-storage.rs"); + + t.compile_fail("tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs"); + t.compile_fail("tests/ui/contract/fail/N-02-namespace-invalid-type.rs"); + t.compile_fail("tests/ui/contract/fail/N-03-namespace-missing-argument.rs"); } #[test] diff --git a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs b/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs new file mode 100644 index 0000000000..21d08c2d3d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs @@ -0,0 +1,20 @@ +use ink_lang as ink; + +#[ink::contract] +mod invalid_namespace_identifier { + #[ink(storage)] + pub struct MyStorage {} + + #[ink(namespace = "::invalid_identifier")] + impl MyStorage { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr b/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr new file mode 100644 index 0000000000..77219460e1 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr @@ -0,0 +1,5 @@ +error: encountered invalid non-Rust identifier for namespace argument + --> $DIR/N-01-namespace-invalid-identifier.rs:8:23 + | +8 | #[ink(namespace = "::invalid_identifier")] + | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.rs b/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.rs new file mode 100644 index 0000000000..60871df1e5 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.rs @@ -0,0 +1,20 @@ +use ink_lang as ink; + +#[ink::contract] +mod invalid_namespace_identifier { + #[ink(storage)] + pub struct MyStorage {} + + #[ink(namespace = true)] + impl MyStorage { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr b/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr new file mode 100644 index 0000000000..aed0beed38 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr @@ -0,0 +1,5 @@ +error: expecteded string type for `namespace` argument, e.g. #[ink(namespace = "hello")] + --> $DIR/N-02-namespace-invalid-type.rs:8:11 + | +8 | #[ink(namespace = true)] + | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.rs b/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.rs new file mode 100644 index 0000000000..a4af79c249 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.rs @@ -0,0 +1,20 @@ +use ink_lang as ink; + +#[ink::contract] +mod invalid_namespace_identifier { + #[ink(storage)] + pub struct MyStorage {} + + #[ink(namespace)] + impl MyStorage { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.stderr b/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.stderr new file mode 100644 index 0000000000..e5298677d2 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.stderr @@ -0,0 +1,5 @@ +error: encountered #[ink(namespace)] that is missing its string parameter. Did you mean #[ink(namespace = name: str)] ? + --> $DIR/N-03-namespace-missing-argument.rs:8:11 + | +8 | #[ink(namespace)] + | ^^^^^^^^^ From 049fa9ec1527048704a6f0d3de5549a0590a74c5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 11:30:42 +0200 Subject: [PATCH 220/493] fix UI test --- .../ui/contract/fail/N-01-namespace-invalid-identifier.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr b/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr index 77219460e1..8e3bacd08e 100644 --- a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr @@ -1,4 +1,4 @@ -error: encountered invalid non-Rust identifier for namespace argument +error: encountered invalid Rust identifier for namespace argument --> $DIR/N-01-namespace-invalid-identifier.rs:8:23 | 8 | #[ink(namespace = "::invalid_identifier")] From 4950267cbdce358db3e4340a4150cd4d67369552 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 12:45:24 +0200 Subject: [PATCH 221/493] use impl_as_ref_for_generator macro where possible --- crates/lang/codegen/src/generator/as_dependency/mod.rs | 7 +------ crates/lang/codegen/src/generator/contract.rs | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/mod.rs b/crates/lang/codegen/src/generator/as_dependency/mod.rs index 2c6da30819..4a6acacadb 100644 --- a/crates/lang/codegen/src/generator/as_dependency/mod.rs +++ b/crates/lang/codegen/src/generator/as_dependency/mod.rs @@ -79,12 +79,7 @@ pub struct ContractReference<'a> { /// The contract to generate code for. contract: &'a ir::Contract, } - -impl AsRef for ContractReference<'_> { - fn as_ref(&self) -> &ir::Contract { - self.contract - } -} +impl_as_ref_for_generator!(ContractReference); impl GenerateCode for ContractReference<'_> { /// Generates ink! contract code. diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index eb0f7e18ad..4e8da7365b 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -27,12 +27,7 @@ pub struct Contract<'a> { /// The contract to generate code for. contract: &'a ir::Contract, } - -impl AsRef for Contract<'_> { - fn as_ref(&self) -> &ir::Contract { - self.contract - } -} +impl_as_ref_for_generator!(Contract); impl GenerateCode for Contract<'_> { /// Generates ink! contract code. From 2244a013d3ddf17da02d3822e76941311d1538b6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 12:54:04 +0200 Subject: [PATCH 222/493] move enforced_error.rs into root module --- .../lang/codegen/src/{generator => }/enforced_error.rs | 0 crates/lang/codegen/src/generator/mod.rs | 1 - .../codegen/src/generator/trait_def/trait_registry.rs | 6 ++---- crates/lang/codegen/src/lib.rs | 10 +++++++--- 4 files changed, 9 insertions(+), 8 deletions(-) rename crates/lang/codegen/src/{generator => }/enforced_error.rs (100%) diff --git a/crates/lang/codegen/src/generator/enforced_error.rs b/crates/lang/codegen/src/enforced_error.rs similarity index 100% rename from crates/lang/codegen/src/generator/enforced_error.rs rename to crates/lang/codegen/src/enforced_error.rs diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 0dbb5fdc68..99862e31ea 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -31,7 +31,6 @@ mod as_dependency; mod chain_extension; mod contract; mod dispatch; -mod enforced_error; mod env; mod events; mod ink_test; diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 8c93848410..6a431ff0db 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -21,11 +21,9 @@ use super::TraitDefinition; use crate::{ - generator::{ - self, - enforced_error::EnforcedErrors, - }, + generator::{self,}, traits::GenerateCode, + EnforcedErrors, }; use derive_more::From; use ir::HexLiteral; diff --git a/crates/lang/codegen/src/lib.rs b/crates/lang/codegen/src/lib.rs index 26403fd46d..486159e079 100644 --- a/crates/lang/codegen/src/lib.rs +++ b/crates/lang/codegen/src/lib.rs @@ -12,12 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod enforced_error; mod generator; mod traits; -use self::traits::{ - GenerateCode, - GenerateCodeUsing, +use self::{ + enforced_error::EnforcedErrors, + traits::{ + GenerateCode, + GenerateCodeUsing, + }, }; use proc_macro2::TokenStream as TokenStream2; From 355c3b637f05976a7a609a71ddf86dd3098d2a94 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 16:13:13 +0200 Subject: [PATCH 223/493] re-export TraitMessageInfo codegen utility trait --- crates/lang/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index bf549534bd..9feb9781e4 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -86,6 +86,7 @@ pub use self::{ TraitCallForwarderFor, TraitCallForwarderRegistry, TraitImplementer, + TraitMessageInfo, TraitModulePath, TraitUniqueId, True, From 872c1f48f9ff6670d88a1b8c1bdfa6dd7e3629fa Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 16:15:06 +0200 Subject: [PATCH 224/493] implement codegen for TraitMessageInfo trait for all ink! trait messages The generated ink! trait definition info object implements the ink_lang::TraitMessageInfo trait for every ink! message defined by the ink! trait definition that it is associated with using the trait local ink! message ID. The ink_lang::TraitMessageInfo trait contains properties about the ink! message defined by the ink! trait definition such as payability and its selector. Those properties can then be queried using the Rust type system by other parts of the ink! codegen. --- .../src/generator/trait_def/trait_registry.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 6a431ff0db..19641572c0 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -201,6 +201,7 @@ impl TraitRegistry<'_> { let unique_id = self.trait_def.trait_def.id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let trait_call_forwarder = self.trait_def.call_forwarder_ident(); + let trait_message_info = self.generate_info_for_trait_messages(); quote_spanned!(span => #[doc(hidden)] #[allow(non_camel_case_types)] @@ -208,6 +209,8 @@ impl TraitRegistry<'_> { marker: ::core::marker::PhantomData E>, } + #trait_message_info + unsafe impl ::ink_lang::TraitImplementer<#unique_id> for #trait_info_ident where @@ -239,4 +242,41 @@ impl TraitRegistry<'_> { } ) } + + /// Generates the [`::ink_lang::TraitMessageInfo`] implementations for all + /// ink! messages defined by the ink! trait definition. + fn generate_info_for_trait_messages(&self) -> TokenStream2 { + let span = self.span(); + let message_impls = self.trait_def.trait_def.item().iter_items().filter_map( + |(trait_item, selector)| { + trait_item.filter_map_message().map(|message| { + self.generate_info_for_trait_for_message(&message, selector) + }) + }, + ); + quote_spanned!(span=> + #( #message_impls )* + ) + } + + /// Generates the [`::ink_lang::TraitMessageInfo`] implementation for a single + /// ink! message defined by the ink! trait definition. + fn generate_info_for_trait_for_message( + &self, + message: &ir::InkTraitMessage, + selector: ir::Selector, + ) -> TokenStream2 { + let span = message.span(); + let trait_info_ident = self.trait_def.trait_info_ident(); + let local_id = message.local_id(); + let selector_bytes = selector.hex_lits(); + let is_payable = message.ink_attrs().is_payable(); + quote_spanned!(span=> + impl ::ink_lang::TraitMessageInfo<#local_id> for #trait_info_ident { + const PAYABLE: ::core::primitive::bool = #is_payable; + + const SELECTOR: [::core::primitive::u8; 4usize] = [ #( #selector_bytes ),* ]; + } + ) + } } From 59be012b6ac6e01efb5d3b38b77fbfb74c94e3af Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 20:29:28 +0200 Subject: [PATCH 225/493] clean up IterInkTraitItems --- crates/lang/ir/src/ir/trait_def/item/iter.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def/item/iter.rs b/crates/lang/ir/src/ir/trait_def/item/iter.rs index c967a19082..38a5acd263 100644 --- a/crates/lang/ir/src/ir/trait_def/item/iter.rs +++ b/crates/lang/ir/src/ir/trait_def/item/iter.rs @@ -85,12 +85,9 @@ impl<'a> Iterator for IterInkTraitItems<'a> { type Item = (InkTraitItem<'a>, Selector); fn next(&mut self) -> Option { - match self.iter.next() { - None => None, - Some(item @ InkTraitItem::Message(_)) => { - let selector = self.message_selectors[item.ident()]; - Some((item, selector)) - } - } + self.iter.next().map(|item| { + let selector = self.message_selectors[item.ident()]; + (item, selector) + }) } } From 898af50985f44d29cb427a2d2199bd7aeca82bb5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 21 Sep 2021 20:29:53 +0200 Subject: [PATCH 226/493] add missing UI test guard --- .../M-04-message-returns-non-codec.stderr | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr new file mode 100644 index 0000000000..712a3111c8 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr @@ -0,0 +1,26 @@ +error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied + --> $DIR/M-04-message-returns-non-codec.rs:18:49 + | +18 | pub fn returns_non_codec_type(&self) -> NonCodec { + | ^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` + | + = note: required because of the requirements on the impl of `Encode` for `NonCodec` +note: required by a bound in `ink_lang::FnOutput::Output` + --> $DIR/traits.rs:80:18 + | +80 | type Output: scale::Encode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `ink_lang::FnOutput::Output` + +error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied + --> $DIR/M-04-message-returns-non-codec.rs:18:9 + | +6 | pub struct NonCodec; + | -------------------- doesn't satisfy `_: message_returns_non_codec::_::_parity_scale_codec::Decode` +... +18 | / pub fn returns_non_codec_type(&self) -> NonCodec { +19 | | NonCodec +20 | | } + | |_________^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NonCodec: message_returns_non_codec::_::_parity_scale_codec::Decode` From 273fd13a924fea6a43cc23dd56d5277aa96330cc Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 11:34:25 +0200 Subject: [PATCH 227/493] improve macro hygiene in message and constructor selector namespace types --- crates/lang/codegen/src/generator/dispatch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 698578048d..25fbb3affd 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -171,7 +171,7 @@ impl Dispatch<'_> { // - The `ID` const parameter uniquely identifies one of the ink! messages // implemented by the root smart contract. #[doc(hidden)] - pub struct #message_namespace {} + pub struct #message_namespace {} // Selector namespace for ink! constructors of the root smart contract. // @@ -182,7 +182,7 @@ impl Dispatch<'_> { // - The `ID` const parameter uniquely identifies one of the ink! constructors // implemented by the root smart contract. #[doc(hidden)] - pub struct #constructor_namespace {} + pub struct #constructor_namespace {} } } From 9d3787eabeffe54000f3c48d75e7fc75b09927f6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 13:24:21 +0200 Subject: [PATCH 228/493] guard against payable property of ink! trait messages in UI test --- crates/lang/macro/Cargo.toml | 2 + .../ui/trait_def/pass/payable_message.rs | 59 ++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index 29cc59537d..11314c0e24 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -30,6 +30,8 @@ ink_storage = { version = "3.0.0-rc5", path = "../../storage/" } ink_lang = { version = "3.0.0-rc5", path = ".." } ink_prelude = { version = "3.0.0-rc5", path = "../../prelude/" } +blake2 = "0.9" + trybuild = "1.0.24" scale-info = { version = "0.6", default-features = false, features = ["derive"] } diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 8eccff66f3..5492df68bc 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -6,6 +6,63 @@ pub trait PayableDefinition { fn payable(&self); #[ink(message, payable)] fn payable_mut(&mut self); + + #[ink(message)] + fn unpayable(&self); + #[ink(message)] + fn unpayable_mut(&mut self); +} + +/// Mimics computation of ink! trait local message ID calculation. +fn local_id(ident: &str) -> u32 { + let buffer = format!("message::{}", ident).into_bytes(); + use blake2::digest::generic_array::sequence::Split as _; + let (head_32, _rest) = + ::digest(&buffer).split(); + let head_32: [u8; 4] = head_32.into(); + u32::from_be_bytes(head_32) } -fn main() {} +/// Computed using `local_id("payable")`. +const PAYABLE_ID: u32 = 0xFDDBE704; + +/// Computed using `local_id("payable_mut")`. +const PAYABLE_MUT_ID: u32 = 0x1CE6275F; + +/// Computed using `local_id("unpayable")`. +const UNPAYABLE_ID: u32 = 0x511647A5; + +/// Computed using `local_id("unpayable_mut")`. +const UNPAYABLE_MUT_ID: u32 = 0x4A60F1E1; + +fn main() { + // Uncomment these in order to print out the local IDs of + // all the ink! trait messages for this test. + // + // println!("local_id(\"payable\") = {:X}", local_id("payable")); + // println!("local_id(\"payable_mut\") = {:X}", local_id("payable_mut")); + // println!("local_id(\"unpayable\") = {:X}", local_id("unpayable")); + // println!("local_id(\"unpayable_mut\") = {:X}", local_id("unpayable_mut")); + assert!( + <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + as PayableDefinition>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo>::PAYABLE, + ); + assert!( + <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + as PayableDefinition>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo>::PAYABLE, + ); + assert_eq!( + <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + as PayableDefinition>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo>::PAYABLE, + false + ); + assert_eq!( + <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + as PayableDefinition>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo>::PAYABLE, + false + ); +} From d758f536400bfcbe16b09df7b35243381c822077 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 13:26:05 +0200 Subject: [PATCH 229/493] apply rustfmt --- crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 5492df68bc..00e6cab2be 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -17,8 +17,7 @@ pub trait PayableDefinition { fn local_id(ident: &str) -> u32 { let buffer = format!("message::{}", ident).into_bytes(); use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&buffer).split(); + let (head_32, _rest) = ::digest(&buffer).split(); let head_32: [u8; 4] = head_32.into(); u32::from_be_bytes(head_32) } From d16bdf2caceff1479341b135a6efaf5643eba14b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 15:13:22 +0200 Subject: [PATCH 230/493] add InkTraitMessage::compute_local_id method This is used by some UI tests so that they do not have to mimic the formula. --- .../lang/ir/src/ir/trait_def/item/trait_item.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs index 934842790e..8efc1261b9 100644 --- a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs @@ -144,6 +144,16 @@ impl<'a> InkTraitMessage<'a> { &self.item.sig.ident } + /// Returns a local ID unique to the ink! trait definition for the identifier. + pub fn compute_local_id(ident: &syn::Ident) -> u32 { + let buffer = format!("message::{}", ident).into_bytes(); + use blake2::digest::generic_array::sequence::Split as _; + let (head_32, _rest) = + ::digest(&buffer).split(); + let head_32: [u8; 4] = head_32.into(); + u32::from_be_bytes(head_32) + } + /// Returns a local ID unique to the ink! trait definition of the ink! trait message. /// /// # Note @@ -152,12 +162,7 @@ impl<'a> InkTraitMessage<'a> { /// Although the above scenario is very unlikely since the local ID is computed /// solely by the identifier of the ink! message. pub fn local_id(&self) -> u32 { - let buffer = format!("message::{}", self.ident()).into_bytes(); - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&buffer).split(); - let head_32: [u8; 4] = head_32.into(); - u32::from_be_bytes(head_32) + Self::compute_local_id(self.ident()) } /// Returns the span of the ink! message. From 3c82b9f45c87e89e53b7f5f0a78962e78fc65d2d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 15:14:02 +0200 Subject: [PATCH 231/493] use InkTraitMessage::compute_local_id instead of mimicking the formula --- crates/lang/macro/Cargo.toml | 1 - .../tests/ui/trait_def/pass/payable_message.rs | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index 11314c0e24..9d2bca3c74 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -30,7 +30,6 @@ ink_storage = { version = "3.0.0-rc5", path = "../../storage/" } ink_lang = { version = "3.0.0-rc5", path = ".." } ink_prelude = { version = "3.0.0-rc5", path = "../../prelude/" } -blake2 = "0.9" trybuild = "1.0.24" scale-info = { version = "0.6", default-features = false, features = ["derive"] } diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 00e6cab2be..c80f0294a8 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -13,15 +13,6 @@ pub trait PayableDefinition { fn unpayable_mut(&mut self); } -/// Mimics computation of ink! trait local message ID calculation. -fn local_id(ident: &str) -> u32 { - let buffer = format!("message::{}", ident).into_bytes(); - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = ::digest(&buffer).split(); - let head_32: [u8; 4] = head_32.into(); - u32::from_be_bytes(head_32) -} - /// Computed using `local_id("payable")`. const PAYABLE_ID: u32 = 0xFDDBE704; @@ -35,6 +26,15 @@ const UNPAYABLE_ID: u32 = 0x511647A5; const UNPAYABLE_MUT_ID: u32 = 0x4A60F1E1; fn main() { + use ink_lang_ir as ir; + /// Returns the local ID for the given name. + #[allow(dead_code)] + fn local_id(name: &str) -> u32 { + ir::InkTraitMessage::compute_local_id(&syn::Ident::new( + name, + proc_macro2::Span::call_site(), + )) + } // Uncomment these in order to print out the local IDs of // all the ink! trait messages for this test. // From 70b613183be8d85c676bb753139ce8fca0a18674 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 15:14:14 +0200 Subject: [PATCH 232/493] unconstrain trybuild version for UI tests --- crates/lang/macro/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index 9d2bca3c74..6559c0ad7d 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -30,8 +30,7 @@ ink_storage = { version = "3.0.0-rc5", path = "../../storage/" } ink_lang = { version = "3.0.0-rc5", path = ".." } ink_prelude = { version = "3.0.0-rc5", path = "../../prelude/" } - -trybuild = "1.0.24" +trybuild = "1" scale-info = { version = "0.6", default-features = false, features = ["derive"] } [lib] From 3e86be8d002cd4366f1a17b364993f36ab94208f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 16:33:57 +0200 Subject: [PATCH 233/493] apply rustfmt --- examples/trait-flipper/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/trait-flipper/lib.rs b/examples/trait-flipper/lib.rs index bb3236a193..46a7c01148 100644 --- a/examples/trait-flipper/lib.rs +++ b/examples/trait-flipper/lib.rs @@ -27,7 +27,9 @@ pub mod flipper { /// Creates a new flipper smart contract initialized to `false`. #[ink(constructor)] pub fn new() -> Self { - Self { value: Default::default() } + Self { + value: Default::default(), + } } } From 39e27761205f8749e193c47e9d38792c7d1f2dc3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 22 Sep 2021 16:46:37 +0200 Subject: [PATCH 234/493] rename ink_lang::TraitCallForwarderRegistry -> InkTraitDefinitionRegistry --- crates/lang/codegen/src/generator/arg_list.rs | 2 +- .../codegen/src/generator/as_dependency/call_builder.rs | 2 +- .../codegen/src/generator/as_dependency/contract_ref.rs | 2 +- crates/lang/codegen/src/generator/item_impls.rs | 2 +- .../codegen/src/generator/trait_def/trait_registry.rs | 4 ++-- .../lang/macro/tests/ui/trait_def/pass/payable_message.rs | 8 ++++---- crates/lang/src/lib.rs | 2 +- crates/lang/src/traits.rs | 6 +++--- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 2f9f8e96a6..a448eb1522 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -73,7 +73,7 @@ where pub fn generate_unique_trait_id(span: Span, trait_path: &syn::Path) -> TokenStream2 { quote_spanned!(span=> { - <<::ink_lang::TraitCallForwarderRegistry + <<::ink_lang::InkTraitDefinitionRegistry as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitUniqueId>::ID } diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 6190a0ddac..55f0839def 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -246,7 +246,7 @@ impl CallBuilder<'_> { .map(|message| self.generate_ink_trait_impl_for_message(trait_path, message)); quote_spanned!(span=> impl #trait_path for #cb_ident { - type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry + type __ink_TraitInfo = <::ink_lang::InkTraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #( #messages )* diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 82a20e0130..21608f23c5 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -210,7 +210,7 @@ impl ContractRef<'_> { #( #attrs )* impl #trait_path for #forwarder_ident { #[doc(hidden)] - type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry + type __ink_TraitInfo = <::ink_lang::InkTraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #messages diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 454299c6a8..b74880de81 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -91,7 +91,7 @@ impl ItemImpls<'_> { quote_spanned!(span => #( #attrs )* impl #trait_path for #self_type { - type __ink_TraitInfo = <::ink_lang::TraitCallForwarderRegistry + type __ink_TraitInfo = <::ink_lang::InkTraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #( #messages )* diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 40ee678549..8cc00afc2d 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -94,7 +94,7 @@ impl TraitRegistry<'_> { /// call forwarder and call builder types as such for the ink! trait. /// /// This is done by the fact that ink! implements all ink! traits by the - /// [`ink_lang::TraitCallForwarderRegistry`] type and uses the `__ink_ConcreteImplementer` + /// [`ink_lang::InkTraitDefinitionRegistry`] type and uses the `__ink_ConcreteImplementer` /// associated type to refer back to the actual call forwarder and call builder types. fn generate_registry_impl(&self) -> TokenStream2 { let span = self.span(); @@ -102,7 +102,7 @@ impl TraitRegistry<'_> { let trait_info_ident = self.trait_def.trait_info_ident(); let messages = self.generate_registry_messages(); quote_spanned!(span=> - impl #name for ::ink_lang::TraitCallForwarderRegistry + impl #name for ::ink_lang::InkTraitDefinitionRegistry where E: ::ink_env::Environment, { diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index c80f0294a8..e243bfd4d7 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -43,23 +43,23 @@ fn main() { // println!("local_id(\"unpayable\") = {:X}", local_id("unpayable")); // println!("local_id(\"unpayable_mut\") = {:X}", local_id("unpayable_mut")); assert!( - <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, ); assert!( - <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, ); assert_eq!( - <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, false ); assert_eq!( - <<::ink_lang::TraitCallForwarderRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, false diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 9feb9781e4..0bb1e15e35 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -78,13 +78,13 @@ pub use self::{ FnSelector, FnState, ImpliesReturn, + InkTraitDefinitionRegistry, MessageMut, MessageRef, NoConcreteImplementer, TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, - TraitCallForwarderRegistry, TraitImplementer, TraitMessageInfo, TraitModulePath, diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 5df25d70d4..e0cff10032 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -149,18 +149,18 @@ pub trait True {} /// that ink! can serialize and deserialize as if it was an `AccountId` and call /// ink! messages on it according to the ink! trait definition interface. #[doc(hidden)] -pub struct TraitCallForwarderRegistry { +pub struct InkTraitDefinitionRegistry { marker: PhantomData E>, } -impl crate::ContractEnv for TraitCallForwarderRegistry +impl crate::ContractEnv for InkTraitDefinitionRegistry where E: ink_env::Environment, { type Env = E; } -unsafe impl TraitImplementer for TraitCallForwarderRegistry {} +unsafe impl TraitImplementer for InkTraitDefinitionRegistry {} /// The default type that ink! trait definition implementations use for the /// `__ink_DynamicCallForwarder` associated type. From 4992bfdabe1f7fd96ca7a9859952afc79207a4ee Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 23 Sep 2021 11:29:17 +0200 Subject: [PATCH 235/493] use generator::input_bindings in generate_input_bindings --- crates/lang/codegen/src/generator/dispatch.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 25fbb3affd..c2d5236e37 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -279,11 +279,7 @@ impl Dispatch<'_> { where C: ir::Callable, { - let input_bindings = callable - .inputs() - .enumerate() - .map(|(n, _pat_type)| format_ident!("__ink_binding_{}", n)) - .collect::>(); + let input_bindings = generator::input_bindings(callable.inputs()); let inputs_as_tuple_or_wildcard = match input_bindings.len() { 0 => quote! { _ }, 1 => quote! { #( #input_bindings ),* }, From 5e1db51fac6e271794a8c2262594138d7a5befc6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 23 Sep 2021 11:29:39 +0200 Subject: [PATCH 236/493] rename generate_input_bindings to generate_inputs_bindings_tuple --- crates/lang/codegen/src/generator/dispatch.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index c2d5236e37..fb25937b71 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -275,7 +275,7 @@ impl Dispatch<'_> { /// quote! { (__ink_binding_0, __ink_binding_1, ..) } ) /// # ; /// ``` - fn generate_input_bindings(callable: &C) -> (Vec, TokenStream2) + fn generate_input_bindings_tuple(callable: &C) -> (Vec, TokenStream2) where C: ir::Callable, { @@ -321,7 +321,7 @@ impl Dispatch<'_> { (None, format_ident!("MessageRef")) }; let (input_bindings, inputs_as_tuple_or_wildcard) = - Self::generate_input_bindings(message); + Self::generate_input_bindings_tuple(message); let as_trait = cws.item_impl().trait_path().map(|trait_path| { quote_spanned!(message_span => as #trait_path @@ -359,7 +359,7 @@ impl Dispatch<'_> { Self::dispatch_trait_impl_namespace(ir::CallableKind::Constructor); let callable_impl = self.generate_trait_impls_for_callable(cws); let (input_bindings, inputs_as_tuple_or_wildcard) = - Self::generate_input_bindings(constructor); + Self::generate_input_bindings_tuple(constructor); let as_trait = cws.item_impl().trait_path().map(|trait_path| { quote_spanned!(constructor_span => as #trait_path From ab74baca8230c9af140018162fa7c16e13b48a2a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 12:19:54 +0200 Subject: [PATCH 237/493] move local_message_id into shared utils module --- crates/lang/ir/src/ir/item_impl/message.rs | 13 ++++++++++++- .../ir/src/ir/trait_def/item/trait_item.rs | 18 ++---------------- crates/lang/ir/src/ir/utils.rs | 14 ++++++++++++++ crates/lang/ir/src/lib.rs | 1 + .../tests/ui/trait_def/pass/payable_message.rs | 2 +- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/crates/lang/ir/src/ir/item_impl/message.rs b/crates/lang/ir/src/ir/item_impl/message.rs index 90b44e9941..cf39d31e0b 100644 --- a/crates/lang/ir/src/ir/item_impl/message.rs +++ b/crates/lang/ir/src/ir/item_impl/message.rs @@ -19,7 +19,7 @@ use super::{ InputsIter, Visibility, }; -use crate::ir; +use crate::ir::{self, utils}; use core::convert::TryFrom; use proc_macro2::{ Ident, @@ -279,6 +279,17 @@ impl Message { syn::ReturnType::Type(_, return_type) => Some(return_type), } } + + /// Returns a local ID unique to the ink! message with respect to its impl block. + /// + /// # Note + /// + /// It is a compile error if two ink! trait messages share the same local ID. + /// Although the above scenario is very unlikely since the local ID is computed + /// solely by the identifier of the ink! message. + pub fn local_id(&self) -> u32 { + utils::local_message_id(self.ident()) + } } #[cfg(test)] diff --git a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs index 8efc1261b9..5e2e1946fb 100644 --- a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs @@ -13,11 +13,7 @@ // limitations under the License. use super::super::InkAttribute; -use crate::{ - ir, - InputsIter, - Receiver, -}; +use crate::{InputsIter, Receiver, ir::{self, utils}}; use proc_macro2::Span; use syn::{ spanned::Spanned as _, @@ -144,16 +140,6 @@ impl<'a> InkTraitMessage<'a> { &self.item.sig.ident } - /// Returns a local ID unique to the ink! trait definition for the identifier. - pub fn compute_local_id(ident: &syn::Ident) -> u32 { - let buffer = format!("message::{}", ident).into_bytes(); - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&buffer).split(); - let head_32: [u8; 4] = head_32.into(); - u32::from_be_bytes(head_32) - } - /// Returns a local ID unique to the ink! trait definition of the ink! trait message. /// /// # Note @@ -162,7 +148,7 @@ impl<'a> InkTraitMessage<'a> { /// Although the above scenario is very unlikely since the local ID is computed /// solely by the identifier of the ink! message. pub fn local_id(&self) -> u32 { - Self::compute_local_id(self.ident()) + utils::local_message_id(self.ident()) } /// Returns the span of the ink! message. diff --git a/crates/lang/ir/src/ir/utils.rs b/crates/lang/ir/src/ir/utils.rs index 51b2bd5b8d..5c895fc377 100644 --- a/crates/lang/ir/src/ir/utils.rs +++ b/crates/lang/ir/src/ir/utils.rs @@ -42,3 +42,17 @@ pub fn ensure_pub_visibility( } Ok(()) } + +/// Returns a local ID unique to the ink! trait definition for the identifier. +/// +/// # Note +/// +/// Used from within ink! trait definitions as well as ink! trait implementation blocks. +pub fn local_message_id(ident: &syn::Ident) -> u32 { + let buffer = format!("message::{}", ident).into_bytes(); + use blake2::digest::generic_array::sequence::Split as _; + let (head_32, _rest) = + ::digest(&buffer).split(); + let head_32: [u8; 4] = head_32.into(); + u32::from_be_bytes(head_32) +} diff --git a/crates/lang/ir/src/lib.rs b/crates/lang/ir/src/lib.rs index 6cd2db198b..86aaa115eb 100644 --- a/crates/lang/ir/src/lib.rs +++ b/crates/lang/ir/src/lib.rs @@ -36,6 +36,7 @@ mod literal; pub use self::{ ir::{ + utils, Callable, CallableKind, CallableWithSelector, diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index e243bfd4d7..783d2ffbef 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -30,7 +30,7 @@ fn main() { /// Returns the local ID for the given name. #[allow(dead_code)] fn local_id(name: &str) -> u32 { - ir::InkTraitMessage::compute_local_id(&syn::Ident::new( + ir::utils::local_message_id(&syn::Ident::new( name, proc_macro2::Span::call_site(), )) From 7209c2d118c5566a29194fdfe37fd9bd5003286c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 12:20:27 +0200 Subject: [PATCH 238/493] add new dispatch codegen traits to ink_lang --- crates/lang/src/lib.rs | 8 +++ crates/lang/src/traits.rs | 103 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 0bb1e15e35..1ad7055e22 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -73,6 +73,14 @@ pub use self::{ }, traits::{ Constructor, + ContractAmountDispatchables, + ContractConstructorDecoder, + ContractDispatchableConstructors, + ContractDispatchableMessages, + ContractMessageDecoder, + DispatchableConstructorInfo, + DispatchableMessageInfo, + ExecuteDispatchable, FnInput, FnOutput, FnSelector, diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index e0cff10032..289cd0efba 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::DispatchError; use core::marker::PhantomData; use ink_env::{ call::{ @@ -301,3 +302,105 @@ pub trait TraitMessageInfo { /// ink! trait definition site. const SELECTOR: [u8; 4]; } + +/// Implemented by all ink! smart contracts. +/// +/// Reflects the number of dispatchable ink! messages and constructors respectively. +pub trait ContractAmountDispatchables { + /// The number of dispatchable ink! messages. + const MESSAGES: usize; + /// The number of dispatchable ink! constructors. + const CONSTRUCTORS: usize; +} + +/// Implemented by all ink! smart contracts. +/// +/// Stores a sequence of all dispatchable ink! message of the ink! smart contract. +/// +/// # Note +/// +/// Implemented for the amount of dispatchable ink! messages of the ink! smart contract. +pub trait ContractDispatchableMessages { + /// The sequence stores selector IDs of all ink! messages dispatchable by the ink! smart contract. + const IDS: [u32; AMOUNT]; +} + +/// Implemented by all ink! smart contracts. +/// +/// Stores a sequence of all dispatchable ink! constructors of the ink! smart contract. +/// +/// # Note +/// +/// Implemented for the amount of dispatchable ink! constructors of the ink! smart contract. +pub trait ContractDispatchableConstructors { + /// The sequence stores selector IDs of all ink! constructors dispatchable by the ink! smart contract. + const IDS: [u32; AMOUNT]; +} + +/// Implemented by the ink! message namespace type for every ink! message selector ID. +/// +/// Stores various information properties of the respective dispatchable ink! message. +pub trait DispatchableMessageInfo { + /// Reflects the input types of the dispatchable ink! message. + type Input; + /// Reflects the output type of the dispatchable ink! message. + type Output; + /// The ink! storage struct type. + type Storage; + + /// The closure that can be used to dispatch into the dispatchable ink! message. + /// + /// # Note + /// + /// We unify `&self` and `&mut self` ink! messages here and always take a `&mut self`. + /// This is mainly done for simplification but also because we can easily convert from + /// `&mut self` to `&self` with our current dispatch codegen architecture. + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output; + + /// Yields `true` if the dispatchable ink! message mutates the ink! storage. + const MUTATES: bool; + /// Yields `true` if the dispatchable ink! message is payable. + const PAYABLE: bool; + /// The selectors of the dispatchable ink! message. + const SELECTOR: [u8; 4]; + /// The label of the dispatchable ink! message. + const LABEL: &'static str; +} + +/// Implemented by the ink! constructor namespace type for every ink! constructor selector ID. +/// +/// Stores various information of the respective dispatchable ink! constructor. +pub trait DispatchableConstructorInfo { + /// Reflects the input types of the dispatchable ink! constructor. + type Input; + /// The ink! storage struct type. + type Storage; + + /// The closure that can be used to dispatch into the dispatchable ink! constructor. + const CALLABLE: fn(Self::Input) -> Self::Storage; + + /// The selectors of the dispatchable ink! constructor. + const SELECTOR: [u8; 4]; + /// The label of the dispatchable ink! constructor. + const LABEL: &'static str; +} + +/// Generated type used to decode all dispatchable ink! messages of the ink! smart contract. +pub trait ContractMessageDecoder { + /// The ink! smart contract message decoder type. + type Type: scale::Decode; +} + +/// Generated type used to decode all dispatchable ink! constructors of the ink! smart contract. +pub trait ContractConstructorDecoder { + /// The ink! smart contract constructor decoder type. + type Type: scale::Decode; +} + +/// Implemented by the ink! smart contract message or constructor decoder. +/// +/// Starts the execution of the respective ink! message or constructor call. +pub trait ExecuteDispatchable { + /// Executes the ink! smart contract message or constructor. + fn execute_dispatchable(self) -> Result<(), DispatchError>; +} From 4b8039f2191d015e498c57dc4846b63da05feae4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 12:20:45 +0200 Subject: [PATCH 239/493] start to implement new dispatch codegen for ink! --- crates/lang/codegen/src/generator/contract.rs | 2 + .../lang/codegen/src/generator/dispatch2.rs | 213 ++++++++++++++++++ crates/lang/codegen/src/generator/mod.rs | 2 + 3 files changed, 217 insertions(+) create mode 100644 crates/lang/codegen/src/generator/dispatch2.rs diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index 4e8da7365b..2481e65819 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -40,6 +40,7 @@ impl GenerateCode for Contract<'_> { let storage = self.generate_code_using::(); let events = self.generate_code_using::(); let dispatch = self.generate_code_using::(); + let dispatch2 = self.generate_code_using::(); let item_impls = self.generate_code_using::(); let metadata = self.generate_code_using::(); let contract_reference = @@ -57,6 +58,7 @@ impl GenerateCode for Contract<'_> { #storage #events #dispatch + #dispatch2 #item_impls #contract_reference #metadata diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs new file mode 100644 index 0000000000..5087bff8c2 --- /dev/null +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -0,0 +1,213 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::iter; + +use crate::{ + generator, + GenerateCode, + GenerateCodeUsing as _, +}; +use derive_more::From; +use ir::HexLiteral as _; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ + quote, + quote_spanned, +}; +use syn::spanned::Spanned as _; + +/// Generates code for the message and constructor dispatcher. +/// +/// This code efficiently selects the dispatched ink! constructor or message +/// by inspecting the first four bytes (selector) of the given input bytes. +/// +/// As this happens on every contract execution this code must be highly optimized. +/// For that purpose a so-called dispatch enum is being generated that has a +/// specialized `scale::Decode` implementation taking the first four bytes of +/// the input stream in order to identify the enum variant that it is going to +/// produce out of the rest of the input buffer. +/// +/// The rest of the input buffer is then automatically decoded directly into the +/// expected input types of the respective ink! constructor or message. +#[derive(From)] +pub struct Dispatch<'a> { + contract: &'a ir::Contract, +} +impl_as_ref_for_generator!(Dispatch); + +impl GenerateCode for Dispatch<'_> { + fn generate_code(&self) -> TokenStream2 { + let cfg_not_as_dependency = + self.generate_code_using::(); + let amount_dispatchables = + self.generate_contract_amount_dispatchables_trait_impl(); + let contract_dispatchable_messages = + self.generate_contract_dispatchable_messages_trait_impl(); + let contract_dispatchable_constructors = + self.generate_contract_dispatchable_constructors_trait_impl(); + // let entry_points = self.generate_entry_points(); + // let dispatch_using_mode = self.generate_dispatch_using_mode(); + // let dispatch_trait_impl_namespaces = self.generate_trait_impl_namespaces(); + // let dispatch_trait_impls = self.generate_dispatch_trait_impls(); + // let message_dispatch_enum = self.generate_message_dispatch_enum(); + // let constructor_dispatch_enum = self.generate_constructor_dispatch_enum(); + quote! { + // We do not generate contract dispatch code while the contract + // is being tested or the contract is a dependency of another + // since both resulting compilations do not require dispatching. + #[cfg(not(test))] + #cfg_not_as_dependency + const _: () = { + #amount_dispatchables + #contract_dispatchable_messages + #contract_dispatchable_constructors + // #entry_points + // #dispatch_using_mode + // #dispatch_trait_impl_namespaces + // #dispatch_trait_impls + // #message_dispatch_enum + // #constructor_dispatch_enum + }; + } + } +} + +impl Dispatch<'_> { + /// Generates code for the [`ink_lang::ContractDispatchables`] trait implementation. + /// + /// This trait implementation stores information of how many dispatchable + /// ink! messages and ink! constructors there are for the ink! smart contract. + fn generate_contract_amount_dispatchables_trait_impl(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let count_messages = self + .contract + .module() + .impls() + .map(|item_impl| item_impl.iter_messages()) + .flatten() + .count(); + let count_constructors = self + .contract + .module() + .impls() + .map(|item_impl| item_impl.iter_constructors()) + .flatten() + .count(); + quote_spanned!(span=> + impl ::ink_lang::ContractAmountDispatchables for #storage_ident { + const MESSAGES: ::core::primitive::usize = #count_messages; + const CONSTRUCTORS: ::core::primitive::usize = #count_constructors; + } + ) + } + + /// Generates code for the [`ink_lang::ContractDispatchableMessages`] trait implementation. + /// + /// This trait implementation stores the selector ID of each dispatchable + /// ink! messages of the ink! smart contract. + fn generate_contract_dispatchable_messages_trait_impl(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let inherent_ids = self + .contract + .module() + .impls() + .filter(|item_impl| item_impl.trait_path().is_none()) + .map(|item_impl| item_impl.iter_messages()) + .flatten() + .map(|message| { + let span = message.span(); + let id = message + .composed_selector() + .into_be_u32() + .hex_padded_suffixed(); + quote_spanned!(span=> #id) + }); + let trait_ids = self + .contract + .module() + .impls() + .filter_map(|item_impl| { + item_impl + .trait_path() + .map(|trait_path| { + iter::repeat(trait_path).zip(item_impl.iter_messages()) + }) + }) + .flatten() + .map(|(trait_path, message)| { + let local_id = message.local_id().hex_padded_suffixed(); + let span = message.span(); + quote_spanned!(span=> + { + ::core::primitive::u32::from_be_bytes( + <<::ink_lang::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR + ) + } + ) + }); + quote_spanned!(span=> + impl ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }> for #storage_ident { + const IDS: [ + ::core::primitive::u32; + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + ] = [ + #( #inherent_ids , )* + #( #trait_ids ),* + ]; + } + ) + } + + /// Generates code for the [`ink_lang::ContractDispatchableConstructors`] trait implementation. + /// + /// This trait implementation stores the selector ID of each dispatchable + /// ink! constructor of the ink! smart contract. + fn generate_contract_dispatchable_constructors_trait_impl(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let constructor_ids = self + .contract + .module() + .impls() + .filter(|item_impl| item_impl.trait_path().is_none()) + .map(|item_impl| item_impl.iter_constructors()) + .flatten() + .map(|message| { + let span = message.span(); + let id = message + .composed_selector() + .into_be_u32() + .hex_padded_suffixed(); + quote_spanned!(span=> #id) + }); + quote_spanned!(span=> + impl ::ink_lang::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + }> for #storage_ident { + const IDS: [ + ::core::primitive::u32; + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + ] = [ + #( #constructor_ids ),* + ]; + } + ) + } +} diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 99862e31ea..72e73e18ba 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -31,6 +31,7 @@ mod as_dependency; mod chain_extension; mod contract; mod dispatch; +mod dispatch2; mod env; mod events; mod ink_test; @@ -55,6 +56,7 @@ pub use self::{ chain_extension::ChainExtension, contract::Contract, dispatch::Dispatch, + dispatch2::Dispatch as Dispatch2, env::Env, events::Events, ink_test::InkTest, From 94d13702b477b238fdfa33aea5aa951118190a57 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 12:20:58 +0200 Subject: [PATCH 240/493] apply rustfmt --- crates/lang/ir/src/ir/item_impl/message.rs | 5 ++++- crates/lang/ir/src/ir/trait_def/item/trait_item.rs | 9 ++++++++- crates/lang/ir/src/ir/utils.rs | 3 +-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/lang/ir/src/ir/item_impl/message.rs b/crates/lang/ir/src/ir/item_impl/message.rs index cf39d31e0b..addd320660 100644 --- a/crates/lang/ir/src/ir/item_impl/message.rs +++ b/crates/lang/ir/src/ir/item_impl/message.rs @@ -19,7 +19,10 @@ use super::{ InputsIter, Visibility, }; -use crate::ir::{self, utils}; +use crate::ir::{ + self, + utils, +}; use core::convert::TryFrom; use proc_macro2::{ Ident, diff --git a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs index 5e2e1946fb..9fddf5cbd8 100644 --- a/crates/lang/ir/src/ir/trait_def/item/trait_item.rs +++ b/crates/lang/ir/src/ir/trait_def/item/trait_item.rs @@ -13,7 +13,14 @@ // limitations under the License. use super::super::InkAttribute; -use crate::{InputsIter, Receiver, ir::{self, utils}}; +use crate::{ + ir::{ + self, + utils, + }, + InputsIter, + Receiver, +}; use proc_macro2::Span; use syn::{ spanned::Spanned as _, diff --git a/crates/lang/ir/src/ir/utils.rs b/crates/lang/ir/src/ir/utils.rs index 5c895fc377..64985e90cd 100644 --- a/crates/lang/ir/src/ir/utils.rs +++ b/crates/lang/ir/src/ir/utils.rs @@ -51,8 +51,7 @@ pub fn ensure_pub_visibility( pub fn local_message_id(ident: &syn::Ident) -> u32 { let buffer = format!("message::{}", ident).into_bytes(); use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&buffer).split(); + let (head_32, _rest) = ::digest(&buffer).split(); let head_32: [u8; 4] = head_32.into(); u32::from_be_bytes(head_32) } From 96e761c5942686111c75016701ee49eaa335b394 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 22:46:40 +0200 Subject: [PATCH 241/493] impl ExactSizeIterator for InputsIter --- crates/lang/ir/src/ir/item_impl/callable.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index 4337064262..d8a72f7dd7 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -519,6 +519,12 @@ impl<'a> Iterator for InputsIter<'a> { } } +impl<'a> ExactSizeIterator for InputsIter<'a> { + fn len(&self) -> usize { + self.iter.len() + } +} + #[cfg(test)] mod tests { use super::*; From d3d1118c184a210f88532cdc5d8cbeaa4de5fbe0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 22:47:09 +0200 Subject: [PATCH 242/493] add input_bindings_tuple and input_types_tuple to utility generator module --- crates/lang/codegen/src/generator/arg_list.rs | 23 +++++++++++++++++++ crates/lang/codegen/src/generator/mod.rs | 2 ++ 2 files changed, 25 insertions(+) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index a448eb1522..3722baa361 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -46,6 +46,29 @@ pub fn input_types(inputs: ir::InputsIter) -> Vec<&syn::Type> { inputs.map(|pat_type| &*pat_type.ty).collect::>() } +/// Returns a tuple type representing the types yielded by the input types. +pub fn input_types_tuple(inputs: ir::InputsIter) -> TokenStream2 { + let input_types = input_types(inputs); + if input_types.len() != 1 { + // Pack all types into a tuple if they are not exactly 1. + // This results in `()` for zero input types. + quote! { ( #( #input_types ),* ) } + } else { + // Return the single type without turning it into a tuple. + quote! { #( #input_types )* } + } +} + +/// Returns a tuple expression representing the bindings yielded by the inputs. +pub fn input_bindings_tuple(inputs: ir::InputsIter) -> TokenStream2 { + let input_bindings = input_bindings(inputs); + match input_bindings.len() { + 0 => quote! { _ }, + 1 => quote! { #( #input_bindings ),* }, + _ => quote! { ( #( #input_bindings ),* ) }, + } +} + /// Builds up the `ink_env::call::utils::ArgumentList` type structure for the given types. pub fn generate_argument_list<'b, Args>(args: Args) -> TokenStream2 where diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 72e73e18ba..8bd1fdea5f 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -45,7 +45,9 @@ pub use self::{ generate_argument_list, generate_unique_trait_id, input_bindings, + input_bindings_tuple, input_types, + input_types_tuple, output_ident, }, as_dependency::{ From bf0b31e5e401233845152537231e42a655541221 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 22:47:33 +0200 Subject: [PATCH 243/493] remove unnecessary filter chain call --- crates/lang/codegen/src/generator/dispatch2.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 5087bff8c2..08e949d58a 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -186,7 +186,6 @@ impl Dispatch<'_> { .contract .module() .impls() - .filter(|item_impl| item_impl.trait_path().is_none()) .map(|item_impl| item_impl.iter_constructors()) .flatten() .map(|message| { From 6ba6c66aee79fdf0d50480feb04ebfdc18b3959c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 22:47:55 +0200 Subject: [PATCH 244/493] add missing environment type parameter in codegen --- crates/lang/codegen/src/generator/dispatch2.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 08e949d58a..9e61339cda 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -154,7 +154,8 @@ impl Dispatch<'_> { quote_spanned!(span=> { ::core::primitive::u32::from_be_bytes( - <<::ink_lang::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo + <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR ) } From 9958f09c69e8567972fc79318959fdf0981e5ca6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 22:48:12 +0200 Subject: [PATCH 245/493] rename message to constructor where applicable --- crates/lang/codegen/src/generator/dispatch2.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 9e61339cda..1fa97a6491 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -189,9 +189,9 @@ impl Dispatch<'_> { .impls() .map(|item_impl| item_impl.iter_constructors()) .flatten() - .map(|message| { - let span = message.span(); - let id = message + .map(|constructor| { + let span = constructor.span(); + let id = constructor .composed_selector() .into_be_u32() .hex_padded_suffixed(); From 714fc3b4a029cc15de22ab39062b3d2cf603c46a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 22:48:29 +0200 Subject: [PATCH 246/493] implement codegen for constructor info trait impls --- .../lang/codegen/src/generator/dispatch2.rs | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 1fa97a6491..b16e69fad6 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -20,7 +20,10 @@ use crate::{ GenerateCodeUsing as _, }; use derive_more::From; -use ir::HexLiteral as _; +use ir::{ + Callable, + HexLiteral as _, +}; use proc_macro2::TokenStream as TokenStream2; use quote::{ quote, @@ -57,6 +60,8 @@ impl GenerateCode for Dispatch<'_> { self.generate_contract_dispatchable_messages_trait_impl(); let contract_dispatchable_constructors = self.generate_contract_dispatchable_constructors_trait_impl(); + let contract_dispatchable_constructor_infos = + self.generate_dispatchable_constructor_infos(); // let entry_points = self.generate_entry_points(); // let dispatch_using_mode = self.generate_dispatch_using_mode(); // let dispatch_trait_impl_namespaces = self.generate_trait_impl_namespaces(); @@ -73,6 +78,7 @@ impl GenerateCode for Dispatch<'_> { #amount_dispatchables #contract_dispatchable_messages #contract_dispatchable_constructors + #contract_dispatchable_constructor_infos // #entry_points // #dispatch_using_mode // #dispatch_trait_impl_namespaces @@ -210,4 +216,43 @@ impl Dispatch<'_> { } ) } + + /// Generate code for the [`ink_lang::DispatchableConstructorInfo`] trait implementations. + /// + /// These trait implementations store relevant dispatch information for every + /// dispatchable ink! constructor of the ink! smart contract. + fn generate_dispatchable_constructor_infos(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let constructor_infos = self + .contract + .module() + .impls() + .map(|item_impl| item_impl.iter_constructors()) + .flatten() + .map(|constructor| { + let constructor_span = constructor.span(); + let constructor_ident = constructor.ident(); + let selector_id = constructor.composed_selector().into_be_u32().hex_padded_suffixed(); + let selector_bytes = constructor.composed_selector().hex_lits(); + let input_bindings = generator::input_bindings(constructor.inputs()); + let input_tuple_type = generator::input_types_tuple(constructor.inputs()); + let input_tuple_bindings = generator::input_bindings_tuple(constructor.inputs()); + quote_spanned!(constructor_span=> + impl ::ink_lang::DispatchableConstructorInfo<#selector_id> for #storage_ident { + type Input = #input_tuple_type; + type Storage = #storage_ident; + + const CALLABLE: fn(Self::Input) -> Self::Storage = |#input_tuple_bindings| { + #storage_ident::#constructor_ident( #( #input_bindings ),* ) + }; + const SELECTOR: [::core::primitive::u8; 4usize] = [ #( #selector_bytes ),* ]; + const LABEL: &'static ::core::primitive::str = ::core::stringify!(#constructor_ident); + } + ) + }); + quote_spanned!(span=> + #( #constructor_infos )* + ) + } } From 7b85f1f8817986d1b7e8ec5cdd3c7afedc9e67b0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 24 Sep 2021 23:54:40 +0200 Subject: [PATCH 247/493] implement dispatchable message info trait impl codegen --- .../lang/codegen/src/generator/dispatch2.rs | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index b16e69fad6..833d2a0334 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -62,6 +62,8 @@ impl GenerateCode for Dispatch<'_> { self.generate_contract_dispatchable_constructors_trait_impl(); let contract_dispatchable_constructor_infos = self.generate_dispatchable_constructor_infos(); + let contract_dispatchable_messages_infos = + self.generate_dispatchable_message_infos(); // let entry_points = self.generate_entry_points(); // let dispatch_using_mode = self.generate_dispatch_using_mode(); // let dispatch_trait_impl_namespaces = self.generate_trait_impl_namespaces(); @@ -79,6 +81,7 @@ impl GenerateCode for Dispatch<'_> { #contract_dispatchable_messages #contract_dispatchable_constructors #contract_dispatchable_constructor_infos + #contract_dispatchable_messages_infos // #entry_points // #dispatch_using_mode // #dispatch_trait_impl_namespaces @@ -255,4 +258,113 @@ impl Dispatch<'_> { #( #constructor_infos )* ) } + + /// Generate code for the [`ink_lang::DispatchableConstructorInfo`] trait implementations. + /// + /// These trait implementations store relevant dispatch information for every + /// dispatchable ink! constructor of the ink! smart contract. + fn generate_dispatchable_message_infos(&self) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let inherent_message_infos = self + .contract + .module() + .impls() + .filter(|item_impl| item_impl.trait_path().is_none()) + .map(|item_impl| item_impl.iter_messages()) + .flatten() + .map(|message| { + let message_span = message.span(); + let message_ident = message.ident(); + let payable = message.is_payable(); + let mutates = message.receiver().is_ref_mut(); + let selector_id = message.composed_selector().into_be_u32().hex_padded_suffixed(); + let selector_bytes = message.composed_selector().hex_lits(); + let output_tuple_type = message + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote! { () }); + let input_bindings = generator::input_bindings(message.inputs()); + let input_tuple_type = generator::input_types_tuple(message.inputs()); + let input_tuple_bindings = generator::input_bindings_tuple(message.inputs()); + quote_spanned!(message_span=> + impl ::ink_lang::DispatchableMessageInfo<#selector_id> for #storage_ident { + type Input = #input_tuple_type; + type Output = #output_tuple_type; + type Storage = #storage_ident; + + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = + |storage, #input_tuple_bindings| { + #storage_ident::#message_ident( storage #( , #input_bindings )* ) + }; + const SELECTOR: [::core::primitive::u8; 4usize] = [ #( #selector_bytes ),* ]; + const PAYABLE: ::core::primitive::bool = #payable; + const MUTATES: ::core::primitive::bool = #mutates; + const LABEL: &'static ::core::primitive::str = ::core::stringify!(#message_ident); + } + ) + }); + let trait_message_infos = self + .contract + .module() + .impls() + .filter_map(|item_impl| { + item_impl + .trait_path() + .map(|trait_path| { + let trait_ident = item_impl.trait_ident().expect( + "must have an ink! trait identifier if it is an ink! trait implementation" + ); + iter::repeat((trait_ident, trait_path)).zip(item_impl.iter_messages()) + }) + }) + .flatten() + .map(|((trait_ident, trait_path), message)| { + let message_span = message.span(); + let message_ident = message.ident(); + let mutates = message.receiver().is_ref_mut(); + let local_id = message.local_id().hex_padded_suffixed(); + let payable = quote! {{ + <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE + }}; + let selector = quote! {{ + <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR + }}; + let selector_id = quote! {{ + ::core::primitive::u32::from_be_bytes(#selector) + }}; + let output_tuple_type = message + .output() + .map(quote::ToTokens::to_token_stream) + .unwrap_or_else(|| quote! { () }); + let input_bindings = generator::input_bindings(message.inputs()); + let input_tuple_type = generator::input_types_tuple(message.inputs()); + let input_tuple_bindings = generator::input_bindings_tuple(message.inputs()); + let label = format!("{}::{}", trait_ident, message_ident); + quote_spanned!(message_span=> + impl ::ink_lang::DispatchableMessageInfo<#selector_id> for #storage_ident { + type Input = #input_tuple_type; + type Output = #output_tuple_type; + type Storage = #storage_ident; + + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output = + |storage, #input_tuple_bindings| { + #storage_ident::#message_ident( storage #( , #input_bindings )* ) + }; + const SELECTOR: [::core::primitive::u8; 4usize] = #selector; + const PAYABLE: ::core::primitive::bool = #payable; + const MUTATES: ::core::primitive::bool = #mutates; + const LABEL: &'static ::core::primitive::str = #label; + } + ) + }); + quote_spanned!(span=> + #( #inherent_message_infos )* + #( #trait_message_infos )* + ) + } } From fe0a44e75611f257b21f85677f5da14f9ff01915 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 00:01:00 +0200 Subject: [PATCH 248/493] fix UI test --- .../ui/contract/fail/M-04-message-returns-non-codec.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr index 712a3111c8..c4f1e57cca 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodec` note: required by a bound in `ink_lang::FnOutput::Output` - --> $DIR/traits.rs:80:18 + --> $DIR/traits.rs:81:18 | -80 | type Output: scale::Encode + 'static; +81 | type Output: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `ink_lang::FnOutput::Output` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied From f65aaa1b7333c6245ca8d0e0d83bccb3aaa90132 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 08:09:14 +0200 Subject: [PATCH 249/493] fix spelling error in docs --- crates/lang/ir/src/ir/item_impl/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/item_impl/message.rs b/crates/lang/ir/src/ir/item_impl/message.rs index addd320660..d68466c131 100644 --- a/crates/lang/ir/src/ir/item_impl/message.rs +++ b/crates/lang/ir/src/ir/item_impl/message.rs @@ -283,7 +283,7 @@ impl Message { } } - /// Returns a local ID unique to the ink! message with respect to its impl block. + /// Returns a local ID unique to the ink! message with respect to its implementation block. /// /// # Note /// From a4e0fb0787060b5ad1024fb38098182611584d11 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 08:37:20 +0200 Subject: [PATCH 250/493] remove commented-out code --- crates/lang/codegen/src/generator/dispatch2.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 833d2a0334..df896fc9a0 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -64,16 +64,7 @@ impl GenerateCode for Dispatch<'_> { self.generate_dispatchable_constructor_infos(); let contract_dispatchable_messages_infos = self.generate_dispatchable_message_infos(); - // let entry_points = self.generate_entry_points(); - // let dispatch_using_mode = self.generate_dispatch_using_mode(); - // let dispatch_trait_impl_namespaces = self.generate_trait_impl_namespaces(); - // let dispatch_trait_impls = self.generate_dispatch_trait_impls(); - // let message_dispatch_enum = self.generate_message_dispatch_enum(); - // let constructor_dispatch_enum = self.generate_constructor_dispatch_enum(); quote! { - // We do not generate contract dispatch code while the contract - // is being tested or the contract is a dependency of another - // since both resulting compilations do not require dispatching. #[cfg(not(test))] #cfg_not_as_dependency const _: () = { @@ -82,12 +73,6 @@ impl GenerateCode for Dispatch<'_> { #contract_dispatchable_constructors #contract_dispatchable_constructor_infos #contract_dispatchable_messages_infos - // #entry_points - // #dispatch_using_mode - // #dispatch_trait_impl_namespaces - // #dispatch_trait_impls - // #message_dispatch_enum - // #constructor_dispatch_enum }; } } From acc157efcdbef7c4fc88eeadd7511fe7a73e0922 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 09:45:16 +0200 Subject: [PATCH 251/493] move query_amount_{constructors,messages} utilities into own functions --- .../lang/codegen/src/generator/dispatch2.rs | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index df896fc9a0..8ce8876de0 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -79,6 +79,28 @@ impl GenerateCode for Dispatch<'_> { } impl Dispatch<'_> { + /// Returns the number of dispatchable ink! constructors of the ink! smart contract. + fn query_amount_constructors(&self) -> usize { + self.contract + .module() + .impls() + .map(|item_impl| item_impl.iter_constructors()) + .flatten() + .count() + } + + /// Returns the number of dispatchable ink! messages of the ink! smart contract. + /// + /// This includes inherent ink! messages as well as trait ink! messages. + fn query_amount_messages(&self) -> usize { + self.contract + .module() + .impls() + .map(|item_impl| item_impl.iter_messages()) + .flatten() + .count() + } + /// Generates code for the [`ink_lang::ContractDispatchables`] trait implementation. /// /// This trait implementation stores information of how many dispatchable @@ -86,20 +108,8 @@ impl Dispatch<'_> { fn generate_contract_amount_dispatchables_trait_impl(&self) -> TokenStream2 { let span = self.contract.module().storage().span(); let storage_ident = self.contract.module().storage().ident(); - let count_messages = self - .contract - .module() - .impls() - .map(|item_impl| item_impl.iter_messages()) - .flatten() - .count(); - let count_constructors = self - .contract - .module() - .impls() - .map(|item_impl| item_impl.iter_constructors()) - .flatten() - .count(); + let count_messages = self.query_amount_messages(); + let count_constructors = self.query_amount_constructors(); quote_spanned!(span=> impl ::ink_lang::ContractAmountDispatchables for #storage_ident { const MESSAGES: ::core::primitive::usize = #count_messages; From 894ec3299eaaaef04fff35b61b2d40b92e801883 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 09:45:53 +0200 Subject: [PATCH 252/493] implement codegen for constructor decoder enum type --- .../lang/codegen/src/generator/dispatch2.rs | 119 +++++++++++++++++- 1 file changed, 114 insertions(+), 5 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 8ce8876de0..e83a1345c1 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -52,18 +52,25 @@ impl_as_ref_for_generator!(Dispatch); impl GenerateCode for Dispatch<'_> { fn generate_code(&self) -> TokenStream2 { + let mut constructor_spans = Vec::new(); + let mut message_spans = Vec::new(); + let cfg_not_as_dependency = self.generate_code_using::(); let amount_dispatchables = self.generate_contract_amount_dispatchables_trait_impl(); let contract_dispatchable_messages = - self.generate_contract_dispatchable_messages_trait_impl(); - let contract_dispatchable_constructors = - self.generate_contract_dispatchable_constructors_trait_impl(); + self.generate_contract_dispatchable_messages_trait_impl(&mut message_spans); + let contract_dispatchable_constructors = self + .generate_contract_dispatchable_constructors_trait_impl( + &mut constructor_spans, + ); let contract_dispatchable_constructor_infos = self.generate_dispatchable_constructor_infos(); let contract_dispatchable_messages_infos = self.generate_dispatchable_message_infos(); + let constructor_decoder_type = + self.generate_constructor_decoder_type(&constructor_spans); quote! { #[cfg(not(test))] #cfg_not_as_dependency @@ -73,6 +80,7 @@ impl GenerateCode for Dispatch<'_> { #contract_dispatchable_constructors #contract_dispatchable_constructor_infos #contract_dispatchable_messages_infos + #constructor_decoder_type }; } } @@ -122,7 +130,10 @@ impl Dispatch<'_> { /// /// This trait implementation stores the selector ID of each dispatchable /// ink! messages of the ink! smart contract. - fn generate_contract_dispatchable_messages_trait_impl(&self) -> TokenStream2 { + fn generate_contract_dispatchable_messages_trait_impl( + &self, + message_spans: &mut Vec, + ) -> TokenStream2 { let span = self.contract.module().storage().span(); let storage_ident = self.contract.module().storage().ident(); let inherent_ids = self @@ -134,6 +145,7 @@ impl Dispatch<'_> { .flatten() .map(|message| { let span = message.span(); + message_spans.push(span); let id = message .composed_selector() .into_be_u32() @@ -184,7 +196,10 @@ impl Dispatch<'_> { /// /// This trait implementation stores the selector ID of each dispatchable /// ink! constructor of the ink! smart contract. - fn generate_contract_dispatchable_constructors_trait_impl(&self) -> TokenStream2 { + fn generate_contract_dispatchable_constructors_trait_impl( + &self, + constructor_spans: &mut Vec, + ) -> TokenStream2 { let span = self.contract.module().storage().span(); let storage_ident = self.contract.module().storage().ident(); let constructor_ids = self @@ -195,6 +210,7 @@ impl Dispatch<'_> { .flatten() .map(|constructor| { let span = constructor.span(); + constructor_spans.push(span); let id = constructor .composed_selector() .into_be_u32() @@ -362,4 +378,97 @@ impl Dispatch<'_> { #( #trait_message_infos )* ) } + + /// Generates code for the ink! constructor decoder type of the ink! smart contract. + /// + /// This type can be used in order to decode the input bytes received by a call to `deploy` + /// into one of the available dispatchable ink! constructors and their arguments. + fn generate_constructor_decoder_type( + &self, + constructor_spans: &[proc_macro2::Span], + ) -> TokenStream2 { + assert_eq!(constructor_spans.len(), self.query_amount_constructors()); + + /// Expands into the token sequence to represent the + /// input type of the ink! constructor at the given index. + fn expand_constructor_input( + span: proc_macro2::Span, + storage_ident: &syn::Ident, + constructor_index: usize, + ) -> TokenStream2 { + quote_spanned!(span=> + <#storage_ident as ::ink_lang::DispatchableConstructorInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + }>>::IDS[#constructor_index] + }>>::Input + ) + } + + /// Returns the n-th constructor identifier for the decoder type. + fn constructor_variant_ident(n: usize) -> syn::Ident { + quote::format_ident!("Constructor{}", n) + } + + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let count_constructors = self.query_amount_constructors(); + let constructors_variants = (0..count_constructors).map(|index| { + let constructor_span = constructor_spans[index]; + let constructor_ident = constructor_variant_ident(index); + let constructor_input = + expand_constructor_input(constructor_span, storage_ident, index); + quote_spanned!(constructor_span=> + #constructor_ident(#constructor_input) + ) + }); + let constructor_match = (0..count_constructors).map(|index| { + let constructor_span = constructor_spans[index]; + let constructor_ident = constructor_variant_ident(index); + let constructor_selector = quote_spanned!(span=> + <#storage_ident as ::ink_lang::DispatchableConstructorInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + }>>::IDS[#index] + }>>::SELECTOR + ); + let constructor_input = expand_constructor_input(constructor_span, storage_ident, index); + quote_spanned!(constructor_span=> + #constructor_selector => { + ::core::result::Result::Ok(Self::#constructor_ident( + <#constructor_input as ::scale::Decode>::decode(input)? + )) + } + ) + }); + quote_spanned!(span=> + const _: () = { + #[derive(::core::fmt::Debug)] + #[allow(non_camel_case_types)] + pub enum __ink_ConstructorDecoder { + #( #constructors_variants ),* + } + + impl ::scale::Decode for __ink_ConstructorDecoder { + fn decode(input: &mut I) -> ::core::result::Result + where + I: ::scale::Input, + { + match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { + #( #constructor_match , )* + _invalid => ::core::result::Result::Err( + <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( + "encountered unknown ink! constructor selector" + ) + ) + } + } + } + + impl ::ink_lang::ContractConstructorDecoder for #storage_ident { + type Type = __ink_ConstructorDecoder; + } + }; + ) + } } From 24b896f3474911e561ce2a365c2f17cb8f9ef08f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:04:41 +0200 Subject: [PATCH 253/493] slightly refactor AcceptsPayments and EnablesDynamicStorageAllocator --- crates/lang/src/dispatcher.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index aeedebb603..c261a889ad 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -72,10 +72,10 @@ pub trait Execute { #[doc(hidden)] pub struct AcceptsPayments(pub bool); -impl From for bool { - #[inline] - fn from(accepts_payments: AcceptsPayments) -> Self { - accepts_payments.0 +impl AcceptsPayments { + /// Returns the value of the property. + pub const fn value(self) -> bool { + self.0 } } @@ -84,10 +84,10 @@ impl From for bool { #[doc(hidden)] pub struct EnablesDynamicStorageAllocator(pub bool); -impl From for bool { - #[inline] - fn from(enables_dynamic_storage_allocator: EnablesDynamicStorageAllocator) -> Self { - enables_dynamic_storage_allocator.0 +impl EnablesDynamicStorageAllocator { + /// Returns the value of the property. + pub const fn value(self) -> bool { + self.0 } } @@ -109,9 +109,9 @@ where M: MessageRef, F: FnOnce(&::State) -> ::Output, { - let accepts_payments: bool = accepts_payments.into(); + let accepts_payments: bool = accepts_payments.value(); let enables_dynamic_storage_allocator: bool = - enables_dynamic_storage_allocator.into(); + enables_dynamic_storage_allocator.value(); if !accepts_payments { deny_payment::()?; } @@ -167,9 +167,9 @@ where M: MessageMut, F: FnOnce(&mut ::State) -> ::Output, { - let accepts_payments: bool = accepts_payments.into(); + let accepts_payments: bool = accepts_payments.value(); let enables_dynamic_storage_allocator: bool = - enables_dynamic_storage_allocator.into(); + enables_dynamic_storage_allocator.value(); if !accepts_payments { deny_payment::()?; } @@ -207,7 +207,7 @@ where F: FnOnce() -> ::State, { let enables_dynamic_storage_allocator: bool = - enables_dynamic_storage_allocator.into(); + enables_dynamic_storage_allocator.value(); if enables_dynamic_storage_allocator { alloc::initialize(ContractPhase::Deploy); } From fe6ce66bada578aa75f27334a6df94da3a0f7f19 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:05:29 +0200 Subject: [PATCH 254/493] fix bug that spans of ink! trait messages have not been registered --- crates/lang/codegen/src/generator/dispatch2.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index e83a1345c1..dfe7006cc8 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -151,7 +151,8 @@ impl Dispatch<'_> { .into_be_u32() .hex_padded_suffixed(); quote_spanned!(span=> #id) - }); + }) + .collect::>(); let trait_ids = self .contract .module() @@ -167,6 +168,7 @@ impl Dispatch<'_> { .map(|(trait_path, message)| { let local_id = message.local_id().hex_padded_suffixed(); let span = message.span(); + message_spans.push(span); quote_spanned!(span=> { ::core::primitive::u32::from_be_bytes( From 7ee4b7d659b7107be1a16a26974723f07c0c68bb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:06:05 +0200 Subject: [PATCH 255/493] add codegen for ExecuteDispatchable for constructor decoder --- .../lang/codegen/src/generator/dispatch2.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index dfe7006cc8..23cdb08765 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -443,6 +443,29 @@ impl Dispatch<'_> { } ) }); + let constructor_execute = (0..count_constructors).map(|index| { + let constructor_span = constructor_spans[index]; + let constructor_ident = constructor_variant_ident(index); + let constructor_callable = quote_spanned!(constructor_span=> + <#storage_ident as ::ink_lang::DispatchableConstructorInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + }>>::IDS[#index] + }>>::CALLABLE + ); + let is_dynamic_storage_allocation_enabled = self + .contract + .config() + .is_dynamic_storage_allocator_enabled(); + quote_spanned!(constructor_span=> + Self::#constructor_ident(input) => { + ::ink_lang::execute_constructor_2::<#storage_ident, _>( + ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), + move || { #constructor_callable(input) } + ) + } + ) + }); quote_spanned!(span=> const _: () = { #[derive(::core::fmt::Debug)] @@ -467,6 +490,14 @@ impl Dispatch<'_> { } } + impl ::ink_lang::ExecuteDispatchable for __ink_ConstructorDecoder { + fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { + match self { + #( #constructor_execute ),* + } + } + } + impl ::ink_lang::ContractConstructorDecoder for #storage_ident { type Type = __ink_ConstructorDecoder; } From 68111773a0adc98109427e445a6f1ef8c690c1f9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:06:31 +0200 Subject: [PATCH 256/493] add codegen for expr to query if any ink! message if payable --- .../lang/codegen/src/generator/dispatch2.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 23cdb08765..c225cf922c 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -504,4 +504,35 @@ impl Dispatch<'_> { }; ) } + + /// Generates code to express if any dispatchable ink! message accepts payment. + /// + /// This information can be used to speed-up dispatch since denying of payment + /// can be generalized to work before dispatch happens if none of the ink! messages + /// accept payment anyways. + fn any_message_accepts_payment_expr( + &self, + message_spans: &[proc_macro2::Span], + ) -> TokenStream2 { + assert_eq!(message_spans.len(), self.query_amount_messages()); + + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let count_messages = self.query_amount_messages(); + let message_is_payable = (0..count_messages).map(|index| { + let message_span = message_spans[index]; + quote_spanned!(message_span=> + { + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::PAYABLE + } + ) + }); + quote_spanned!(span=> + { false #( || #message_is_payable )* } + ) + } } From 8c7958947c51e80e85c97dab3f1a7046f34e728c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:06:51 +0200 Subject: [PATCH 257/493] implement preliminary codegen for new ink! dispatch entry points --- .../lang/codegen/src/generator/dispatch2.rs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index c225cf922c..00f250b0d5 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -71,6 +71,7 @@ impl GenerateCode for Dispatch<'_> { self.generate_dispatchable_message_infos(); let constructor_decoder_type = self.generate_constructor_decoder_type(&constructor_spans); + let _entry_points = self.generate_entry_points(&message_spans); quote! { #[cfg(not(test))] #cfg_not_as_dependency @@ -81,6 +82,7 @@ impl GenerateCode for Dispatch<'_> { #contract_dispatchable_constructor_infos #contract_dispatchable_messages_infos #constructor_decoder_type + // #entry_points }; } } @@ -381,6 +383,51 @@ impl Dispatch<'_> { ) } + /// Generates code for the entry points of the root ink! smart contract. + /// + /// This generates the `deploy` and `call` functions with which the smart + /// contract runtime mainly interacts with the ink! smart contract. + fn generate_entry_points(&self, message_spans: &[proc_macro2::Span]) -> TokenStream2 { + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let any_message_accept_payment = self.any_message_accepts_payment_expr(message_spans); + quote_spanned!(span=> + #[cfg(not(test))] + #[no_mangle] + fn deploy() { + ::ink_env::decode_input::< + <#storage_ident as ::ink_lang::ContractConstructorDecoder>::Type>() + .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput) + .and_then(|decoder| { + <<#storage_ident as ::ink_lang::ContractConstructorDecoder>::Type + as ::ink_lang::ExecuteDispatchable>::execute_dispatchable(decoder) + }) + .unwrap_or_else(|error| { + ::core::panic!("dispatching ink! constructor failed: {}", error) + }) + } + + #[cfg(not(test))] + #[no_mangle] + fn call() { + if !#any_message_accept_payment { + ::ink_lang::deny_payment::<<#storage_ident as ::ink_lang::ContractEnv>::Env>() + .unwrap_or_else(|error| ::core::panic!("{}", error)) + } + ::ink_env::decode_input::< + <#storage_ident as ::ink_lang::ContractMessageDecoder>::Type>() + .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput) + .and_then(|decoder| { + <<#storage_ident as ::ink_lang::ContractMessageDecoder>::Type + as ::ink_lang::ExecuteDispatchable>::execute_dispatchable(decoder) + }) + .unwrap_or_else(|error| { + ::core::panic!("dispatching ink! message failed: {}", error) + }) + } + ) + } + /// Generates code for the ink! constructor decoder type of the ink! smart contract. /// /// This type can be used in order to decode the input bytes received by a call to `deploy` From 0961b7a6e054ba4ebea7450f847188c3af74e78b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:07:14 +0200 Subject: [PATCH 258/493] add ink_lang::execute_constructor_2 utility dispatch function --- crates/lang/src/dispatcher.rs | 30 ++++++++++++++++++++++++++++++ crates/lang/src/lib.rs | 1 + 2 files changed, 31 insertions(+) diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index c261a889ad..d745a977b9 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -219,3 +219,33 @@ where } Ok(()) } + +/// Executes the given ink! constructor. +/// +/// # Note +/// +/// The closure is supposed to already contain all the arguments that the real +/// constructor message requires and forwards them. +#[inline] +#[doc(hidden)] +pub fn execute_constructor_2( + uses_dynamic_storage_allocator: EnablesDynamicStorageAllocator, + f: F, +) -> Result<()> +where + S: ink_storage::traits::SpreadLayout, + F: FnOnce() -> S, +{ + let uses_dynamic_storage_allocator: bool = + uses_dynamic_storage_allocator.value(); + if uses_dynamic_storage_allocator { + alloc::initialize(ContractPhase::Deploy); + } + let storage = ManuallyDrop::new(f()); + let root_key = Key::from([0x00; 32]); + push_spread_root::(&storage, &root_key); + if uses_dynamic_storage_allocator { + alloc::finalize(); + } + Ok(()) +} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 1ad7055e22..41c6e0c184 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -49,6 +49,7 @@ pub use self::{ dispatcher::{ deny_payment, execute_constructor, + execute_constructor_2, execute_message, execute_message_mut, AcceptsPayments, From 6eb20db0ef34e9f465be92a422a64f20794327f7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:07:30 +0200 Subject: [PATCH 259/493] demand ExecuteDispatch trait impl from generated decoder types --- crates/lang/src/traits.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 289cd0efba..08f5dec9b5 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -388,13 +388,13 @@ pub trait DispatchableConstructorInfo { /// Generated type used to decode all dispatchable ink! messages of the ink! smart contract. pub trait ContractMessageDecoder { /// The ink! smart contract message decoder type. - type Type: scale::Decode; + type Type: scale::Decode + ExecuteDispatchable; } /// Generated type used to decode all dispatchable ink! constructors of the ink! smart contract. pub trait ContractConstructorDecoder { /// The ink! smart contract constructor decoder type. - type Type: scale::Decode; + type Type: scale::Decode + ExecuteDispatchable; } /// Implemented by the ink! smart contract message or constructor decoder. From 4781e5334d0adcb282fe47c107efb8d2ad532778 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:07:56 +0200 Subject: [PATCH 260/493] trait-incrementer constructor now takes and sets initial value --- examples/trait-incrementer/lib.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/trait-incrementer/lib.rs b/examples/trait-incrementer/lib.rs index da1ec86357..09d701f8f5 100644 --- a/examples/trait-incrementer/lib.rs +++ b/examples/trait-incrementer/lib.rs @@ -53,10 +53,8 @@ pub mod incrementer { impl Incrementer { /// Creates a new incrementer smart contract initialized with zero. #[ink(constructor)] - pub fn new() -> Self { - Self { - value: Default::default(), - } + pub fn new(init_value: u64) -> Self { + Self { value: init_value } } /// Increases the value of the incrementer by an amount. @@ -91,13 +89,13 @@ pub mod incrementer { #[test] fn default_works() { - let incrementer = Incrementer::new(); + let incrementer = Incrementer::new(0); assert_eq!(incrementer.get(), 0); } #[test] fn it_works() { - let mut incrementer = Incrementer::new(); + let mut incrementer = Incrementer::new(0); // Can call using universal call syntax using the trait. assert_eq!(::get(&incrementer), 0); ::inc(&mut incrementer); From 47c50bd3bde36c8f86b342fce9e6ecf93382de41 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 12:08:05 +0200 Subject: [PATCH 261/493] apply rustfmt --- crates/lang/codegen/src/generator/dispatch2.rs | 3 ++- crates/lang/src/dispatcher.rs | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 00f250b0d5..1b8f28ff4d 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -390,7 +390,8 @@ impl Dispatch<'_> { fn generate_entry_points(&self, message_spans: &[proc_macro2::Span]) -> TokenStream2 { let span = self.contract.module().storage().span(); let storage_ident = self.contract.module().storage().ident(); - let any_message_accept_payment = self.any_message_accepts_payment_expr(message_spans); + let any_message_accept_payment = + self.any_message_accepts_payment_expr(message_spans); quote_spanned!(span=> #[cfg(not(test))] #[no_mangle] diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index d745a977b9..488cbee998 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -236,8 +236,7 @@ where S: ink_storage::traits::SpreadLayout, F: FnOnce() -> S, { - let uses_dynamic_storage_allocator: bool = - uses_dynamic_storage_allocator.value(); + let uses_dynamic_storage_allocator: bool = uses_dynamic_storage_allocator.value(); if uses_dynamic_storage_allocator { alloc::initialize(ContractPhase::Deploy); } From 0c22563d50c974c114317bc80a54385bee70f966 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:19:11 +0200 Subject: [PATCH 262/493] implement message decoder type codegen for new dispatch --- .../lang/codegen/src/generator/dispatch2.rs | 160 ++++++++++++++++++ crates/lang/src/dispatcher.rs | 54 ++++++ crates/lang/src/lib.rs | 2 + 3 files changed, 216 insertions(+) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 1b8f28ff4d..97bb2d225c 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -71,6 +71,7 @@ impl GenerateCode for Dispatch<'_> { self.generate_dispatchable_message_infos(); let constructor_decoder_type = self.generate_constructor_decoder_type(&constructor_spans); + let message_decoder_type = self.generate_message_decoder_type(&message_spans); let _entry_points = self.generate_entry_points(&message_spans); quote! { #[cfg(not(test))] @@ -82,6 +83,7 @@ impl GenerateCode for Dispatch<'_> { #contract_dispatchable_constructor_infos #contract_dispatchable_messages_infos #constructor_decoder_type + #message_decoder_type // #entry_points }; } @@ -553,6 +555,164 @@ impl Dispatch<'_> { ) } + /// Generates code for the ink! message decoder type of the ink! smart contract. + /// + /// This type can be used in order to decode the input bytes received by a call to `call` + /// into one of the available dispatchable ink! messages and their arguments. + fn generate_message_decoder_type( + &self, + message_spans: &[proc_macro2::Span], + ) -> TokenStream2 { + assert_eq!(message_spans.len(), self.query_amount_messages()); + + /// Expands into the token sequence to represent the + /// input type of the ink! message at the given index. + fn expand_message_input( + span: proc_macro2::Span, + storage_ident: &syn::Ident, + message_index: usize, + ) -> TokenStream2 { + quote_spanned!(span=> + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#message_index] + }>>::Input + ) + } + + /// Returns the n-th ink! message identifier for the decoder type. + fn message_variant_ident(n: usize) -> syn::Ident { + quote::format_ident!("Message{}", n) + } + + let span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let count_messages = self.query_amount_messages(); + let message_variants = (0..count_messages).map(|index| { + let message_span = message_spans[index]; + let message_ident = message_variant_ident(index); + let message_input = expand_message_input(message_span, storage_ident, index); + quote_spanned!(message_span=> + #message_ident(#message_input) + ) + }); + let message_match = (0..count_messages).map(|index| { + let message_span = message_spans[index]; + let message_ident = message_variant_ident(index); + let message_selector = quote_spanned!(span=> + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::SELECTOR + ); + let message_input = expand_message_input(message_span, storage_ident, index); + quote_spanned!(message_span=> + #message_selector => { + ::core::result::Result::Ok(Self::#message_ident( + <#message_input as ::scale::Decode>::decode(input)? + )) + } + ) + }); + let any_message_accept_payment = self.any_message_accepts_payment_expr(message_spans); + let message_execute = (0..count_messages).map(|index| { + let message_span = message_spans[index]; + let message_ident = message_variant_ident(index); + let message_callable = quote_spanned!(message_span=> + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::CALLABLE + ); + let message_output = quote_spanned!(message_span=> + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::Output + ); + let accepts_payment = quote_spanned!(message_span=> + { + true && + #any_message_accept_payment && + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::PAYABLE + } + ); + let mutates_storage = quote_spanned!(message_span=> + { + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::MUTATES + } + ); + let is_dynamic_storage_allocation_enabled = self + .contract + .config() + .is_dynamic_storage_allocator_enabled(); + quote_spanned!(message_span=> + Self::#message_ident(input) => { + ::ink_lang::execute_message_2::< + #storage_ident, + #message_output, + _ + >( + ::ink_lang::AcceptsPayments(#accepts_payment), + ::ink_lang::MutatesStorage(#mutates_storage), + ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), + move |storage: &mut #storage_ident| { #message_callable(storage, input) } + ) + } + ) + }); + + quote_spanned!(span=> + const _: () = { + #[derive(::core::fmt::Debug)] + #[allow(non_camel_case_types)] + pub enum __ink_MessageDecoder { + #( #message_variants ),* + } + + impl ::scale::Decode for __ink_MessageDecoder { + fn decode(input: &mut I) -> ::core::result::Result + where + I: ::scale::Input, + { + match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { + #( #message_match , )* + _invalid => ::core::result::Result::Err( + <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( + "encountered unknown ink! message selector" + ) + ) + } + } + } + + impl ::ink_lang::ExecuteDispatchable for __ink_MessageDecoder { + fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { + match self { + #( #message_execute ),* + } + } + } + + impl ::ink_lang::ContractMessageDecoder for #storage_ident { + type Type = __ink_MessageDecoder; + } + }; + ) + } + /// Generates code to express if any dispatchable ink! message accepts payment. /// /// This information can be used to speed-up dispatch since denying of payment diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index 488cbee998..c9e9cbe90f 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -14,6 +14,7 @@ use crate::{ Constructor, + ContractEnv, DispatchError, FnOutput, FnState, @@ -35,6 +36,7 @@ use ink_storage::{ traits::{ pull_spread_root, push_spread_root, + SpreadLayout, }, }; @@ -79,6 +81,18 @@ impl AcceptsPayments { } } +/// Yields `true` if the associated ink! message may mutate contract storage. +#[derive(Copy, Clone)] +#[doc(hidden)] +pub struct MutatesStorage(pub bool); + +impl MutatesStorage { + /// Returns the value of the property. + pub const fn value(self) -> bool { + self.0 + } +} + /// Yields `true` if the dynamic storage allocator is enabled for the given call. #[derive(Copy, Clone)] #[doc(hidden)] @@ -248,3 +262,43 @@ where } Ok(()) } + +/// Executes the given `&mut self` message closure. +/// +/// # Note +/// +/// The closure is supposed to already contain all the arguments that the real +/// message requires and forwards them. +#[inline] +#[doc(hidden)] +pub fn execute_message_2( + AcceptsPayments(accepts_payments): AcceptsPayments, + MutatesStorage(mutates_storage): MutatesStorage, + EnablesDynamicStorageAllocator(enables_dynamic_storage_allocator): EnablesDynamicStorageAllocator, + f: F, +) -> Result<()> +where + Storage: SpreadLayout + ContractEnv, + Output: scale::Encode + 'static, + F: FnOnce(&mut Storage) -> Output, +{ + if !accepts_payments { + deny_payment::<::Env>()?; + } + if enables_dynamic_storage_allocator { + alloc::initialize(ContractPhase::Call); + } + let root_key = Key::from([0x00; 32]); + let mut storage = ManuallyDrop::new(pull_spread_root::(&root_key)); + let result = f(&mut storage); + if mutates_storage { + push_spread_root::(&storage, &root_key); + } + if enables_dynamic_storage_allocator { + alloc::finalize(); + } + if TypeId::of::() != TypeId::of::<()>() { + ink_env::return_value::(ReturnFlags::default(), &result) + } + Ok(()) +} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 41c6e0c184..9f31e775fe 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -51,12 +51,14 @@ pub use self::{ execute_constructor, execute_constructor_2, execute_message, + execute_message_2, execute_message_mut, AcceptsPayments, ConstructorDispatcher, EnablesDynamicStorageAllocator, Execute, MessageDispatcher, + MutatesStorage, }, env_access::{ ContractEnv, From c3e3e70e86690b7248e573eff4189a57929ffc48 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:19:28 +0200 Subject: [PATCH 263/493] enable entry point codegen for new dispatch --- crates/lang/codegen/src/generator/dispatch2.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 97bb2d225c..826b8fe315 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -72,7 +72,7 @@ impl GenerateCode for Dispatch<'_> { let constructor_decoder_type = self.generate_constructor_decoder_type(&constructor_spans); let message_decoder_type = self.generate_message_decoder_type(&message_spans); - let _entry_points = self.generate_entry_points(&message_spans); + let entry_points = self.generate_entry_points(&message_spans); quote! { #[cfg(not(test))] #cfg_not_as_dependency @@ -84,7 +84,7 @@ impl GenerateCode for Dispatch<'_> { #contract_dispatchable_messages_infos #constructor_decoder_type #message_decoder_type - // #entry_points + #entry_points }; } } From 4d57a8dc1696d9ab1a0582f81f61d4f130035372 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:19:49 +0200 Subject: [PATCH 264/493] fix doc comment --- crates/lang/codegen/src/generator/dispatch2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch2.rs index 826b8fe315..88aa57f491 100644 --- a/crates/lang/codegen/src/generator/dispatch2.rs +++ b/crates/lang/codegen/src/generator/dispatch2.rs @@ -457,7 +457,7 @@ impl Dispatch<'_> { ) } - /// Returns the n-th constructor identifier for the decoder type. + /// Returns the n-th ink! constructor identifier for the decoder type. fn constructor_variant_ident(n: usize) -> syn::Ident { quote::format_ident!("Constructor{}", n) } From 7e9128d7d82a8d073918330ede84c6be770cf0b5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:20:55 +0200 Subject: [PATCH 265/493] remove old dispatch codegen --- crates/lang/codegen/src/generator/contract.rs | 2 - crates/lang/codegen/src/generator/dispatch.rs | 700 ------------------ crates/lang/codegen/src/generator/mod.rs | 2 - 3 files changed, 704 deletions(-) delete mode 100644 crates/lang/codegen/src/generator/dispatch.rs diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index 2481e65819..d71dc55d16 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -39,7 +39,6 @@ impl GenerateCode for Contract<'_> { let env = self.generate_code_using::(); let storage = self.generate_code_using::(); let events = self.generate_code_using::(); - let dispatch = self.generate_code_using::(); let dispatch2 = self.generate_code_using::(); let item_impls = self.generate_code_using::(); let metadata = self.generate_code_using::(); @@ -57,7 +56,6 @@ impl GenerateCode for Contract<'_> { #env #storage #events - #dispatch #dispatch2 #item_impls #contract_reference diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs deleted file mode 100644 index fb25937b71..0000000000 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ /dev/null @@ -1,700 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::{ - generator, - GenerateCode, - GenerateCodeUsing as _, -}; -use derive_more::From; -use ir::{ - Callable as _, - HexLiteral as _, -}; -use proc_macro2::{ - Ident, - TokenStream as TokenStream2, -}; -use quote::{ - format_ident, - quote, - quote_spanned, -}; -use syn::spanned::Spanned as _; - -/// Generates code for the message and constructor dispatcher. -/// -/// This code efficiently selects the dispatched ink! constructor or message -/// by inspecting the first four bytes (selector) of the given input bytes. -/// -/// As this happens on every contract execution this code must be highly optimized. -/// For that purpose a so-called dispatch enum is being generated that has a -/// specialized `scale::Decode` implementation taking the first four bytes of -/// the input stream in order to identify the enum variant that it is going to -/// produce out of the rest of the input buffer. -/// -/// The rest of the input buffer is then automatically decoded directly into the -/// expected input types of the respective ink! constructor or message. -#[derive(From)] -pub struct Dispatch<'a> { - contract: &'a ir::Contract, -} -impl_as_ref_for_generator!(Dispatch); - -impl GenerateCode for Dispatch<'_> { - fn generate_code(&self) -> TokenStream2 { - let no_cross_calling_cfg = - self.generate_code_using::(); - let entry_points = self.generate_entry_points(); - let dispatch_using_mode = self.generate_dispatch_using_mode(); - let dispatch_trait_impl_namespaces = self.generate_trait_impl_namespaces(); - let dispatch_trait_impls = self.generate_dispatch_trait_impls(); - let message_dispatch_enum = self.generate_message_dispatch_enum(); - let constructor_dispatch_enum = self.generate_constructor_dispatch_enum(); - quote! { - // We do not generate contract dispatch code while the contract - // is being tested or the contract is a dependency of another - // since both resulting compilations do not require dispatching. - #[cfg(not(test))] - #no_cross_calling_cfg - const _: () = { - #entry_points - #dispatch_using_mode - #dispatch_trait_impl_namespaces - #dispatch_trait_impls - #message_dispatch_enum - #constructor_dispatch_enum - }; - } - } -} - -impl Dispatch<'_> { - /// Generates the static ink! contract entry points. - /// - /// # Note - /// - /// Those are expected to exist by the smart contracts host module. - /// They guide the dispatch, set-up and tear-down of a smart contract. - fn generate_entry_points(&self) -> TokenStream2 { - let storage_ident = self.contract.module().storage().ident(); - let all_messages_deny_payment = self.all_messages_deny_payment(); - quote! { - #[cfg(not(test))] - #[no_mangle] - fn deploy() { - <#storage_ident as ::ink_lang::DispatchUsingMode>::dispatch_using_mode( - ::ink_lang::DispatchMode::Instantiate, - ).unwrap_or_else(|error| { - ::core::panic!("dispatching constructor failed: {}", error) - }) - } - - #[cfg(not(test))] - #[no_mangle] - fn call() { - if #all_messages_deny_payment { - ::ink_lang::deny_payment::<<#storage_ident as ::ink_lang::ContractEnv>::Env>() - .expect("caller transferred value even though all ink! message deny payments") - } - <#storage_ident as ::ink_lang::DispatchUsingMode>::dispatch_using_mode( - ::ink_lang::DispatchMode::Call, - ).unwrap_or_else(|error| { - ::core::panic!("dispatching message failed: {}", error) - }) - } - } - } - - /// Generates the `DispatchUsingMode` trait implementation to guide contract dispatch. - fn generate_dispatch_using_mode(&self) -> TokenStream2 { - let storage_ident = self.contract.module().storage().ident(); - quote! { - impl ::ink_lang::DispatchUsingMode for #storage_ident { - #[allow(unused_parens)] - fn dispatch_using_mode( - mode: ::ink_lang::DispatchMode - ) -> ::core::result::Result<(), ::ink_lang::DispatchError> { - match mode { - ::ink_lang::DispatchMode::Instantiate => { - <<#storage_ident as ::ink_lang::ConstructorDispatcher>::Type as ::ink_lang::Execute>::execute( - ::ink_env::decode_input::<<#storage_ident as ::ink_lang::ConstructorDispatcher>::Type>() - .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput)? - ) - } - ::ink_lang::DispatchMode::Call => { - <<#storage_ident as ::ink_lang::MessageDispatcher>::Type as ::ink_lang::Execute>::execute( - ::ink_env::decode_input::<<#storage_ident as ::ink_lang::MessageDispatcher>::Type>() - .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput)? - ) - } - } - } - } - } - } - - /// Returns the generated ink! namespace identifier for the given callable kind. - fn dispatch_trait_impl_namespace(kind: ir::CallableKind) -> Ident { - match kind { - ir::CallableKind::Constructor => format_ident!("__ink_ConstructorInfo"), - ir::CallableKind::Message => format_ident!("__ink_MessageInfo"), - } - } - - /// Generates utility types to emulate namespaces to disambiguate dispatch trait - /// implementations for ink! messages and ink! constructors with overlapping - /// selectors. - fn generate_trait_impl_namespaces(&self) -> TokenStream2 { - let message_namespace = - Self::dispatch_trait_impl_namespace(ir::CallableKind::Message); - let constructor_namespace = - Self::dispatch_trait_impl_namespace(ir::CallableKind::Constructor); - quote! { - // Selector namespace for ink! messages of the root smart contract. - // - // # Note - // - // - We have separate namespaces for ink! messages and constructors to - // allow for overlapping selectors between them. - // - The `ID` const parameter uniquely identifies one of the ink! messages - // implemented by the root smart contract. - #[doc(hidden)] - pub struct #message_namespace {} - - // Selector namespace for ink! constructors of the root smart contract. - // - // # Note - // - // - We have separate namespaces for ink! messages and constructors to - // allow for overlapping selectors between them. - // - The `ID` const parameter uniquely identifies one of the ink! constructors - // implemented by the root smart contract. - #[doc(hidden)] - pub struct #constructor_namespace {} - } - } - - /// Generates code for the dispatch trait implementations for a generic ink! callable. - fn generate_trait_impls_for_callable( - &self, - cws: ir::CallableWithSelector<'_, C>, - ) -> TokenStream2 - where - C: ir::Callable + quote::ToTokens, - { - let callable = cws.callable(); - let callable_span = callable.span(); - let selector = cws.composed_selector(); - let (selector_bytes, selector_id) = ( - selector.hex_lits(), - selector.into_be_u32().hex_padded_suffixed(), - ); - let input_types = callable - .inputs() - .map(|pat_type| &pat_type.ty) - .collect::>(); - let storage_ident = self.contract.module().storage().ident(); - let namespace = Self::dispatch_trait_impl_namespace(cws.kind()); - let input_types_tuple = if input_types.len() != 1 { - // Pack all types into a tuple if they are not exactly 1. - // This results in `()` for zero input types. - quote! { ( #( #input_types ),* ) } - } else { - // Return the single type without turning it into a tuple. - quote! { #( #input_types )* } - }; - let fn_input_impl = quote_spanned!(callable.inputs_span() => - impl ::ink_lang::FnInput for #namespace::<#selector_id> { - type Input = #input_types_tuple; - } - ); - let fn_selector_impl = quote_spanned!(callable_span => - impl ::ink_lang::FnSelector for #namespace::<#selector_id> { - const SELECTOR: ::ink_env::call::Selector = ::ink_env::call::Selector::new([ - #( #selector_bytes ),* - ]); - } - ); - let fn_state_impl = quote_spanned!(callable_span => - impl ::ink_lang::FnState for #namespace::<#selector_id> { - type State = #storage_ident; - } - ); - quote! { - #fn_input_impl - #fn_selector_impl - #fn_state_impl - } - } - - /// Returns a tuple of: - /// - /// - Vector over the generated identifier bindings (`__ink_binding_N`) for all inputs. - /// - `TokenStream` representing the binding identifiers as tuple (for equal to two or more inputs), - /// as single identifier (for exactly one input) or as wildcard (`_`) if there are - /// no input bindings. - /// - /// # Examples - /// - /// **No inputs:** - /// ``` - /// # use quote::quote; - /// # let x: (Vec<()>, _) = - /// ( vec![], - /// quote! { _ } ) - /// # ; - /// ``` - /// - /// **Exactly one input:** - /// ``` - /// # use quote::quote; - /// # let __ink_binding_0 = (); - /// ( vec![__ink_binding_0], - /// quote! { __ink_binding_0 } ) - /// # ; - /// ``` - /// - /// **Multiple (equal to two or more) inputs:** - /// ``` - /// # use quote::quote; - /// # let __ink_binding_0 = (); - /// # let __ink_binding_1 = (); - /// ( vec![__ink_binding_0, __ink_binding_1, /* ... */], - /// quote! { (__ink_binding_0, __ink_binding_1, ..) } ) - /// # ; - /// ``` - fn generate_input_bindings_tuple(callable: &C) -> (Vec, TokenStream2) - where - C: ir::Callable, - { - let input_bindings = generator::input_bindings(callable.inputs()); - let inputs_as_tuple_or_wildcard = match input_bindings.len() { - 0 => quote! { _ }, - 1 => quote! { #( #input_bindings ),* }, - _ => quote! { ( #( #input_bindings ),* ) }, - }; - (input_bindings, inputs_as_tuple_or_wildcard) - } - - /// Generates all the dispatch trait implementations for the given ink! message. - fn generate_trait_impls_for_message( - &self, - cws: ir::CallableWithSelector<'_, ir::Message>, - ) -> TokenStream2 { - let message = cws.callable(); - let message_span = message.span(); - let selector = cws.composed_selector(); - let selector_id = selector.into_be_u32().hex_padded_suffixed(); - let output_tokens = message - .output() - .map(quote::ToTokens::to_token_stream) - .unwrap_or_else(|| quote! { () }); - let is_mut = message.receiver().is_ref_mut(); - let storage_ident = self.contract.module().storage().ident(); - let message_ident = message.ident(); - let namespace = Self::dispatch_trait_impl_namespace(ir::CallableKind::Message); - let fn_output_impl = quote_spanned!(message.output().span() => - impl ::ink_lang::FnOutput for #namespace::<#selector_id> { - #[allow(unused_parens)] - type Output = #output_tokens; - } - ); - let callable_impl = self.generate_trait_impls_for_callable(cws); - let (mut_token, message_trait_ident) = if is_mut { - ( - Some(syn::token::Mut::default()), - format_ident!("MessageMut"), - ) - } else { - (None, format_ident!("MessageRef")) - }; - let (input_bindings, inputs_as_tuple_or_wildcard) = - Self::generate_input_bindings_tuple(message); - let as_trait = cws.item_impl().trait_path().map(|trait_path| { - quote_spanned!(message_span => - as #trait_path - ) - }); - let message_impl = quote_spanned!(message_span => - impl ::ink_lang::#message_trait_ident for #namespace::<#selector_id> { - const CALLABLE: fn( - &#mut_token ::State, - ::Input - ) -> ::Output = |state, #inputs_as_tuple_or_wildcard| { - <#storage_ident #as_trait>::#message_ident(state, #( #input_bindings ),* ) - }; - } - ); - quote_spanned!(message_span => - #callable_impl - #fn_output_impl - #message_impl - ) - } - - /// Generates all the dispatch trait implementations for the given ink! constructor. - fn generate_trait_impls_for_constructor( - &self, - cws: ir::CallableWithSelector<'_, ir::Constructor>, - ) -> TokenStream2 { - let constructor = cws.callable(); - let constructor_span = constructor.span(); - let selector = cws.composed_selector(); - let selector_id = selector.into_be_u32().hex_padded_suffixed(); - let storage_ident = self.contract.module().storage().ident(); - let constructor_ident = constructor.ident(); - let namespace = - Self::dispatch_trait_impl_namespace(ir::CallableKind::Constructor); - let callable_impl = self.generate_trait_impls_for_callable(cws); - let (input_bindings, inputs_as_tuple_or_wildcard) = - Self::generate_input_bindings_tuple(constructor); - let as_trait = cws.item_impl().trait_path().map(|trait_path| { - quote_spanned!(constructor_span => - as #trait_path - ) - }); - let constructor_impl = quote_spanned!(constructor_span => - impl ::ink_lang::Constructor for #namespace::<#selector_id> { - const CALLABLE: fn( - ::Input - ) -> ::State = |#inputs_as_tuple_or_wildcard| { - <#storage_ident #as_trait>::#constructor_ident(#( #input_bindings ),* ) - }; - } - ); - quote_spanned!(constructor_span => - #callable_impl - #constructor_impl - ) - } - - /// Generate all dispatch trait implementations for ink! messages and ink! constructors. - fn generate_dispatch_trait_impls(&self) -> TokenStream2 { - let message_impls = self - .contract_messages() - .map(|message| self.generate_trait_impls_for_message(message)); - let constructor_impls = self - .contract_constructors() - .map(|constructor| self.generate_trait_impls_for_constructor(constructor)); - quote! { - #( #message_impls )* - #( #constructor_impls )* - } - } - - /// Generates variant identifiers for the generated dispatch enum. - /// - /// Since we want to avoid generating random names we generate identifiers - /// in terms of the selectors of the associated ink! messages or constructors. - /// - /// ## Example - /// - /// Given prefix of `"Message"` and selector with bytes `0xDEADBEEF` we - /// generate the following identifier: `__ink_Message_0xdeadbeef` - /// - /// This way it is clear that this is an ink! generated identifier and even - /// encodes the unique selector bytes to make the identifier unique. - fn generate_dispatch_variant_ident( - &self, - cws: ir::CallableWithSelector<'_, C>, - ) -> Ident - where - C: ir::Callable, - { - let selector_bytes = cws.composed_selector().as_bytes().to_owned(); - let prefix = match cws.callable().kind() { - ir::CallableKind::Message => "Message", - ir::CallableKind::Constructor => "Constructor", - }; - quote::format_ident!( - "__ink_{}_0x{:02X}{:02X}{:02X}{:02X}", - prefix, - selector_bytes[0], - selector_bytes[1], - selector_bytes[2], - selector_bytes[3] - ) - } - - /// Generates one match arm of the dispatch `scale::Decode` implementation. - /// - /// # Note - /// - /// There is one match arm per ink! constructor or message for the dispatch - /// `scale::Decode` implementation. - fn generate_dispatch_variant_decode( - &self, - cws: ir::CallableWithSelector<'_, C>, - ) -> TokenStream2 - where - C: ir::Callable, - { - let selector_bytes = cws.composed_selector().hex_lits(); - let variant_ident = self.generate_dispatch_variant_ident(cws); - let variant_types = cws.callable().inputs().map(|arg| &arg.ty); - quote! { - [ #( #selector_bytes ),* ] => { - ::core::result::Result::Ok(Self::#variant_ident( - #( - <#variant_types as ::scale::Decode>::decode(input)? - ),* - )) - } - } - } - - /// Generates one match arm of the dispatch variant enum. - /// - /// # Note - /// - /// There is one match arm per ink! constructor or message for the dispatch - /// `scale::Decode` implementation. - fn generate_dispatch_variant_arm( - &self, - cws: ir::CallableWithSelector<'_, C>, - ) -> TokenStream2 - where - C: ir::Callable, - { - let input_types = cws.callable().inputs().map(|arg| &arg.ty); - let variant_ident = self.generate_dispatch_variant_ident(cws); - quote! { - #variant_ident(#(#input_types),*) - } - } - - /// Returns `true` if all ink! messages of `self` deny payments. - /// - /// # Note - /// - /// This information is used to produce better code in this scenario. - fn all_messages_deny_payment(&self) -> bool { - self.contract - .module() - .impls() - .flat_map(ir::ItemImpl::iter_messages) - .all(|message| !message.is_payable()) - } - - /// Generates one match arm of the dispatch message for the `execute` implementation. - /// - /// # Note - /// - /// This is basically the code per ink! message that is going to be executed after - /// the dispatch has already taken place. - fn generate_dispatch_execute_message_arm( - &self, - cws: ir::CallableWithSelector<'_, ir::Message>, - ) -> TokenStream2 { - let storage_ident = self.contract.module().storage().ident(); - let ident = self.generate_dispatch_variant_ident(cws); - let message = cws.callable(); - let arg_pats = message.inputs().map(|arg| &arg.pat).collect::>(); - let arg_inputs = if arg_pats.len() == 1 { - quote! { #(#arg_pats),* } - } else { - quote! { ( #(#arg_pats),* ) } - }; - let (mut_mod, msg_trait, exec_fn) = match message.receiver() { - ir::Receiver::RefMut => { - ( - Some(quote! { mut }), - quote! { MessageMut }, - quote! { execute_message_mut }, - ) - } - ir::Receiver::Ref => { - (None, quote! { MessageRef }, quote! { execute_message }) - } - }; - let selector_id = cws.composed_selector().into_be_u32().hex_padded_suffixed(); - let namespace = Self::dispatch_trait_impl_namespace(ir::CallableKind::Message); - // If all ink! messages deny payment we can move the payment check to before - // the message dispatch which is more efficient. - let accepts_payments = cws.is_payable() || self.all_messages_deny_payment(); - let is_dynamic_storage_allocation_enabled = self - .contract - .config() - .is_dynamic_storage_allocator_enabled(); - quote! { - Self::#ident(#(#arg_pats),*) => { - ::ink_lang::#exec_fn::<<#storage_ident as ::ink_lang::ContractEnv>::Env, #namespace::<#selector_id>, _>( - ::ink_lang::AcceptsPayments(#accepts_payments), - ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), - move |state: &#mut_mod #storage_ident| { - <#namespace::<#selector_id> as ::ink_lang::#msg_trait>::CALLABLE( - state, #arg_inputs - ) - } - ) - } - } - } - - /// Returns an iterator over all ink! messages of the ink! contract. - fn contract_messages( - &self, - ) -> impl Iterator> { - self.contract - .module() - .impls() - .map(|impl_item| impl_item.iter_messages()) - .flatten() - } - - /// Generates the entire dispatch variant enum for all ink! messages. - fn generate_message_dispatch_enum(&self) -> TokenStream2 { - let storage_ident = self.contract.module().storage().ident(); - let message_variants = self - .contract_messages() - .map(|message| self.generate_dispatch_variant_arm(message)); - let decode_message = self - .contract_messages() - .map(|message| self.generate_dispatch_variant_decode(message)); - let execute_variants = self - .contract_messages() - .map(|message| self.generate_dispatch_execute_message_arm(message)); - quote! { - const _: () = { - #[doc(hidden)] - pub enum __ink_MessageDispatchEnum { - #( #message_variants ),* - } - - impl ::ink_lang::MessageDispatcher for #storage_ident { - type Type = __ink_MessageDispatchEnum; - } - - impl ::scale::Decode for __ink_MessageDispatchEnum { - fn decode(input: &mut I) -> ::core::result::Result { - match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { - #( #decode_message )* - _invalid => ::core::result::Result::Err( - <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( - "encountered unknown ink! message selector" - ) - ) - } - } - } - - impl ::ink_lang::Execute for __ink_MessageDispatchEnum { - fn execute(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { - match self { - #( #execute_variants )* - } - } - } - }; - } - } - - /// Generates one match arm of the dispatch constructor for the `execute` implementation. - /// - /// # Note - /// - /// This is basically the code per ink! constructor that is going to be executed after - /// the dispatch has already taken place. - fn generate_dispatch_execute_constructor_arm( - &self, - cws: ir::CallableWithSelector<'_, ir::Constructor>, - ) -> TokenStream2 { - let ident = self.generate_dispatch_variant_ident(cws); - let constructor = cws.callable(); - let arg_pats = constructor.inputs().map(|arg| &arg.pat).collect::>(); - let arg_inputs = if arg_pats.len() == 1 { - quote! { #(#arg_pats),* } - } else { - quote! { ( #(#arg_pats),* ) } - }; - let selector_id = cws.composed_selector().into_be_u32().hex_padded_suffixed(); - let namespace = - Self::dispatch_trait_impl_namespace(ir::CallableKind::Constructor); - let is_dynamic_storage_allocation_enabled = self - .contract - .config() - .is_dynamic_storage_allocator_enabled(); - quote! { - Self::#ident(#(#arg_pats),*) => { - ::ink_lang::execute_constructor::<#namespace::<#selector_id>, _>( - ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), - move || { - <#namespace::<#selector_id> as ::ink_lang::Constructor>::CALLABLE( - #arg_inputs - ) - } - ) - } - } - } - - /// Returns an iterator over all ink! constructors of the ink! contract. - fn contract_constructors( - &self, - ) -> impl Iterator> { - self.contract - .module() - .impls() - .map(|impl_item| impl_item.iter_constructors()) - .flatten() - } - - /// Generates the entire dispatch variant enum for all ink! messages. - fn generate_constructor_dispatch_enum(&self) -> TokenStream2 { - let storage_ident = self.contract.module().storage().ident(); - let message_variants = self - .contract_constructors() - .map(|message| self.generate_dispatch_variant_arm(message)); - let decode_message = self - .contract_constructors() - .map(|message| self.generate_dispatch_variant_decode(message)); - let execute_variants = self - .contract_constructors() - .map(|cws| self.generate_dispatch_execute_constructor_arm(cws)); - quote! { - const _: () = { - #[doc(hidden)] - pub enum __ink_ConstructorDispatchEnum { - #( #message_variants ),* - } - - impl ::ink_lang::ConstructorDispatcher for #storage_ident { - type Type = __ink_ConstructorDispatchEnum; - } - - impl ::scale::Decode for __ink_ConstructorDispatchEnum { - fn decode(input: &mut I) -> ::core::result::Result { - match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { - #( #decode_message )* - _invalid => ::core::result::Result::Err( - <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( - "encountered unknown ink! constructor selector" - ) - ) - } - } - } - - impl ::ink_lang::Execute for __ink_ConstructorDispatchEnum { - fn execute(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { - match self { - #( #execute_variants )* - } - } - } - }; - } - } -} diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 8bd1fdea5f..8d27c20f1b 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -30,7 +30,6 @@ mod arg_list; mod as_dependency; mod chain_extension; mod contract; -mod dispatch; mod dispatch2; mod env; mod events; @@ -57,7 +56,6 @@ pub use self::{ }, chain_extension::ChainExtension, contract::Contract, - dispatch::Dispatch, dispatch2::Dispatch as Dispatch2, env::Env, events::Events, From 8a833a716bbbe9ac3285c94349daaed1f5e409f0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:21:43 +0200 Subject: [PATCH 266/493] rename dispatch2 module to dispatch --- crates/lang/codegen/src/generator/contract.rs | 2 +- .../lang/codegen/src/generator/{dispatch2.rs => dispatch.rs} | 0 crates/lang/codegen/src/generator/mod.rs | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename crates/lang/codegen/src/generator/{dispatch2.rs => dispatch.rs} (100%) diff --git a/crates/lang/codegen/src/generator/contract.rs b/crates/lang/codegen/src/generator/contract.rs index d71dc55d16..47074f9a8f 100644 --- a/crates/lang/codegen/src/generator/contract.rs +++ b/crates/lang/codegen/src/generator/contract.rs @@ -39,7 +39,7 @@ impl GenerateCode for Contract<'_> { let env = self.generate_code_using::(); let storage = self.generate_code_using::(); let events = self.generate_code_using::(); - let dispatch2 = self.generate_code_using::(); + let dispatch2 = self.generate_code_using::(); let item_impls = self.generate_code_using::(); let metadata = self.generate_code_using::(); let contract_reference = diff --git a/crates/lang/codegen/src/generator/dispatch2.rs b/crates/lang/codegen/src/generator/dispatch.rs similarity index 100% rename from crates/lang/codegen/src/generator/dispatch2.rs rename to crates/lang/codegen/src/generator/dispatch.rs diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 8d27c20f1b..eeb6ee7a7a 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -30,7 +30,7 @@ mod arg_list; mod as_dependency; mod chain_extension; mod contract; -mod dispatch2; +mod dispatch; mod env; mod events; mod ink_test; @@ -56,7 +56,7 @@ pub use self::{ }, chain_extension::ChainExtension, contract::Contract, - dispatch2::Dispatch as Dispatch2, + dispatch::Dispatch, env::Env, events::Events, ink_test::InkTest, From 5250fb98f1fcd8fd13267279d87520c3f7e71935 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:21:53 +0200 Subject: [PATCH 267/493] apply rustfmt --- crates/lang/codegen/src/generator/dispatch.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 88aa57f491..6d8990ddda 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -616,7 +616,8 @@ impl Dispatch<'_> { } ) }); - let any_message_accept_payment = self.any_message_accepts_payment_expr(message_spans); + let any_message_accept_payment = + self.any_message_accepts_payment_expr(message_spans); let message_execute = (0..count_messages).map(|index| { let message_span = message_spans[index]; let message_ident = message_variant_ident(index); From 8600023c6c0b5f887c24706e8b6ccb2f1fb4b2ee Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:27:44 +0200 Subject: [PATCH 268/493] generate dispatch info trait impls always They are useful generally and not only when compiled as root contract. --- crates/lang/codegen/src/generator/dispatch.rs | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 6d8990ddda..ce79cce161 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -74,16 +74,17 @@ impl GenerateCode for Dispatch<'_> { let message_decoder_type = self.generate_message_decoder_type(&message_spans); let entry_points = self.generate_entry_points(&message_spans); quote! { + #amount_dispatchables + #contract_dispatchable_messages + #contract_dispatchable_constructors + #contract_dispatchable_constructor_infos + #contract_dispatchable_messages_infos + #constructor_decoder_type + #message_decoder_type + #[cfg(not(test))] #cfg_not_as_dependency const _: () = { - #amount_dispatchables - #contract_dispatchable_messages - #contract_dispatchable_constructors - #contract_dispatchable_constructor_infos - #contract_dispatchable_messages_infos - #constructor_decoder_type - #message_decoder_type #entry_points }; } @@ -731,13 +732,11 @@ impl Dispatch<'_> { let message_is_payable = (0..count_messages).map(|index| { let message_span = message_spans[index]; quote_spanned!(message_span=> - { - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES - }>>::IDS[#index] - }>>::PAYABLE - } + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::PAYABLE ) }); quote_spanned!(span=> From 3cb6cecb929130758dafdc43e007fd7acaeeee6d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:34:33 +0200 Subject: [PATCH 269/493] no longer generate unnecessary braces in new dispatch codegen --- crates/lang/codegen/src/generator/dispatch.rs | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index ce79cce161..900d27ee40 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -637,24 +637,20 @@ impl Dispatch<'_> { }>>::Output ); let accepts_payment = quote_spanned!(message_span=> - { - true && - #any_message_accept_payment && - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES - }>>::IDS[#index] - }>>::PAYABLE - } + true && + #any_message_accept_payment && + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::PAYABLE ); let mutates_storage = quote_spanned!(message_span=> - { - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES - }>>::IDS[#index] - }>>::MUTATES - } + <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + }>>::IDS[#index] + }>>::MUTATES ); let is_dynamic_storage_allocation_enabled = self .contract From c0a0393158536c5fc2c03b4b7bd3c49700fa6969 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 13:34:46 +0200 Subject: [PATCH 270/493] adjust UI tests for new dispatch codegen --- .../M-04-message-returns-non-codec.stderr | 24 ++++++++++--------- .../fail/S-04-non-storage-ink-impls.stderr | 24 +++++++++---------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr index c4f1e57cca..251a87e5cf 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr @@ -1,15 +1,17 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied - --> $DIR/M-04-message-returns-non-codec.rs:18:49 - | -18 | pub fn returns_non_codec_type(&self) -> NonCodec { - | ^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` - | - = note: required because of the requirements on the impl of `Encode` for `NonCodec` -note: required by a bound in `ink_lang::FnOutput::Output` - --> $DIR/traits.rs:81:18 - | -81 | type Output: scale::Encode + 'static; - | ^^^^^^^^^^^^^ required by this bound in `ink_lang::FnOutput::Output` + --> $DIR/M-04-message-returns-non-codec.rs:18:9 + | +18 | / pub fn returns_non_codec_type(&self) -> NonCodec { +19 | | NonCodec +20 | | } + | |_________^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` + | + = note: required because of the requirements on the impl of `Encode` for `NonCodec` +note: required by a bound in `execute_message_2` + --> $DIR/dispatcher.rs:282:13 + | +282 | Output: scale::Encode + 'static, + | ^^^^^^^^^^^^^ required by this bound in `execute_message_2` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied --> $DIR/M-04-message-returns-non-codec.rs:18:9 diff --git a/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr b/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr index 93e6fa7855..327a92c10d 100644 --- a/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr @@ -14,18 +14,6 @@ note: required by a bound in `non_storage_ink_impls::_::_::{closure#0}::assert_t | required by this bound in `non_storage_ink_impls::_::_::{closure#0}::assert_type_eq_all` = note: this error originates in the macro `::ink_lang::static_assertions::assert_type_eq_all` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0599]: no function or associated item named `message2` found for struct `StorageStruct` in the current scope - --> $DIR/S-04-non-storage-ink-impls.rs:35:16 - | -9 | pub struct StorageStruct {} - | ------------------------ function or associated item `message2` not found for this -... -35 | pub fn message2(&self) {} - | ^^^^^^^^ - | | - | function or associated item not found in `StorageStruct` - | help: there is an associated function with a similar name: `message1` - error[E0599]: no function or associated item named `constructor2` found for struct `StorageStruct` in the current scope --> $DIR/S-04-non-storage-ink-impls.rs:30:16 | @@ -37,3 +25,15 @@ error[E0599]: no function or associated item named `constructor2` found for stru | | | function or associated item not found in `StorageStruct` | help: there is an associated function with a similar name: `constructor1` + +error[E0599]: no function or associated item named `message2` found for struct `StorageStruct` in the current scope + --> $DIR/S-04-non-storage-ink-impls.rs:35:16 + | +9 | pub struct StorageStruct {} + | ------------------------ function or associated item `message2` not found for this +... +35 | pub fn message2(&self) {} + | ^^^^^^^^ + | | + | function or associated item not found in `StorageStruct` + | help: there is an associated function with a similar name: `message1` From 82d74ff53544deacc937d5d9c1afee1d9464881b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 19:35:56 +0200 Subject: [PATCH 271/493] no longer derive core::fmt::Debug for dispatch decoder types This fixes a doc test since this implied a Debug bound on all message and constructor inputs. --- crates/lang/codegen/src/generator/dispatch.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 900d27ee40..147a0b949d 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -519,7 +519,6 @@ impl Dispatch<'_> { }); quote_spanned!(span=> const _: () = { - #[derive(::core::fmt::Debug)] #[allow(non_camel_case_types)] pub enum __ink_ConstructorDecoder { #( #constructors_variants ),* @@ -674,7 +673,6 @@ impl Dispatch<'_> { quote_spanned!(span=> const _: () = { - #[derive(::core::fmt::Debug)] #[allow(non_camel_case_types)] pub enum __ink_MessageDecoder { #( #message_variants ),* From a9953e8c89c252048cb7dc8ab6c0fb947e732568 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 19:47:37 +0200 Subject: [PATCH 272/493] fix bug in dispatcher utility method --- crates/lang/src/dispatcher.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index c9e9cbe90f..5ab5890968 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -243,14 +243,13 @@ where #[inline] #[doc(hidden)] pub fn execute_constructor_2( - uses_dynamic_storage_allocator: EnablesDynamicStorageAllocator, + EnablesDynamicStorageAllocator(uses_dynamic_storage_allocator): EnablesDynamicStorageAllocator, f: F, ) -> Result<()> where S: ink_storage::traits::SpreadLayout, F: FnOnce() -> S, { - let uses_dynamic_storage_allocator: bool = uses_dynamic_storage_allocator.value(); if uses_dynamic_storage_allocator { alloc::initialize(ContractPhase::Deploy); } From 820206912b889f73ecfd4a81574378038472c432 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 19:48:42 +0200 Subject: [PATCH 273/493] remove all no longer needed types and traits from ink_lang crate Due to the new ink! codegen many of these definitions have become deprecated or obsolete. --- crates/lang/src/contract.rs | 36 --- crates/lang/src/contract_ref.rs | 411 +------------------------------ crates/lang/src/cross_calling.rs | 56 ----- crates/lang/src/dispatcher.rs | 161 ------------ crates/lang/src/env_access.rs | 3 +- crates/lang/src/lib.rs | 27 -- crates/lang/src/traits.rs | 61 ----- 7 files changed, 13 insertions(+), 742 deletions(-) delete mode 100644 crates/lang/src/contract.rs delete mode 100644 crates/lang/src/cross_calling.rs diff --git a/crates/lang/src/contract.rs b/crates/lang/src/contract.rs deleted file mode 100644 index 79109122f6..0000000000 --- a/crates/lang/src/contract.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use crate::DispatchError; - -/// The contract dispatch mode. -/// -/// Tells the [`DispatchUsingMode`](`crate::DispatchUsingMode`) implementation for -/// an ink! smart contract how to dispatch for a call. -#[derive(Copy, Clone, PartialEq, Eq)] -#[doc(hidden)] -pub enum DispatchMode { - /// Mode for instantiating a contract. - Instantiate, - /// Mode for calling a contract. - Call, -} - -/// Trait implemented by contracts themselves in order to provide a clean -/// interface for the C-ABI specified `call` and `create` functions to forward -/// calls to. -#[doc(hidden)] -pub trait DispatchUsingMode { - fn dispatch_using_mode(mode: DispatchMode) -> Result<(), DispatchError>; -} diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index 0d9301ce26..f1124c79fe 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -12,7 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -use core::marker::PhantomData; +use ink_env::Environment; + +/// Implemented by contracts that are compiled as dependencies. +/// +/// Allows them to return their underlying account identifier. +pub trait ToAccountId +where + T: Environment, +{ + /// Returns the underlying account identifier of the instantiated contract. + fn to_account_id(&self) -> ::AccountId; +} /// Used to refer to the generated contract reference from the given contract storage struct. pub trait ContractReference { @@ -34,401 +45,3 @@ pub trait ContractName { /// The name of the ink! smart contract. const NAME: &'static str; } - -/// A generic ink! smart contract call builder. -/// -/// This utility struct is generic over the ink! environment `E` -/// as well as over a `T`, usually a concrete smart contract. -/// -/// This is used by the ink! codegen in order to implement various -/// implementations for calling smart contract instances of contract -/// `T` using environment `E` on-chain. -#[repr(transparent)] -pub struct CallBuilderBase -where - E: ink_env::Environment, -{ - account_id: ::AccountId, - __marker: PhantomData T>, -} - -impl core::fmt::Debug for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: core::fmt::Debug, - T: ContractName, -{ - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let name = ::NAME; - f.debug_struct("ContractRef") - .field("name", &name) - .field("account_id", &self.account_id) - .finish() - } -} - -impl Copy for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: Copy, -{ -} - -impl Clone for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: Clone, -{ - #[inline] - fn clone(&self) -> Self { - Self { - account_id: self.account_id.clone(), - __marker: PhantomData, - } - } -} - -impl scale::Encode for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: scale::Encode, -{ - #[inline] - fn size_hint(&self) -> usize { - <::AccountId as scale::Encode>::size_hint( - &self.account_id, - ) - } - - #[inline] - fn encode_to(&self, dest: &mut O) { - <::AccountId as scale::Encode>::encode_to( - &self.account_id, - dest, - ) - } -} - -impl scale::Decode for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: scale::Decode, -{ - #[inline] - fn decode(input: &mut I) -> Result { - <::AccountId as scale::Decode>::decode(input) - .map(>::from_account_id) - } -} - -impl ink_env::call::FromAccountId for CallBuilderBase -where - E: ink_env::Environment, -{ - #[inline] - fn from_account_id(account_id: ::AccountId) -> Self { - Self { - account_id, - __marker: PhantomData, - } - } -} - -impl crate::ToAccountId for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: Clone, -{ - #[inline] - fn to_account_id(&self) -> ::AccountId { - <::AccountId as core::clone::Clone>::clone( - &self.account_id, - ) - } -} - -impl core::hash::Hash for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: core::hash::Hash, -{ - #[inline] - fn hash(&self, state: &mut H) - where - H: core::hash::Hasher, - { - <::AccountId as core::hash::Hash>::hash( - &self.account_id, - state, - ) - } -} - -impl core::cmp::PartialEq for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: core::cmp::PartialEq, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.account_id == other.account_id - } -} - -impl core::cmp::Eq for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: Eq, -{ -} - -impl ink_storage::traits::SpreadLayout for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: ink_storage::traits::SpreadLayout, -{ - const FOOTPRINT: u64 = 1; - const REQUIRES_DEEP_CLEAN_UP: bool = false; - - #[inline] - fn pull_spread(ptr: &mut ::ink_primitives::KeyPtr) -> Self { - Self { - account_id: <::AccountId - as ink_storage::traits::SpreadLayout>::pull_spread(ptr), - __marker: PhantomData, - } - } - - #[inline] - fn push_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { - <::AccountId - as ink_storage::traits::SpreadLayout>::push_spread(&self.account_id, ptr) - } - - #[inline] - fn clear_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { - <::AccountId - as ink_storage::traits::SpreadLayout>::clear_spread(&self.account_id, ptr) - } -} - -impl ink_storage::traits::PackedLayout for CallBuilderBase -where - E: ink_env::Environment, - ::AccountId: ink_storage::traits::PackedLayout, -{ - #[inline(always)] - fn pull_packed(&mut self, _at: &ink_primitives::Key) {} - - #[inline(always)] - fn push_packed(&self, _at: &ink_primitives::Key) {} - - #[inline(always)] - fn clear_packed(&self, _at: &ink_primitives::Key) {} -} - -/// A generic ink! smart contract call forwader. -/// -/// A call forwarder is a thin wrapper around a call builder -/// that forwards the long-hand calls to the builder and directly -/// serves as the interface for the short-hand calls and constructors. -/// -/// This utility struct is generic over the ink! environment `E` -/// as well as over a `T`, usually a concrete smart contract. -/// -/// This is used by the ink! codegen in order to implement various -/// implementations for calling smart contract instances of contract -/// `T` using environment `E` on-chain. -#[repr(transparent)] -pub struct ContractRef -where - E: ink_env::Environment, -{ - call_builder: CallBuilderBase, -} - -impl crate::TraitCallBuilder for ContractRef -where - E: ink_env::Environment, -{ - type Builder = CallBuilderBase; - - #[inline] - fn call(&self) -> &Self::Builder { - &self.call_builder - } - - #[inline] - fn call_mut(&mut self) -> &mut Self::Builder { - &mut self.call_builder - } -} - -impl core::fmt::Debug for ContractRef -where - E: ink_env::Environment, - ::AccountId: core::fmt::Debug, - T: ContractName, -{ - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("CallForwarderBase") - .field("call_builder", &self.call_builder) - .finish() - } -} - -impl Copy for ContractRef -where - E: ink_env::Environment, - ::AccountId: Copy, -{ -} - -impl Clone for ContractRef -where - E: ink_env::Environment, - ::AccountId: Clone, -{ - #[inline] - fn clone(&self) -> Self { - Self { - call_builder: as Clone>::clone(&self.call_builder), - } - } -} - -impl scale::Encode for ContractRef -where - E: ink_env::Environment, - ::AccountId: scale::Encode, -{ - #[inline] - fn size_hint(&self) -> usize { - as scale::Encode>::size_hint(&self.call_builder) - } - - #[inline] - fn encode_to(&self, dest: &mut O) { - as scale::Encode>::encode_to(&self.call_builder, dest) - } -} - -impl scale::Decode for ContractRef -where - E: ink_env::Environment, - ::AccountId: scale::Decode, -{ - #[inline] - fn decode(input: &mut I) -> Result { - as scale::Decode>::decode(input) - .map(|call_builder| Self { call_builder }) - } -} - -impl ink_env::call::FromAccountId for ContractRef -where - E: ink_env::Environment, -{ - #[inline] - fn from_account_id(account_id: ::AccountId) -> Self { - Self { - call_builder: - as ink_env::call::FromAccountId>::from_account_id(account_id) - } - } -} - -impl crate::ToAccountId for ContractRef -where - E: ink_env::Environment, - ::AccountId: Clone, -{ - #[inline] - fn to_account_id(&self) -> ::AccountId { - as crate::ToAccountId>::to_account_id( - &self.call_builder, - ) - } -} - -impl core::hash::Hash for ContractRef -where - E: ink_env::Environment, - ::AccountId: core::hash::Hash, -{ - #[inline] - fn hash(&self, state: &mut H) - where - H: core::hash::Hasher, - { - as core::hash::Hash>::hash(&self.call_builder, state) - } -} - -impl core::cmp::PartialEq for ContractRef -where - E: ink_env::Environment, - ::AccountId: core::cmp::PartialEq, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.call_builder == other.call_builder - } -} - -impl core::cmp::Eq for ContractRef -where - E: ink_env::Environment, - ::AccountId: Eq, -{ -} - -impl ink_storage::traits::SpreadLayout for ContractRef -where - E: ink_env::Environment, - ::AccountId: ink_storage::traits::SpreadLayout, -{ - const FOOTPRINT: u64 = 1; - const REQUIRES_DEEP_CLEAN_UP: bool = false; - - #[inline] - fn pull_spread(ptr: &mut ::ink_primitives::KeyPtr) -> Self { - Self { - call_builder: - as ink_storage::traits::SpreadLayout>::pull_spread( - ptr, - ), - } - } - - #[inline] - fn push_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { - as ink_storage::traits::SpreadLayout>::push_spread( - &self.call_builder, - ptr, - ) - } - - #[inline] - fn clear_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { - as ink_storage::traits::SpreadLayout>::clear_spread( - &self.call_builder, - ptr, - ) - } -} - -impl ink_storage::traits::PackedLayout for ContractRef -where - E: ink_env::Environment, - ::AccountId: ink_storage::traits::PackedLayout, -{ - #[inline(always)] - fn pull_packed(&mut self, _at: &ink_primitives::Key) {} - - #[inline(always)] - fn push_packed(&self, _at: &ink_primitives::Key) {} - - #[inline(always)] - fn clear_packed(&self, _at: &ink_primitives::Key) {} -} diff --git a/crates/lang/src/cross_calling.rs b/crates/lang/src/cross_calling.rs deleted file mode 100644 index 088fb2667e..0000000000 --- a/crates/lang/src/cross_calling.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use ink_env::Environment; - -/// The type that can never be returned because it is not possible to craft an instance of it. -#[doc(hidden)] -pub enum NeverReturns {} - -/// Implemented by contracts that are compiled as dependencies. -/// -/// This allows to forward `&self` calls to a call forwarder -/// that encodes and dispatches the calls to the chain. -#[doc(hidden)] -pub trait ForwardCall { - /// The call forwarder that handles `&self` messages. - type Forwarder; - - /// Instantiates a call forwarder to forward `&self` messages. - fn call(self) -> Self::Forwarder; -} - -/// Implemented by contracts that are compiled as dependencies. -/// -/// This allows to forward `&mut self` calls to a call forwarder -/// that encodes and dispatches the calls to the chain. -#[doc(hidden)] -pub trait ForwardCallMut { - /// The call forwarder that handles `&mut self` messages. - type Forwarder; - - /// Instantiates a call forwarder to forward `&mut self` messages. - fn call_mut(self) -> Self::Forwarder; -} - -/// Implemented by contracts that are compiled as dependencies. -/// -/// Allows them to return their underlying account identifier. -pub trait ToAccountId -where - T: Environment, -{ - /// Returns the underlying account identifier of the instantiated contract. - fn to_account_id(&self) -> ::AccountId; -} diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index 5ab5890968..9fa0739bb6 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -13,13 +13,8 @@ // limitations under the License. use crate::{ - Constructor, ContractEnv, DispatchError, - FnOutput, - FnState, - MessageMut, - MessageRef, }; use core::{ any::TypeId, @@ -44,106 +39,21 @@ use ink_storage::{ #[doc(hidden)] pub type Result = core::result::Result; -/// Connector trait: Connects enum dispatcher for messages with the contract. -#[doc(hidden)] -pub trait MessageDispatcher { - /// The contract's message dispatcher type. - type Type; -} - -/// Connector trait: Connects enum dispatcher for constructors with the contract. -#[doc(hidden)] -pub trait ConstructorDispatcher { - /// The contract's constructors dispatcher type. - type Type; -} - -/// Connector trait used to start the execution of a smart contract. -/// -/// The generated message and constructor dispatch enums implement this trait -/// in order to forward their already decoded state to the selected messages -/// or constructors. -#[doc(hidden)] -pub trait Execute { - /// Starts the smart contract execution. - fn execute(self) -> Result<()>; -} - /// Yields `true` if the message accepts payments. #[derive(Copy, Clone)] #[doc(hidden)] pub struct AcceptsPayments(pub bool); -impl AcceptsPayments { - /// Returns the value of the property. - pub const fn value(self) -> bool { - self.0 - } -} - /// Yields `true` if the associated ink! message may mutate contract storage. #[derive(Copy, Clone)] #[doc(hidden)] pub struct MutatesStorage(pub bool); -impl MutatesStorage { - /// Returns the value of the property. - pub const fn value(self) -> bool { - self.0 - } -} - /// Yields `true` if the dynamic storage allocator is enabled for the given call. #[derive(Copy, Clone)] #[doc(hidden)] pub struct EnablesDynamicStorageAllocator(pub bool); -impl EnablesDynamicStorageAllocator { - /// Returns the value of the property. - pub const fn value(self) -> bool { - self.0 - } -} - -/// Executes the given `&self` message closure. -/// -/// # Note -/// -/// The closure is supposed to already contain all the arguments that the real -/// message requires and forwards them. -#[inline] -#[doc(hidden)] -pub fn execute_message( - accepts_payments: AcceptsPayments, - enables_dynamic_storage_allocator: EnablesDynamicStorageAllocator, - f: F, -) -> Result<()> -where - E: Environment, - M: MessageRef, - F: FnOnce(&::State) -> ::Output, -{ - let accepts_payments: bool = accepts_payments.value(); - let enables_dynamic_storage_allocator: bool = - enables_dynamic_storage_allocator.value(); - if !accepts_payments { - deny_payment::()?; - } - if enables_dynamic_storage_allocator { - alloc::initialize(ContractPhase::Call); - } - let root_key = Key::from([0x00; 32]); - let state = ManuallyDrop::new(pull_spread_root::<::State>(&root_key)); - let result = f(&state); - if enables_dynamic_storage_allocator { - alloc::finalize(); - } - if TypeId::of::<::Output>() != TypeId::of::<()>() { - ink_env::return_value::<::Output>(ReturnFlags::default(), &result) - } - Ok(()) -} - /// Returns `Ok` if the caller did not transfer additional value to the callee. /// /// # Errors @@ -163,77 +73,6 @@ where Ok(()) } -/// Executes the given `&mut self` message closure. -/// -/// # Note -/// -/// The closure is supposed to already contain all the arguments that the real -/// message requires and forwards them. -#[inline] -#[doc(hidden)] -pub fn execute_message_mut( - accepts_payments: AcceptsPayments, - enables_dynamic_storage_allocator: EnablesDynamicStorageAllocator, - f: F, -) -> Result<()> -where - E: Environment, - M: MessageMut, - F: FnOnce(&mut ::State) -> ::Output, -{ - let accepts_payments: bool = accepts_payments.value(); - let enables_dynamic_storage_allocator: bool = - enables_dynamic_storage_allocator.value(); - if !accepts_payments { - deny_payment::()?; - } - if enables_dynamic_storage_allocator { - alloc::initialize(ContractPhase::Call); - } - let root_key = Key::from([0x00; 32]); - let mut state = - ManuallyDrop::new(pull_spread_root::<::State>(&root_key)); - let result = f(&mut state); - push_spread_root::<::State>(&state, &root_key); - if enables_dynamic_storage_allocator { - alloc::finalize(); - } - if TypeId::of::<::Output>() != TypeId::of::<()>() { - ink_env::return_value::<::Output>(ReturnFlags::default(), &result) - } - Ok(()) -} - -/// Executes the given constructor closure. -/// -/// # Note -/// -/// The closure is supposed to already contain all the arguments that the real -/// constructor message requires and forwards them. -#[inline] -#[doc(hidden)] -pub fn execute_constructor( - enables_dynamic_storage_allocator: EnablesDynamicStorageAllocator, - f: F, -) -> Result<()> -where - C: Constructor, - F: FnOnce() -> ::State, -{ - let enables_dynamic_storage_allocator: bool = - enables_dynamic_storage_allocator.value(); - if enables_dynamic_storage_allocator { - alloc::initialize(ContractPhase::Deploy); - } - let state = ManuallyDrop::new(f()); - let root_key = Key::from([0x00; 32]); - push_spread_root::<::State>(&state, &root_key); - if enables_dynamic_storage_allocator { - alloc::finalize(); - } - Ok(()) -} - /// Executes the given ink! constructor. /// /// # Note diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs index 0c393fc442..9dabe722c9 100644 --- a/crates/lang/src/env_access.rs +++ b/crates/lang/src/env_access.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::ChainExtensionInstance; use core::marker::PhantomData; use ink_env::{ call::{ @@ -30,8 +31,6 @@ use ink_env::{ }; use ink_primitives::Key; -use crate::ChainExtensionInstance; - /// The environment of the compiled ink! smart contract. pub trait ContractEnv { /// The environment type. diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 9f31e775fe..c620b3eef6 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -15,9 +15,7 @@ #![cfg_attr(not(feature = "std"), no_std)] mod chain_extension; -mod contract; mod contract_ref; -mod cross_calling; mod dispatcher; mod env_access; mod error; @@ -29,35 +27,18 @@ pub use self::{ ChainExtensionInstance, IsResultType, }, - contract::{ - DispatchMode, - DispatchUsingMode, - }, contract_ref::{ - CallBuilderBase, ContractCallBuilder, ContractName, - ContractRef, ContractReference, - }, - cross_calling::{ - ForwardCall, - ForwardCallMut, - NeverReturns, ToAccountId, }, dispatcher::{ deny_payment, - execute_constructor, execute_constructor_2, - execute_message, execute_message_2, - execute_message_mut, AcceptsPayments, - ConstructorDispatcher, EnablesDynamicStorageAllocator, - Execute, - MessageDispatcher, MutatesStorage, }, env_access::{ @@ -75,7 +56,6 @@ pub use self::{ EmitEvent, }, traits::{ - Constructor, ContractAmountDispatchables, ContractConstructorDecoder, ContractDispatchableConstructors, @@ -84,15 +64,8 @@ pub use self::{ DispatchableConstructorInfo, DispatchableMessageInfo, ExecuteDispatchable, - FnInput, - FnOutput, - FnSelector, - FnState, ImpliesReturn, InkTraitDefinitionRegistry, - MessageMut, - MessageRef, - NoConcreteImplementer, TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 08f5dec9b5..67413f5050 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -22,11 +22,9 @@ use ink_env::{ }, CallBuilder, ExecutionInput, - Selector, }, Environment, }; -use ink_storage::traits::SpreadLayout; /// Trait used to indicate that an ink! trait definition has been checked /// by the `#[ink::trait_definition]` procedural macro. @@ -67,58 +65,6 @@ where { } -/// Dispatchable functions that have inputs. -#[doc(hidden)] -pub trait FnInput { - /// The tuple-type of all inputs. - type Input: scale::Decode + 'static; -} - -/// Dispatchable functions that have an output. -#[doc(hidden)] -pub trait FnOutput { - /// The output type. - type Output: scale::Encode + 'static; -} - -/// The selector of dispatchable functions. -#[doc(hidden)] -pub trait FnSelector { - /// The selector. - const SELECTOR: Selector; -} - -/// The storage state that the dispatchable function acts on. -#[doc(hidden)] -pub trait FnState { - /// The storage state. - type State: SpreadLayout + Sized; -} - -/// A dispatchable contract constructor message. -#[doc(hidden)] -pub trait Constructor: FnInput + FnSelector + FnState { - const CALLABLE: fn(::Input) -> ::State; -} - -/// A `&self` dispatchable contract message. -#[doc(hidden)] -pub trait MessageRef: FnInput + FnOutput + FnSelector + FnState { - const CALLABLE: fn( - &::State, - ::Input, - ) -> ::Output; -} - -/// A `&mut self` dispatchable contract message. -#[doc(hidden)] -pub trait MessageMut: FnInput + FnOutput + FnSelector + FnState { - const CALLABLE: fn( - &mut ::State, - ::Input, - ) -> ::Output; -} - /// Indicates that some compile time expression is expected to be `true`. #[doc(hidden)] pub trait True {} @@ -163,13 +109,6 @@ where unsafe impl TraitImplementer for InkTraitDefinitionRegistry {} -/// The default type that ink! trait definition implementations use for the -/// `__ink_DynamicCallForwarder` associated type. -/// -/// Read more about its use [here][TraitDefinitionRegistry]. -#[doc(hidden)] -pub enum NoConcreteImplementer {} - /// The global call builder type for an ink! trait definition. pub trait TraitCallBuilder { /// The call builder type. From d05b57ca91dbf77d66b4cf6e5178f7af77347020 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 19:48:47 +0200 Subject: [PATCH 274/493] fix UI test --- .../ui/contract/fail/M-04-message-returns-non-codec.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr index 251a87e5cf..d4063c98a1 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr @@ -8,9 +8,9 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodec` note: required by a bound in `execute_message_2` - --> $DIR/dispatcher.rs:282:13 + --> $DIR/dispatcher.rs:120:13 | -282 | Output: scale::Encode + 'static, +120 | Output: scale::Encode + 'static, | ^^^^^^^^^^^^^ required by this bound in `execute_message_2` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied From 87e1338f928e858b0557d73599fb89fad8dcabc8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 25 Sep 2021 20:21:51 +0200 Subject: [PATCH 275/493] silence non-minimal bool clippy warning in expanded code --- crates/lang/codegen/src/generator/dispatch.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 147a0b949d..105fa09176 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -695,6 +695,7 @@ impl Dispatch<'_> { } impl ::ink_lang::ExecuteDispatchable for __ink_MessageDecoder { + #[allow(clippy::nonminimal_bool)] fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { match self { #( #message_execute ),* From b3a67a87b84c6cb4d444f443d87c240177046cd2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sun, 26 Sep 2021 12:07:26 +0200 Subject: [PATCH 276/493] fix bug in dispatch codegen Only check for payment if message is not payable and not all messages are not payable, too. --- crates/lang/codegen/src/generator/dispatch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 105fa09176..04afb79c63 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -636,8 +636,8 @@ impl Dispatch<'_> { }>>::Output ); let accepts_payment = quote_spanned!(message_span=> - true && - #any_message_accept_payment && + false || + !#any_message_accept_payment || <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES From b1647e8f8fccd8c57193a411f8cad1fbe72a98b7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 02:07:41 +0200 Subject: [PATCH 277/493] add IsDocAttribute::extract_docs utility method for ink! IR --- crates/lang/ir/src/ir/attrs.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 97ac1ae2af..4759cb8a0b 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -35,12 +35,29 @@ use syn::spanned::Spanned; pub trait IsDocAttribute { /// Returns `true` if the attribute is a Rust documentation attribute. fn is_doc_attribute(&self) -> bool; + + /// Returns the contents of the Rust documentation attribute or `None`. + fn extract_docs(&self) -> Option; } impl IsDocAttribute for syn::Attribute { fn is_doc_attribute(&self) -> bool { self.path.is_ident("doc") } + + fn extract_docs(&self) -> Option { + if !self.is_doc_attribute() { + return None + } + if let Ok(syn::Meta::NameValue(syn::MetaNameValue { + lit: syn::Lit::Str(lit_str), + .. + })) = self.parse_meta() + { + return Some(lit_str.value()) + } + None + } } /// Either an ink! specific attribute, or another uninterpreted attribute. From b4076c5024984f9778b8f87cb051b9f33f150718 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 02:08:23 +0200 Subject: [PATCH 278/493] overhaul ink! metadata codegen This now properly takes into consideration the payable and selector properties of ink! trait messages. --- crates/lang/codegen/src/generator/metadata.rs | 315 ++++++++++-------- 1 file changed, 171 insertions(+), 144 deletions(-) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index 20f0aa1aef..98d32b2611 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -12,9 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::GenerateCode; +use crate::{ + generator, + GenerateCode, + GenerateCodeUsing as _, +}; +use ::core::iter; use derive_more::From; -use ir::Callable as _; +use ir::{ + Callable as _, + HexLiteral, + IsDocAttribute, +}; use proc_macro2::TokenStream as TokenStream2; use quote::{ quote, @@ -28,35 +37,22 @@ pub struct Metadata<'a> { /// The contract to generate code for. contract: &'a ir::Contract, } - -impl Metadata<'_> { - fn generate_cgf(&self) -> TokenStream2 { - if self.contract.config().is_compile_as_dependency_enabled() { - return quote! { #[cfg(feature = "__ink_DO_NOT_COMPILE")] } - } - quote! { #[cfg(not(feature = "ink-as-dependency"))] } - } -} +impl_as_ref_for_generator!(Metadata); impl GenerateCode for Metadata<'_> { fn generate_code(&self) -> TokenStream2 { let contract = self.generate_contract(); let layout = self.generate_layout(); - let no_cross_calling_cfg = self.generate_cgf(); + let cfg_not_as_dependency = + self.generate_code_using::(); quote! { #[cfg(feature = "std")] - #no_cross_calling_cfg + #cfg_not_as_dependency const _: () = { #[no_mangle] pub fn __ink_generate_metadata() -> ::ink_metadata::InkProject { - let contract: ::ink_metadata::ContractSpec = { - #contract - }; - let layout: ::ink_metadata::layout::Layout = { - #layout - }; - ::ink_metadata::InkProject::new(layout, contract) + ::ink_metadata::InkProject::new(#layout, #contract) } }; } @@ -65,22 +61,27 @@ impl GenerateCode for Metadata<'_> { impl Metadata<'_> { fn generate_layout(&self) -> TokenStream2 { - let contract_ident = self.contract.module().storage().ident(); - quote! { - <#contract_ident as ::ink_storage::traits::StorageLayout>::layout( + let storage_span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + quote_spanned!(storage_span=> + <#storage_ident as ::ink_storage::traits::StorageLayout>::layout( &mut <::ink_primitives::KeyPtr as ::core::convert::From<::ink_primitives::Key>>::from( <::ink_primitives::Key as ::core::convert::From<[::core::primitive::u8; 32usize]>>::from([0x00_u8; 32usize]) ) ) - } + ) } fn generate_contract(&self) -> TokenStream2 { let constructors = self.generate_constructors(); let messages = self.generate_messages(); let events = self.generate_events(); - let docs = self.generate_docs(); - + let docs = self + .contract + .module() + .attrs() + .iter() + .filter_map(|attr| attr.extract_docs()); quote! { ::ink_metadata::ContractSpec::new() .constructors([ @@ -99,83 +100,51 @@ impl Metadata<'_> { } } - /// Extracts the doc strings from the given slice of attributes. - fn extract_doc_comments( - attributes: &[syn::Attribute], - ) -> impl Iterator + '_ { - attributes - .iter() - .filter_map(|attribute| { - match attribute.parse_meta() { - Ok(syn::Meta::NameValue(name_value)) => Some(name_value), - Ok(_) | Err(_) => None, - } - }) - .filter(|name_value| name_value.path.is_ident("doc")) - .filter_map(|name_value| { - match name_value.lit { - syn::Lit::Str(lit_str) => Some(lit_str.value()), - _ => None, - } - }) - } - - /// Generates ink! metadata for all contract constructors. + /// Generates ink! metadata for all ink! smart contract constructors. fn generate_constructors(&self) -> impl Iterator + '_ { self.contract .module() .impls() - .flat_map(|impl_block| { - let trait_ident = impl_block - .trait_path() - .map(|path| path.segments.last().map(|seg| &seg.ident)) - .flatten(); - impl_block - .iter_constructors() - .map(move |constructor| (trait_ident, constructor)) - }) - .map(|(trait_ident, constructor)| { - let span = constructor.span(); - let attrs = constructor.attrs(); - let docs = Self::extract_doc_comments(attrs); - let selector_bytes = constructor.composed_selector().hex_lits(); - let constructor = constructor.callable(); - let ident = constructor.ident(); - let args = constructor - .inputs() - .map(|arg| Self::generate_message_param(arg)); - let constr = match trait_ident { - Some(trait_ident) => { - quote_spanned!(span => from_trait_and_name( - ::core::stringify!(#trait_ident), - ::core::stringify!(#ident) - )) - } - None => { - quote_spanned!(span => from_name(::core::stringify!(#ident))) - } - }; - quote_spanned!(span => - ::ink_metadata::ConstructorSpec::#constr - .selector([ - #( #selector_bytes ),* - ]) - .args([ - #( #args ),* - ]) - .docs([ - #( #docs ),* - ]) - .done() - ) - }) + .map(|item_impl| item_impl.iter_constructors()) + .flatten() + .map(|constructor| Self::generate_constructor(constructor)) + } + + /// Generates ink! metadata for a single ink! constructor. + fn generate_constructor( + constructor: ir::CallableWithSelector, + ) -> TokenStream2 { + let span = constructor.span(); + let docs = constructor + .attrs() + .iter() + .filter_map(|attr| attr.extract_docs()); + let selector_bytes = constructor.composed_selector().hex_lits(); + let constructor = constructor.callable(); + let ident = constructor.ident(); + let args = constructor + .inputs() + .map(|arg| Self::generate_dispatch_argument(arg)); + quote_spanned!(span=> + ::ink_metadata::ConstructorSpec::from_name(::core::stringify!(#ident)) + .selector([ + #( #selector_bytes ),* + ]) + .args([ + #( #args ),* + ]) + .docs([ + #( #docs ),* + ]) + .done() + ) } /// Generates the ink! metadata for the given parameter and parameter type. - fn generate_message_param(pat_type: &syn::PatType) -> TokenStream2 { + fn generate_dispatch_argument(pat_type: &syn::PatType) -> TokenStream2 { let ident = match &*pat_type.pat { syn::Pat::Ident(ident) => &ident.ident, - _ => unreachable!("encountered unexpected non identifier in ink! parameter"), + _ => unreachable!("encountered ink! dispatch input with missing identifier"), }; let type_spec = Self::generate_type_spec(&pat_type.ty); quote! { @@ -201,11 +170,11 @@ impl Metadata<'_> { let segs = path .segments .iter() - .map(|seg| seg.ident.to_string()) + .map(|seg| &seg.ident) .collect::>(); quote! { ::ink_metadata::TypeSpec::with_name_segs::<#ty, _>( - ::core::iter::IntoIterator::into_iter([ #( #segs ),* ]) + ::core::iter::IntoIterator::into_iter([ #( ::core::stringify!(#segs) ),* ]) .map(::core::convert::AsRef::as_ref) ) } @@ -214,23 +183,30 @@ impl Metadata<'_> { } } - fn generate_messages(&self) -> impl Iterator + '_ { + /// Generates the ink! metadata for all ink! smart contract messages. + fn generate_messages(&self) -> Vec { + let mut messages = Vec::new(); + let inherent_messages = self.generate_inherent_messages(); + let trait_messages = self.generate_trait_messages(); + messages.extend(inherent_messages); + messages.extend(trait_messages); + messages + } + + /// Generates the ink! metadata for all inherent ink! smart contract messages. + fn generate_inherent_messages(&self) -> Vec { self.contract .module() .impls() - .flat_map(|impl_block| { - let trait_ident = impl_block - .trait_path() - .map(|path| path.segments.last().map(|seg| &seg.ident)) - .flatten(); - impl_block - .iter_messages() - .map(move |message| (trait_ident, message)) - }) - .map(|(trait_ident, message)| { + .filter(|item_impl| item_impl.trait_path().is_none()) + .map(|item_impl| item_impl.iter_messages()) + .flatten() + .map(|message| { let span = message.span(); - let attrs = message.attrs(); - let docs = Self::extract_doc_comments(attrs); + let docs = message + .attrs() + .iter() + .filter_map(|attr| attr.extract_docs()); let selector_bytes = message.composed_selector().hex_lits(); let is_payable = message.is_payable(); let message = message.callable(); @@ -238,21 +214,10 @@ impl Metadata<'_> { let ident = message.ident(); let args = message .inputs() - .map(|arg| Self::generate_message_param(arg)); + .map(|arg| Self::generate_dispatch_argument(arg)); let ret_ty = Self::generate_return_type(message.output()); - let constr = match trait_ident { - Some(trait_ident) => { - quote_spanned!(span => from_trait_and_name( - ::core::stringify!(#trait_ident), - ::core::stringify!(#ident), - )) - } - None => { - quote_spanned!(span => from_name(::core::stringify!(#ident))) - } - }; quote_spanned!(span => - ::ink_metadata::MessageSpec::#constr + ::ink_metadata::MessageSpec::from_name(::core::stringify!(#ident)) .selector([ #( #selector_bytes ),* ]) @@ -268,6 +233,68 @@ impl Metadata<'_> { .done() ) }) + .collect() + } + + /// Generates the ink! metadata for all inherent ink! smart contract messages. + fn generate_trait_messages(&self) -> Vec { + let storage_ident = self.contract.module().storage().ident(); + self.contract + .module() + .impls() + .filter_map(|item_impl| { + item_impl + .trait_path() + .map(|trait_path| { + let trait_ident = item_impl.trait_ident().expect( + "must have an ink! trait identifier if it is an ink! trait implementation" + ); + iter::repeat((trait_ident, trait_path)).zip(item_impl.iter_messages()) + }) + }) + .flatten() + .map(|((trait_ident, trait_path), message)| { + let message_span = message.span(); + let message_ident = message.ident(); + let message_docs = message + .attrs() + .iter() + .filter_map(|attr| attr.extract_docs()); + let message_args = message + .inputs() + .map(|arg| Self::generate_dispatch_argument(arg)); + let mutates = message.receiver().is_ref_mut(); + let local_id = message.local_id().hex_padded_suffixed(); + let is_payable = quote! {{ + <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE + }}; + let selector = quote! {{ + <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR + }}; + let ret_ty = Self::generate_return_type(message.output()); + quote_spanned!(message_span=> + ::ink_metadata::MessageSpec::from_trait_and_name( + ::core::stringify!(#trait_ident), + ::core::stringify!(#message_ident) + ) + .selector(#selector) + .args([ + #( #message_args ),* + ]) + .returns(#ret_ty) + .mutates(#mutates) + .payable(#is_payable) + .docs([ + #( #message_docs ),* + ]) + .done() + ) + }) + .collect() } /// Generates ink! metadata for the given return type. @@ -292,7 +319,7 @@ impl Metadata<'_> { self.contract.module().events().map(|event| { let span = event.span(); let ident = event.ident(); - let docs = Self::extract_doc_comments(event.attrs()); + let docs = event.attrs().iter().filter_map(|attr| attr.extract_docs()); let args = Self::generate_event_args(event); quote_spanned!(span => ::ink_metadata::EventSpec::new(::core::stringify!(#ident)) @@ -313,8 +340,10 @@ impl Metadata<'_> { let span = event_field.span(); let ident = event_field.ident(); let is_topic = event_field.is_topic; - let attrs = event_field.attrs(); - let docs = Self::extract_doc_comments(&attrs); + let docs = event_field + .attrs() + .into_iter() + .filter_map(|attr| attr.extract_docs()); let ty = Self::generate_type_spec(event_field.ty()); quote_spanned!(span => ::ink_metadata::EventParamSpec::new(::core::stringify!(#ident)) @@ -327,39 +356,39 @@ impl Metadata<'_> { ) }) } - - /// Generates the documentation for the contract module. - fn generate_docs(&self) -> impl Iterator + '_ { - Self::extract_doc_comments(self.contract.module().attrs()) - } } #[cfg(test)] mod tests { use super::*; + /// Extracts and collects the contents of the Rust documentation attributes. + fn extract_doc_attributes(attrs: &[syn::Attribute]) -> Vec { + attrs + .iter() + .filter_map(|attr| attr.extract_docs()) + .collect() + } + #[test] fn extract_doc_comments_works() { assert_eq!( - Metadata::extract_doc_comments(&[syn::parse_quote!( #[doc = r"content"] )]) - .collect::>(), + extract_doc_attributes(&[syn::parse_quote!( #[doc = r"content"] )]), vec!["content".to_string()], ); assert_eq!( - Metadata::extract_doc_comments(&[syn::parse_quote!( + extract_doc_attributes(&[syn::parse_quote!( /// content - )]) - .collect::>(), + )]), vec![" content".to_string()], ); assert_eq!( - Metadata::extract_doc_comments(&[syn::parse_quote!( + extract_doc_attributes(&[syn::parse_quote!( /** * Multi-line comments ... * May span many lines */ - )]) - .collect::>(), + )]), vec![r" * Multi-line comments ... * May span many lines @@ -367,7 +396,7 @@ mod tests { .to_string()], ); assert_eq!( - Metadata::extract_doc_comments(&[ + extract_doc_attributes(&[ syn::parse_quote!( /// multiple ), @@ -380,8 +409,7 @@ mod tests { syn::parse_quote!( /// comments ), - ]) - .collect::>(), + ]), vec![ " multiple".to_string(), " single".to_string(), @@ -390,7 +418,7 @@ mod tests { ], ); assert_eq!( - Metadata::extract_doc_comments(&[ + extract_doc_attributes(&[ syn::parse_quote!( #[doc = r"a"] ), syn::parse_quote!( #[non_doc] ), syn::parse_quote!( #[doc = r"b"] ), @@ -400,8 +428,7 @@ mod tests { syn::parse_quote!( #[doc = r"d"] ), syn::parse_quote!( #[doc(Nope)] ), syn::parse_quote!( #[doc = r"e"] ), - ]) - .collect::>(), + ]), vec![ "a".to_string(), "b".to_string(), From 618de63104965a9f1ecde43c65a4858a6c893c77 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 02:19:21 +0200 Subject: [PATCH 279/493] silence bad clippy warning --- crates/lang/codegen/src/generator/metadata.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index 98d32b2611..e63b135fa8 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -101,6 +101,7 @@ impl Metadata<'_> { } /// Generates ink! metadata for all ink! smart contract constructors. + #[allow(clippy::redundant_closure)] // We are getting arcane lifetime errors otherwise. fn generate_constructors(&self) -> impl Iterator + '_ { self.contract .module() From aa70e3c550fbfa060dfc40e403e0a9ac390a9f55 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 12:01:12 +0200 Subject: [PATCH 280/493] rename execute_{message_2, constructor_2} to execute_{message, constructor} --- crates/lang/codegen/src/generator/dispatch.rs | 4 ++-- .../ui/contract/fail/M-04-message-returns-non-codec.stderr | 4 ++-- crates/lang/src/dispatcher.rs | 4 ++-- crates/lang/src/lib.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 04afb79c63..de7bdc81c6 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -510,7 +510,7 @@ impl Dispatch<'_> { .is_dynamic_storage_allocator_enabled(); quote_spanned!(constructor_span=> Self::#constructor_ident(input) => { - ::ink_lang::execute_constructor_2::<#storage_ident, _>( + ::ink_lang::execute_constructor::<#storage_ident, _>( ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), move || { #constructor_callable(input) } ) @@ -657,7 +657,7 @@ impl Dispatch<'_> { .is_dynamic_storage_allocator_enabled(); quote_spanned!(message_span=> Self::#message_ident(input) => { - ::ink_lang::execute_message_2::< + ::ink_lang::execute_message::< #storage_ident, #message_output, _ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr index d4063c98a1..66f0ba65c6 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr @@ -7,11 +7,11 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied | |_________^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` | = note: required because of the requirements on the impl of `Encode` for `NonCodec` -note: required by a bound in `execute_message_2` +note: required by a bound in `execute_message` --> $DIR/dispatcher.rs:120:13 | 120 | Output: scale::Encode + 'static, - | ^^^^^^^^^^^^^ required by this bound in `execute_message_2` + | ^^^^^^^^^^^^^ required by this bound in `execute_message` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied --> $DIR/M-04-message-returns-non-codec.rs:18:9 diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index 9fa0739bb6..435ebf34bc 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -81,7 +81,7 @@ where /// constructor message requires and forwards them. #[inline] #[doc(hidden)] -pub fn execute_constructor_2( +pub fn execute_constructor( EnablesDynamicStorageAllocator(uses_dynamic_storage_allocator): EnablesDynamicStorageAllocator, f: F, ) -> Result<()> @@ -109,7 +109,7 @@ where /// message requires and forwards them. #[inline] #[doc(hidden)] -pub fn execute_message_2( +pub fn execute_message( AcceptsPayments(accepts_payments): AcceptsPayments, MutatesStorage(mutates_storage): MutatesStorage, EnablesDynamicStorageAllocator(enables_dynamic_storage_allocator): EnablesDynamicStorageAllocator, diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index c620b3eef6..f040f54cee 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -35,8 +35,8 @@ pub use self::{ }, dispatcher::{ deny_payment, - execute_constructor_2, - execute_message_2, + execute_constructor, + execute_message, AcceptsPayments, EnablesDynamicStorageAllocator, MutatesStorage, From 7a6192f4addcfbab2fd9b88ca1db5e9080f577ce Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 12:02:20 +0200 Subject: [PATCH 281/493] make ink! root contract messages revert state when returning Result::Err(_) --- crates/lang/codegen/src/generator/dispatch.rs | 2 + crates/lang/src/dispatcher.rs | 13 ++- crates/lang/src/lib.rs | 5 + crates/lang/src/result_info.rs | 95 +++++++++++++++++++ 4 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 crates/lang/src/result_info.rs diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index de7bdc81c6..8443dd0dad 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -651,6 +651,7 @@ impl Dispatch<'_> { }>>::IDS[#index] }>>::MUTATES ); + let may_revert = ::core::cfg!(not(feature = "ink-as-dependency")); let is_dynamic_storage_allocation_enabled = self .contract .config() @@ -664,6 +665,7 @@ impl Dispatch<'_> { >( ::ink_lang::AcceptsPayments(#accepts_payment), ::ink_lang::MutatesStorage(#mutates_storage), + ::ink_lang::MayRevert(#may_revert), ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), move |storage: &mut #storage_ident| { #message_callable(storage, input) } ) diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index 435ebf34bc..4f9c2597f2 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -49,6 +49,11 @@ pub struct AcceptsPayments(pub bool); #[doc(hidden)] pub struct MutatesStorage(pub bool); +/// Yields `true` if the associated ink! message may revert execution. +#[derive(Copy, Clone)] +#[doc(hidden)] +pub struct MayRevert(pub bool); + /// Yields `true` if the dynamic storage allocator is enabled for the given call. #[derive(Copy, Clone)] #[doc(hidden)] @@ -112,6 +117,7 @@ where pub fn execute_message( AcceptsPayments(accepts_payments): AcceptsPayments, MutatesStorage(mutates_storage): MutatesStorage, + MayRevert(may_revert): MayRevert, EnablesDynamicStorageAllocator(enables_dynamic_storage_allocator): EnablesDynamicStorageAllocator, f: F, ) -> Result<()> @@ -136,7 +142,12 @@ where alloc::finalize(); } if TypeId::of::() != TypeId::of::<()>() { - ink_env::return_value::(ReturnFlags::default(), &result) + let revert_state = + may_revert && is_result_type!(Output) && is_result_err!(&result); + ink_env::return_value::( + ReturnFlags::default().set_reverted(revert_state), + &result, + ) } Ok(()) } diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index f040f54cee..607fda6cd0 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -14,6 +14,10 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[macro_use] +#[doc(hidden)] +mod result_info; + mod chain_extension; mod contract_ref; mod dispatcher; @@ -39,6 +43,7 @@ pub use self::{ execute_message, AcceptsPayments, EnablesDynamicStorageAllocator, + MayRevert, MutatesStorage, }, env_access::{ diff --git a/crates/lang/src/result_info.rs b/crates/lang/src/result_info.rs new file mode 100644 index 0000000000..936525783e --- /dev/null +++ b/crates/lang/src/result_info.rs @@ -0,0 +1,95 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub struct IsResultType { + marker: core::marker::PhantomData T>, +} + +impl IsResultType<::core::result::Result> { + // We need to allow for dead code at this point because + // the Rust compiler thinks this function is unused even + // though it acts as the specialized case for detection. + #[allow(dead_code)] + pub const VALUE: bool = true; +} + +pub trait IsResultTypeFallback { + const VALUE: bool = false; +} +impl IsResultTypeFallback for IsResultType {} + +/// Returns `true` if the given type is a `Result` type. +macro_rules! is_result_type { + ( $T:ty $(,)? ) => {{ + #[allow(unused_imports)] + use $crate::result_info::IsResultTypeFallback as _; + + $crate::result_info::IsResultType::<$T>::VALUE + }}; +} + +pub struct IsResultErr<'lt, T>(pub &'lt T); + +impl IsResultErr<'_, ::core::result::Result> { + #[inline(always)] + // We need to allow for dead code at this point because + // the Rust compiler thinks this function is unused even + // though it acts as the specialized case for detection. + #[allow(dead_code)] + pub fn value(&self) -> bool { + self.0.is_err() + } +} + +pub trait IsResultErrFallback { + #[inline(always)] + fn value(&self) -> bool { + false + } +} +impl IsResultErrFallback for IsResultErr<'_, T> {} + +/// Evaluates to `true` if the given expression is a `Result::Err(_)`. +/// +/// # Note +/// +/// This given expression is not required to be of type `Result`. +macro_rules! is_result_err { + ( $e:expr $(,)? ) => {{ + #[allow(unused_imports)] + use $crate::result_info::IsResultErrFallback as _; + $crate::result_info::IsResultErr(&$e).value() + }}; +} + +#[cfg(test)] +mod tests { + #[test] + fn is_result_type_works() { + assert_eq!(is_result_type!(bool), false,); + assert_eq!(is_result_type!(String), false,); + assert_eq!(is_result_type!(Option), false,); + assert_eq!(is_result_type!( Result<(), i32> ), true,); + } + + #[test] + fn is_result_err_works() { + assert_eq!(is_result_err!(true), false,); + assert_eq!(is_result_err!(42), false,); + assert_eq!(is_result_err!(Ok::<_, String>(())), false,); + assert_eq!(is_result_err!(Err::(false)), true,); + assert_eq!(is_result_err!(Err::<(), i32>(5)), true,); + assert_eq!(is_result_err!("Hello, World!"), false,); + } +} From c1cb26ad9194dbcc992309fd72ce5595e1319113 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 12:12:04 +0200 Subject: [PATCH 282/493] fix some formatting issues --- crates/lang/src/result_info.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/lang/src/result_info.rs b/crates/lang/src/result_info.rs index 936525783e..2bee96b130 100644 --- a/crates/lang/src/result_info.rs +++ b/crates/lang/src/result_info.rs @@ -77,19 +77,19 @@ macro_rules! is_result_err { mod tests { #[test] fn is_result_type_works() { - assert_eq!(is_result_type!(bool), false,); - assert_eq!(is_result_type!(String), false,); - assert_eq!(is_result_type!(Option), false,); - assert_eq!(is_result_type!( Result<(), i32> ), true,); + assert_eq!(is_result_type!(bool), false); + assert_eq!(is_result_type!(String), false); + assert_eq!(is_result_type!(Option), false); + assert_eq!(is_result_type!(Result<(), i32>), true); } #[test] fn is_result_err_works() { - assert_eq!(is_result_err!(true), false,); - assert_eq!(is_result_err!(42), false,); - assert_eq!(is_result_err!(Ok::<_, String>(())), false,); - assert_eq!(is_result_err!(Err::(false)), true,); - assert_eq!(is_result_err!(Err::<(), i32>(5)), true,); - assert_eq!(is_result_err!("Hello, World!"), false,); + assert_eq!(is_result_err!(true), false); + assert_eq!(is_result_err!(42), false); + assert_eq!(is_result_err!(Ok::<_, String>(())), false); + assert_eq!(is_result_err!(Err::(false)), true); + assert_eq!(is_result_err!(Err::<(), i32>(5)), true); + assert_eq!(is_result_err!("Hello, World!"), false); } } From 429185a155d529bef4a3ffbfcab83afde9255102 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 12:22:32 +0200 Subject: [PATCH 283/493] extend is_result_{type, err} unit tests --- crates/lang/src/result_info.rs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/crates/lang/src/result_info.rs b/crates/lang/src/result_info.rs index 2bee96b130..94b3d90447 100644 --- a/crates/lang/src/result_info.rs +++ b/crates/lang/src/result_info.rs @@ -77,19 +77,33 @@ macro_rules! is_result_err { mod tests { #[test] fn is_result_type_works() { - assert_eq!(is_result_type!(bool), false); - assert_eq!(is_result_type!(String), false); - assert_eq!(is_result_type!(Option), false); - assert_eq!(is_result_type!(Result<(), i32>), true); + assert!(!is_result_type!(bool)); + assert!(!is_result_type!(String)); + assert!(!is_result_type!(Option)); + + assert!(is_result_type!(Result<(), ()>)); + assert!(is_result_type!(Result)); + assert!(is_result_type!(Result<(), String>)); + assert!(is_result_type!(Result)); + + assert!(is_result_type!(Result, ()>)); + assert!(is_result_type!(Result<(), Result<(), ()>>)); + assert!(is_result_type!(Result, Result<(), ()>>)); } #[test] fn is_result_err_works() { - assert_eq!(is_result_err!(true), false); - assert_eq!(is_result_err!(42), false); - assert_eq!(is_result_err!(Ok::<_, String>(())), false); - assert_eq!(is_result_err!(Err::(false)), true); - assert_eq!(is_result_err!(Err::<(), i32>(5)), true); - assert_eq!(is_result_err!("Hello, World!"), false); + assert!(!is_result_err!(true)); + assert!(!is_result_err!(42)); + assert!(!is_result_err!("Hello, World!")); + + assert!(!is_result_err!(Ok::<(), ()>(()))); + assert!(!is_result_err!(Ok::(5))); + assert!(!is_result_err!(Ok::(true))); + + assert!(is_result_err!(Err::<(), ()>(()))); + assert!(is_result_err!(Err::<(), i32>(5))); + assert!(is_result_err!(Err::(false))); + assert!(is_result_err!(Err::>(Ok(42)))); } } From 5c38477ddb5878e69d9e079abd9e2dd1e06311e6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 14:15:31 +0200 Subject: [PATCH 284/493] improve error messages for invalid ink! input and output types This checks for ink! constructor and message inputs to be scale::Decode + 'static and for ink! output types to be scale::Encode + 'static. Also added new UI tests to assert that this works for ink! message and constructor inputs. --- .../lang/codegen/src/generator/item_impls.rs | 64 +++++++++++++++++++ crates/lang/macro/tests/compile_tests.rs | 2 + .../ui/contract/fail/C-15-non-codec-input.rs | 22 +++++++ .../fail/M-04-message-returns-non-codec.rs | 12 ++-- .../M-04-message-returns-non-codec.stderr | 28 -------- .../fail/M-07-message-input-non-codec.rs | 22 +++++++ .../fail/M-07-message-input-non-codec.stderr | 51 +++++++++++++++ crates/lang/src/lib.rs | 3 + crates/lang/src/type_check.rs | 40 ++++++++++++ 9 files changed, 210 insertions(+), 34 deletions(-) create mode 100644 crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr create mode 100644 crates/lang/src/type_check.rs diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index a6ad9c7934..1613c956fa 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -39,17 +39,81 @@ impl GenerateCode for ItemImpls<'_> { .module() .impls() .map(|item_impl| self.generate_item_impl(item_impl)); + let inout_guards = self.generate_input_output_guards(); quote! { const _: () = { use ::ink_lang::{Env as _, EmitEvent as _, StaticEnv as _}; #( #item_impls )* + #inout_guards }; } } } impl ItemImpls<'_> { + /// Generates code to assert that ink! input and output types meet certain properties. + fn generate_input_output_guards(&self) -> TokenStream2 { + let storage_span = self.contract.module().storage().span(); + let constructor_input_guards = self + .contract + .module() + .impls() + .map(|item_impl| item_impl.iter_constructors()) + .flatten() + .map(|constructor| { + let constructor_span = constructor.span(); + let constructor_inputs = constructor.inputs().map(|input| { + let span = input.span(); + let input_type = &*input.ty; + quote_spanned!(span=> + let _: () = ::ink_lang::type_check::identity_type::< + ::ink_lang::type_check::DispatchInput<#input_type> + >(); + ) + }); + quote_spanned!(constructor_span=> + #( #constructor_inputs )* + ) + }); + let message_inout_guards = self + .contract + .module() + .impls() + .map(|item_impl| item_impl.iter_messages()) + .flatten() + .map(|message| { + let message_span = message.span(); + let message_inputs = message.inputs().map(|input| { + let span = input.span(); + let input_type = &*input.ty; + quote_spanned!(span=> + let _: () = ::ink_lang::type_check::identity_type::< + ::ink_lang::type_check::DispatchInput<#input_type> + >(); + ) + }); + let message_output = message.output().map(|output_type| { + let span = output_type.span(); + quote_spanned!(span=> + let _: () = ::ink_lang::type_check::identity_type::< + ::ink_lang::type_check::DispatchOutput<#output_type> + >(); + ) + }); + quote_spanned!(message_span=> + #( #message_inputs )* + #message_output + ) + }); + quote_spanned!(storage_span=> + const _: () = { + #( #constructor_input_guards )* + #( #message_inout_guards )* + }; + ) + } + /// Generates the code for the given ink! message within a trait implementation block. fn generate_trait_message(message: &ir::Message) -> TokenStream2 { let span = message.span(); diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index bb493bfb24..260ef968c2 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -38,6 +38,7 @@ fn contract() { t.compile_fail("tests/ui/contract/fail/C-12-const-constructor.rs"); t.compile_fail("tests/ui/contract/fail/C-13-abi-constructor.rs"); t.compile_fail("tests/ui/contract/fail/C-14-payable-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/C-15-non-codec-input.rs"); t.compile_fail("tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs"); t.compile_fail("tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs"); @@ -50,6 +51,7 @@ fn contract() { t.compile_fail("tests/ui/contract/fail/M-04-message-returns-non-codec.rs"); t.compile_fail("tests/ui/contract/fail/M-05-message-invalid-selector.rs"); t.compile_fail("tests/ui/contract/fail/M-06-message-invalid-selector-type.rs"); + t.compile_fail("tests/ui/contract/fail/M-07-message-input-non-codec.rs"); t.compile_fail("tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs"); t.compile_fail("tests/ui/contract/fail/S-01-missing-storage-struct.rs"); diff --git a/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.rs b/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.rs new file mode 100644 index 0000000000..c12317cfd3 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.rs @@ -0,0 +1,22 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[derive(scale_info::TypeInfo)] + pub struct NonCodecType; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor(_input: NonCodecType) -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs index 9ac92b4691..cc0295f187 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs @@ -1,22 +1,22 @@ use ink_lang as ink; #[ink::contract] -mod message_returns_non_codec { +mod contract { #[derive(scale_info::TypeInfo)] - pub struct NonCodec; + pub struct NonCodecType; #[ink(storage)] - pub struct MessageReturnsNonCodecType {} + pub struct Contract {} - impl MessageReturnsNonCodecType { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} } #[ink(message)] - pub fn returns_non_codec_type(&self) -> NonCodec { - NonCodec + pub fn message(&self) -> NonCodecType { + NonCodecType } } } diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr deleted file mode 100644 index 66f0ba65c6..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied - --> $DIR/M-04-message-returns-non-codec.rs:18:9 - | -18 | / pub fn returns_non_codec_type(&self) -> NonCodec { -19 | | NonCodec -20 | | } - | |_________^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` - | - = note: required because of the requirements on the impl of `Encode` for `NonCodec` -note: required by a bound in `execute_message` - --> $DIR/dispatcher.rs:120:13 - | -120 | Output: scale::Encode + 'static, - | ^^^^^^^^^^^^^ required by this bound in `execute_message` - -error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied - --> $DIR/M-04-message-returns-non-codec.rs:18:9 - | -6 | pub struct NonCodec; - | -------------------- doesn't satisfy `_: message_returns_non_codec::_::_parity_scale_codec::Decode` -... -18 | / pub fn returns_non_codec_type(&self) -> NonCodec { -19 | | NonCodec -20 | | } - | |_________^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NonCodec: message_returns_non_codec::_::_parity_scale_codec::Decode` diff --git a/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.rs b/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.rs new file mode 100644 index 0000000000..575dd04719 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.rs @@ -0,0 +1,22 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[derive(scale_info::TypeInfo)] + pub struct NonCodecType; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self, _input: NonCodecType) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr new file mode 100644 index 0000000000..48eff2f81d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> $DIR/M-07-message-input-non-codec.rs:18:31 + | +18 | pub fn message(&self, _input: NonCodecType) {} + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `DispatchInput` + --> $DIR/type_check.rs:23:8 + | +23 | T: scale::Decode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> $DIR/M-07-message-input-non-codec.rs:18:9 + | +18 | pub fn message(&self, _input: NonCodecType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `contract::_::_parity_scale_codec::Decode::decode` + --> $DIR/codec.rs:284:15 + | +284 | fn decode(input: &mut I) -> Result; + | ^^^^^ required by this bound in `contract::_::_parity_scale_codec::Decode::decode` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied + --> $DIR/M-07-message-input-non-codec.rs:3:1 + | +3 | #[ink::contract] + | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` +... +18 | pub fn message(&self, _input: NonCodecType) {} + | ---------------------------------------------- required by a bound introduced by this call + | + = note: required because of the requirements on the impl of `Encode` for `NonCodecType` + = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied + --> $DIR/M-07-message-input-non-codec.rs:18:9 + | +18 | pub fn message(&self, _input: NonCodecType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds + | + ::: $WORKSPACE/crates/env/src/call/execution_input.rs + | + | pub struct ArgumentList { + | ----------------------------------- doesn't satisfy `_: Encode` + | + = note: the following trait bounds were not satisfied: + `ArgumentList, ArgumentList>: Encode` diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 607fda6cd0..2ef64c55cc 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -18,6 +18,9 @@ #[doc(hidden)] mod result_info; +#[doc(hidden)] +pub mod type_check; + mod chain_extension; mod contract_ref; mod dispatcher; diff --git a/crates/lang/src/type_check.rs b/crates/lang/src/type_check.rs new file mode 100644 index 0000000000..f564b79da7 --- /dev/null +++ b/crates/lang/src/type_check.rs @@ -0,0 +1,40 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Used to check if `T` is allowed as ink! input parameter type. +/// +/// # Note +/// +/// An ink! input parameter type must implement [`scale::Decode`] +/// and must have a `'static` lifetime. +pub struct DispatchInput(T) +where + T: scale::Decode + 'static; + +/// Used to check if `T` is allowed as ink! output parameter type. +/// +/// # Note +/// +/// An ink! input parameter type must implement [`scale::Encode`] +/// and must have a `'static` lifetime. +pub struct DispatchOutput(T) +where + T: scale::Encode + 'static; + +/// Does nothing but takes a generic type as input. +/// +/// # Note +/// +/// Used to trigger some compile time checks. +pub const fn identity_type() {} From fafe9c686ee738bfa608b2a21d0ac939f18a04d6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 14:29:17 +0200 Subject: [PATCH 285/493] add missing UI test expectation files --- .../contract/fail/C-15-non-codec-input.stderr | 41 +++++++++++++++++++ .../M-04-message-returns-non-codec.stderr | 41 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr b/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr new file mode 100644 index 0000000000..af5b775b2c --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> $DIR/C-15-non-codec-input.rs:13:28 + | +13 | pub fn constructor(_input: NonCodecType) -> Self { + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `DispatchInput` + --> $DIR/type_check.rs:23:8 + | +23 | T: scale::Decode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> $DIR/C-15-non-codec-input.rs:13:9 + | +13 | / pub fn constructor(_input: NonCodecType) -> Self { +14 | | Self {} +15 | | } + | |_________^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `contract::_::_parity_scale_codec::Decode::decode` + --> $DIR/codec.rs:284:15 + | +284 | fn decode(input: &mut I) -> Result; + | ^^^^^ required by this bound in `contract::_::_parity_scale_codec::Decode::decode` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied + --> $DIR/C-15-non-codec-input.rs:3:1 + | +3 | #[ink::contract] + | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` +... +13 | / pub fn constructor(_input: NonCodecType) -> Self { +14 | | Self {} +15 | | } + | |_________- required by a bound introduced by this call + | + = note: required because of the requirements on the impl of `Encode` for `NonCodecType` + = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr new file mode 100644 index 0000000000..04bd8566d0 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied + --> $DIR/M-04-message-returns-non-codec.rs:18:34 + | +18 | pub fn message(&self) -> NonCodecType { + | ^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `Encode` for `NonCodecType` +note: required by a bound in `DispatchOutput` + --> $DIR/type_check.rs:33:8 + | +33 | T: scale::Encode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied + --> $DIR/M-04-message-returns-non-codec.rs:18:9 + | +18 | / pub fn message(&self) -> NonCodecType { +19 | | NonCodecType +20 | | } + | |_________^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `Encode` for `NonCodecType` +note: required by a bound in `execute_message` + --> $DIR/dispatcher.rs:126:13 + | +126 | Output: scale::Encode + 'static, + | ^^^^^^^^^^^^^ required by this bound in `execute_message` + +error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied + --> $DIR/M-04-message-returns-non-codec.rs:18:9 + | +6 | pub struct NonCodecType; + | ------------------------ doesn't satisfy `_: contract::_::_parity_scale_codec::Decode` +... +18 | / pub fn message(&self) -> NonCodecType { +19 | | NonCodecType +20 | | } + | |_________^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NonCodecType: contract::_::_parity_scale_codec::Decode` From b3abfb9bdf4b307c78ea8b79f378393840b8cbad Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:08:22 +0200 Subject: [PATCH 286/493] add UI tests for many ink! message and constructor inputs and outputs --- crates/lang/macro/tests/compile_tests.rs | 3 + .../contract/pass/constructor-many-inputs.rs | 125 ++++++++++ .../ui/contract/pass/message-many-inputs.rs | 222 ++++++++++++++++++ .../ui/contract/pass/message-many-outputs.rs | 72 ++++++ 4 files changed, 422 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/constructor-many-inputs.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/message-many-inputs.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/message-many-outputs.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 260ef968c2..d6b221d5bb 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -16,6 +16,9 @@ fn contract() { let t = trybuild::TestCases::new(); + t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); + t.pass("tests/ui/contract/pass/message-many-inputs.rs"); + t.pass("tests/ui/contract/pass/message-many-outputs.rs"); t.pass("tests/ui/contract/pass/01-noop-contract.rs"); t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/constructor-many-inputs.rs b/crates/lang/macro/tests/ui/contract/pass/constructor-many-inputs.rs new file mode 100644 index 0000000000..e1cc2c7af9 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/constructor-many-inputs.rs @@ -0,0 +1,125 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor_0() -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_1(_input_1: i8) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_2(_input_1: i8, _input_2: i16) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_3(_input_1: i8, _input_2: i16, _input_3: i32) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_4( + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + ) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_5( + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + ) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_6( + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + ) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_7( + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + ) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_8( + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + ) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_9( + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + _input_9: u64, + ) -> Self { + Self {} + } + + #[ink(constructor)] + pub fn constructor_10( + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + _input_9: u64, + _input_10: u128, + ) -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/message-many-inputs.rs b/crates/lang/macro/tests/ui/contract/pass/message-many-inputs.rs new file mode 100644 index 0000000000..556ab08e07 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/message-many-inputs.rs @@ -0,0 +1,222 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message_0_ref(&self) {} + + #[ink(message)] + pub fn message_0_mut(&mut self) {} + + #[ink(message)] + pub fn message_1_ref(&self, _input_1: i8) {} + + #[ink(message)] + pub fn message_1_mut(&mut self, _input_1: i8) {} + + #[ink(message)] + pub fn message_2_ref(&self, _input_1: i8, _input_2: i16) {} + + #[ink(message)] + pub fn message_2_mut(&mut self, _input_1: i8, _input_2: i16) {} + + #[ink(message)] + pub fn message_3_ref(&self, _input_1: i8, _input_2: i16, _input_3: i32) {} + + #[ink(message)] + pub fn message_3_mut(&mut self, _input_1: i8, _input_2: i16, _input_3: i32) {} + + #[ink(message)] + pub fn message_4_ref( + &self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + ) { + } + + #[ink(message)] + pub fn message_4_mut( + &mut self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + ) { + } + + #[ink(message)] + pub fn message_5_ref( + &self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + ) { + } + + #[ink(message)] + pub fn message_5_mut( + &mut self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + ) { + } + + #[ink(message)] + pub fn message_6_ref( + &self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + ) { + } + + #[ink(message)] + pub fn message_6_mut( + &mut self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + ) { + } + + #[ink(message)] + pub fn message_7_ref( + &self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + ) { + } + + #[ink(message)] + pub fn message_7_mut( + &mut self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + ) { + } + + #[ink(message)] + pub fn message_8_ref( + &self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + ) { + } + + #[ink(message)] + pub fn message_8_mut( + &mut self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + ) { + } + + #[ink(message)] + pub fn message_9_ref( + &self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + _input_9: u64, + ) { + } + + #[ink(message)] + pub fn message_9_mut( + &mut self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + _input_9: u64, + ) { + } + + #[ink(message)] + pub fn message_10_ref( + &self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + _input_9: u64, + _input_10: u128, + ) { + } + + #[ink(message)] + pub fn message_10_mut( + &mut self, + _input_1: i8, + _input_2: i16, + _input_3: i32, + _input_4: i64, + _input_5: i128, + _input_6: u8, + _input_7: u16, + _input_8: u32, + _input_9: u64, + _input_10: u128, + ) { + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/message-many-outputs.rs b/crates/lang/macro/tests/ui/contract/pass/message-many-outputs.rs new file mode 100644 index 0000000000..5ff863ed93 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/message-many-outputs.rs @@ -0,0 +1,72 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message_0_ref(&self) {} + + #[ink(message)] + pub fn message_0_mut(&mut self) {} + + #[ink(message)] + pub fn message_1_ref(&self) -> i8 { + unimplemented!() + } + + #[ink(message)] + pub fn message_1_mut(&mut self) -> i8 { + unimplemented!() + } + + #[ink(message)] + pub fn message_2_ref(&self) -> (i8, i16) { + unimplemented!() + } + + #[ink(message)] + pub fn message_2_mut(&mut self) -> (i8, i16) { + unimplemented!() + } + + #[ink(message)] + pub fn message_3_ref(&self) -> (i8, i16, i32) { + unimplemented!() + } + + #[ink(message)] + pub fn message_3_mut(&mut self) -> (i8, i16, i32) { + unimplemented!() + } + + #[ink(message)] + pub fn message_4_ref(&self) -> (i8, i16, i32, i64) { + unimplemented!() + } + + #[ink(message)] + pub fn message_4_mut(&mut self) -> (i8, i16, i32, i64) { + unimplemented!() + } + + #[ink(message)] + pub fn message_5_ref(&self) -> (i8, i16, i32, i64, i128) { + unimplemented!() + } + + #[ink(message)] + pub fn message_5_mut(&mut self) -> (i8, i16, i32, i64, i128) { + unimplemented!() + } + } +} + +fn main() {} From d148e581e5bdb9e71d15e7344f39af165381db09 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:10:24 +0200 Subject: [PATCH 287/493] move noop contract UI test --- crates/lang/macro/tests/compile_tests.rs | 2 +- .../contract/pass/{01-noop-contract.rs => minimal-contract.rs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename crates/lang/macro/tests/ui/contract/pass/{01-noop-contract.rs => minimal-contract.rs} (100%) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index d6b221d5bb..6d59f24f3a 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -19,7 +19,7 @@ fn contract() { t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); t.pass("tests/ui/contract/pass/message-many-inputs.rs"); t.pass("tests/ui/contract/pass/message-many-outputs.rs"); - t.pass("tests/ui/contract/pass/01-noop-contract.rs"); + t.pass("tests/ui/contract/pass/minimal-contract.rs"); t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/01-noop-contract.rs b/crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/01-noop-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs From 5183077c97095fdf88b8c7479206b792defee34e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:10:49 +0200 Subject: [PATCH 288/493] normalize UI test --- .../macro/tests/ui/contract/pass/minimal-contract.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs b/crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs index 130e7fb0c8..f20a5b77ff 100644 --- a/crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs +++ b/crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs @@ -1,18 +1,18 @@ use ink_lang as ink; #[ink::contract] -mod noop { +mod contract { #[ink(storage)] - pub struct Noop {} + pub struct Contract {} - impl Noop { + impl Contract { #[ink(constructor)] - pub fn new() -> Self { + pub fn constructor() -> Self { Self {} } #[ink(message)] - pub fn noop(&self) {} + pub fn message(&self) {} } } From 545e9547dfee9b7c6314daeffd81d1913909ad2b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:20:42 +0200 Subject: [PATCH 289/493] add passing UI tests for payable and selector properties --- crates/lang/macro/tests/compile_tests.rs | 2 + .../tests/ui/contract/pass/message-payable.rs | 27 +++++++++ .../ui/contract/pass/message-selector.rs | 57 +++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/message-payable.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/message-selector.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 6d59f24f3a..9a6e4d7b27 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -19,6 +19,8 @@ fn contract() { t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); t.pass("tests/ui/contract/pass/message-many-inputs.rs"); t.pass("tests/ui/contract/pass/message-many-outputs.rs"); + t.pass("tests/ui/contract/pass/message-payable.rs"); + t.pass("tests/ui/contract/pass/message-selector.rs"); t.pass("tests/ui/contract/pass/minimal-contract.rs"); t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/message-payable.rs b/crates/lang/macro/tests/ui/contract/pass/message-payable.rs new file mode 100644 index 0000000000..2463460d5a --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/message-payable.rs @@ -0,0 +1,27 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message, selector = 1, payable)] + pub fn message_1(&self) {} + + #[ink(message, selector = 2)] + pub fn message_2(&self) {} + } +} + +use contract::Contract; + +fn main() { + assert!(>::PAYABLE); + assert!(!>::PAYABLE); +} diff --git a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs new file mode 100644 index 0000000000..941565b0b8 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs @@ -0,0 +1,57 @@ +use contract::Contract; +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message_0(&self) {} + + #[ink(message, selector = 1)] + pub fn message_1(&self) {} + + #[ink(message, selector = 0xC0DE_CAFE)] + pub fn message_2(&self) {} + } +} + +fn main() { + assert_eq!( + ::MESSAGES }, + >>::IDS[0] + }, + >>::SELECTOR, + [90, 106, 193, 93], + ); + assert_eq!( + ::MESSAGES }, + >>::IDS[1] + }, + >>::SELECTOR, + 1_u32.to_be_bytes(), + ); + assert_eq!( + ::MESSAGES }, + >>::IDS[2] + }, + >>::SELECTOR, + 0xC0DE_CAFE_u32.to_be_bytes(), + ); +} From 66f8460485e98ebf537a95a0b24ad9aab1a6ee21 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:25:59 +0200 Subject: [PATCH 290/493] improve passing ink! message selector UI test --- crates/lang/macro/tests/ui/contract/pass/message-selector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs index 941565b0b8..26dd166da8 100644 --- a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs +++ b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs @@ -32,7 +32,7 @@ fn main() { >>::IDS[0] }, >>::SELECTOR, - [90, 106, 193, 93], + [0x5A, 0x6A, 0xC1, 0x5D], ); assert_eq!( Date: Mon, 27 Sep 2021 15:26:18 +0200 Subject: [PATCH 291/493] add passing UI test for ink! constructor selector property --- crates/lang/macro/tests/compile_tests.rs | 1 + .../ui/contract/pass/constructor-selector.rs | 67 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 9a6e4d7b27..949a8995bc 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -17,6 +17,7 @@ fn contract() { let t = trybuild::TestCases::new(); t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); + t.pass("tests/ui/contract/pass/constructor-selector.rs"); t.pass("tests/ui/contract/pass/message-many-inputs.rs"); t.pass("tests/ui/contract/pass/message-many-outputs.rs"); t.pass("tests/ui/contract/pass/message-payable.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs b/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs new file mode 100644 index 0000000000..0e45b36751 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs @@ -0,0 +1,67 @@ +use contract::Contract; +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor_0() -> Self { + Self {} + } + + #[ink(constructor, selector = 1)] + pub fn constructor_1() -> Self { + Self {} + } + + #[ink(constructor, selector = 0xC0DE_CAFE)] + pub fn constructor_2() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() { + assert_eq!( + ::CONSTRUCTORS + }, + >>::IDS[0] + }, + >>::SELECTOR, + [0x5C, 0x5D, 0x42, 0x89], + ); + assert_eq!( + ::CONSTRUCTORS + }, + >>::IDS[1] + }, + >>::SELECTOR, + 1_u32.to_be_bytes(), + ); + assert_eq!( + ::CONSTRUCTORS + }, + >>::IDS[2] + }, + >>::SELECTOR, + 0xC0DE_CAFE_u32.to_be_bytes(), + ); +} From 661bad25dc7d43aed283d31195cd4d5de1092e38 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:34:52 +0200 Subject: [PATCH 292/493] add UI tests for ink! storage structs with various fields --- crates/lang/macro/tests/compile_tests.rs | 2 ++ .../ui/contract/pass/storage-many-fields.rs | 30 +++++++++++++++++++ .../ui/contract/pass/storage-single-field.rs | 21 +++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/storage-many-fields.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/storage-single-field.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 949a8995bc..b309950c5c 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -23,6 +23,8 @@ fn contract() { t.pass("tests/ui/contract/pass/message-payable.rs"); t.pass("tests/ui/contract/pass/message-selector.rs"); t.pass("tests/ui/contract/pass/minimal-contract.rs"); + t.pass("tests/ui/contract/pass/storage-single-field.rs"); + t.pass("tests/ui/contract/pass/storage-many-fields.rs"); t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-many-fields.rs b/crates/lang/macro/tests/ui/contract/pass/storage-many-fields.rs new file mode 100644 index 0000000000..f713eb1926 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/storage-many-fields.rs @@ -0,0 +1,30 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract { + field_1: i8, + field_2: i16, + field_3: i32, + field_4: i64, + field_5: i128, + field_6: u8, + field_7: u16, + field_8: u32, + field_9: u64, + field_10: u128, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + unimplemented!() + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-single-field.rs b/crates/lang/macro/tests/ui/contract/pass/storage-single-field.rs new file mode 100644 index 0000000000..acda95e192 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/storage-single-field.rs @@ -0,0 +1,21 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract { + field: i8, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self { field: 0 } + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From 98aede5a26647993b2a8bdaa480715f4bc9c8e55 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:44:13 +0200 Subject: [PATCH 293/493] add passing UI tests for ink! events --- crates/lang/macro/tests/compile_tests.rs | 3 + .../contract/pass/event-many-definitions.rs | 100 +++++++++++++++ .../contract/pass/event-single-definition.rs | 22 ++++ .../tests/ui/contract/pass/event-topics.rs | 115 ++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/event-many-definitions.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/event-single-definition.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/event-topics.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index b309950c5c..417b394e34 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -25,6 +25,9 @@ fn contract() { t.pass("tests/ui/contract/pass/minimal-contract.rs"); t.pass("tests/ui/contract/pass/storage-single-field.rs"); t.pass("tests/ui/contract/pass/storage-many-fields.rs"); + t.pass("tests/ui/contract/pass/event-single-definition.rs"); + t.pass("tests/ui/contract/pass/event-many-definitions.rs"); + t.pass("tests/ui/contract/pass/event-topics.rs"); t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/event-many-definitions.rs b/crates/lang/macro/tests/ui/contract/pass/event-many-definitions.rs new file mode 100644 index 0000000000..06e0600cf2 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/event-many-definitions.rs @@ -0,0 +1,100 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event)] + pub struct Event0 {} + + #[ink(event)] + pub struct Event1 { + arg_1: i8, + } + + #[ink(event)] + pub struct Event2 { + arg_1: i8, + arg_2: i16, + } + + #[ink(event)] + pub struct Event3 { + arg_1: i8, + arg_2: i16, + arg_3: i32, + } + + #[ink(event)] + pub struct Event4 { + arg_1: i8, + arg_2: i16, + arg_3: i32, + arg_4: i64, + } + + #[ink(event)] + pub struct Event5 { + arg_1: i8, + arg_2: i16, + arg_3: i32, + arg_4: i64, + arg_5: i128, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::env().emit_event(Event0 {}); + Self::env().emit_event(Event1 { arg_1: 1 }); + Self::env().emit_event(Event2 { arg_1: 1, arg_2: 2 }); + Self::env().emit_event(Event3 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + Self::env().emit_event(Event4 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + Self::env().emit_event(Event5 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + }); + Self {} + } + + #[ink(message)] + pub fn message(&self) { + self.env().emit_event(Event0 {}); + self.env().emit_event(Event1 { arg_1: 1 }); + self.env().emit_event(Event2 { arg_1: 1, arg_2: 2 }); + self.env().emit_event(Event3 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + self.env().emit_event(Event4 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + self.env().emit_event(Event5 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + }); + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/event-single-definition.rs b/crates/lang/macro/tests/ui/contract/pass/event-single-definition.rs new file mode 100644 index 0000000000..ae2896bb0d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/event-single-definition.rs @@ -0,0 +1,22 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event)] + pub struct Event0 {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/event-topics.rs b/crates/lang/macro/tests/ui/contract/pass/event-topics.rs new file mode 100644 index 0000000000..500a832317 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/event-topics.rs @@ -0,0 +1,115 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event)] + pub struct Event0 {} + + #[ink(event)] + pub struct Event1 { + #[ink(topic)] + arg_1: i8, + } + + #[ink(event)] + pub struct Event2 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + } + + #[ink(event)] + pub struct Event3 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + } + + #[ink(event)] + pub struct Event4 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + #[ink(topic)] + arg_4: i64, + } + + #[ink(event)] + pub struct Event5 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + #[ink(topic)] + arg_4: i64, + // #[ink(topic)] <- Cannot have more than 4 topics by default. + arg_5: i128, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::env().emit_event(Event0 {}); + Self::env().emit_event(Event1 { arg_1: 1 }); + Self::env().emit_event(Event2 { arg_1: 1, arg_2: 2 }); + Self::env().emit_event(Event3 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + Self::env().emit_event(Event4 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + Self::env().emit_event(Event5 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + }); + Self {} + } + + #[ink(message)] + pub fn message(&self) { + self.env().emit_event(Event0 {}); + self.env().emit_event(Event1 { arg_1: 1 }); + self.env().emit_event(Event2 { arg_1: 1, arg_2: 2 }); + self.env().emit_event(Event3 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + self.env().emit_event(Event4 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + self.env().emit_event(Event5 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + }); + } + } +} + +fn main() {} From ed86a03a57bd2c33679e322506401ff90707025b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:49:01 +0200 Subject: [PATCH 294/493] add passing packed ink! storage struct UI test --- crates/lang/macro/tests/compile_tests.rs | 1 + .../ui/contract/pass/storage-packed-fields.rs | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/storage-packed-fields.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 417b394e34..940011c625 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -25,6 +25,7 @@ fn contract() { t.pass("tests/ui/contract/pass/minimal-contract.rs"); t.pass("tests/ui/contract/pass/storage-single-field.rs"); t.pass("tests/ui/contract/pass/storage-many-fields.rs"); + t.pass("tests/ui/contract/pass/storage-packed-fields.rs"); t.pass("tests/ui/contract/pass/event-single-definition.rs"); t.pass("tests/ui/contract/pass/event-many-definitions.rs"); t.pass("tests/ui/contract/pass/event-topics.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-packed-fields.rs b/crates/lang/macro/tests/ui/contract/pass/storage-packed-fields.rs new file mode 100644 index 0000000000..dc86aab8a7 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/storage-packed-fields.rs @@ -0,0 +1,51 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + use ink_storage::traits::{ + PackedLayout, + SpreadLayout, + StorageLayout, + }; + + #[ink(storage)] + pub struct Contract { + packed: PackedFields, + } + + #[derive( + Debug, + Default, + SpreadLayout, + PackedLayout, + StorageLayout, + scale::Encode, + scale::Decode, + )] + pub struct PackedFields { + field_1: i8, + field_2: i16, + field_3: i32, + field_4: i64, + field_5: i128, + field_6: u8, + field_7: u16, + field_8: u32, + field_9: u64, + field_10: u128, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self { + packed: Default::default(), + } + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From 4d6deecd1057857f41d787e84a639b9501df0568 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 15:57:51 +0200 Subject: [PATCH 295/493] improve macro hygiene in StorageLayout derive impl --- crates/storage/derive/src/storage_layout.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/storage/derive/src/storage_layout.rs b/crates/storage/derive/src/storage_layout.rs index c215121855..54aa39e36d 100644 --- a/crates/storage/derive/src/storage_layout.rs +++ b/crates/storage/derive/src/storage_layout.rs @@ -51,7 +51,7 @@ fn storage_layout_struct(s: &synstructure::Structure) -> TokenStream2 { gen impl ::ink_storage::traits::StorageLayout for @Self { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(vec![ + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ #(#field_layouts ,)* ]) ) @@ -79,7 +79,7 @@ fn storage_layout_enum(s: &synstructure::Structure) -> TokenStream2 { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(#discriminant), - ::ink_metadata::layout::StructLayout::new(vec![ + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ #(#field_layouts ,)* ]), ) @@ -93,7 +93,7 @@ fn storage_layout_enum(s: &synstructure::Structure) -> TokenStream2 { ::ink_metadata::layout::Layout::Enum( ::ink_metadata::layout::EnumLayout::new( ::ink_metadata::layout::LayoutKey::from(dispatch_key), - vec![ + ::ink_prelude::vec![ #(#variant_layouts ,)* ] ) From 0bdb371f39ee4a7a25a62ff98e70ffdce4c51c52 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:01:16 +0200 Subject: [PATCH 296/493] add no-implicit-prelude passing UI test Currently disabled since static_assertions dependency has macro hygiene problems with respect to no_implicit_prelude. --- crates/lang/macro/tests/compile_tests.rs | 1 + .../ui/contract/pass/no-implicit-prelude.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 940011c625..0fbf6fa7c2 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -29,6 +29,7 @@ fn contract() { t.pass("tests/ui/contract/pass/event-single-definition.rs"); t.pass("tests/ui/contract/pass/event-many-definitions.rs"); t.pass("tests/ui/contract/pass/event-topics.rs"); + // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs b/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs new file mode 100644 index 0000000000..e288ee4a57 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs @@ -0,0 +1,19 @@ +#![no_implicit_prelude] + +#[::ink_lang::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From 819649d142cc497c62d4f06c38ff0cd1cb56799d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:06:28 +0200 Subject: [PATCH 297/493] add impl alias passing UI test --- crates/lang/macro/tests/compile_tests.rs | 2 +- .../pass/11-alias-storage-struct-impl.rs | 21 ------------------- .../ui/contract/pass/impl-alias-storage.rs | 21 +++++++++++++++++++ 3 files changed, 22 insertions(+), 22 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/contract/pass/11-alias-storage-struct-impl.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/impl-alias-storage.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 0fbf6fa7c2..d41a410f58 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -29,6 +29,7 @@ fn contract() { t.pass("tests/ui/contract/pass/event-single-definition.rs"); t.pass("tests/ui/contract/pass/event-many-definitions.rs"); t.pass("tests/ui/contract/pass/event-topics.rs"); + t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); @@ -39,7 +40,6 @@ fn contract() { t.pass("tests/ui/contract/pass/08-flipper-as-dependency-trait.rs"); t.pass("tests/ui/contract/pass/09-static-env.rs"); t.pass("tests/ui/contract/pass/10-derive-for-storage.rs"); - t.pass("tests/ui/contract/pass/11-alias-storage-struct-impl.rs"); t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/11-alias-storage-struct-impl.rs b/crates/lang/macro/tests/ui/contract/pass/11-alias-storage-struct-impl.rs deleted file mode 100644 index f287c2f762..0000000000 --- a/crates/lang/macro/tests/ui/contract/pass/11-alias-storage-struct-impl.rs +++ /dev/null @@ -1,21 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - pub type NoopAlias = Noop; - - impl NoopAlias { - #[ink(constructor)] - pub fn new() -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-alias-storage.rs b/crates/lang/macro/tests/ui/contract/pass/impl-alias-storage.rs new file mode 100644 index 0000000000..fbbebe55ad --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/impl-alias-storage.rs @@ -0,0 +1,21 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + type ContractAlias = Contract; + + impl ContractAlias { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From 18951bd082ae1a3603053edda38f5cc102f1f790 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:07:46 +0200 Subject: [PATCH 298/493] modernize passing UI test for ink! storage struct derives --- crates/lang/macro/tests/compile_tests.rs | 2 +- .../ui/contract/pass/10-derive-for-storage.rs | 20 ---------------- .../ui/contract/pass/storage-with-derives.rs | 23 +++++++++++++++++++ 3 files changed, 24 insertions(+), 21 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/contract/pass/10-derive-for-storage.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/storage-with-derives.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index d41a410f58..518e6a425e 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -26,6 +26,7 @@ fn contract() { t.pass("tests/ui/contract/pass/storage-single-field.rs"); t.pass("tests/ui/contract/pass/storage-many-fields.rs"); t.pass("tests/ui/contract/pass/storage-packed-fields.rs"); + t.pass("tests/ui/contract/pass/storage-with-derives.rs"); t.pass("tests/ui/contract/pass/event-single-definition.rs"); t.pass("tests/ui/contract/pass/event-many-definitions.rs"); t.pass("tests/ui/contract/pass/event-topics.rs"); @@ -39,7 +40,6 @@ fn contract() { t.pass("tests/ui/contract/pass/07-flipper-as-dependency.rs"); t.pass("tests/ui/contract/pass/08-flipper-as-dependency-trait.rs"); t.pass("tests/ui/contract/pass/09-static-env.rs"); - t.pass("tests/ui/contract/pass/10-derive-for-storage.rs"); t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/10-derive-for-storage.rs b/crates/lang/macro/tests/ui/contract/pass/10-derive-for-storage.rs deleted file mode 100644 index 9f823ee498..0000000000 --- a/crates/lang/macro/tests/ui/contract/pass/10-derive-for-storage.rs +++ /dev/null @@ -1,20 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod derive_for_storage { - #[ink(storage)] - #[derive(Default)] - pub struct DeriveForStorage {} - - impl DeriveForStorage { - #[ink(constructor)] - pub fn constructor() -> Self { - Default::default() - } - - #[ink(message)] - pub fn message(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-with-derives.rs b/crates/lang/macro/tests/ui/contract/pass/storage-with-derives.rs new file mode 100644 index 0000000000..20e709298e --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/storage-with-derives.rs @@ -0,0 +1,23 @@ +use contract::Contract; +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + #[derive(Debug, Default, PartialEq, Eq)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::default() + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() { + assert_eq!(Contract::constructor(), Contract::default()); +} From f630bd26539539795173a680c69281cecbe6fed9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:20:54 +0200 Subject: [PATCH 299/493] modernize flipper example contract passing UI test --- crates/lang/macro/tests/compile_tests.rs | 2 +- ...r-contract.rs => example-flipper-works.rs} | 27 +++++-------------- 2 files changed, 8 insertions(+), 21 deletions(-) rename crates/lang/macro/tests/ui/contract/pass/{02-flipper-contract.rs => example-flipper-works.rs} (53%) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 518e6a425e..541ebc73f5 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -32,7 +32,7 @@ fn contract() { t.pass("tests/ui/contract/pass/event-topics.rs"); t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); - t.pass("tests/ui/contract/pass/02-flipper-contract.rs"); + t.pass("tests/ui/contract/pass/example-flipper-works.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/02-flipper-contract.rs b/crates/lang/macro/tests/ui/contract/pass/example-flipper-works.rs similarity index 53% rename from crates/lang/macro/tests/ui/contract/pass/02-flipper-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/example-flipper-works.rs index 89f173cf98..0aef590fb6 100644 --- a/crates/lang/macro/tests/ui/contract/pass/02-flipper-contract.rs +++ b/crates/lang/macro/tests/ui/contract/pass/example-flipper-works.rs @@ -1,3 +1,4 @@ +use flipper::Flipper; use ink_lang as ink; #[ink::contract] @@ -13,11 +14,6 @@ mod flipper { Self { value: init_value } } - #[ink(constructor)] - pub fn default() -> Self { - Self::new(false) - } - #[ink(message)] pub fn flip(&mut self) { self.value = !self.value; @@ -28,20 +24,11 @@ mod flipper { self.value } } - - #[cfg(test)] - mod tests { - use super::*; - use ink_lang as ink; - - #[ink::test] - fn it_works() { - let mut flipper = Flipper::new(false); - assert!(!flipper.get()); - flipper.flip(); - assert!(flipper.get()); - } - } } -fn main() {} +fn main() { + let mut flipper = Flipper::new(false); + assert!(!flipper.get()); + flipper.flip(); + assert!(flipper.get()); +} From 0bba5b3f0bdf174fb1e5354e36b4daf1422d779e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:25:56 +0200 Subject: [PATCH 300/493] add new trait-flipper example passing UI test --- crates/lang/macro/tests/compile_tests.rs | 1 + .../pass/example-trait-flipper-works.rs | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/example-trait-flipper-works.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 541ebc73f5..1f9dfed64a 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -33,6 +33,7 @@ fn contract() { t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/example-flipper-works.rs"); + t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/example-trait-flipper-works.rs b/crates/lang/macro/tests/ui/contract/pass/example-trait-flipper-works.rs new file mode 100644 index 0000000000..8a8f920ca1 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/example-trait-flipper-works.rs @@ -0,0 +1,50 @@ +use flipper::Flipper; +use ink_lang as ink; + +#[ink::trait_definition] +pub trait Flip { + #[ink(message)] + fn flip(&mut self); + + #[ink(message)] + fn get(&self) -> bool; +} + +#[ink::contract] +mod flipper { + use super::Flip; + + #[ink(storage)] + pub struct Flipper { + value: bool, + } + + impl Flipper { + #[ink(constructor)] + pub fn new(init_value: bool) -> Self { + Self { value: init_value } + } + } + + impl Flip for Flipper { + #[ink(message)] + fn flip(&mut self) { + self.value = !self.value; + } + + #[ink(message)] + fn get(&self) -> bool { + self.value + } + } +} + +fn main() { + // We use the verbose universal call syntax for trait methods + // in order to make sure that the trait flipper example actually + // implements its messages as Rust traits. + let mut flipper = Flipper::new(false); + assert!(!::get(&flipper)); + ::flip(&mut flipper); + assert!(::get(&flipper)); +} From 9855df62b2c904b3804bbe6b6b6bd201851cfad4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:27:48 +0200 Subject: [PATCH 301/493] add new passing UI test for #[ink(impl)] property --- crates/lang/macro/tests/compile_tests.rs | 1 + .../ui/contract/pass/impl-with-property.rs | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/impl-with-property.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 1f9dfed64a..b57996130b 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -31,6 +31,7 @@ fn contract() { t.pass("tests/ui/contract/pass/event-many-definitions.rs"); t.pass("tests/ui/contract/pass/event-topics.rs"); t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); + t.pass("tests/ui/contract/pass/impl-with-property.rs"); // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/example-flipper-works.rs"); t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-with-property.rs b/crates/lang/macro/tests/ui/contract/pass/impl-with-property.rs new file mode 100644 index 0000000000..8f58c32e65 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/impl-with-property.rs @@ -0,0 +1,23 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(impl)] + impl Contract {} + + #[ink(impl)] + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From 4762b96f11ca09204262e0d7bbb0e26be1db013a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:29:22 +0200 Subject: [PATCH 302/493] rename 03-incrementer-contract UI test --- crates/lang/macro/tests/compile_tests.rs | 2 +- ...{03-incrementer-contract.rs => example-incrementer-works.rs} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename crates/lang/macro/tests/ui/contract/pass/{03-incrementer-contract.rs => example-incrementer-works.rs} (100%) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index b57996130b..2db4ec511a 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -35,7 +35,7 @@ fn contract() { // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/example-flipper-works.rs"); t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); - t.pass("tests/ui/contract/pass/03-incrementer-contract.rs"); + t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); t.pass("tests/ui/contract/pass/06-non-ink-items.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/03-incrementer-contract.rs b/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/03-incrementer-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs From d31fecb1d757ef9820f8cb8057ea5d2f33df60ca Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:31:53 +0200 Subject: [PATCH 303/493] modernize example incrementer passing UI test --- .../pass/example-incrementer-works.rs | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs b/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs index 612d1ffbba..ca5953adb0 100644 --- a/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs +++ b/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs @@ -1,4 +1,5 @@ use ink_lang as ink; +use incrementer::Incrementer; #[ink::contract] mod incrementer { @@ -7,32 +8,17 @@ mod incrementer { value: i64, } - #[ink(event)] - pub struct Incremented { - #[ink(topic)] - caller: AccountId, - #[ink(topic)] - by: i32, - } - impl Incrementer { #[ink(constructor)] - pub fn new(init_value: i32) -> Self { + pub fn new(init_value: i64) -> Self { Self { - value: init_value as i64, + value: init_value, } } - #[ink(constructor)] - pub fn default() -> Self { - Self::new(0) - } - #[ink(message)] - pub fn inc_by(&mut self, by: i32) { - let caller = self.env().caller(); - self.env().emit_event(Incremented { caller, by }); - self.value += by as i64; + pub fn inc_by(&mut self, delta: i64) { + self.value += delta; } #[ink(message)] @@ -42,4 +28,11 @@ mod incrementer { } } -fn main() {} +fn main() { + let mut incrementer = Incrementer::new(0); + assert_eq!(incrementer.get(), 0); + incrementer.inc_by(1); + assert_eq!(incrementer.get(), 1); + incrementer.inc_by(-1); + assert_eq!(incrementer.get(), 0); +} From 21f7c1914478d7a17c9ed92b872e9f5b3e3d9b03 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:37:33 +0200 Subject: [PATCH 304/493] apply rustfmt to UI test --- .../tests/ui/contract/pass/example-incrementer-works.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs b/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs index ca5953adb0..959f0dfc02 100644 --- a/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs +++ b/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs @@ -1,5 +1,5 @@ -use ink_lang as ink; use incrementer::Incrementer; +use ink_lang as ink; #[ink::contract] mod incrementer { @@ -11,9 +11,7 @@ mod incrementer { impl Incrementer { #[ink(constructor)] pub fn new(init_value: i64) -> Self { - Self { - value: init_value, - } + Self { value: init_value } } #[ink(message)] From 92d6bcdd49cd7224620f0479c0dce3dba5cf5f2b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:37:46 +0200 Subject: [PATCH 305/493] fix a doc test in ink_storage_derive crate --- crates/storage/derive/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/storage/derive/Cargo.toml b/crates/storage/derive/Cargo.toml index 72c57f81e5..8818a5b867 100644 --- a/crates/storage/derive/Cargo.toml +++ b/crates/storage/derive/Cargo.toml @@ -28,4 +28,5 @@ scale = { package = "parity-scale-codec", version = "2", default-features = fals ink_env = { version = "3.0.0-rc5", path = "../../env" } ink_primitives = { version = "3.0.0-rc5", path = "../../primitives" } ink_metadata = { version = "3.0.0-rc5", path = "../../metadata" } +ink_prelude = { version = "3.0.0-rc5", path = "../../prelude/" } ink_storage = { version = "3.0.0-rc5", path = ".." } From 04c44ce749b7975c466d96f50f9cab5978ad611d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:44:17 +0200 Subject: [PATCH 306/493] add passing UI test for trait based incrementer example ink! smart contract --- crates/lang/macro/tests/compile_tests.rs | 3 +- .../pass/example-trait-incrementer-works.rs | 72 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 2db4ec511a..f5c50e7981 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -34,8 +34,9 @@ fn contract() { t.pass("tests/ui/contract/pass/impl-with-property.rs"); // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/example-flipper-works.rs"); - t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); + t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); + t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); t.pass("tests/ui/contract/pass/06-non-ink-items.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs b/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs new file mode 100644 index 0000000000..91f94ef999 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs @@ -0,0 +1,72 @@ +use incrementer::Incrementer; +use ink_lang as ink; + +#[ink::trait_definition] +pub trait Increment { + #[ink(message)] + fn inc(&mut self); + + #[ink(message)] + fn get(&self) -> i64; +} + +#[ink::trait_definition] +pub trait Reset { + #[ink(message)] + fn reset(&mut self); +} + +#[ink::contract] +mod incrementer { + use super::{Increment, Reset}; + + #[ink(storage)] + pub struct Incrementer { + value: i64, + } + + impl Incrementer { + #[ink(constructor)] + pub fn new(init_value: i64) -> Self { + Self { value: init_value } + } + + #[ink(message)] + pub fn inc_by(&mut self, delta: i64) { + self.value += delta; + } + } + + impl Increment for Incrementer { + #[ink(message)] + fn inc(&mut self) { + self.inc_by(1) + } + + #[ink(message)] + fn get(&self) -> i64 { + self.value + } + } + + impl Reset for Incrementer { + #[ink(message)] + fn reset(&mut self) { + self.value = 0; + } + } +} + +fn main() { + let mut incrementer = Incrementer::new(0); + assert_eq!(::get(&incrementer), 0); + incrementer.inc_by(1); + assert_eq!(::get(&incrementer), 1); + incrementer.inc_by(-1); + assert_eq!(::get(&incrementer), 0); + + ::inc(&mut incrementer); + assert_eq!(::get(&incrementer), 1); + ::inc(&mut incrementer); + assert_eq!(::get(&incrementer), 2); +} From a450b71745cd196f9ee2686cb9512b0246945f31 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 16:44:28 +0200 Subject: [PATCH 307/493] apply rustfmt to UI test --- .../ui/contract/pass/example-trait-incrementer-works.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs b/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs index 91f94ef999..493021ddfe 100644 --- a/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs +++ b/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs @@ -18,7 +18,10 @@ pub trait Reset { #[ink::contract] mod incrementer { - use super::{Increment, Reset}; + use super::{ + Increment, + Reset, + }; #[ink(storage)] pub struct Incrementer { From 7a9a5c14c5e0b907557c033a3b38550a349c9772 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 17:07:16 +0200 Subject: [PATCH 308/493] add passing UI tests for #[ink::contract] configs --- crates/lang/macro/tests/compile_tests.rs | 6 ++- .../contract/pass/07-flipper-as-dependency.rs | 33 --------------- .../pass/08-flipper-as-dependency-trait.rs | 41 ------------------- .../config-compile-as-dependency-false.rs | 19 +++++++++ .../pass/config-compile-as-dependency-true.rs | 19 +++++++++ .../config-dynamic-storage-allocator-false.rs | 19 +++++++++ .../config-dynamic-storage-allocator-true.rs | 19 +++++++++ 7 files changed, 80 insertions(+), 76 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/contract/pass/07-flipper-as-dependency.rs delete mode 100644 crates/lang/macro/tests/ui/contract/pass/08-flipper-as-dependency-trait.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-false.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-true.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index f5c50e7981..f9ade41365 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -37,11 +37,13 @@ fn contract() { t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); + t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); + t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); + t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); + t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); t.pass("tests/ui/contract/pass/06-non-ink-items.rs"); - t.pass("tests/ui/contract/pass/07-flipper-as-dependency.rs"); - t.pass("tests/ui/contract/pass/08-flipper-as-dependency-trait.rs"); t.pass("tests/ui/contract/pass/09-static-env.rs"); t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/07-flipper-as-dependency.rs b/crates/lang/macro/tests/ui/contract/pass/07-flipper-as-dependency.rs deleted file mode 100644 index ace96903df..0000000000 --- a/crates/lang/macro/tests/ui/contract/pass/07-flipper-as-dependency.rs +++ /dev/null @@ -1,33 +0,0 @@ -use ink_lang as ink; - -#[ink::contract(compile_as_dependency = true)] -mod flipper { - #[ink(storage)] - pub struct Flipper { - value: bool, - } - - impl Flipper { - #[ink(constructor)] - pub fn new(init_value: bool) -> Self { - Self { value: init_value } - } - - #[ink(constructor)] - pub fn default() -> Self { - Self::new(false) - } - - #[ink(message)] - pub fn flip(&mut self) { - self.value = !self.value; - } - - #[ink(message)] - pub fn get(&self) -> bool { - self.value - } - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/08-flipper-as-dependency-trait.rs b/crates/lang/macro/tests/ui/contract/pass/08-flipper-as-dependency-trait.rs deleted file mode 100644 index f8afea65aa..0000000000 --- a/crates/lang/macro/tests/ui/contract/pass/08-flipper-as-dependency-trait.rs +++ /dev/null @@ -1,41 +0,0 @@ -use ink_lang as ink; - -#[ink::contract(compile_as_dependency = true)] -mod flipper { - #[ink_lang::trait_definition] - pub trait FlipperTrait { - #[ink(message)] - fn flip(&mut self); - - #[ink(message)] - fn get(&self) -> bool; - } - - #[ink(storage)] - pub struct Flipper { - value: bool, - } - - impl Flipper { - #[ink(constructor)] - pub fn new() -> Self { - Self { - value: Default::default(), - } - } - } - - impl FlipperTrait for Flipper { - #[ink(message)] - fn flip(&mut self) { - self.value = !self.value; - } - - #[ink(message)] - fn get(&self) -> bool { - self.value - } - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-false.rs b/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-false.rs new file mode 100644 index 0000000000..3f6997962c --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-false.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(compile_as_dependency = false)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-true.rs b/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-true.rs new file mode 100644 index 0000000000..003163166a --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-true.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(compile_as_dependency = true)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs b/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs new file mode 100644 index 0000000000..953d0afb4f --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(dynamic_storage_allocator = true)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs b/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs new file mode 100644 index 0000000000..953d0afb4f --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(dynamic_storage_allocator = true)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From f31759623f6a37c7e160aa13027d9d0f3f6e28fc Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 17:16:19 +0200 Subject: [PATCH 309/493] add passing UI test for #[ink::contract(env = ..)] config --- crates/lang/macro/tests/compile_tests.rs | 1 + .../ui/contract/pass/config-custom-env.rs | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/config-custom-env.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index f9ade41365..539ab943a8 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -41,6 +41,7 @@ fn contract() { t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs"); + t.pass("tests/ui/contract/pass/config-custom-env.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); t.pass("tests/ui/contract/pass/06-non-ink-items.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/config-custom-env.rs b/crates/lang/macro/tests/ui/contract/pass/config-custom-env.rs new file mode 100644 index 0000000000..613205f007 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/config-custom-env.rs @@ -0,0 +1,34 @@ +use ink_lang as ink; + +pub struct CustomEnv; + +impl ink_env::Environment for CustomEnv { + const MAX_EVENT_TOPICS: usize = 3; + type AccountId = [u8; 32]; + type Balance = u64; + type Hash = [u8; 32]; + type Timestamp = u64; + type BlockNumber = u64; + type ChainExtension = (); + // Too lazy to define a test type that fits the required trait bounds. + type RentFraction = + ::RentFraction; +} + +#[ink::contract(env = super::CustomEnv)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From f510ebcf66b764d0477419513a9943eab5f27794 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 17:32:11 +0200 Subject: [PATCH 310/493] modernize env-access passing UI test --- crates/lang/macro/tests/compile_tests.rs | 2 +- .../tests/ui/contract/pass/09-static-env.rs | 22 ---------- .../tests/ui/contract/pass/env-access.rs | 40 +++++++++++++++++++ 3 files changed, 41 insertions(+), 23 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/contract/pass/09-static-env.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/env-access.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 539ab943a8..25ddc0eb44 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -42,10 +42,10 @@ fn contract() { t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs"); t.pass("tests/ui/contract/pass/config-custom-env.rs"); + t.pass("tests/ui/contract/pass/env-access.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); t.pass("tests/ui/contract/pass/06-non-ink-items.rs"); - t.pass("tests/ui/contract/pass/09-static-env.rs"); t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/09-static-env.rs b/crates/lang/macro/tests/ui/contract/pass/09-static-env.rs deleted file mode 100644 index 80e967db2d..0000000000 --- a/crates/lang/macro/tests/ui/contract/pass/09-static-env.rs +++ /dev/null @@ -1,22 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod static_env { - #[ink(storage)] - pub struct UsesStaticEnv {} - - impl UsesStaticEnv { - #[ink(constructor)] - pub fn new() -> Self { - assert!(Self::env().balance() > 0); - Self {} - } - - #[ink(message)] - pub fn gas_left(&mut self) -> u64 { - Self::env().gas_left() - } - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/env-access.rs b/crates/lang/macro/tests/ui/contract/pass/env-access.rs new file mode 100644 index 0000000000..46437085c5 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/env-access.rs @@ -0,0 +1,40 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn new() -> Self { + let _ = Self::env().account_id(); + let _ = Self::env().balance(); + let _ = Self::env().block_timestamp(); + let _ = Self::env().block_number(); + let _ = Self::env().caller(); + let _ = Self::env().gas_left(); + let _ = Self::env().minimum_balance(); + let _ = Self::env().random(&[]); + let _ = Self::env().transferred_balance(); + let _ = Self::env().weight_to_fee(0); + Self {} + } + + #[ink(message)] + pub fn message(&self) { + let _ = self.env().account_id(); + let _ = self.env().balance(); + let _ = self.env().block_timestamp(); + let _ = self.env().block_number(); + let _ = self.env().caller(); + let _ = self.env().gas_left(); + let _ = self.env().minimum_balance(); + let _ = self.env().random(&[]); + let _ = self.env().transferred_balance(); + let _ = self.env().weight_to_fee(0); + } + } +} + +fn main() {} From 82cf1dba0382e211729ad67a61cf46751ba29e29 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 17:40:58 +0200 Subject: [PATCH 311/493] modernize passing UI test to assert Rust items are properly expanded --- crates/lang/macro/tests/compile_tests.rs | 2 +- .../ui/contract/pass/06-non-ink-items.rs | 27 ----------- .../ui/contract/pass/module-non-ink-items.rs | 48 +++++++++++++++++++ 3 files changed, 49 insertions(+), 28 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/contract/pass/06-non-ink-items.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/module-non-ink-items.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 25ddc0eb44..fcfb876bff 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -43,9 +43,9 @@ fn contract() { t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs"); t.pass("tests/ui/contract/pass/config-custom-env.rs"); t.pass("tests/ui/contract/pass/env-access.rs"); + t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); - t.pass("tests/ui/contract/pass/06-non-ink-items.rs"); t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/06-non-ink-items.rs b/crates/lang/macro/tests/ui/contract/pass/06-non-ink-items.rs deleted file mode 100644 index b7d5d4e071..0000000000 --- a/crates/lang/macro/tests/ui/contract/pass/06-non-ink-items.rs +++ /dev/null @@ -1,27 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - impl Noop { - #[ink(constructor)] - pub fn new() -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self) {} - } - - struct NonInkStruct {} - enum NonInkEnum {} - impl NonInkStruct { - fn do_nothing() {} - } - - type NonInkTypeAlias = u32; -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/module-non-ink-items.rs b/crates/lang/macro/tests/ui/contract/pass/module-non-ink-items.rs new file mode 100644 index 0000000000..3cb84013f8 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/module-non-ink-items.rs @@ -0,0 +1,48 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } + + pub enum RustEnum { + A, + B, + } + pub union RustUnion { + pub field_a: i32, + pub field_b: [u8; 4], + } + pub struct RustStruct { + pub a: i32, + pub b: i32, + } + + impl RustStruct { + pub fn rust_method() {} + } + + pub const RUST_CONST: bool = true; + pub type RustAlias = RustStruct; +} + +fn main() { + // Use the Rust types defined in the ink! smart contract module + // in order to assert that they are properly re-generated by ink!. + let _ = contract::RustEnum::A; + let _ = contract::RustUnion { field_a: 42 }; + let _ = contract::RustStruct { a: 0, b: 1 }; + let _ = contract::RustStruct::rust_method(); + let _ = contract::RUST_CONST; + let _: contract::RustAlias = contract::RustStruct { a: 0, b: 1 }; +} From e9c0e597e3007c41ad73b589d2c48bfb9288e4ed Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 18:00:31 +0200 Subject: [PATCH 312/493] add passing UI test to assert existence of aliases for all env types --- crates/lang/macro/tests/compile_tests.rs | 1 + .../ui/contract/pass/module-env-types.rs | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/module-env-types.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index fcfb876bff..540b611b1d 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -44,6 +44,7 @@ fn contract() { t.pass("tests/ui/contract/pass/config-custom-env.rs"); t.pass("tests/ui/contract/pass/env-access.rs"); t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); + t.pass("tests/ui/contract/pass/module-env-types.rs"); t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/module-env-types.rs b/crates/lang/macro/tests/ui/contract/pass/module-env-types.rs new file mode 100644 index 0000000000..149bdd244f --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/module-env-types.rs @@ -0,0 +1,25 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract { + account_id: AccountId, + balance: Balance, + hash: Hash, + timestamp: Timestamp, + block_number: BlockNumber, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + unimplemented!() + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From cfe8764edd8c6f6ef5056d40ccd301346f5a6551 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 18:05:40 +0200 Subject: [PATCH 313/493] rename remaining passing UI tests --- crates/lang/macro/tests/compile_tests.rs | 4 ++-- .../pass/{04-erc20-contract.rs => example-erc20-works.rs} | 0 .../pass/{05-erc721-contract.rs => example-erc721-works.rs} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename crates/lang/macro/tests/ui/contract/pass/{04-erc20-contract.rs => example-erc20-works.rs} (100%) rename crates/lang/macro/tests/ui/contract/pass/{05-erc721-contract.rs => example-erc721-works.rs} (100%) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 540b611b1d..5e66cee645 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -37,6 +37,8 @@ fn contract() { t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); + t.pass("tests/ui/contract/pass/example-erc20-works.rs"); + t.pass("tests/ui/contract/pass/example-erc721-works.rs"); t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); @@ -45,8 +47,6 @@ fn contract() { t.pass("tests/ui/contract/pass/env-access.rs"); t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); t.pass("tests/ui/contract/pass/module-env-types.rs"); - t.pass("tests/ui/contract/pass/04-erc20-contract.rs"); - t.pass("tests/ui/contract/pass/05-erc721-contract.rs"); t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/04-erc20-contract.rs b/crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/04-erc20-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/05-erc721-contract.rs b/crates/lang/macro/tests/ui/contract/pass/example-erc721-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/05-erc721-contract.rs rename to crates/lang/macro/tests/ui/contract/pass/example-erc721-works.rs From 10579bbb540898912d98fa5cfad139c82130f8ed Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 18:05:53 +0200 Subject: [PATCH 314/493] move commented out UI test to top --- crates/lang/macro/tests/compile_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 5e66cee645..5fde5bb74f 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -16,6 +16,7 @@ fn contract() { let t = trybuild::TestCases::new(); + // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); t.pass("tests/ui/contract/pass/constructor-selector.rs"); t.pass("tests/ui/contract/pass/message-many-inputs.rs"); @@ -32,7 +33,6 @@ fn contract() { t.pass("tests/ui/contract/pass/event-topics.rs"); t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); t.pass("tests/ui/contract/pass/impl-with-property.rs"); - // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); t.pass("tests/ui/contract/pass/example-flipper-works.rs"); t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); From 0cce1f89b42c291a36209d0ec3d6f196d9970941 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 18:06:19 +0200 Subject: [PATCH 315/493] move passing UI contract example tests to end --- crates/lang/macro/tests/compile_tests.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 5fde5bb74f..ccd817d902 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -33,12 +33,6 @@ fn contract() { t.pass("tests/ui/contract/pass/event-topics.rs"); t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); t.pass("tests/ui/contract/pass/impl-with-property.rs"); - t.pass("tests/ui/contract/pass/example-flipper-works.rs"); - t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); - t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); - t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); - t.pass("tests/ui/contract/pass/example-erc20-works.rs"); - t.pass("tests/ui/contract/pass/example-erc721-works.rs"); t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); @@ -47,6 +41,12 @@ fn contract() { t.pass("tests/ui/contract/pass/env-access.rs"); t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); t.pass("tests/ui/contract/pass/module-env-types.rs"); + t.pass("tests/ui/contract/pass/example-flipper-works.rs"); + t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); + t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); + t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); + t.pass("tests/ui/contract/pass/example-erc20-works.rs"); + t.pass("tests/ui/contract/pass/example-erc721-works.rs"); t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); From dd116b44f57222b723c665f749abb736986cc776 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 18:14:29 +0200 Subject: [PATCH 316/493] fix StorageLayout derive unit tests --- .../derive/src/tests/storage_layout.rs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/storage/derive/src/tests/storage_layout.rs b/crates/storage/derive/src/tests/storage_layout.rs index 2a71f50482..a50d96d94b 100644 --- a/crates/storage/derive/src/tests/storage_layout.rs +++ b/crates/storage/derive/src/tests/storage_layout.rs @@ -25,7 +25,7 @@ fn unit_struct_works() { impl ::ink_storage::traits::StorageLayout for UnitStruct { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(vec![]) + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]) ) } } @@ -45,7 +45,7 @@ fn tuple_struct_works() { impl ::ink_storage::traits::StorageLayout for TupleStruct { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(vec![ + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::None, ::layout(__key_ptr), @@ -82,7 +82,7 @@ fn named_fields_struct_works() { impl ::ink_storage::traits::StorageLayout for NamedFieldsStruct { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(vec![ + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::Some("a"), ::layout(__key_ptr), @@ -118,13 +118,13 @@ fn clike_enum_works() { ::ink_metadata::layout::Layout::Enum( ::ink_metadata::layout::EnumLayout::new( ::ink_metadata::layout::LayoutKey::from(dispatch_key), - vec![ + ::ink_prelude::vec![ { let mut __variant_key_ptr = *__key_ptr; let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(0usize), - ::ink_metadata::layout::StructLayout::new(vec![]), + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), ) }, { @@ -132,7 +132,7 @@ fn clike_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(1usize), - ::ink_metadata::layout::StructLayout::new(vec![]), + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), ) }, { @@ -140,7 +140,7 @@ fn clike_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(2usize), - ::ink_metadata::layout::StructLayout::new(vec![]), + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), ) }, ] @@ -175,13 +175,13 @@ fn mixed_enum_works() { ::ink_metadata::layout::Layout::Enum( ::ink_metadata::layout::EnumLayout::new( ::ink_metadata::layout::LayoutKey::from(dispatch_key), - vec![ + ::ink_prelude::vec![ { let mut __variant_key_ptr = *__key_ptr; let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(0usize), - ::ink_metadata::layout::StructLayout::new(vec![]), + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), ) }, { @@ -189,7 +189,7 @@ fn mixed_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(1usize), - ::ink_metadata::layout::StructLayout::new(vec![ + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::None, ::layout(__key_ptr), @@ -210,7 +210,7 @@ fn mixed_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(2usize), - ::ink_metadata::layout::StructLayout::new(vec![ + ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::Some("a"), ::layout(__key_ptr), From dd66528cc06687c7f72511bfd22bc2720a16d261 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 18:22:24 +0200 Subject: [PATCH 317/493] replace vec! by plain old arrays in StorageLayout derive expansion --- crates/storage/derive/src/storage_layout.rs | 6 ++--- .../derive/src/tests/storage_layout.rs | 22 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/storage/derive/src/storage_layout.rs b/crates/storage/derive/src/storage_layout.rs index 54aa39e36d..f4949f061b 100644 --- a/crates/storage/derive/src/storage_layout.rs +++ b/crates/storage/derive/src/storage_layout.rs @@ -51,7 +51,7 @@ fn storage_layout_struct(s: &synstructure::Structure) -> TokenStream2 { gen impl ::ink_storage::traits::StorageLayout for @Self { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ + ::ink_metadata::layout::StructLayout::new([ #(#field_layouts ,)* ]) ) @@ -79,7 +79,7 @@ fn storage_layout_enum(s: &synstructure::Structure) -> TokenStream2 { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(#discriminant), - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ + ::ink_metadata::layout::StructLayout::new([ #(#field_layouts ,)* ]), ) @@ -93,7 +93,7 @@ fn storage_layout_enum(s: &synstructure::Structure) -> TokenStream2 { ::ink_metadata::layout::Layout::Enum( ::ink_metadata::layout::EnumLayout::new( ::ink_metadata::layout::LayoutKey::from(dispatch_key), - ::ink_prelude::vec![ + [ #(#variant_layouts ,)* ] ) diff --git a/crates/storage/derive/src/tests/storage_layout.rs b/crates/storage/derive/src/tests/storage_layout.rs index a50d96d94b..b11d7c7ec5 100644 --- a/crates/storage/derive/src/tests/storage_layout.rs +++ b/crates/storage/derive/src/tests/storage_layout.rs @@ -25,7 +25,7 @@ fn unit_struct_works() { impl ::ink_storage::traits::StorageLayout for UnitStruct { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]) + ::ink_metadata::layout::StructLayout::new([]) ) } } @@ -45,7 +45,7 @@ fn tuple_struct_works() { impl ::ink_storage::traits::StorageLayout for TupleStruct { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ + ::ink_metadata::layout::StructLayout::new([ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::None, ::layout(__key_ptr), @@ -82,7 +82,7 @@ fn named_fields_struct_works() { impl ::ink_storage::traits::StorageLayout for NamedFieldsStruct { fn layout(__key_ptr: &mut ::ink_storage::traits::KeyPtr) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ + ::ink_metadata::layout::StructLayout::new([ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::Some("a"), ::layout(__key_ptr), @@ -118,13 +118,13 @@ fn clike_enum_works() { ::ink_metadata::layout::Layout::Enum( ::ink_metadata::layout::EnumLayout::new( ::ink_metadata::layout::LayoutKey::from(dispatch_key), - ::ink_prelude::vec![ + [ { let mut __variant_key_ptr = *__key_ptr; let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(0usize), - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), + ::ink_metadata::layout::StructLayout::new([]), ) }, { @@ -132,7 +132,7 @@ fn clike_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(1usize), - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), + ::ink_metadata::layout::StructLayout::new([]), ) }, { @@ -140,7 +140,7 @@ fn clike_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(2usize), - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), + ::ink_metadata::layout::StructLayout::new([]), ) }, ] @@ -175,13 +175,13 @@ fn mixed_enum_works() { ::ink_metadata::layout::Layout::Enum( ::ink_metadata::layout::EnumLayout::new( ::ink_metadata::layout::LayoutKey::from(dispatch_key), - ::ink_prelude::vec![ + [ { let mut __variant_key_ptr = *__key_ptr; let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(0usize), - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![]), + ::ink_metadata::layout::StructLayout::new([]), ) }, { @@ -189,7 +189,7 @@ fn mixed_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(1usize), - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ + ::ink_metadata::layout::StructLayout::new([ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::None, ::layout(__key_ptr), @@ -210,7 +210,7 @@ fn mixed_enum_works() { let mut __key_ptr = &mut __variant_key_ptr; ( ::ink_metadata::layout::Discriminant::from(2usize), - ::ink_metadata::layout::StructLayout::new(::ink_prelude::vec![ + ::ink_metadata::layout::StructLayout::new([ ::ink_metadata::layout::FieldLayout::new( ::core::option::Option::Some("a"), ::layout(__key_ptr), From f7644734b62cf0d47af097626e7ee7b1a98fad3b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 18:32:32 +0200 Subject: [PATCH 318/493] remove plenty of usages of vec! macro in the ink! codebase --- .../src/generator/trait_def/call_builder.rs | 16 +++++++--------- crates/metadata/src/specs.rs | 15 +++++++++------ crates/storage/src/alloc/allocator.rs | 2 +- crates/storage/src/alloc/boxed/storage.rs | 2 +- .../src/collections/binary_heap/storage.rs | 2 +- .../storage/src/collections/bitstash/storage.rs | 2 +- crates/storage/src/collections/bitvec/storage.rs | 2 +- .../storage/src/collections/hashmap/storage.rs | 2 +- .../storage/src/collections/smallvec/storage.rs | 2 +- crates/storage/src/collections/stash/storage.rs | 2 +- crates/storage/src/collections/vec/storage.rs | 2 +- crates/storage/src/traits/layout/impls.rs | 12 ++++++------ examples/trait-erc20/lib.rs | 2 +- 13 files changed, 32 insertions(+), 31 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index fe741237cc..11b75c220f 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -142,15 +142,13 @@ impl CallBuilder<'_> { __key_ptr: &mut ::ink_storage::traits::KeyPtr, ) -> ::ink_metadata::layout::Layout { ::ink_metadata::layout::Layout::Struct( - ::ink_metadata::layout::StructLayout::new( - <[_]>::into_vec(::std::vec![ - ::ink_metadata::layout::FieldLayout::new( - Some("account_id"), - <::AccountId - as ::ink_storage::traits::StorageLayout>::layout(__key_ptr) - ) - ].into_boxed_slice()) - ) + ::ink_metadata::layout::StructLayout::new([ + ::ink_metadata::layout::FieldLayout::new( + Some("account_id"), + <::AccountId + as ::ink_storage::traits::StorageLayout>::layout(__key_ptr) + ) + ]) ) } } diff --git a/crates/metadata/src/specs.rs b/crates/metadata/src/specs.rs index f166a115aa..30383131f1 100644 --- a/crates/metadata/src/specs.rs +++ b/crates/metadata/src/specs.rs @@ -290,12 +290,15 @@ pub struct ConstructorSpecBuilder { impl ConstructorSpec { /// Creates a new constructor spec builder. - fn from_name_segments( - segments: Vec<&'static str>, - ) -> ConstructorSpecBuilder> { + fn from_name_segments( + segments: T, + ) -> ConstructorSpecBuilder> + where + T: IntoIterator, + { ConstructorSpecBuilder { spec: Self { - name: segments, + name: segments.into_iter().collect(), selector: Selector::default(), args: Vec::new(), docs: Vec::new(), @@ -308,7 +311,7 @@ impl ConstructorSpec { pub fn from_name( name: &'static str, ) -> ConstructorSpecBuilder> { - Self::from_name_segments(vec![name]) + Self::from_name_segments([name]) } /// Creates a new constructor spec builder for a trait provided constructor. @@ -316,7 +319,7 @@ impl ConstructorSpec { trait_name: &'static str, constructor_name: &'static str, ) -> ConstructorSpecBuilder> { - Self::from_name_segments(vec![trait_name, constructor_name]) + Self::from_name_segments([trait_name, constructor_name]) } } diff --git a/crates/storage/src/alloc/allocator.rs b/crates/storage/src/alloc/allocator.rs index 26c8dea52c..8a55130089 100644 --- a/crates/storage/src/alloc/allocator.rs +++ b/crates/storage/src/alloc/allocator.rs @@ -40,7 +40,7 @@ const _: () = { impl StorageLayout for DynamicAllocator { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![FieldLayout::new( + Layout::Struct(StructLayout::new([FieldLayout::new( "allocations", ::layout(key_ptr), )])) diff --git a/crates/storage/src/alloc/boxed/storage.rs b/crates/storage/src/alloc/boxed/storage.rs index 6a0811d5ee..b8d2fcf7ef 100644 --- a/crates/storage/src/alloc/boxed/storage.rs +++ b/crates/storage/src/alloc/boxed/storage.rs @@ -56,7 +56,7 @@ const _: () = { fn type_info() -> scale_info::Type { scale_info::Type::builder() .path( - scale_info::Path::from_segments(vec!["ink_storage", "alloc", "Box"]) + scale_info::Path::from_segments(["ink_storage", "alloc", "Box"]) .expect("encountered invalid Rust path"), ) // Unfortunately we cannot encode the type parameters of the box since they diff --git a/crates/storage/src/collections/binary_heap/storage.rs b/crates/storage/src/collections/binary_heap/storage.rs index 88e42cb7a3..e6dc332002 100644 --- a/crates/storage/src/collections/binary_heap/storage.rs +++ b/crates/storage/src/collections/binary_heap/storage.rs @@ -39,7 +39,7 @@ const _: () = { T: PackedLayout + Ord + TypeInfo + 'static, { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![FieldLayout::new( + Layout::Struct(StructLayout::new([FieldLayout::new( "elements", as StorageLayout>::layout(key_ptr), )])) diff --git a/crates/storage/src/collections/bitstash/storage.rs b/crates/storage/src/collections/bitstash/storage.rs index 6a72a86ee7..40e67977f6 100644 --- a/crates/storage/src/collections/bitstash/storage.rs +++ b/crates/storage/src/collections/bitstash/storage.rs @@ -43,7 +43,7 @@ const _: () = { impl StorageLayout for BitStash { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![ + Layout::Struct(StructLayout::new([ FieldLayout::new( "counts", as StorageLayout>::layout(key_ptr), diff --git a/crates/storage/src/collections/bitvec/storage.rs b/crates/storage/src/collections/bitvec/storage.rs index 29c24657b3..a7f291cdc8 100644 --- a/crates/storage/src/collections/bitvec/storage.rs +++ b/crates/storage/src/collections/bitvec/storage.rs @@ -44,7 +44,7 @@ const _: () = { impl StorageLayout for StorageBitvec { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![ + Layout::Struct(StructLayout::new([ FieldLayout::new("len", as StorageLayout>::layout(key_ptr)), FieldLayout::new( "elems", diff --git a/crates/storage/src/collections/hashmap/storage.rs b/crates/storage/src/collections/hashmap/storage.rs index 917ece1c77..920d90b8f6 100644 --- a/crates/storage/src/collections/hashmap/storage.rs +++ b/crates/storage/src/collections/hashmap/storage.rs @@ -59,7 +59,7 @@ const _: () = { Key: From<::Type>, { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![ + Layout::Struct(StructLayout::new([ FieldLayout::new( "keys", as StorageLayout>::layout(key_ptr), diff --git a/crates/storage/src/collections/smallvec/storage.rs b/crates/storage/src/collections/smallvec/storage.rs index cabbe2d1d8..8557813035 100644 --- a/crates/storage/src/collections/smallvec/storage.rs +++ b/crates/storage/src/collections/smallvec/storage.rs @@ -37,7 +37,7 @@ const _: () = { T: PackedLayout + TypeInfo + 'static, { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![ + Layout::Struct(StructLayout::new([ FieldLayout::new("len", ::layout(key_ptr)), FieldLayout::new( "elems", diff --git a/crates/storage/src/collections/stash/storage.rs b/crates/storage/src/collections/stash/storage.rs index 6ef6ec704c..fcab4595f1 100644 --- a/crates/storage/src/collections/stash/storage.rs +++ b/crates/storage/src/collections/stash/storage.rs @@ -60,7 +60,7 @@ const _: () = { T: PackedLayout + TypeInfo + 'static, { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![ + Layout::Struct(StructLayout::new([ FieldLayout::new("header",

::layout(key_ptr)), FieldLayout::new( "entries", diff --git a/crates/storage/src/collections/vec/storage.rs b/crates/storage/src/collections/vec/storage.rs index 7fb5c5e19e..8d290fe9b9 100644 --- a/crates/storage/src/collections/vec/storage.rs +++ b/crates/storage/src/collections/vec/storage.rs @@ -42,7 +42,7 @@ const _: () = { T: PackedLayout + TypeInfo + 'static, { fn layout(key_ptr: &mut KeyPtr) -> Layout { - Layout::Struct(StructLayout::new(vec![ + Layout::Struct(StructLayout::new([ FieldLayout::new("len", as StorageLayout>::layout(key_ptr)), FieldLayout::new( "elems", diff --git a/crates/storage/src/traits/layout/impls.rs b/crates/storage/src/traits/layout/impls.rs index d82bd2da2d..04a37f38b8 100644 --- a/crates/storage/src/traits/layout/impls.rs +++ b/crates/storage/src/traits/layout/impls.rs @@ -99,7 +99,7 @@ macro_rules! impl_layout_for_tuple { { fn layout(key_ptr: &mut KeyPtr) -> Layout { Layout::Struct( - StructLayout::new(vec![ + StructLayout::new([ $( FieldLayout::new(None, <$frag as StorageLayout>::layout(key_ptr)), )* @@ -137,10 +137,10 @@ where let dispatch_key = key_ptr.advance_by(1); Layout::Enum(EnumLayout::new( *dispatch_key, - vec![ + [ ( Discriminant::from(0), - StructLayout::new(vec![FieldLayout::new( + StructLayout::new([FieldLayout::new( None, ::layout(&mut key_ptr.clone()), )]), @@ -160,17 +160,17 @@ where let dispatch_key = key_ptr.advance_by(1); Layout::Enum(EnumLayout::new( *dispatch_key, - vec![ + [ ( Discriminant::from(0), - StructLayout::new(vec![FieldLayout::new( + StructLayout::new([FieldLayout::new( None, ::layout(&mut key_ptr.clone()), )]), ), ( Discriminant::from(1), - StructLayout::new(vec![FieldLayout::new( + StructLayout::new([FieldLayout::new( None, ::layout(&mut key_ptr.clone()), )]), diff --git a/examples/trait-erc20/lib.rs b/examples/trait-erc20/lib.rs index c0e584917a..7cc023aee1 100644 --- a/examples/trait-erc20/lib.rs +++ b/examples/trait-erc20/lib.rs @@ -291,7 +291,7 @@ mod erc20 { result.as_mut()[0..copy_len].copy_from_slice(&hash_output[0..copy_len]); result } - let expected_topics = vec![ + let expected_topics = [ encoded_into_hash(&PrefixedValue { prefix: b"", value: b"Erc20::Transfer", From 752db0296e30783d7945ac199e6c48100f942702 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 27 Sep 2021 19:19:42 +0200 Subject: [PATCH 319/493] improve macro hygiene in call_builder codegen --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 11b75c220f..0ca744e8bc 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -144,7 +144,7 @@ impl CallBuilder<'_> { ::ink_metadata::layout::Layout::Struct( ::ink_metadata::layout::StructLayout::new([ ::ink_metadata::layout::FieldLayout::new( - Some("account_id"), + ::core::option::Option::Some("account_id"), <::AccountId as ::ink_storage::traits::StorageLayout>::layout(__key_ptr) ) From 31e7551db4162fe8c518a6d4d43b0333d53674d8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 09:28:54 +0200 Subject: [PATCH 320/493] slightly reformat erc20 UI test --- .../macro/tests/ui/contract/pass/example-erc20-works.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs b/crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs index 153bb79af0..4ae6274d64 100644 --- a/crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs +++ b/crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs @@ -119,7 +119,7 @@ mod erc20 { } fn balance_of_or_zero(&self, owner: &AccountId) -> Balance { - *self.balances.get(owner).unwrap_or(&0) + self.balances.get(owner).copied().unwrap_or_default() } fn allowance_of_or_zero( @@ -127,7 +127,10 @@ mod erc20 { owner: &AccountId, spender: &AccountId, ) -> Balance { - *self.allowances.get(&(*owner, *spender)).unwrap_or(&0) + self.allowances + .get(&(*owner, *spender)) + .copied() + .unwrap_or_default() } } } From 28073d57a8d746d9920c966544e698653ac80ef1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 09:41:31 +0200 Subject: [PATCH 321/493] add ink! event passing UI tests --- crates/lang/macro/tests/compile_tests.rs | 2 + .../tests/ui/contract/pass/event-anonymous.rs | 115 ++++++++++++++++++ .../contract/pass/event-config-more-topics.rs | 86 +++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/event-anonymous.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/event-config-more-topics.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index ccd817d902..f3549dc1b3 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -31,6 +31,8 @@ fn contract() { t.pass("tests/ui/contract/pass/event-single-definition.rs"); t.pass("tests/ui/contract/pass/event-many-definitions.rs"); t.pass("tests/ui/contract/pass/event-topics.rs"); + t.pass("tests/ui/contract/pass/event-anonymous.rs"); + t.pass("tests/ui/contract/pass/event-config-more-topics.rs"); t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); t.pass("tests/ui/contract/pass/impl-with-property.rs"); t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/event-anonymous.rs b/crates/lang/macro/tests/ui/contract/pass/event-anonymous.rs new file mode 100644 index 0000000000..7489ee198b --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/event-anonymous.rs @@ -0,0 +1,115 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event, anonymous)] + pub struct Event0 {} + + #[ink(event, anonymous)] + pub struct Event1 { + #[ink(topic)] + arg_1: i8, + } + + #[ink(event, anonymous)] + pub struct Event2 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + } + + #[ink(event, anonymous)] + pub struct Event3 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + } + + #[ink(event, anonymous)] + pub struct Event4 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + #[ink(topic)] + arg_4: i64, + } + + #[ink(event, anonymous)] + pub struct Event5 { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + #[ink(topic)] + arg_4: i64, + // #[ink(topic)] <- Cannot have more than 4 topics by default. + arg_5: i128, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::env().emit_event(Event0 {}); + Self::env().emit_event(Event1 { arg_1: 1 }); + Self::env().emit_event(Event2 { arg_1: 1, arg_2: 2 }); + Self::env().emit_event(Event3 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + Self::env().emit_event(Event4 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + Self::env().emit_event(Event5 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + }); + Self {} + } + + #[ink(message)] + pub fn message(&self) { + self.env().emit_event(Event0 {}); + self.env().emit_event(Event1 { arg_1: 1 }); + self.env().emit_event(Event2 { arg_1: 1, arg_2: 2 }); + self.env().emit_event(Event3 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + self.env().emit_event(Event4 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + self.env().emit_event(Event5 { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + }); + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/event-config-more-topics.rs b/crates/lang/macro/tests/ui/contract/pass/event-config-more-topics.rs new file mode 100644 index 0000000000..e7b73525a8 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/event-config-more-topics.rs @@ -0,0 +1,86 @@ +use ink_env::{ + DefaultEnvironment, + Environment, +}; +use ink_lang as ink; + +pub struct EnvironmentMoreTopics; + +impl ink_env::Environment for EnvironmentMoreTopics { + const MAX_EVENT_TOPICS: usize = 10; // Default is 4. + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Hash = ::Hash; + type Timestamp = ::Timestamp; + type BlockNumber = ::BlockNumber; + type ChainExtension = (); + type RentFraction = ::RentFraction; +} + +#[ink::contract(env = super::EnvironmentMoreTopics)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event, anonymous)] + pub struct EventWithManyTopics { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + #[ink(topic)] + arg_4: i64, + #[ink(topic)] + arg_5: i128, + #[ink(topic)] + arg_6: u8, + #[ink(topic)] + arg_7: u16, + #[ink(topic)] + arg_8: u32, + #[ink(topic)] + arg_9: u64, + #[ink(topic)] + arg_10: u128, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::env().emit_event(EventWithManyTopics { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + arg_6: 6, + arg_7: 7, + arg_8: 8, + arg_9: 9, + arg_10: 10, + }); + Self {} + } + + #[ink(message)] + pub fn message(&self) { + self.env().emit_event(EventWithManyTopics { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + arg_5: 5, + arg_6: 6, + arg_7: 7, + arg_8: 8, + arg_9: 9, + arg_10: 10, + }); + } + } +} + +fn main() {} From 0b84f77c66826b6e1fb27480fc14e4c2ae062056 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 09:42:31 +0200 Subject: [PATCH 322/493] move minimal ink! smart contract UI test case to front --- crates/lang/macro/tests/compile_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index f3549dc1b3..413c830720 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -17,13 +17,13 @@ fn contract() { let t = trybuild::TestCases::new(); // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); + t.pass("tests/ui/contract/pass/minimal-contract.rs"); t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); t.pass("tests/ui/contract/pass/constructor-selector.rs"); t.pass("tests/ui/contract/pass/message-many-inputs.rs"); t.pass("tests/ui/contract/pass/message-many-outputs.rs"); t.pass("tests/ui/contract/pass/message-payable.rs"); t.pass("tests/ui/contract/pass/message-selector.rs"); - t.pass("tests/ui/contract/pass/minimal-contract.rs"); t.pass("tests/ui/contract/pass/storage-single-field.rs"); t.pass("tests/ui/contract/pass/storage-many-fields.rs"); t.pass("tests/ui/contract/pass/storage-packed-fields.rs"); From 032c3dc2ee0deafb1eca0ecd4e5b4284e544153f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 11:55:17 +0200 Subject: [PATCH 323/493] modernize simple definition UI test --- .../lang/macro/tests/ui/trait_def/pass/simple_definition.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs b/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs index c2ac026d63..3bf7133d5d 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs @@ -1,11 +1,11 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait SimpleDefinition { +pub trait TraitDefinition { #[ink(message)] - fn simple(&self); + fn message(&self); #[ink(message)] - fn simple_mut(&mut self); + fn message_mut(&mut self); } fn main() {} From 3adb95563a117fea77c95bb96c3d5f7eecaf005d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 11:55:58 +0200 Subject: [PATCH 324/493] add simple no-implicit-prelude UI test for ink::trait_definition macro The test case is disabled for now since the currently used parity-scale-codec produces macro hygiene errors. --- crates/lang/macro/tests/compile_tests.rs | 1 + .../tests/ui/trait_def/pass/no-implicit-prelude.rs | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/no-implicit-prelude.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 413c830720..33afc60ea5 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -98,6 +98,7 @@ fn chain_extension() { fn trait_definition() { let t = trybuild::TestCases::new(); t.pass("tests/ui/trait_def/pass/simple_definition.rs"); + // t.pass("tests/ui/trait_def/pass/no-implicit-prelude.rs"); t.pass("tests/ui/trait_def/pass/many_inputs.rs"); t.pass("tests/ui/trait_def/pass/many_outputs.rs"); t.pass("tests/ui/trait_def/pass/payable_message.rs"); diff --git a/crates/lang/macro/tests/ui/trait_def/pass/no-implicit-prelude.rs b/crates/lang/macro/tests/ui/trait_def/pass/no-implicit-prelude.rs new file mode 100644 index 0000000000..29180717b1 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/no-implicit-prelude.rs @@ -0,0 +1,11 @@ +#![no_implicit_prelude] + +#[::ink_lang::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self); + #[ink(message)] + fn message_mut(&mut self); +} + +fn main() {} From 99b46f976420d7071f15d77dbafc569a8ff1fe0d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 12:38:59 +0200 Subject: [PATCH 325/493] add some #[ink::trait_definition] UI tests --- crates/lang/macro/tests/compile_tests.rs | 5 +++++ .../ui/trait_def/fail/message_invalid_receiver_1.rs | 9 +++++++++ .../ui/trait_def/fail/message_invalid_receiver_1.stderr | 5 +++++ .../ui/trait_def/fail/message_invalid_receiver_2.rs | 9 +++++++++ .../ui/trait_def/fail/message_invalid_receiver_2.stderr | 5 +++++ .../ui/trait_def/fail/message_invalid_receiver_3.rs | 9 +++++++++ .../ui/trait_def/fail/message_invalid_receiver_3.stderr | 5 +++++ .../tests/ui/trait_def/fail/message_missing_receiver.rs | 9 +++++++++ .../ui/trait_def/fail/message_missing_receiver.stderr | 5 +++++ crates/lang/macro/tests/ui/trait_def/fail/rust_method.rs | 8 ++++++++ .../macro/tests/ui/trait_def/fail/rust_method.stderr | 5 +++++ 11 files changed, 74 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/rust_method.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/rust_method.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 33afc60ea5..680ad5085a 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -117,4 +117,9 @@ fn trait_definition() { t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_2.rs"); t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_3.rs"); t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_4.rs"); + t.compile_fail("tests/ui/trait_def/fail/rust_method.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_missing_receiver.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_invalid_receiver_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_invalid_receiver_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_invalid_receiver_3.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.rs new file mode 100644 index 0000000000..bd3551d85c --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.stderr new file mode 100644 index 0000000000..7774082157 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.stderr @@ -0,0 +1,5 @@ +error: missing or malformed `&self` or `&mut self` receiver for ink! message + --> $DIR/message_invalid_receiver_1.rs:6:5 + | +6 | fn message(); + | ^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.rs new file mode 100644 index 0000000000..1569878e5a --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(this: Self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.stderr new file mode 100644 index 0000000000..f7ea630994 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.stderr @@ -0,0 +1,5 @@ +error: missing or malformed `&self` or `&mut self` receiver for ink! message + --> $DIR/message_invalid_receiver_2.rs:6:5 + | +6 | fn message(this: Self); + | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.rs new file mode 100644 index 0000000000..91a28bf11a --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(this: &Self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.stderr new file mode 100644 index 0000000000..805f73be2f --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.stderr @@ -0,0 +1,5 @@ +error: missing or malformed `&self` or `&mut self` receiver for ink! message + --> $DIR/message_invalid_receiver_3.rs:6:5 + | +6 | fn message(this: &Self); + | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.rs new file mode 100644 index 0000000000..bd3551d85c --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.stderr new file mode 100644 index 0000000000..31475920ce --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.stderr @@ -0,0 +1,5 @@ +error: missing or malformed `&self` or `&mut self` receiver for ink! message + --> $DIR/message_missing_receiver.rs:6:5 + | +6 | fn message(); + | ^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/rust_method.rs b/crates/lang/macro/tests/ui/trait_def/fail/rust_method.rs new file mode 100644 index 0000000000..61618c1d58 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/rust_method.rs @@ -0,0 +1,8 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + fn rust_method(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/rust_method.stderr b/crates/lang/macro/tests/ui/trait_def/fail/rust_method.stderr new file mode 100644 index 0000000000..f932c8634d --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/rust_method.stderr @@ -0,0 +1,5 @@ +error: missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method + --> $DIR/rust_method.rs:5:5 + | +5 | fn rust_method(&self); + | ^^^^^^^^^^^^^^^^^^^^^^ From 9668272fe1e8c81efc9f86c9cf1373366f2161f2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 12:50:08 +0200 Subject: [PATCH 326/493] rename #[ink::trait_definition] UI tests --- crates/lang/macro/tests/compile_tests.rs | 36 +++++++++---------- ...ace_1.rs => config_namespace_invalid_1.rs} | 0 ...derr => config_namespace_invalid_1.stderr} | 2 +- ...ace_2.rs => config_namespace_invalid_2.rs} | 0 ...derr => config_namespace_invalid_2.stderr} | 2 +- ...ace_3.rs => config_namespace_invalid_3.rs} | 0 ...derr => config_namespace_invalid_3.stderr} | 2 +- ...ace_4.rs => config_namespace_invalid_4.rs} | 0 ...derr => config_namespace_invalid_4.stderr} | 2 +- ...soc_const.rs => definition_assoc_const.rs} | 0 ...t.stderr => definition_assoc_const.stderr} | 2 +- ...assoc_type.rs => definition_assoc_type.rs} | 0 ...pe.stderr => definition_assoc_type.stderr} | 2 +- ...nstructor.rs => definition_constructor.rs} | 0 ...r.stderr => definition_constructor.stderr} | 2 +- ...mpty_definition.rs => definition_empty.rs} | 0 ...inition.stderr => definition_empty.stderr} | 2 +- ...st_method.rs => definition_rust_method.rs} | 0 ...d.stderr => definition_rust_method.stderr} | 2 +- ...able_1.rs => message_payable_invalid_1.rs} | 0 ...tderr => message_payable_invalid_1.stderr} | 2 +- ...able_2.rs => message_payable_invalid_2.rs} | 0 ...tderr => message_payable_invalid_2.stderr} | 2 +- ...ver_1.rs => message_receiver_invalid_1.rs} | 0 ...derr => message_receiver_invalid_1.stderr} | 2 +- ...ver_2.rs => message_receiver_invalid_2.rs} | 0 ...derr => message_receiver_invalid_2.stderr} | 2 +- ...ver_3.rs => message_receiver_invalid_3.rs} | 0 ...derr => message_receiver_invalid_3.stderr} | 2 +- ...eceiver.rs => message_receiver_missing.rs} | 0 ...stderr => message_receiver_missing.stderr} | 2 +- ...tor_1.rs => message_selector_invalid_1.rs} | 0 ...derr => message_selector_invalid_1.stderr} | 2 +- ...tor_2.rs => message_selector_invalid_2.rs} | 0 ...derr => message_selector_invalid_2.stderr} | 2 +- ...lectors.rs => message_selector_overlap.rs} | 0 ...stderr => message_selector_overlap.stderr} | 4 +-- 37 files changed, 37 insertions(+), 37 deletions(-) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_1.rs => config_namespace_invalid_1.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_1.stderr => config_namespace_invalid_1.stderr} (83%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_2.rs => config_namespace_invalid_2.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_2.stderr => config_namespace_invalid_2.stderr} (85%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_3.rs => config_namespace_invalid_3.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_3.stderr => config_namespace_invalid_3.stderr} (80%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_4.rs => config_namespace_invalid_4.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_namespace_4.stderr => config_namespace_invalid_4.stderr} (80%) rename crates/lang/macro/tests/ui/trait_def/fail/{with_assoc_const.rs => definition_assoc_const.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{with_assoc_const.stderr => definition_assoc_const.stderr} (79%) rename crates/lang/macro/tests/ui/trait_def/fail/{with_assoc_type.rs => definition_assoc_type.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{with_assoc_type.stderr => definition_assoc_type.stderr} (78%) rename crates/lang/macro/tests/ui/trait_def/fail/{with_constructor.rs => definition_constructor.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{with_constructor.stderr => definition_constructor.stderr} (78%) rename crates/lang/macro/tests/ui/trait_def/fail/{empty_definition.rs => definition_empty.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{empty_definition.stderr => definition_empty.stderr} (78%) rename crates/lang/macro/tests/ui/trait_def/fail/{rust_method.rs => definition_rust_method.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{rust_method.stderr => definition_rust_method.stderr} (78%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_payable_1.rs => message_payable_invalid_1.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_payable_1.stderr => message_payable_invalid_1.stderr} (75%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_payable_2.rs => message_payable_invalid_2.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_payable_2.stderr => message_payable_invalid_2.stderr} (75%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_invalid_receiver_1.rs => message_receiver_invalid_1.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_invalid_receiver_1.stderr => message_receiver_invalid_1.stderr} (73%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_invalid_receiver_2.rs => message_receiver_invalid_2.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_invalid_receiver_2.stderr => message_receiver_invalid_2.stderr} (76%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_invalid_receiver_3.rs => message_receiver_invalid_3.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_invalid_receiver_3.stderr => message_receiver_invalid_3.stderr} (76%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_missing_receiver.rs => message_receiver_missing.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{message_missing_receiver.stderr => message_receiver_missing.stderr} (74%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_selector_1.rs => message_selector_invalid_1.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_selector_1.stderr => message_selector_invalid_1.stderr} (79%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_selector_2.rs => message_selector_invalid_2.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{invalid_selector_2.stderr => message_selector_invalid_2.stderr} (70%) rename crates/lang/macro/tests/ui/trait_def/fail/{overlapping_selectors.rs => message_selector_overlap.rs} (100%) rename crates/lang/macro/tests/ui/trait_def/fail/{overlapping_selectors.stderr => message_selector_overlap.stderr} (76%) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 680ad5085a..182befbeb9 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -104,22 +104,22 @@ fn trait_definition() { t.pass("tests/ui/trait_def/pass/payable_message.rs"); t.pass("tests/ui/trait_def/pass/custom_selector.rs"); t.pass("tests/ui/trait_def/pass/with_namespace.rs"); - t.compile_fail("tests/ui/trait_def/fail/empty_definition.rs"); - t.compile_fail("tests/ui/trait_def/fail/with_constructor.rs"); - t.compile_fail("tests/ui/trait_def/fail/overlapping_selectors.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_selector_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_selector_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_payable_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_payable_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/with_assoc_type.rs"); - t.compile_fail("tests/ui/trait_def/fail/with_assoc_const.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_3.rs"); - t.compile_fail("tests/ui/trait_def/fail/invalid_namespace_4.rs"); - t.compile_fail("tests/ui/trait_def/fail/rust_method.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_missing_receiver.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_invalid_receiver_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_invalid_receiver_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_invalid_receiver_3.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_empty.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_constructor.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_rust_method.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_assoc_type.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_assoc_const.rs"); + t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_3.rs"); + t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_4.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_selector_overlap.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_selector_invalid_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_selector_invalid_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_payable_invalid_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_payable_invalid_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_receiver_missing.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_3.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.rs rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr similarity index 83% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr index 02ccdfb125..4b43b6bc9e 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr @@ -1,5 +1,5 @@ error: encountered invalid Rust identifier for the ink! namespace configuration parameter - --> $DIR/invalid_namespace_1.rs:3:37 + --> $DIR/config_namespace_invalid_1.rs:3:37 | 3 | #[ink::trait_definition(namespace = "::invalid::rust::identifier")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.rs rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr similarity index 85% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr index 4b2b2a38b9..02cdce5c1a 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr @@ -1,5 +1,5 @@ error: expected `=` - --> $DIR/invalid_namespace_2.rs:3:1 + --> $DIR/config_namespace_invalid_2.rs:3:1 | 3 | #[ink::trait_definition(namespace)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.rs rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr similarity index 80% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr index 628b95d3c1..df82146b0b 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_3.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr @@ -1,5 +1,5 @@ error: encountered invalid Rust identifier for the ink! namespace configuration parameter - --> $DIR/invalid_namespace_3.rs:3:37 + --> $DIR/config_namespace_invalid_3.rs:3:37 | 3 | #[ink::trait_definition(namespace = "")] | ^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.rs rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr similarity index 80% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr index 2724b2541c..5ad2705959 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_namespace_4.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr @@ -1,5 +1,5 @@ error: expected a string literal for `namespace` ink! trait definition configuration argument - --> $DIR/invalid_namespace_4.rs:3:25 + --> $DIR/config_namespace_invalid_4.rs:3:25 | 3 | #[ink::trait_definition(namespace = true)] | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.rs rename to crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr similarity index 79% rename from crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr index f02424f83e..f9410e769f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_const.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr @@ -1,5 +1,5 @@ error: associated constants in ink! trait definitions are not supported, yet - --> $DIR/with_assoc_const.rs:5:5 + --> $DIR/definition_assoc_const.rs:5:5 | 5 | const INVALID_CONST: bool; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.rs rename to crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr similarity index 78% rename from crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr index e2f9260ff1..90d05d12af 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/with_assoc_type.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr @@ -1,5 +1,5 @@ error: associated types in ink! trait definitions are not supported, yet - --> $DIR/with_assoc_type.rs:5:5 + --> $DIR/definition_assoc_type.rs:5:5 | 5 | type InvalidAssocType; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/with_constructor.rs rename to crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr similarity index 78% rename from crates/lang/macro/tests/ui/trait_def/fail/with_constructor.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr index 87807e8d59..9a9b5587bc 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/with_constructor.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr @@ -1,5 +1,5 @@ error: ink! trait definitions must not have constructors - --> $DIR/with_constructor.rs:5:5 + --> $DIR/definition_constructor.rs:5:5 | 5 | / #[ink(constructor)] 6 | | fn new() -> Self; diff --git a/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/empty_definition.rs rename to crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr similarity index 78% rename from crates/lang/macro/tests/ui/trait_def/fail/empty_definition.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr index 5289ee7699..dfbce2d653 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/empty_definition.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr @@ -1,5 +1,5 @@ error: encountered invalid empty ink! trait definition - --> $DIR/empty_definition.rs:4:1 + --> $DIR/definition_empty.rs:4:1 | 4 | pub trait EmptyDefinition {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/rust_method.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/rust_method.rs rename to crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/rust_method.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr similarity index 78% rename from crates/lang/macro/tests/ui/trait_def/fail/rust_method.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr index f932c8634d..e0cc2dc76f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/rust_method.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr @@ -1,5 +1,5 @@ error: missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method - --> $DIR/rust_method.rs:5:5 + --> $DIR/definition_rust_method.rs:5:5 | 5 | fn rust_method(&self); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr similarity index 75% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr index 7c4cecdee3..e207aa54bb 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr @@ -1,5 +1,5 @@ error: unknown ink! attribute argument (name = value) - --> $DIR/invalid_payable_1.rs:5:20 + --> $DIR/message_payable_invalid_1.rs:5:20 | 5 | #[ink(message, payable = false)] | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr similarity index 75% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr index 25eec3ed87..16f8b5ebbe 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_payable_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr @@ -1,5 +1,5 @@ error: unknown ink! attribute argument (name = value) - --> $DIR/invalid_payable_2.rs:5:20 + --> $DIR/message_payable_invalid_2.rs:5:20 | 5 | #[ink(message, payable = true)] | ^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr similarity index 73% rename from crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr index 7774082157..fb10f7034f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_invalid_receiver_1.rs:6:5 + --> $DIR/message_receiver_invalid_1.rs:6:5 | 6 | fn message(); | ^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr similarity index 76% rename from crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr index f7ea630994..7edfb1ce81 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_invalid_receiver_2.rs:6:5 + --> $DIR/message_receiver_invalid_2.rs:6:5 | 6 | fn message(this: Self); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr similarity index 76% rename from crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr index 805f73be2f..8e26f4c4ed 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_invalid_receiver_3.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_invalid_receiver_3.rs:6:5 + --> $DIR/message_receiver_invalid_3.rs:6:5 | 6 | fn message(this: &Self); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr similarity index 74% rename from crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr index 31475920ce..9ae0881e6a 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_missing_receiver.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_missing_receiver.rs:6:5 + --> $DIR/message_receiver_missing.rs:6:5 | 6 | fn message(); | ^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr similarity index 79% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr index b2198e4dfb..4aed23d8e8 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr @@ -1,5 +1,5 @@ error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE] - --> $DIR/invalid_selector_1.rs:5:20 + --> $DIR/message_selector_invalid_1.rs:5:20 | 5 | #[ink(message, selector = true)] | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr similarity index 70% rename from crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr index 78f8cae889..113f484512 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/invalid_selector_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr @@ -1,5 +1,5 @@ error: unknown ink! attribute (path) - --> $DIR/invalid_selector_2.rs:5:20 + --> $DIR/message_selector_invalid_2.rs:5:20 | 5 | #[ink(message, selector)] | ^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.rs rename to crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr similarity index 76% rename from crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.stderr rename to crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr index 9e0f937f1b..38c4be1d35 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/overlapping_selectors.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr @@ -1,11 +1,11 @@ error: encountered duplicate selector ([0, 0, 0, 1]) in the same ink! trait definition - --> $DIR/overlapping_selectors.rs:8:8 + --> $DIR/message_selector_overlap.rs:8:8 | 8 | fn selector2(&self); | ^^^^^^^^^ error: first ink! trait constructor or message with same selector found here - --> $DIR/overlapping_selectors.rs:6:8 + --> $DIR/message_selector_overlap.rs:6:8 | 6 | fn selector1(&self); | ^^^^^^^^^ From df3abd414911cf67ec1d86cbfc5811aeff9f59df Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 12:54:11 +0200 Subject: [PATCH 327/493] add UI tests for #[ink::trait_definition] with async and const messages --- crates/lang/macro/tests/compile_tests.rs | 2 ++ .../tests/ui/trait_def/fail/message_async_invalid.rs | 12 ++++++++++++ .../ui/trait_def/fail/message_async_invalid.stderr | 5 +++++ .../tests/ui/trait_def/fail/message_const_invalid.rs | 12 ++++++++++++ .../ui/trait_def/fail/message_const_invalid.stderr | 5 +++++ 5 files changed, 36 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 182befbeb9..39a991a5c4 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -122,4 +122,6 @@ fn trait_definition() { t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_1.rs"); t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_2.rs"); t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_3.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_async_invalid.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_const_invalid.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.rs new file mode 100644 index 0000000000..0f28b00f51 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.rs @@ -0,0 +1,12 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + async fn message_ref(&self); + + #[ink(message)] + async fn message_mut(&mut self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr new file mode 100644 index 0000000000..83761ecbab --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr @@ -0,0 +1,5 @@ +error: async ink! trait methods are not supported + --> $DIR/message_async_invalid.rs:6:5 + | +6 | async fn message_ref(&self); + | ^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.rs new file mode 100644 index 0000000000..e5fec9a3a0 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.rs @@ -0,0 +1,12 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + const fn message_ref(&self); + + #[ink(message)] + const fn message_mut(&mut self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr new file mode 100644 index 0000000000..b5af29423e --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr @@ -0,0 +1,5 @@ +error: const ink! trait methods are not supported + --> $DIR/message_const_invalid.rs:6:5 + | +6 | const fn message_ref(&self); + | ^^^^^ From c19799b468073f8dd48cbf212132f68945576ce0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:01:00 +0200 Subject: [PATCH 328/493] add more UI tests for #[ink::trait_definition] --- crates/lang/macro/tests/compile_tests.rs | 2 ++ .../ui/trait_def/fail/message_constructor_conflict.rs | 9 +++++++++ .../trait_def/fail/message_constructor_conflict.stderr | 5 +++++ .../tests/ui/trait_def/fail/message_default_impl.rs | 9 +++++++++ .../tests/ui/trait_def/fail/message_default_impl.stderr | 5 +++++ 5 files changed, 30 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 39a991a5c4..a7512a16ee 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -124,4 +124,6 @@ fn trait_definition() { t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_3.rs"); t.compile_fail("tests/ui/trait_def/fail/message_async_invalid.rs"); t.compile_fail("tests/ui/trait_def/fail/message_const_invalid.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_default_impl.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_constructor_conflict.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.rs new file mode 100644 index 0000000000..304b077bef --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message, constructor)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr new file mode 100644 index 0000000000..539f48c611 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr @@ -0,0 +1,5 @@ +error: encountered conflicting ink! attribute argument + --> $DIR/message_constructor_conflict.rs:5:20 + | +5 | #[ink(message, constructor)] + | ^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.rs new file mode 100644 index 0000000000..9345cd8d27 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self) {} +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr new file mode 100644 index 0000000000..ee7fc0005f --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr @@ -0,0 +1,5 @@ +error: ink! trait methods with default implementations are not supported + --> $DIR/message_default_impl.rs:6:23 + | +6 | fn message(&self) {} + | ^^ From 505ac664bf2e58c826f3129973f3954defc886ab Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:01:12 +0200 Subject: [PATCH 329/493] normalize #[ink::trait_definition] UI tests --- .../tests/ui/trait_def/fail/config_namespace_invalid_1.rs | 2 +- .../tests/ui/trait_def/fail/config_namespace_invalid_2.rs | 2 +- .../tests/ui/trait_def/fail/config_namespace_invalid_3.rs | 2 +- .../tests/ui/trait_def/fail/config_namespace_invalid_4.rs | 2 +- .../tests/ui/trait_def/fail/definition_assoc_const.rs | 4 ++-- .../tests/ui/trait_def/fail/definition_assoc_const.stderr | 4 ++-- .../macro/tests/ui/trait_def/fail/definition_assoc_type.rs | 4 ++-- .../tests/ui/trait_def/fail/definition_assoc_type.stderr | 4 ++-- .../tests/ui/trait_def/fail/definition_constructor.rs | 4 ++-- .../tests/ui/trait_def/fail/definition_constructor.stderr | 4 ++-- .../lang/macro/tests/ui/trait_def/fail/definition_empty.rs | 2 +- .../macro/tests/ui/trait_def/fail/definition_empty.stderr | 2 +- .../tests/ui/trait_def/fail/message_payable_invalid_1.rs | 4 ++-- .../tests/ui/trait_def/fail/message_payable_invalid_2.rs | 4 ++-- .../tests/ui/trait_def/fail/message_selector_invalid_1.rs | 4 ++-- .../tests/ui/trait_def/fail/message_selector_invalid_2.rs | 4 ++-- .../tests/ui/trait_def/fail/message_selector_overlap.rs | 7 ++++--- .../ui/trait_def/fail/message_selector_overlap.stderr | 6 +++--- 18 files changed, 33 insertions(+), 32 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs index b25cdce751..4a1469bf84 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs @@ -1,7 +1,7 @@ use ink_lang as ink; #[ink::trait_definition(namespace = "::invalid::rust::identifier")] -pub trait InvalidNamespace { +pub trait TraitDefinition { #[ink(message)] fn message(&self); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs index 27bf7d801e..902c33b819 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs @@ -1,7 +1,7 @@ use ink_lang as ink; #[ink::trait_definition(namespace)] -pub trait InvalidNamespace { +pub trait TraitDefinition { #[ink(message)] fn message(&self); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs index ea773ef945..a958d19b9a 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs @@ -1,7 +1,7 @@ use ink_lang as ink; #[ink::trait_definition(namespace = "")] -pub trait InvalidNamespace { +pub trait TraitDefinition { #[ink(message)] fn message(&self); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs index 6b7d789bf6..8a3bf56356 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs @@ -1,7 +1,7 @@ use ink_lang as ink; #[ink::trait_definition(namespace = true)] -pub trait InvalidNamespace { +pub trait TraitDefinition { #[ink(message)] fn message(&self); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs index 81a648d614..ffcefe15f5 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs @@ -1,8 +1,8 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait WithAssocType { - const INVALID_CONST: bool; +pub trait TraitDefinition { + const CONST: bool; #[ink(message)] fn message(&self); diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr index f9410e769f..adb4402568 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr @@ -1,5 +1,5 @@ error: associated constants in ink! trait definitions are not supported, yet --> $DIR/definition_assoc_const.rs:5:5 | -5 | const INVALID_CONST: bool; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +5 | const CONST: bool; + | ^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs index 3c6458cb44..ec92bf262f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs @@ -1,8 +1,8 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait WithAssocType { - type InvalidAssocType; +pub trait TraitDefinition { + type Type; #[ink(message)] fn message(&self); diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr index 90d05d12af..5719ca6e62 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr @@ -1,5 +1,5 @@ error: associated types in ink! trait definitions are not supported, yet --> $DIR/definition_assoc_type.rs:5:5 | -5 | type InvalidAssocType; - | ^^^^^^^^^^^^^^^^^^^^^^ +5 | type Type; + | ^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs index 66626fd260..d33b5b2ac9 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs @@ -1,9 +1,9 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait WithConstructor { +pub trait TraitDefinition { #[ink(constructor)] - fn new() -> Self; + fn constructor() -> Self; } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr index 9a9b5587bc..3cea1be911 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr @@ -2,5 +2,5 @@ error: ink! trait definitions must not have constructors --> $DIR/definition_constructor.rs:5:5 | 5 | / #[ink(constructor)] -6 | | fn new() -> Self; - | |_____________________^ +6 | | fn constructor() -> Self; + | |_____________________________^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs index f1157d58e7..16017df57c 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs @@ -1,6 +1,6 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait EmptyDefinition {} +pub trait TraitDefinition {} fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr index dfbce2d653..b084b40280 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr @@ -1,5 +1,5 @@ error: encountered invalid empty ink! trait definition --> $DIR/definition_empty.rs:4:1 | -4 | pub trait EmptyDefinition {} +4 | pub trait TraitDefinition {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs index 367e22efa3..9810fc483f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs @@ -1,9 +1,9 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait InvalidPayable { +pub trait TraitDefinition { #[ink(message, payable = false)] - fn invalid_payable(&self); + fn message(&self); } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs index 95693e4462..efef582630 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs @@ -1,9 +1,9 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait InvalidPayable { +pub trait TraitDefinition { #[ink(message, payable = true)] - fn invalid_payable(&self); + fn message(&self); } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs index ba7f6a04a0..e90847277f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs @@ -1,9 +1,9 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait InvalidSelector { +pub trait TraitDefinition { #[ink(message, selector = true)] - fn invalid_selector(&self); + fn message(&self); } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs index 10d7fbe811..d76a5e1ca8 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs @@ -1,9 +1,9 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait InvalidSelector { +pub trait TraitDefinition { #[ink(message, selector)] - fn invalid_selector(&self); + fn message(&self); } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs index 3e06d25745..0201eb8802 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs @@ -1,11 +1,12 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait OverlappingSelectors { +pub trait TraitDefinition { #[ink(message, selector = 1)] - fn selector1(&self); + fn message_1(&self); + #[ink(message, selector = 1)] - fn selector2(&self); + fn message_2(&self); } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr index 38c4be1d35..386c093424 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr @@ -1,11 +1,11 @@ error: encountered duplicate selector ([0, 0, 0, 1]) in the same ink! trait definition - --> $DIR/message_selector_overlap.rs:8:8 + --> $DIR/message_selector_overlap.rs:9:8 | -8 | fn selector2(&self); +9 | fn message_2(&self); | ^^^^^^^^^ error: first ink! trait constructor or message with same selector found here --> $DIR/message_selector_overlap.rs:6:8 | -6 | fn selector1(&self); +6 | fn message_1(&self); | ^^^^^^^^^ From c58350e56d111b6869211a82aafadbadf525c010 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:08:38 +0200 Subject: [PATCH 330/493] normalize some UI tests --- .../lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs | 4 ++-- crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs b/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs index 7e0e8a801b..bb8f866246 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs @@ -1,9 +1,9 @@ use ink_lang as ink; #[ink::trait_definition] -pub trait InvalidSelector { +pub trait TraitDefinition { #[ink(message, selector = 0xC0DECAFE)] - fn invalid_selector(&self); + fn message(&self); } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 783d2ffbef..5c2e1ded4d 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -4,11 +4,13 @@ use ink_lang as ink; pub trait PayableDefinition { #[ink(message, payable)] fn payable(&self); + #[ink(message, payable)] fn payable_mut(&mut self); #[ink(message)] fn unpayable(&self); + #[ink(message)] fn unpayable_mut(&mut self); } From 083ed0e27bbb19e8418b35538c0886dfa5d1d56c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:08:49 +0200 Subject: [PATCH 331/493] add new UI tests for #[ink::trait_definition] --- crates/lang/macro/tests/compile_tests.rs | 2 ++ .../fail/definition_super_trait_invalid_1.rs | 11 +++++++++++ .../fail/definition_super_trait_invalid_1.stderr | 5 +++++ .../fail/definition_super_trait_invalid_2.rs | 15 +++++++++++++++ .../fail/definition_super_trait_invalid_2.stderr | 5 +++++ 5 files changed, 38 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index a7512a16ee..58214d7eb7 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -109,6 +109,8 @@ fn trait_definition() { t.compile_fail("tests/ui/trait_def/fail/definition_rust_method.rs"); t.compile_fail("tests/ui/trait_def/fail/definition_assoc_type.rs"); t.compile_fail("tests/ui/trait_def/fail/definition_assoc_const.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs"); t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_1.rs"); t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_2.rs"); t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_3.rs"); diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs new file mode 100644 index 0000000000..7ac4c1bd7e --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +pub trait SuperTraitDefinition {} + +#[ink::trait_definition] +pub trait TraitDefinition: SuperTraitDefinition { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr new file mode 100644 index 0000000000..e13ce9e491 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr @@ -0,0 +1,5 @@ +error: ink! trait definitions with supertraits are not supported, yet + --> $DIR/definition_super_trait_invalid_1.rs:6:28 + | +6 | pub trait TraitDefinition: SuperTraitDefinition { + | ^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs new file mode 100644 index 0000000000..7cd35ebd11 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs @@ -0,0 +1,15 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait SuperTraitDefinition { + #[ink(message)] + fn super_message(&self); +} + +#[ink::trait_definition] +pub trait TraitDefinition: SuperTraitDefinition { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr new file mode 100644 index 0000000000..1561de9505 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr @@ -0,0 +1,5 @@ +error: ink! trait definitions with supertraits are not supported, yet + --> $DIR/definition_super_trait_invalid_2.rs:10:28 + | +10 | pub trait TraitDefinition: SuperTraitDefinition { + | ^^^^^^^^^^^^^^^^^^^^ From 6e39ecaf200f47d9496d9a8e9f4e9ac62dd64226 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:17:02 +0200 Subject: [PATCH 332/493] add more UI tests for #[ink::trait_definition] --- crates/lang/macro/tests/compile_tests.rs | 3 +++ .../macro/tests/ui/trait_def/fail/definition_generic.rs | 9 +++++++++ .../tests/ui/trait_def/fail/definition_generic.stderr | 5 +++++ .../macro/tests/ui/trait_def/fail/definition_non_pub.rs | 9 +++++++++ .../tests/ui/trait_def/fail/definition_non_pub.stderr | 7 +++++++ .../macro/tests/ui/trait_def/fail/definition_unsafe.rs | 9 +++++++++ .../tests/ui/trait_def/fail/definition_unsafe.stderr | 5 +++++ 7 files changed, 47 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_generic.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 58214d7eb7..884af2c864 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -111,6 +111,9 @@ fn trait_definition() { t.compile_fail("tests/ui/trait_def/fail/definition_assoc_const.rs"); t.compile_fail("tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs"); t.compile_fail("tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_non_pub.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_unsafe.rs"); + t.compile_fail("tests/ui/trait_def/fail/definition_generic.rs"); t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_1.rs"); t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_2.rs"); t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_3.rs"); diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.rs new file mode 100644 index 0000000000..7d1d4dd1e2 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr new file mode 100644 index 0000000000..edd92f6b44 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr @@ -0,0 +1,5 @@ +error: ink! trait definitions must not be generic + --> $DIR/definition_generic.rs:4:27 + | +4 | pub trait TraitDefinition { + | ^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.rs new file mode 100644 index 0000000000..01feb85065 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +trait TraitDefinition { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr new file mode 100644 index 0000000000..4a66ed5714 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr @@ -0,0 +1,7 @@ +error: ink! trait definitions must have public visibility + --> $DIR/definition_non_pub.rs:3:1 + | +3 | #[ink::trait_definition] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `ink::trait_definition` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.rs b/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.rs new file mode 100644 index 0000000000..cd4b6a23d9 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub unsafe trait TraitDefinition { + #[ink(message)] + fn message(&self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr new file mode 100644 index 0000000000..c558155d3f --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr @@ -0,0 +1,5 @@ +error: ink! trait definitions cannot be unsafe + --> $DIR/definition_unsafe.rs:4:5 + | +4 | pub unsafe trait TraitDefinition { + | ^^^^^^ From fdfd62544d056ca52489b3c3f5aa2e77e3661268 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:24:50 +0200 Subject: [PATCH 333/493] add more UI tests for #[ink::trait_definition] --- crates/lang/macro/tests/compile_tests.rs | 4 ++++ .../tests/ui/trait_def/fail/message_abi_invalid.rs | 12 ++++++++++++ .../ui/trait_def/fail/message_abi_invalid.stderr | 5 +++++ .../ui/trait_def/fail/message_generic_invalid.rs | 12 ++++++++++++ .../ui/trait_def/fail/message_generic_invalid.stderr | 5 +++++ .../trait_def/fail/message_input_pattern_invalid.rs | 9 +++++++++ .../fail/message_input_pattern_invalid.stderr | 5 +++++ .../ui/trait_def/fail/message_unsafe_invalid.rs | 12 ++++++++++++ .../ui/trait_def/fail/message_unsafe_invalid.stderr | 5 +++++ 9 files changed, 69 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 884af2c864..38cbb0e424 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -129,6 +129,10 @@ fn trait_definition() { t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_3.rs"); t.compile_fail("tests/ui/trait_def/fail/message_async_invalid.rs"); t.compile_fail("tests/ui/trait_def/fail/message_const_invalid.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_unsafe_invalid.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_abi_invalid.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_generic_invalid.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_input_pattern_invalid.rs"); t.compile_fail("tests/ui/trait_def/fail/message_default_impl.rs"); t.compile_fail("tests/ui/trait_def/fail/message_constructor_conflict.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs new file mode 100644 index 0000000000..cb0b399eab --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs @@ -0,0 +1,12 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + extern fn message_ref(&self); + + #[ink(message)] + extern fn message_mut(&mut self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr new file mode 100644 index 0000000000..b1671bca98 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr @@ -0,0 +1,5 @@ +error: ink! trait methods with non default ABI are not supported + --> $DIR/message_abi_invalid.rs:6:5 + | +6 | extern fn message_ref(&self); + | ^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.rs new file mode 100644 index 0000000000..9c618b3dcf --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.rs @@ -0,0 +1,12 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message_ref(&self); + + #[ink(message)] + fn message_mut(&mut self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr new file mode 100644 index 0000000000..5a5e1442dd --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr @@ -0,0 +1,5 @@ +error: generic ink! trait methods are not supported + --> $DIR/message_generic_invalid.rs:6:20 + | +6 | fn message_ref(&self); + | ^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.rs new file mode 100644 index 0000000000..a38362c3d9 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.rs @@ -0,0 +1,9 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self, (a, b): (i32, i32)); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr new file mode 100644 index 0000000000..678fd877ba --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr @@ -0,0 +1,5 @@ +error[E0642]: patterns aren't allowed in functions without bodies + --> $DIR/message_input_pattern_invalid.rs:6:23 + | +6 | fn message(&self, (a, b): (i32, i32)); + | ^^^^^^ pattern not allowed in function without body diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.rs new file mode 100644 index 0000000000..b208bc3869 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.rs @@ -0,0 +1,12 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + unsafe fn message_ref(&self); + + #[ink(message)] + unsafe fn message_mut(&mut self); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr new file mode 100644 index 0000000000..671a0ff9b7 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr @@ -0,0 +1,5 @@ +error: unsafe ink! trait methods are not supported + --> $DIR/message_unsafe_invalid.rs:6:5 + | +6 | unsafe fn message_ref(&self); + | ^^^^^^ From ed3c4c38756df9ac860e7b840855c198c21a514e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:36:47 +0200 Subject: [PATCH 334/493] generate guards for scale::Codec message inputs and outputs for ink! trait definitions --- .../codegen/src/generator/trait_def/mod.rs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 6f480a6320..255b084fda 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -27,6 +27,7 @@ use quote::{ format_ident, quote_spanned, }; +use syn::spanned::Spanned as _; /// Generator to create the ink! storage struct and important trait impls. #[derive(From, Copy, Clone)] @@ -66,13 +67,54 @@ impl GenerateCode for TraitDefinition<'_> { let trait_registry = self.generate_trait_registry_impl(); let trait_call_builder = self.generate_call_builder(); let trait_call_forwarder = self.generate_call_forwarder(); + let input_output_guards = self.generate_input_output_guards(); quote_spanned!(span => #trait_definition const _: () = { #trait_registry #trait_call_builder #trait_call_forwarder + #input_output_guards }; ) } } + +impl TraitDefinition<'_> { + /// Generates code to assert that ink! input and output types meet certain properties. + fn generate_input_output_guards(&self) -> TokenStream2 { + let storage_span = self.trait_def.item().span(); + let message_inout_guards = self + .trait_def + .item() + .iter_items() + .filter_map(|(impl_item, _)| impl_item.filter_map_message()) + .map(|message| { + let message_span = message.span(); + let message_inputs = message.inputs().map(|input| { + let input_span = input.span(); + let input_type = &*input.ty; + quote_spanned!(input_span=> + let _: () = ::ink_lang::type_check::identity_type::< + ::ink_lang::type_check::DispatchInput<#input_type> + >(); + ) + }); + let message_output = message.output().map(|output_type| { + let output_span = output_type.span(); + quote_spanned!(output_span=> + let _: () = ::ink_lang::type_check::identity_type::< + ::ink_lang::type_check::DispatchOutput<#output_type> + >(); + ) + }); + quote_spanned!(message_span=> + #( #message_inputs )* + #message_output + ) + }); + quote_spanned!(storage_span=> + #( #message_inout_guards )* + ) + } +} From 689b9f71949d0cd08bb248b14ecd94e6676417c9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:38:53 +0200 Subject: [PATCH 335/493] add UI tests for non-codec message inputs and outputs for #[ink::trait_definition] --- crates/lang/macro/tests/compile_tests.rs | 2 + .../trait_def/fail/message_input_non_codec.rs | 11 +++++ .../fail/message_input_non_codec.stderr | 40 +++++++++++++++++++ .../fail/message_output_non_codec.rs | 11 +++++ .../fail/message_output_non_codec.stderr | 25 ++++++++++++ 5 files changed, 89 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 38cbb0e424..ac17da5bbc 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -133,6 +133,8 @@ fn trait_definition() { t.compile_fail("tests/ui/trait_def/fail/message_abi_invalid.rs"); t.compile_fail("tests/ui/trait_def/fail/message_generic_invalid.rs"); t.compile_fail("tests/ui/trait_def/fail/message_input_pattern_invalid.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_input_non_codec.rs"); + t.compile_fail("tests/ui/trait_def/fail/message_output_non_codec.rs"); t.compile_fail("tests/ui/trait_def/fail/message_default_impl.rs"); t.compile_fail("tests/ui/trait_def/fail/message_constructor_conflict.rs"); } diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.rs new file mode 100644 index 0000000000..597145606f --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +pub struct NonCodec; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self, input: NonCodec); +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr new file mode 100644 index 0000000000..7db027be08 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr @@ -0,0 +1,40 @@ +error[E0277]: the trait bound `NonCodec: WrapperTypeDecode` is not satisfied + --> $DIR/message_input_non_codec.rs:8:23 + | +8 | fn message(&self, input: NonCodec); + | ^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodec` + | + = note: required because of the requirements on the impl of `_::_::_parity_scale_codec::Decode` for `NonCodec` +note: required by a bound in `DispatchInput` + --> $DIR/type_check.rs:23:8 + | +23 | T: scale::Decode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` + +error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied + --> $DIR/message_input_non_codec.rs:5:1 + | +5 | #[ink::trait_definition] + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` +6 | pub trait TraitDefinition { +7 | / #[ink(message)] +8 | | fn message(&self, input: NonCodec); + | |_______________________________________- required by a bound introduced by this call + | + = note: required because of the requirements on the impl of `Encode` for `NonCodec` + = note: this error originates in the attribute macro `ink::trait_definition` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied + --> $DIR/message_input_non_codec.rs:7:5 + | +7 | / #[ink(message)] +8 | | fn message(&self, input: NonCodec); + | |_______________________________________^ method cannot be called on `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds + | + ::: $WORKSPACE/crates/env/src/call/execution_input.rs + | + | pub struct ArgumentList { + | ----------------------------------- doesn't satisfy `_: Encode` + | + = note: the following trait bounds were not satisfied: + `ArgumentList, ArgumentList>: Encode` diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.rs new file mode 100644 index 0000000000..32555e9d6d --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.rs @@ -0,0 +1,11 @@ +use ink_lang as ink; + +pub struct NonCodec; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self) -> NonCodec; +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr new file mode 100644 index 0000000000..4f41c5baad --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied + --> $DIR/message_output_non_codec.rs:8:26 + | +8 | fn message(&self) -> NonCodec; + | ^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` + | + = note: required because of the requirements on the impl of `Encode` for `NonCodec` +note: required by a bound in `DispatchOutput` + --> $DIR/type_check.rs:33:8 + | +33 | T: scale::Encode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` + +error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>`, but its trait bounds were not satisfied + --> $DIR/message_output_non_codec.rs:7:5 + | +3 | pub struct NonCodec; + | -------------------- doesn't satisfy `NonCodec: _::_::_parity_scale_codec::Decode` +... +7 | / #[ink(message)] +8 | | fn message(&self) -> NonCodec; + | |__________________________________^ method cannot be called on `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NonCodec: _::_::_parity_scale_codec::Decode` From 9e1f8c2aa46b635ed5aa8b4d6f634c2b49c9e010 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 13:46:32 +0200 Subject: [PATCH 336/493] fix spelling issue --- crates/lang/codegen/src/generator/trait_def/call_builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index 0ca744e8bc..e5e9b2fc25 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -266,7 +266,7 @@ impl CallBuilder<'_> { ) } - /// Generate trait impls for `FromAccountId` and `ToAccountId` for the account wrapper. + /// Generate trait implementations for `FromAccountId` and `ToAccountId` for the account wrapper. /// /// # Note /// From 62832c85f4de2dc61076b8d117cc7a742c5e7d35 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 14:07:24 +0200 Subject: [PATCH 337/493] apply rustfmt to test case --- .../lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs | 4 ++-- .../macro/tests/ui/trait_def/fail/message_abi_invalid.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs index cb0b399eab..187c6fd565 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs @@ -3,10 +3,10 @@ use ink_lang as ink; #[ink::trait_definition] pub trait TraitDefinition { #[ink(message)] - extern fn message_ref(&self); + extern "C" fn message_ref(&self); #[ink(message)] - extern fn message_mut(&mut self); + extern "C" fn message_mut(&mut self); } fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr index b1671bca98..37e22a8ab9 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr @@ -1,5 +1,5 @@ error: ink! trait methods with non default ABI are not supported --> $DIR/message_abi_invalid.rs:6:5 | -6 | extern fn message_ref(&self); - | ^^^^^^ +6 | extern "C" fn message_ref(&self); + | ^^^^^^^^^^ From 61cc4dcc774f13c550915ff96e34816874f71c14 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 14:08:55 +0200 Subject: [PATCH 338/493] fix some spelling issues --- crates/lang/codegen/src/generator/trait_def/mod.rs | 2 +- crates/lang/ir/src/ir/trait_def/config.rs | 2 +- crates/lang/ir/src/ir/trait_def/item/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 255b084fda..c238e3d92a 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -29,7 +29,7 @@ use quote::{ }; use syn::spanned::Spanned as _; -/// Generator to create the ink! storage struct and important trait impls. +/// Generator to create the ink! storage struct and important trait implementations. #[derive(From, Copy, Clone)] pub struct TraitDefinition<'a> { trait_def: &'a ir::InkTraitDefinition, diff --git a/crates/lang/ir/src/ir/trait_def/config.rs b/crates/lang/ir/src/ir/trait_def/config.rs index ba228aced9..8f564a0e90 100644 --- a/crates/lang/ir/src/ir/trait_def/config.rs +++ b/crates/lang/ir/src/ir/trait_def/config.rs @@ -26,7 +26,7 @@ pub struct TraitDefinitionConfig { /// /// # Note /// - /// The namespace config parameter is used to influence the generated + /// The namespace configuration parameter is used to influence the generated /// selectors of the ink! trait messages. This is useful to disambiguate /// ink! trait definitions with equal names. namespace: Option, diff --git a/crates/lang/ir/src/ir/trait_def/item/mod.rs b/crates/lang/ir/src/ir/trait_def/item/mod.rs index 906b331a75..0ee8eb6f34 100644 --- a/crates/lang/ir/src/ir/trait_def/item/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/item/mod.rs @@ -308,7 +308,7 @@ impl InkItemTrait { /// Extract selectors for ink! trait constructors and messages. /// /// The composed or manually specified selectors are stored into the provided - /// hashtables for later look-up when querying ink! constructors or messages. + /// hash tables for later look-up when querying ink! constructors or messages. /// This way we are more flexible with regard to the underlying structures of the IR. /// /// In this step we assume that all sanitation checks have taken place prior so From 484e21d43a1edb69df77875051d7d8ee226771bf Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 16:56:52 +0200 Subject: [PATCH 339/493] implement ink! trait message selector and payable property guards --- .../lang/codegen/src/generator/item_impls.rs | 62 ++++++++++++++++++- crates/lang/src/lib.rs | 2 + crates/lang/src/traits.rs | 20 ++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 1613c956fa..9db3bad39b 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -12,10 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::iter; + use crate::GenerateCode; use derive_more::From; use heck::CamelCase as _; -use ir::Callable as _; +use ir::{ + Callable as _, + HexLiteral, +}; use proc_macro2::TokenStream as TokenStream2; use quote::{ format_ident, @@ -40,18 +45,73 @@ impl GenerateCode for ItemImpls<'_> { .impls() .map(|item_impl| self.generate_item_impl(item_impl)); let inout_guards = self.generate_input_output_guards(); + let trait_message_property_guards = self.generate_trait_message_property_guards(); quote! { const _: () = { use ::ink_lang::{Env as _, EmitEvent as _, StaticEnv as _}; #( #item_impls )* #inout_guards + #trait_message_property_guards }; } } } impl ItemImpls<'_> { + /// Generates code to guard annotated ink! trait message properties. + /// + /// These guarded properties include `selector` and `payable`. + /// If an ink! trait message is annotated with `#[ink(payable)]` + /// or `#[ink(selector = ..)]` then code is generated to guard that + /// the given argument to `payable` or `selector` is equal to + /// what the associated ink! trait definition defines for the same + /// ink! message. + fn generate_trait_message_property_guards(&self) -> TokenStream2 { + let storage_span = self.contract.module().storage().span(); + let storage_ident = self.contract.module().storage().ident(); + let trait_message_guards = self + .contract + .module() + .impls() + .filter_map(|item_impl| item_impl.trait_path().map(|trait_path| { + iter::repeat(trait_path).zip(item_impl.iter_messages()) + })) + .flatten() + .map(|(trait_path, message)| { + let message_span = message.span(); + let message_local_id = message.local_id().hex_padded_suffixed(); + let message_guard_payable = message.is_payable().then(|| { + quote_spanned!(message_span=> + const _: ::ink_lang::TraitMessagePayable<{ + <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo<#message_local_id>>::PAYABLE + }> = ::ink_lang::TraitMessagePayable::; + ) + }); + let message_guard_selector = message.user_provided_selector().map(|selector| { + let given_selector = selector.into_be_u32().hex_padded_suffixed(); + quote_spanned!(message_span=> + const _: ::ink_lang::TraitMessageSelector<{ + ::core::primitive::u32::from_be_bytes( + <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + as #trait_path>::__ink_TraitInfo + as ::ink_lang::TraitMessageInfo<#message_local_id>>::SELECTOR + ) + }> = ::ink_lang::TraitMessageSelector::<#given_selector>; + ) + }); + quote_spanned!(message_span=> + #message_guard_payable + #message_guard_selector + ) + }); + quote_spanned!(storage_span=> + #( #trait_message_guards )* + ) + } + /// Generates code to assert that ink! input and output types meet certain properties. fn generate_input_output_guards(&self) -> TokenStream2 { let storage_span = self.contract.module().storage().span(); diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 2ef64c55cc..ee2edf40a0 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -79,6 +79,8 @@ pub use self::{ TraitCallForwarderFor, TraitImplementer, TraitMessageInfo, + TraitMessagePayable, + TraitMessageSelector, TraitModulePath, TraitUniqueId, True, diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 67413f5050..36cfff8f17 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -343,3 +343,23 @@ pub trait ExecuteDispatchable { /// Executes the ink! smart contract message or constructor. fn execute_dispatchable(self) -> Result<(), DispatchError>; } + +/// Used as `payable` property guard for ink! trait messages. +/// +/// # Note +/// +/// When an ink! trait message is annotated with `#[ink(payable)]` +/// a compile time check is generated by ink! to guard that the +/// payability of the ink! trait message matches the payability of +/// the same ink! message as defined by the ink! trait message. +pub struct TraitMessagePayable; + +/// Used as `selector` property guard for ink! trait messages. +/// +/// # Note +/// +/// When an ink! trait message is annotated with `#[ink(selector = ..)]` +/// a compile time check is generated by ink! to guard that the +/// selector of the ink! trait message matches the selector of +/// the same ink! message as defined by the ink! trait message. +pub struct TraitMessageSelector; From d7d7c73d97120628a5d64ff04c3a943203c583e3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 16:57:21 +0200 Subject: [PATCH 340/493] add UI tests for ink! trait message payable and selector property guards --- crates/lang/macro/tests/compile_tests.rs | 3 ++ .../fail/trait-message-payable-mismatch.rs | 29 +++++++++++++++++++ .../trait-message-payable-mismatch.stderr | 8 +++++ .../fail/trait-message-selector-mismatch.rs | 29 +++++++++++++++++++ .../trait-message-selector-mismatch.stderr | 8 +++++ 5 files changed, 77 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index ac17da5bbc..b1fa8d787f 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -86,6 +86,9 @@ fn contract() { t.compile_fail("tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs"); t.compile_fail("tests/ui/contract/fail/N-02-namespace-invalid-type.rs"); t.compile_fail("tests/ui/contract/fail/N-03-namespace-missing-argument.rs"); + + t.compile_fail("tests/ui/contract/fail/trait-message-selector-mismatch.rs"); + t.compile_fail("tests/ui/contract/fail/trait-message-payable-mismatch.rs"); } #[test] diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.rs b/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.rs new file mode 100644 index 0000000000..163d3c194b --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.rs @@ -0,0 +1,29 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self); +} + +#[ink::contract] +mod contract { + use super::TraitDefinition; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl TraitDefinition for Contract { + #[ink(message, payable)] + fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr new file mode 100644 index 0000000000..fa51818549 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr @@ -0,0 +1,8 @@ +error[E0308]: mismatched types + --> $DIR/trait-message-payable-mismatch.rs:25:9 + | +25 | fn message(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ expected `false`, found `true` + | + = note: expected struct `TraitMessagePayable` + found struct `TraitMessagePayable` diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.rs b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.rs new file mode 100644 index 0000000000..c342ec457b --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.rs @@ -0,0 +1,29 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message, selector = 1)] + fn message(&self); +} + +#[ink::contract] +mod contract { + use super::TraitDefinition; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl TraitDefinition for Contract { + #[ink(message, selector = 2)] + fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr new file mode 100644 index 0000000000..626ab04c9d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr @@ -0,0 +1,8 @@ +error[E0308]: mismatched types + --> $DIR/trait-message-selector-mismatch.rs:25:9 + | +25 | fn message(&self) {} + | ^^^^^^^^^^^^^^^^^^^^ expected `1_u32`, found `2_u32` + | + = note: expected struct `TraitMessageSelector<1_u32>` + found struct `TraitMessageSelector<2_u32>` From 0adab4a53d743891ee61db451b72b1eb08f56c8e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 17:00:36 +0200 Subject: [PATCH 341/493] add passing UI tests for payable and selector property guards --- crates/lang/macro/tests/compile_tests.rs | 2 ++ .../pass/trait-message-payable-guard.rs | 29 +++++++++++++++++++ .../pass/trait-message-selector-guard.rs | 29 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/trait-message-payable-guard.rs create mode 100644 crates/lang/macro/tests/ui/contract/pass/trait-message-selector-guard.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index b1fa8d787f..832a432ea9 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -43,6 +43,8 @@ fn contract() { t.pass("tests/ui/contract/pass/env-access.rs"); t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); t.pass("tests/ui/contract/pass/module-env-types.rs"); + t.pass("tests/ui/contract/pass/trait-message-payable-guard.rs"); + t.pass("tests/ui/contract/pass/trait-message-selector-guard.rs"); t.pass("tests/ui/contract/pass/example-flipper-works.rs"); t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); diff --git a/crates/lang/macro/tests/ui/contract/pass/trait-message-payable-guard.rs b/crates/lang/macro/tests/ui/contract/pass/trait-message-payable-guard.rs new file mode 100644 index 0000000000..888c2735bd --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/trait-message-payable-guard.rs @@ -0,0 +1,29 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message, payable)] + fn message(&self); +} + +#[ink::contract] +mod contract { + use super::TraitDefinition; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl TraitDefinition for Contract { + #[ink(message, payable)] + fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/pass/trait-message-selector-guard.rs b/crates/lang/macro/tests/ui/contract/pass/trait-message-selector-guard.rs new file mode 100644 index 0000000000..632c9fd439 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/trait-message-selector-guard.rs @@ -0,0 +1,29 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message, selector = 1)] + fn message(&self); +} + +#[ink::contract] +mod contract { + use super::TraitDefinition; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl TraitDefinition for Contract { + #[ink(message, selector = 1)] + fn message(&self) {} + } +} + +fn main() {} From 76921711ee11cc1e94b849cfe15b0073eaf73704 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 17:22:33 +0200 Subject: [PATCH 342/493] fix ERC-1155 example ink! smart contract The contract broke due to ink! now checking if selectors of ink! trait message definitions and implemented ink! trait messages match. --- examples/erc1155/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index d730346242..d91d5af194 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -152,7 +152,7 @@ pub trait Erc1155TokenReceiver { /// /// Any callers must revert if they receive anything other than `ON_ERC_1155_RECEIVED_SELECTOR` as a return /// value. - #[ink(message)] + #[ink(message, selector = 0xF23A6E61)] fn on_received( &mut self, operator: AccountId, @@ -172,7 +172,7 @@ pub trait Erc1155TokenReceiver { /// /// Any callers must revert if they receive anything other than `BATCH_ON_ERC_1155_RECEIVED_SELECTOR` as a return /// value. - #[ink(message)] + #[ink(message, selector = 0xBC197C81)] fn on_batch_received( &mut self, operator: AccountId, From 2dcb14a861cd5db120d22c124a075ce3ed0d9f02 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 18:43:11 +0200 Subject: [PATCH 343/493] disallow #[ink(namespace)] property on ink! trait impl blocks --- crates/lang/ir/src/ir/item_impl/mod.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/item_impl/mod.rs b/crates/lang/ir/src/ir/item_impl/mod.rs index 6f8f9dc8e0..1e7ed9acd5 100644 --- a/crates/lang/ir/src/ir/item_impl/mod.rs +++ b/crates/lang/ir/src/ir/item_impl/mod.rs @@ -292,7 +292,7 @@ impl TryFrom for ItemImpl { } } let (ink_attrs, other_attrs) = ir::partition_attributes(item_impl.attrs)?; - let mut namespace = None; + let mut namespace: Option = None; if !ink_attrs.is_empty() { let normalized = ir::InkAttribute::from_expanded(ink_attrs).map_err(|err| { @@ -308,6 +308,12 @@ impl TryFrom for ItemImpl { })?; namespace = normalized.namespace(); } + if namespace.is_some() && is_trait_impl { + return Err(format_err!( + impl_block_span, + "namespace ink! property is not allowed on ink! trait implementation blocks", + )) + } Ok(Self { attrs: other_attrs, defaultness: item_impl.defaultness, From b3463228823025a1bd4de68d44fc29bf2823c1e4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 18:43:30 +0200 Subject: [PATCH 344/493] add UI tests for #[ink(namespace)] attribute --- crates/lang/macro/tests/compile_tests.rs | 2 ++ .../fail/trait-impl-namespace-invalid.rs | 30 +++++++++++++++++++ .../fail/trait-impl-namespace-invalid.stderr | 9 ++++++ .../ui/contract/pass/impl-block-namespace.rs | 22 ++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr create mode 100644 crates/lang/macro/tests/ui/contract/pass/impl-block-namespace.rs diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 832a432ea9..3419657e3b 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -35,6 +35,7 @@ fn contract() { t.pass("tests/ui/contract/pass/event-config-more-topics.rs"); t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); t.pass("tests/ui/contract/pass/impl-with-property.rs"); + t.pass("tests/ui/contract/pass/impl-block-namespace.rs"); t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); @@ -91,6 +92,7 @@ fn contract() { t.compile_fail("tests/ui/contract/fail/trait-message-selector-mismatch.rs"); t.compile_fail("tests/ui/contract/fail/trait-message-payable-mismatch.rs"); + t.compile_fail("tests/ui/contract/fail/trait-impl-namespace-invalid.rs"); } #[test] diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.rs b/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.rs new file mode 100644 index 0000000000..b344b011ee --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.rs @@ -0,0 +1,30 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message(&self); +} + +#[ink::contract] +mod contract { + use super::TraitDefinition; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + #[ink(namespace = "namespace")] + impl TraitDefinition for Contract { + #[ink(message)] + fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr new file mode 100644 index 0000000000..7090f19090 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr @@ -0,0 +1,9 @@ +error: namespace ink! property is not allowed on ink! trait implementation blocks + --> $DIR/trait-impl-namespace-invalid.rs:23:5 + | +23 | / #[ink(namespace = "namespace")] +24 | | impl TraitDefinition for Contract { +25 | | #[ink(message)] +26 | | fn message(&self) {} +27 | | } + | |_____^ diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-block-namespace.rs b/crates/lang/macro/tests/ui/contract/pass/impl-block-namespace.rs new file mode 100644 index 0000000000..a8f055a946 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/impl-block-namespace.rs @@ -0,0 +1,22 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + #[ink(namespace = "namespace")] + impl Contract { + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} From aa8635781a22bc854b2bb50ec30ad4446dcede5d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 19:27:13 +0200 Subject: [PATCH 345/493] fix unit tests that make use of #[ink(namespace = ..)] --- crates/lang/ir/src/ir/item_impl/callable.rs | 4 +-- crates/lang/ir/src/ir/item_mod.rs | 27 --------------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index d8a72f7dd7..c8a7eaa2e8 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -617,13 +617,13 @@ mod tests { assert_compose_selector::( syn::parse_quote! { #[ink(impl, namespace = "my_namespace")] - impl MyTrait for MyStorage {} + impl MyStorage {} }, syn::parse_quote! { #[ink(message)] fn my_message(&self) {} }, - b"my_namespace::MyTrait::my_message".to_vec(), + b"my_namespace::my_message".to_vec(), ); assert_compose_selector::( syn::parse_quote! { diff --git a/crates/lang/ir/src/ir/item_mod.rs b/crates/lang/ir/src/ir/item_mod.rs index d6c1b31034..6472fdce55 100644 --- a/crates/lang/ir/src/ir/item_mod.rs +++ b/crates/lang/ir/src/ir/item_mod.rs @@ -785,33 +785,6 @@ mod tests { ); } - #[test] - fn namespaced_overlapping_trait_impls_works() { - assert!( - >::try_from(syn::parse_quote! { - mod my_module { - #[ink(storage)] - pub struct MyStorage {} - - #[ink(namespace = "first")] - impl first::MyTrait for MyStorage { - #[ink(constructor)] - fn my_constructor() -> Self {} - - #[ink(message)] - fn my_message(&self) {} - } - - impl second::MyTrait for MyStorage { - #[ink(message)] - fn my_message(&self) {} - } - } - }) - .is_ok() - ); - } - #[test] fn allow_overlap_between_messages_and_constructors() { assert!( From 5df261614ac7d696620d5bed264c34835fe629fb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 20:12:09 +0200 Subject: [PATCH 346/493] update UI test case expectations --- .../tests/ui/contract/fail/C-15-non-codec-input.stderr | 8 ++++---- .../contract/fail/M-04-message-returns-non-codec.stderr | 4 ++-- .../ui/contract/fail/M-07-message-input-non-codec.stderr | 8 ++++---- .../ui/trait_def/fail/message_input_non_codec.stderr | 2 +- .../ui/trait_def/fail/message_output_non_codec.stderr | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr b/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr index af5b775b2c..e3a81cc1f6 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied 13 | pub fn constructor(_input: NonCodecType) -> Self { | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` | - = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` --> $DIR/type_check.rs:23:8 | @@ -19,12 +19,12 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied 15 | | } | |_________^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` | - = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` -note: required by a bound in `contract::_::_parity_scale_codec::Decode::decode` + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `parity_scale_codec::Decode::decode` --> $DIR/codec.rs:284:15 | 284 | fn decode(input: &mut I) -> Result; - | ^^^^^ required by this bound in `contract::_::_parity_scale_codec::Decode::decode` + | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied --> $DIR/C-15-non-codec-input.rs:3:1 diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr index 04bd8566d0..1f5f2cc433 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr @@ -30,7 +30,7 @@ error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder $DIR/M-04-message-returns-non-codec.rs:18:9 | 6 | pub struct NonCodecType; - | ------------------------ doesn't satisfy `_: contract::_::_parity_scale_codec::Decode` + | ------------------------ doesn't satisfy `NonCodecType: parity_scale_codec::Decode` ... 18 | / pub fn message(&self) -> NonCodecType { 19 | | NonCodecType @@ -38,4 +38,4 @@ error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: - `NonCodecType: contract::_::_parity_scale_codec::Decode` + `NonCodecType: parity_scale_codec::Decode` diff --git a/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr index 48eff2f81d..50797d22e1 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` | - = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` --> $DIR/type_check.rs:23:8 | @@ -17,12 +17,12 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` | - = note: required because of the requirements on the impl of `contract::_::_parity_scale_codec::Decode` for `NonCodecType` -note: required by a bound in `contract::_::_parity_scale_codec::Decode::decode` + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `parity_scale_codec::Decode::decode` --> $DIR/codec.rs:284:15 | 284 | fn decode(input: &mut I) -> Result; - | ^^^^^ required by this bound in `contract::_::_parity_scale_codec::Decode::decode` + | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied --> $DIR/M-07-message-input-non-codec.rs:3:1 diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr index 7db027be08..08f790909f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeDecode` is not satisfied 8 | fn message(&self, input: NonCodec); | ^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodec` | - = note: required because of the requirements on the impl of `_::_::_parity_scale_codec::Decode` for `NonCodec` + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodec` note: required by a bound in `DispatchInput` --> $DIR/type_check.rs:23:8 | diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr index 4f41c5baad..ad73fae70f 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr @@ -15,11 +15,11 @@ error[E0599]: the method `fire` exists for struct `CallBuilder $DIR/message_output_non_codec.rs:7:5 | 3 | pub struct NonCodec; - | -------------------- doesn't satisfy `NonCodec: _::_::_parity_scale_codec::Decode` + | -------------------- doesn't satisfy `NonCodec: parity_scale_codec::Decode` ... 7 | / #[ink(message)] 8 | | fn message(&self) -> NonCodec; | |__________________________________^ method cannot be called on `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: - `NonCodec: _::_::_parity_scale_codec::Decode` + `NonCodec: parity_scale_codec::Decode` From 4e0f2e5b5867cff817c73fec82cfb127a00a6a7a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 28 Sep 2021 20:12:26 +0200 Subject: [PATCH 347/493] use "diff" crate feature of trybuild crate --- crates/lang/macro/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index 6559c0ad7d..e781982f6f 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -30,7 +30,7 @@ ink_storage = { version = "3.0.0-rc5", path = "../../storage/" } ink_lang = { version = "3.0.0-rc5", path = ".." } ink_prelude = { version = "3.0.0-rc5", path = "../../prelude/" } -trybuild = "1" +trybuild = { version = "1", features = ["diff"] } scale-info = { version = "0.6", default-features = false, features = ["derive"] } [lib] From 213339b965b5fdbf22f4281fd988e92c4feeb5ef Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 11:51:51 +0200 Subject: [PATCH 348/493] fix some ink! specific error messages --- crates/lang/ir/src/ir/item_impl/constructor.rs | 5 ++++- crates/lang/ir/src/ir/item_impl/message.rs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/item_impl/constructor.rs b/crates/lang/ir/src/ir/item_impl/constructor.rs index 6d32e64627..f44be1ca1a 100644 --- a/crates/lang/ir/src/ir/item_impl/constructor.rs +++ b/crates/lang/ir/src/ir/item_impl/constructor.rs @@ -501,7 +501,10 @@ mod tests { }, ]; for item_method in item_methods { - assert_try_from_fails(item_method, "ink! constructors must have explicit ABI") + assert_try_from_fails( + item_method, + "ink! constructors must not have explicit ABI", + ) } } diff --git a/crates/lang/ir/src/ir/item_impl/message.rs b/crates/lang/ir/src/ir/item_impl/message.rs index d68466c131..9659531f80 100644 --- a/crates/lang/ir/src/ir/item_impl/message.rs +++ b/crates/lang/ir/src/ir/item_impl/message.rs @@ -689,7 +689,7 @@ mod tests { }, ]; for item_method in item_methods { - assert_try_from_fails(item_method, "ink! messages must have explicit ABI") + assert_try_from_fails(item_method, "ink! messages must not have explicit ABI") } } From ce7b371b9e87416c7bb70ee9956da8b071a80913 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 12:56:59 +0200 Subject: [PATCH 349/493] fix and improve some attribute error messages --- crates/lang/ir/src/ast/attr_args.rs | 9 ++++++++- crates/lang/ir/src/ir/attrs.rs | 11 ++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/crates/lang/ir/src/ast/attr_args.rs b/crates/lang/ir/src/ast/attr_args.rs index 187e19ede5..a32459ae31 100644 --- a/crates/lang/ir/src/ast/attr_args.rs +++ b/crates/lang/ir/src/ast/attr_args.rs @@ -24,6 +24,7 @@ use syn::{ ParseStream, }, punctuated::Punctuated, + spanned::Spanned, Token, }; @@ -130,9 +131,15 @@ impl MetaNameValue { name: syn::Path, input: ParseStream, ) -> Result { + let span = name.span(); Ok(MetaNameValue { name, - eq_token: input.parse()?, + eq_token: input.parse().map_err(|_error| { + format_err!( + span, + "ink! config options require an argument separated by '='", + ) + })?, value: input.parse()?, }) } diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 4759cb8a0b..83262d7c25 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -848,7 +848,7 @@ impl TryFrom for AttributeFrag { ), }) } - return Err(format_err!(name_value, "expecteded string type for `namespace` argument, e.g. #[ink(namespace = \"hello\")]")) + return Err(format_err!(name_value, "expected string type for `namespace` argument, e.g. #[ink(namespace = \"hello\")]")) } if name_value.path.is_ident("extension") { if let syn::Lit::Int(lit_int) = &name_value.lit { @@ -906,6 +906,11 @@ impl TryFrom for AttributeFrag { "topic" => Ok(AttributeArg::Topic), "payable" => Ok(AttributeArg::Payable), "impl" => Ok(AttributeArg::Implementation), + "selector" => Err(format_err!( + meta, + "encountered #[ink(selector)] that is missing its u32 parameter. \ + Did you mean #[ink(selector = value: u32)] ?" + )), "namespace" => Err(format_err!( meta, "encountered #[ink(namespace)] that is missing its string parameter. \ @@ -914,7 +919,7 @@ impl TryFrom for AttributeFrag { "extension" => Err(format_err!( meta, "encountered #[ink(extension)] that is missing its N parameter. \ - Did you mean #[ink(extension = N: u32)] ?" + Did you mean #[ink(extension = id: u32)] ?" )), "handle_status" => Err(format_err!( meta, @@ -1188,7 +1193,7 @@ mod tests { syn::parse_quote! { #[ink(namespace = 42)] }, - Err("expecteded string type for `namespace` argument, e.g. #[ink(namespace = \"hello\")]"), + Err("expected string type for `namespace` argument, e.g. #[ink(namespace = \"hello\")]"), ); } From be28a2fcc6498939f3366444f8b8f73b39b8d1bf Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 12:57:45 +0200 Subject: [PATCH 350/493] modernize failing #[ink::contract] UI tests --- crates/lang/macro/tests/compile_tests.rs | 157 ++++++++++-------- .../fail/C-00-constructor-self-ref.rs | 19 --- .../fail/C-00-constructor-self-ref.stderr | 5 - .../fail/C-01-constructor-self-mut.stderr | 5 - .../fail/C-02-constructor-self-val.rs | 19 --- .../fail/C-02-constructor-self-val.stderr | 5 - .../C-03-constructor-missing-return.stderr | 5 - .../fail/C-10-async-constructor.stderr | 5 - .../contract/fail/C-11-unsafe-constructor.rs | 19 --- .../fail/C-11-unsafe-constructor.stderr | 5 - .../contract/fail/C-12-const-constructor.rs | 19 --- .../fail/C-12-const-constructor.stderr | 5 - .../ui/contract/fail/C-13-abi-constructor.rs | 19 --- .../contract/fail/C-13-abi-constructor.stderr | 5 - .../C-16-function-arg-struct-destructuring.rs | 24 --- ...6-function-arg-struct-destructuring.stderr | 5 - .../fail/H-03-use-forbidden-idents.rs | 23 --- .../fail/H-03-use-forbidden-idents.stderr | 11 -- .../contract/fail/M-01-missing-message.stderr | 11 -- .../fail/M-02-message-missing-self-arg.stderr | 6 - .../M-10-method-unknown-ink-marker.stderr | 5 - .../fail/N-02-namespace-invalid-type.stderr | 5 - .../fail/S-01-missing-storage-struct.stderr | 11 -- .../fail/S-02-multiple-storage-structs.rs | 33 ---- .../fail/S-02-multiple-storage-structs.stderr | 23 --- .../S-03-struct-unknown-ink-marker.stderr | 5 - .../fail/S-04-non-storage-ink-impls.rs | 39 ----- .../fail/S-04-non-storage-ink-impls.stderr | 39 ----- .../ui/contract/fail/S-05-storage-as-event.rs | 20 --- .../fail/S-05-storage-as-event.stderr | 5 - .../ui/contract/fail/S-06-event-as-storage.rs | 20 --- .../fail/S-06-event-as-storage.stderr | 5 - ...-compile-as-dependency-invalid-type-01.rs} | 6 +- ...pile-as-dependency-invalid-type-01.stderr} | 2 +- ...g-compile-as-dependency-invalid-type-02.rs | 19 +++ ...mpile-as-dependency-invalid-type-02.stderr | 5 + ...onfig-compile-as-dependency-missing-arg.rs | 19 +++ ...g-compile-as-dependency-missing-arg.stderr | 5 + ...amic-storage-allocator-invalid-type-01.rs} | 6 +- ...-storage-allocator-invalid-type-01.stderr} | 2 +- ...namic-storage-allocator-invalid-type-02.rs | 19 +++ ...c-storage-allocator-invalid-type-02.stderr | 5 + ...g-dynamic-storage-allocator-missing-arg.rs | 19 +++ ...namic-storage-allocator-missing-arg.stderr | 5 + .../tests/ui/contract/fail/constructor-abi.rs | 19 +++ .../ui/contract/fail/constructor-abi.stderr | 5 + .../ui/contract/fail/constructor-async.rs | 19 +++ .../ui/contract/fail/constructor-async.stderr | 5 + .../ui/contract/fail/constructor-const.rs | 19 +++ .../ui/contract/fail/constructor-const.stderr | 5 + ...nput.rs => constructor-input-non-codec.rs} | 0 ...err => constructor-input-non-codec.stderr} | 6 +- .../fail/constructor-input-pattern.rs | 19 +++ .../fail/constructor-input-pattern.stderr | 5 + ...eturn.rs => constructor-missing-return.rs} | 10 +- .../fail/constructor-missing-return.stderr | 5 + ...-constructor.rs => constructor-payable.rs} | 10 +- ...ctor.stderr => constructor-payable.stderr} | 4 +- ...tor.rs => constructor-self-receiver-01.rs} | 10 +- .../fail/constructor-self-receiver-01.stderr | 5 + .../fail/constructor-self-receiver-02.rs | 19 +++ .../fail/constructor-self-receiver-02.stderr | 5 + .../fail/constructor-self-receiver-03.rs | 19 +++ .../fail/constructor-self-receiver-03.stderr | 18 ++ ...mut.rs => constructor-self-receiver-04.rs} | 10 +- .../fail/constructor-self-receiver-04.stderr | 5 + .../ui/contract/fail/constructor-unsafe.rs | 19 +++ .../contract/fail/constructor-unsafe.stderr | 5 + .../fail/event-conflicting-storage.rs | 23 +++ .../fail/event-conflicting-storage.stderr | 5 + .../fail/impl-block-for-non-storage-01.rs | 31 ++++ .../fail/impl-block-for-non-storage-01.stderr | 12 ++ .../fail/impl-block-for-non-storage-02.rs | 24 +++ .../fail/impl-block-for-non-storage-02.stderr | 15 ++ ...mpl-block-namespace-invalid-identifier.rs} | 6 +- ...block-namespace-invalid-identifier.stderr} | 2 +- ...s => impl-block-namespace-invalid-type.rs} | 6 +- .../impl-block-namespace-invalid-type.stderr | 5 + ... impl-block-namespace-missing-argument.rs} | 6 +- ...l-block-namespace-missing-argument.stderr} | 2 +- ...on-codec.rs => message-input-non-codec.rs} | 0 ....stderr => message-input-non-codec.stderr} | 8 +- ...g-self-arg.rs => message-input-pattern.rs} | 8 +- .../fail/message-input-pattern.stderr | 5 + ...-codec.rs => message-returns-non-codec.rs} | 0 ...tderr => message-returns-non-codec.stderr} | 6 +- ...eturns-self.rs => message-returns-self.rs} | 6 +- ...elf.stderr => message-returns-self.stderr} | 2 +- ...rs => message-selector-invalid-type-01.rs} | 8 +- ...> message-selector-invalid-type-01.stderr} | 2 +- ...rs => message-selector-invalid-type-02.rs} | 8 +- ...> message-selector-invalid-type-02.stderr} | 2 +- .../fail/message-selector-missing-arg.rs | 19 +++ .../fail/message-selector-missing-arg.stderr | 5 + .../fail/message-self-receiver-invalid-01.rs | 19 +++ .../message-self-receiver-invalid-01.stderr | 5 + .../fail/message-self-receiver-invalid-02.rs | 19 +++ .../message-self-receiver-invalid-02.stderr | 5 + .../fail/message-self-receiver-invalid-03.rs | 19 +++ .../message-self-receiver-invalid-03.stderr | 5 + .../fail/message-self-receiver-missing.rs | 19 +++ .../fail/message-self-receiver-missing.stderr | 6 + ...-marker.rs => message-unknown-property.rs} | 10 +- .../fail/message-unknown-property.stderr | 5 + ...uctor.rs => module-missing-constructor.rs} | 8 +- ...derr => module-missing-constructor.stderr} | 6 +- ...g-message.rs => module-missing-message.rs} | 6 +- .../fail/module-missing-message.stderr | 11 ++ ...ge-struct.rs => module-missing-storage.rs} | 8 +- .../fail/module-missing-storage.stderr | 11 ++ .../contract/fail/module-multiple-storages.rs | 32 ++++ .../fail/module-multiple-storages.stderr | 23 +++ .../fail/module-use-forbidden-idents.rs | 25 +++ .../fail/module-use-forbidden-idents.stderr | 83 +++++++++ .../fail/storage-conflicting-event.rs | 20 +++ .../fail/storage-conflicting-event.stderr | 5 + ...nk-marker.rs => storage-unknown-marker.rs} | 8 +- .../fail/storage-unknown-marker.stderr | 5 + 118 files changed, 933 insertions(+), 586 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.rs delete mode 100644 crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.stderr rename crates/lang/macro/tests/ui/contract/fail/{H-02-invalid-as-dependency.rs => config-compile-as-dependency-invalid-type-01.rs} (73%) rename crates/lang/macro/tests/ui/contract/fail/{H-02-invalid-as-dependency.stderr => config-compile-as-dependency-invalid-type-01.stderr} (75%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr rename crates/lang/macro/tests/ui/contract/fail/{H-01-invalid-dyn-alloc.rs => config-dynamic-storage-allocator-invalid-type-01.rs} (77%) rename crates/lang/macro/tests/ui/contract/fail/{H-01-invalid-dyn-alloc.stderr => config-dynamic-storage-allocator-invalid-type-01.stderr} (75%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-abi.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-async.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-const.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr rename crates/lang/macro/tests/ui/contract/fail/{C-15-non-codec-input.rs => constructor-input-non-codec.rs} (100%) rename crates/lang/macro/tests/ui/contract/fail/{C-15-non-codec-input.stderr => constructor-input-non-codec.stderr} (92%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr rename crates/lang/macro/tests/ui/contract/fail/{C-03-constructor-missing-return.rs => constructor-missing-return.rs} (51%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr rename crates/lang/macro/tests/ui/contract/fail/{C-14-payable-constructor.rs => constructor-payable.rs} (56%) rename crates/lang/macro/tests/ui/contract/fail/{C-14-payable-constructor.stderr => constructor-payable.stderr} (75%) rename crates/lang/macro/tests/ui/contract/fail/{C-10-async-constructor.rs => constructor-self-receiver-01.rs} (54%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr rename crates/lang/macro/tests/ui/contract/fail/{C-01-constructor-self-mut.rs => constructor-self-receiver-04.rs} (54%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr rename crates/lang/macro/tests/ui/contract/fail/{N-01-namespace-invalid-identifier.rs => impl-block-namespace-invalid-identifier.rs} (77%) rename crates/lang/macro/tests/ui/contract/fail/{N-01-namespace-invalid-identifier.stderr => impl-block-namespace-invalid-identifier.stderr} (74%) rename crates/lang/macro/tests/ui/contract/fail/{N-02-namespace-invalid-type.rs => impl-block-namespace-invalid-type.rs} (76%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr rename crates/lang/macro/tests/ui/contract/fail/{N-03-namespace-missing-argument.rs => impl-block-namespace-missing-argument.rs} (75%) rename crates/lang/macro/tests/ui/contract/fail/{N-03-namespace-missing-argument.stderr => impl-block-namespace-missing-argument.stderr} (75%) rename crates/lang/macro/tests/ui/contract/fail/{M-07-message-input-non-codec.rs => message-input-non-codec.rs} (100%) rename crates/lang/macro/tests/ui/contract/fail/{M-07-message-input-non-codec.stderr => message-input-non-codec.stderr} (93%) rename crates/lang/macro/tests/ui/contract/fail/{M-02-message-missing-self-arg.rs => message-input-pattern.rs} (60%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr rename crates/lang/macro/tests/ui/contract/fail/{M-04-message-returns-non-codec.rs => message-returns-non-codec.rs} (100%) rename crates/lang/macro/tests/ui/contract/fail/{M-04-message-returns-non-codec.stderr => message-returns-non-codec.stderr} (93%) rename crates/lang/macro/tests/ui/contract/fail/{M-03-message-returns-self.rs => message-returns-self.rs} (72%) rename crates/lang/macro/tests/ui/contract/fail/{M-03-message-returns-self.stderr => message-returns-self.stderr} (76%) rename crates/lang/macro/tests/ui/contract/fail/{M-05-message-invalid-selector.rs => message-selector-invalid-type-01.rs} (60%) rename crates/lang/macro/tests/ui/contract/fail/{M-05-message-invalid-selector.stderr => message-selector-invalid-type-01.stderr} (83%) rename crates/lang/macro/tests/ui/contract/fail/{M-06-message-invalid-selector-type.rs => message-selector-invalid-type-02.rs} (59%) rename crates/lang/macro/tests/ui/contract/fail/{M-06-message-invalid-selector-type.stderr => message-selector-invalid-type-02.stderr} (77%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr rename crates/lang/macro/tests/ui/contract/fail/{M-10-method-unknown-ink-marker.rs => message-unknown-property.rs} (65%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr rename crates/lang/macro/tests/ui/contract/fail/{C-04-missing-constructor.rs => module-missing-constructor.rs} (53%) rename crates/lang/macro/tests/ui/contract/fail/{C-04-missing-constructor.stderr => module-missing-constructor.stderr} (52%) rename crates/lang/macro/tests/ui/contract/fail/{M-01-missing-message.rs => module-missing-message.rs} (68%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr rename crates/lang/macro/tests/ui/contract/fail/{S-01-missing-storage-struct.rs => module-missing-storage.rs} (54%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr rename crates/lang/macro/tests/ui/contract/fail/{S-03-struct-unknown-ink-marker.rs => storage-unknown-marker.rs} (64%) create mode 100644 crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 3419657e3b..f625e0d24c 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -17,82 +17,105 @@ fn contract() { let t = trybuild::TestCases::new(); // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); - t.pass("tests/ui/contract/pass/minimal-contract.rs"); - t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); - t.pass("tests/ui/contract/pass/constructor-selector.rs"); - t.pass("tests/ui/contract/pass/message-many-inputs.rs"); - t.pass("tests/ui/contract/pass/message-many-outputs.rs"); - t.pass("tests/ui/contract/pass/message-payable.rs"); - t.pass("tests/ui/contract/pass/message-selector.rs"); - t.pass("tests/ui/contract/pass/storage-single-field.rs"); - t.pass("tests/ui/contract/pass/storage-many-fields.rs"); - t.pass("tests/ui/contract/pass/storage-packed-fields.rs"); - t.pass("tests/ui/contract/pass/storage-with-derives.rs"); - t.pass("tests/ui/contract/pass/event-single-definition.rs"); - t.pass("tests/ui/contract/pass/event-many-definitions.rs"); - t.pass("tests/ui/contract/pass/event-topics.rs"); - t.pass("tests/ui/contract/pass/event-anonymous.rs"); - t.pass("tests/ui/contract/pass/event-config-more-topics.rs"); - t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); - t.pass("tests/ui/contract/pass/impl-with-property.rs"); - t.pass("tests/ui/contract/pass/impl-block-namespace.rs"); - t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); - t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); - t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); - t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs"); - t.pass("tests/ui/contract/pass/config-custom-env.rs"); - t.pass("tests/ui/contract/pass/env-access.rs"); - t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); - t.pass("tests/ui/contract/pass/module-env-types.rs"); - t.pass("tests/ui/contract/pass/trait-message-payable-guard.rs"); - t.pass("tests/ui/contract/pass/trait-message-selector-guard.rs"); - t.pass("tests/ui/contract/pass/example-flipper-works.rs"); - t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); - t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); - t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); - t.pass("tests/ui/contract/pass/example-erc20-works.rs"); - t.pass("tests/ui/contract/pass/example-erc721-works.rs"); + // t.pass("tests/ui/contract/pass/minimal-contract.rs"); + // t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); + // t.pass("tests/ui/contract/pass/constructor-selector.rs"); + // t.pass("tests/ui/contract/pass/message-many-inputs.rs"); + // t.pass("tests/ui/contract/pass/message-many-outputs.rs"); + // t.pass("tests/ui/contract/pass/message-payable.rs"); + // t.pass("tests/ui/contract/pass/message-selector.rs"); + // t.pass("tests/ui/contract/pass/storage-single-field.rs"); + // t.pass("tests/ui/contract/pass/storage-many-fields.rs"); + // t.pass("tests/ui/contract/pass/storage-packed-fields.rs"); + // t.pass("tests/ui/contract/pass/storage-with-derives.rs"); + // t.pass("tests/ui/contract/pass/event-single-definition.rs"); + // t.pass("tests/ui/contract/pass/event-many-definitions.rs"); + // t.pass("tests/ui/contract/pass/event-topics.rs"); + // t.pass("tests/ui/contract/pass/event-anonymous.rs"); + // t.pass("tests/ui/contract/pass/event-config-more-topics.rs"); + // t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); + // t.pass("tests/ui/contract/pass/impl-with-property.rs"); + // t.pass("tests/ui/contract/pass/impl-block-namespace.rs"); + // t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); + // t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); + // t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); + // t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs"); + // t.pass("tests/ui/contract/pass/config-custom-env.rs"); + // t.pass("tests/ui/contract/pass/env-access.rs"); + // t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); + // t.pass("tests/ui/contract/pass/module-env-types.rs"); + // t.pass("tests/ui/contract/pass/trait-message-payable-guard.rs"); + // t.pass("tests/ui/contract/pass/trait-message-selector-guard.rs"); + // t.pass("tests/ui/contract/pass/example-flipper-works.rs"); + // t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); + // t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); + // t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); + // t.pass("tests/ui/contract/pass/example-erc20-works.rs"); + // t.pass("tests/ui/contract/pass/example-erc721-works.rs"); - t.compile_fail("tests/ui/contract/fail/C-00-constructor-self-ref.rs"); - t.compile_fail("tests/ui/contract/fail/C-01-constructor-self-mut.rs"); - t.compile_fail("tests/ui/contract/fail/C-02-constructor-self-val.rs"); - t.compile_fail("tests/ui/contract/fail/C-03-constructor-missing-return.rs"); - t.compile_fail("tests/ui/contract/fail/C-04-missing-constructor.rs"); - t.compile_fail("tests/ui/contract/fail/C-10-async-constructor.rs"); - t.compile_fail("tests/ui/contract/fail/C-11-unsafe-constructor.rs"); - t.compile_fail("tests/ui/contract/fail/C-12-const-constructor.rs"); - t.compile_fail("tests/ui/contract/fail/C-13-abi-constructor.rs"); - t.compile_fail("tests/ui/contract/fail/C-14-payable-constructor.rs"); - t.compile_fail("tests/ui/contract/fail/C-15-non-codec-input.rs"); - t.compile_fail("tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs"); + t.compile_fail( + "tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs", + ); + t.compile_fail( + "tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs", + ); + t.compile_fail( + "tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs", + ); + t.compile_fail( + "tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs", + ); + t.compile_fail( + "tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs", + ); + t.compile_fail("tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs"); - t.compile_fail("tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs"); - t.compile_fail("tests/ui/contract/fail/H-02-invalid-as-dependency.rs"); - t.compile_fail("tests/ui/contract/fail/H-03-use-forbidden-idents.rs"); + t.compile_fail("tests/ui/contract/fail/module-use-forbidden-idents.rs"); + t.compile_fail("tests/ui/contract/fail/module-missing-constructor.rs"); + t.compile_fail("tests/ui/contract/fail/module-missing-message.rs"); + t.compile_fail("tests/ui/contract/fail/module-missing-storage.rs"); + t.compile_fail("tests/ui/contract/fail/module-multiple-storages.rs"); - t.compile_fail("tests/ui/contract/fail/M-01-missing-message.rs"); - t.compile_fail("tests/ui/contract/fail/M-02-message-missing-self-arg.rs"); - t.compile_fail("tests/ui/contract/fail/M-03-message-returns-self.rs"); - t.compile_fail("tests/ui/contract/fail/M-04-message-returns-non-codec.rs"); - t.compile_fail("tests/ui/contract/fail/M-05-message-invalid-selector.rs"); - t.compile_fail("tests/ui/contract/fail/M-06-message-invalid-selector-type.rs"); - t.compile_fail("tests/ui/contract/fail/M-07-message-input-non-codec.rs"); - t.compile_fail("tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-01.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-02.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-03.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-04.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-missing-return.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-async.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-unsafe.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-const.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-abi.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-payable.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-input-non-codec.rs"); + t.compile_fail("tests/ui/contract/fail/constructor-input-pattern.rs"); - t.compile_fail("tests/ui/contract/fail/S-01-missing-storage-struct.rs"); - t.compile_fail("tests/ui/contract/fail/S-02-multiple-storage-structs.rs"); - t.compile_fail("tests/ui/contract/fail/S-03-struct-unknown-ink-marker.rs"); - t.compile_fail("tests/ui/contract/fail/S-04-non-storage-ink-impls.rs"); - t.compile_fail("tests/ui/contract/fail/S-05-storage-as-event.rs"); - t.compile_fail("tests/ui/contract/fail/S-06-event-as-storage.rs"); + t.compile_fail("tests/ui/contract/fail/message-input-pattern.rs"); + t.compile_fail("tests/ui/contract/fail/message-self-receiver-missing.rs"); + t.compile_fail("tests/ui/contract/fail/message-self-receiver-invalid-01.rs"); + t.compile_fail("tests/ui/contract/fail/message-self-receiver-invalid-02.rs"); + t.compile_fail("tests/ui/contract/fail/message-self-receiver-invalid-03.rs"); + t.compile_fail("tests/ui/contract/fail/message-returns-self.rs"); + t.compile_fail("tests/ui/contract/fail/message-returns-non-codec.rs"); + t.compile_fail("tests/ui/contract/fail/message-selector-invalid-type-01.rs"); + t.compile_fail("tests/ui/contract/fail/message-selector-invalid-type-02.rs"); + t.compile_fail("tests/ui/contract/fail/message-selector-missing-arg.rs"); + t.compile_fail("tests/ui/contract/fail/message-input-non-codec.rs"); + t.compile_fail("tests/ui/contract/fail/message-unknown-property.rs"); - t.compile_fail("tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs"); - t.compile_fail("tests/ui/contract/fail/N-02-namespace-invalid-type.rs"); - t.compile_fail("tests/ui/contract/fail/N-03-namespace-missing-argument.rs"); + t.compile_fail("tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs"); + t.compile_fail("tests/ui/contract/fail/impl-block-namespace-invalid-type.rs"); + t.compile_fail("tests/ui/contract/fail/impl-block-namespace-missing-argument.rs"); + t.compile_fail("tests/ui/contract/fail/impl-block-for-non-storage-01.rs"); + t.compile_fail("tests/ui/contract/fail/impl-block-for-non-storage-02.rs"); t.compile_fail("tests/ui/contract/fail/trait-message-selector-mismatch.rs"); t.compile_fail("tests/ui/contract/fail/trait-message-payable-mismatch.rs"); t.compile_fail("tests/ui/contract/fail/trait-impl-namespace-invalid.rs"); + + t.compile_fail("tests/ui/contract/fail/storage-unknown-marker.rs"); + t.compile_fail("tests/ui/contract/fail/storage-conflicting-event.rs"); + + t.compile_fail("tests/ui/contract/fail/event-conflicting-storage.rs"); } #[test] diff --git a/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.rs b/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.rs deleted file mode 100644 index f6644cd465..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.rs +++ /dev/null @@ -1,19 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - impl Noop { - #[ink(constructor)] - pub fn invalid_self_ref(&self) -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.stderr b/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.stderr deleted file mode 100644 index e31f0a668f..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-00-constructor-self-ref.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! constructors must have no `self` receiver - --> $DIR/C-00-constructor-self-ref.rs:10:33 - | -10 | pub fn invalid_self_ref(&self) -> Self { - | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.stderr b/crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.stderr deleted file mode 100644 index eb2006c851..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! constructors must have no `self` receiver - --> $DIR/C-01-constructor-self-mut.rs:10:29 - | -10 | pub fn self_mut_arg(&mut self) -> Self { - | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.rs b/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.rs deleted file mode 100644 index 30b661d309..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.rs +++ /dev/null @@ -1,19 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - impl Noop { - #[ink(constructor)] - pub fn invalid_self_val(self) -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.stderr b/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.stderr deleted file mode 100644 index 12fc09440b..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-02-constructor-self-val.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! constructors must have no `self` receiver - --> $DIR/C-02-constructor-self-val.rs:10:33 - | -10 | pub fn invalid_self_val(self) -> Self { - | ^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.stderr b/crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.stderr deleted file mode 100644 index e37d10b07c..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: missing return for ink! constructor - --> $DIR/C-03-constructor-missing-return.rs:10:13 - | -10 | pub fn missing_return() {} - | ^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.stderr deleted file mode 100644 index 998945162b..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! constructors must not be async - --> $DIR/C-10-async-constructor.rs:10:13 - | -10 | pub async fn async_constructor() -> Self { - | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.rs deleted file mode 100644 index 902da3ea8e..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.rs +++ /dev/null @@ -1,19 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - impl Noop { - #[ink(constructor)] - pub unsafe fn unsafe_constructor() -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.stderr deleted file mode 100644 index 5981cbc9bc..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-11-unsafe-constructor.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! constructors must not be unsafe - --> $DIR/C-11-unsafe-constructor.rs:10:13 - | -10 | pub unsafe fn unsafe_constructor() -> Self { - | ^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.rs deleted file mode 100644 index abd6d07fe5..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.rs +++ /dev/null @@ -1,19 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - impl Noop { - #[ink(constructor)] - pub const fn const_constructor() -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.stderr deleted file mode 100644 index a1a456b696..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-12-const-constructor.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! constructors must not be const - --> $DIR/C-12-const-constructor.rs:10:13 - | -10 | pub const fn const_constructor() -> Self { - | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.rs deleted file mode 100644 index 84b06e52a4..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.rs +++ /dev/null @@ -1,19 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - #[ink(storage)] - pub struct Noop {} - - impl Noop { - #[ink(constructor)] - pub extern "C" fn abi_constructor() -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.stderr deleted file mode 100644 index 4eca2e5fe6..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-13-abi-constructor.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! constructors must have explicit ABI - --> $DIR/C-13-abi-constructor.rs:10:13 - | -10 | pub extern "C" fn abi_constructor() -> Self { - | ^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs b/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs deleted file mode 100644 index b811c1f226..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.rs +++ /dev/null @@ -1,24 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod noop { - - struct Args { - foo: (), - } - - #[ink(storage)] - pub struct Noop {} - - impl Noop { - #[ink(constructor)] - pub fn new() -> Self { - Self {} - } - - #[ink(message)] - pub fn noop(&self, Foo { foo }: Foo) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.stderr b/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.stderr deleted file mode 100644 index 33ada0340d..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/C-16-function-arg-struct-destructuring.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: ink! message arguments must have an identifier - --> $DIR/C-16-function-arg-struct-destructuring.rs:20:28 - | -20 | pub fn noop(&self, Foo { foo }: Foo) {} - | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.rs b/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.rs deleted file mode 100644 index 6ae9c95482..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.rs +++ /dev/null @@ -1,23 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod forbidden_indents { - #[ink(storage)] - pub struct ForbiddenIndents {} - - impl ForbiddenIndents { - #[ink(constructor)] - pub fn constructor() -> Self { - Self {} - } - - /// An ink! message starting with __ink_ prefix. - #[ink(message)] - pub fn __ink_message(&self) { - // All identifiers starting with `__ink_` are forbidden to use in ink!. - let __ink_first = (); - } - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.stderr b/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.stderr deleted file mode 100644 index 4dd20eb790..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/H-03-use-forbidden-idents.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: encountered invalid identifier starting with __ink_ - --> $DIR/H-03-use-forbidden-idents.rs:16:16 - | -16 | pub fn __ink_message(&self) { - | ^^^^^^^^^^^^^ - -error: encountered invalid identifier starting with __ink_ - --> $DIR/H-03-use-forbidden-idents.rs:18:17 - | -18 | let __ink_first = (); - | ^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.stderr b/crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.stderr deleted file mode 100644 index 9072ceac84..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: missing ink! message - --> $DIR/M-01-missing-message.rs:4:1 - | -4 | / mod missing_message { -5 | | #[ink(storage)] -6 | | pub struct MissingMessage {} -7 | | -... | -13 | | } -14 | | } - | |_^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.stderr deleted file mode 100644 index 8f96d504a5..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: ink! messages must have `&self` or `&mut self` receiver - --> $DIR/M-02-message-missing-self-arg.rs:14:9 - | -14 | / #[ink(message)] -15 | | pub fn missing_self_arg() {} - | |____________________________________^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.stderr deleted file mode 100644 index 7a05ae99fb..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: unknown ink! attribute (path) - --> $DIR/M-10-method-unknown-ink-marker.rs:17:15 - | -17 | #[ink(unknown_marker)] - | ^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr b/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr deleted file mode 100644 index aed0beed38..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: expecteded string type for `namespace` argument, e.g. #[ink(namespace = "hello")] - --> $DIR/N-02-namespace-invalid-type.rs:8:11 - | -8 | #[ink(namespace = true)] - | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.stderr b/crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.stderr deleted file mode 100644 index ac5146f2e1..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: missing ink! storage struct - --> $DIR/S-01-missing-storage-struct.rs:4:1 - | -4 | / mod missing_storage_struct { -5 | | // We are missing the #[ink(storage)] attribute here -6 | | pub struct MissingStorageStruct {} -7 | | -... | -14 | | } -15 | | } - | |_^ diff --git a/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.rs b/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.rs deleted file mode 100644 index 8bb6b0ea8c..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.rs +++ /dev/null @@ -1,33 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod multiple_storage_structs { - #[ink(storage)] - pub struct FirstStorageStruct {} - - // ink! currently does not allow for multiple #[ink(storage)] structs - #[ink(storage)] - pub struct SecondStorageStruct {} - - impl FirstStorageStruct { - #[ink(constructor)] - pub fn constructor1() -> Self { - Self {} - } - - #[ink(message)] - pub fn message1(&self) {} - } - - impl SecondStorageStruct { - #[ink(constructor)] - pub fn constructor2() -> Self { - Self {} - } - - #[ink(message)] - pub fn message2(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.stderr b/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.stderr deleted file mode 100644 index e521e457f1..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-02-multiple-storage-structs.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: encountered multiple ink! storage structs, expected exactly one - --> $DIR/S-02-multiple-storage-structs.rs:4:1 - | -4 | / mod multiple_storage_structs { -5 | | #[ink(storage)] -6 | | pub struct FirstStorageStruct {} -7 | | -... | -30 | | } -31 | | } - | |_^ - -error: ink! storage struct here - --> $DIR/S-02-multiple-storage-structs.rs:6:5 - | -6 | pub struct FirstStorageStruct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: ink! storage struct here - --> $DIR/S-02-multiple-storage-structs.rs:10:5 - | -10 | pub struct SecondStorageStruct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.stderr deleted file mode 100644 index eab64bedba..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: unknown ink! attribute (path) - --> $DIR/S-03-struct-unknown-ink-marker.rs:8:11 - | -8 | #[ink(unknown_or_unsupported)] - | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.rs b/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.rs deleted file mode 100644 index b3439f06de..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.rs +++ /dev/null @@ -1,39 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod non_storage_ink_impls { - // This test ensures that ink! `impl` blocks are always - // implemented on the only storage struct definition. - - #[ink(storage)] - pub struct StorageStruct {} - - // This ink! `impl` block is okay. - impl StorageStruct { - #[ink(constructor)] - pub fn constructor1() -> Self { - Self {} - } - - #[ink(message)] - pub fn message1(&self) {} - } - - // Missing the `#[ink(storage)]` attribute on purpose. - pub struct NonStorageStruct {} - - // This ink! `impl` block is invalid in that it implements - // the messages and constructors for a non-existing ink! - // storage struct. We expect a failure here. - impl NonStorageStruct { - #[ink(constructor)] - pub fn constructor2() -> Self { - Self {} - } - - #[ink(message)] - pub fn message2(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr b/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr deleted file mode 100644 index 327a92c10d..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-04-non-storage-ink-impls.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0271]: type mismatch resolving `::This == StorageStruct` - --> $DIR/S-04-non-storage-ink-impls.rs:28:10 - | -28 | impl NonStorageStruct { - | ^^^^^^^^^^^^^^^^ expected struct `StorageStruct`, found struct `NonStorageStruct` - | -note: required by a bound in `non_storage_ink_impls::_::_::{closure#0}::assert_type_eq_all` - --> $DIR/S-04-non-storage-ink-impls.rs:28:10 - | -28 | impl NonStorageStruct { - | ^^^^^^^^^^^^^^^^ - | | - | required by a bound in this - | required by this bound in `non_storage_ink_impls::_::_::{closure#0}::assert_type_eq_all` - = note: this error originates in the macro `::ink_lang::static_assertions::assert_type_eq_all` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0599]: no function or associated item named `constructor2` found for struct `StorageStruct` in the current scope - --> $DIR/S-04-non-storage-ink-impls.rs:30:16 - | -9 | pub struct StorageStruct {} - | ------------------------ function or associated item `constructor2` not found for this -... -30 | pub fn constructor2() -> Self { - | ^^^^^^^^^^^^ - | | - | function or associated item not found in `StorageStruct` - | help: there is an associated function with a similar name: `constructor1` - -error[E0599]: no function or associated item named `message2` found for struct `StorageStruct` in the current scope - --> $DIR/S-04-non-storage-ink-impls.rs:35:16 - | -9 | pub struct StorageStruct {} - | ------------------------ function or associated item `message2` not found for this -... -35 | pub fn message2(&self) {} - | ^^^^^^^^ - | | - | function or associated item not found in `StorageStruct` - | help: there is an associated function with a similar name: `message1` diff --git a/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.rs b/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.rs deleted file mode 100644 index 84cffdb25d..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.rs +++ /dev/null @@ -1,20 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod storage_as_event { - #[ink(storage)] - #[ink(event)] // We cannot have #[ink(event)] if we already have #[ink(storage)] - pub struct StorageAsEvent {} - - impl StorageAsEvent { - #[ink(constructor)] - pub fn constructor() -> Self { - Self {} - } - - #[ink(message)] - pub fn message(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.stderr b/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.stderr deleted file mode 100644 index 3c4ea660b7..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-05-storage-as-event.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: encountered conflicting ink! attribute argument - --> $DIR/S-05-storage-as-event.rs:6:11 - | -6 | #[ink(event)] // We cannot have #[ink(event)] if we already have #[ink(storage)] - | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.rs b/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.rs deleted file mode 100644 index 1a932386d3..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.rs +++ /dev/null @@ -1,20 +0,0 @@ -use ink_lang as ink; - -#[ink::contract] -mod event_as_storage { - #[ink(event)] - #[ink(storage)] // We cannot have #[ink(storage)] if we already have #[ink(event)] - pub struct EventAsStorage {} - - impl EventAsStorage { - #[ink(constructor)] - pub fn constructor() -> Self { - Self {} - } - - #[ink(message)] - pub fn message(&self) {} - } -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.stderr b/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.stderr deleted file mode 100644 index 55a85d515b..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/S-06-event-as-storage.stderr +++ /dev/null @@ -1,5 +0,0 @@ -error: encountered conflicting ink! attribute argument - --> $DIR/S-06-event-as-storage.rs:6:11 - | -6 | #[ink(storage)] // We cannot have #[ink(storage)] if we already have #[ink(event)] - | ^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.rs b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs similarity index 73% rename from crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.rs rename to crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs index 8604f93a57..479bab49dc 100644 --- a/crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.rs +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs @@ -1,11 +1,11 @@ use ink_lang as ink; #[ink::contract(compile_as_dependency = "yes")] -mod invalid_as_dependency { +mod contract { #[ink(storage)] - pub struct InvalidAsDependency {} + pub struct Contract {} - impl InvalidAsDependency { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.stderr b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr similarity index 75% rename from crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.stderr rename to crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr index 9ea0cdc5b2..deb458b804 100644 --- a/crates/lang/macro/tests/ui/contract/fail/H-02-invalid-as-dependency.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr @@ -1,5 +1,5 @@ error: expected a bool literal for `compile_as_dependency` ink! configuration argument - --> $DIR/H-02-invalid-as-dependency.rs:3:17 + --> $DIR/config-compile-as-dependency-invalid-type-01.rs:3:17 | 3 | #[ink::contract(compile_as_dependency = "yes")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs new file mode 100644 index 0000000000..e057aab475 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(compile_as_dependency = 42)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr new file mode 100644 index 0000000000..9ac7a98793 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr @@ -0,0 +1,5 @@ +error: expected a bool literal for `compile_as_dependency` ink! configuration argument + --> $DIR/config-compile-as-dependency-invalid-type-02.rs:3:17 + | +3 | #[ink::contract(compile_as_dependency = 42)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs new file mode 100644 index 0000000000..179a18340a --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(compile_as_dependency)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr new file mode 100644 index 0000000000..dc3eb26675 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr @@ -0,0 +1,5 @@ +error: ink! config options require an argument separated by '=' + --> $DIR/config-compile-as-dependency-missing-arg.rs:3:17 + | +3 | #[ink::contract(compile_as_dependency)] + | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs similarity index 77% rename from crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs rename to crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs index 0efde049b0..9921733928 100644 --- a/crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.rs +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs @@ -1,11 +1,11 @@ use ink_lang as ink; #[ink::contract(dynamic_storage_allocator = "foo")] -mod invalid_version { +mod contract { #[ink(storage)] - pub struct InvalidVersion {} + pub struct Contract {} - impl InvalidVersion { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.stderr b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr similarity index 75% rename from crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.stderr rename to crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr index 1875fce7be..6e1c181f0f 100644 --- a/crates/lang/macro/tests/ui/contract/fail/H-01-invalid-dyn-alloc.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr @@ -1,5 +1,5 @@ error: expected a bool literal for `dynamic_storage_allocator` ink! configuration argument - --> $DIR/H-01-invalid-dyn-alloc.rs:3:17 + --> $DIR/config-dynamic-storage-allocator-invalid-type-01.rs:3:17 | 3 | #[ink::contract(dynamic_storage_allocator = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs new file mode 100644 index 0000000000..7a05d13161 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(dynamic_storage_allocator = 42)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr new file mode 100644 index 0000000000..cdf39f773b --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr @@ -0,0 +1,5 @@ +error: expected a bool literal for `dynamic_storage_allocator` ink! configuration argument + --> $DIR/config-dynamic-storage-allocator-invalid-type-02.rs:3:17 + | +3 | #[ink::contract(dynamic_storage_allocator = 42)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs new file mode 100644 index 0000000000..c30ebd1c9e --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract(dynamic_storage_allocator)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr new file mode 100644 index 0000000000..2d9108bc12 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr @@ -0,0 +1,5 @@ +error: ink! config options require an argument separated by '=' + --> $DIR/config-dynamic-storage-allocator-missing-arg.rs:3:17 + | +3 | #[ink::contract(dynamic_storage_allocator)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.rs new file mode 100644 index 0000000000..749c41e30e --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub extern "C" fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr new file mode 100644 index 0000000000..a9f81663fd --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr @@ -0,0 +1,5 @@ +error: ink! constructors must have explicit ABI + --> $DIR/constructor-abi.rs:10:13 + | +10 | pub extern "C" fn constructor() -> Self { + | ^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-async.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-async.rs new file mode 100644 index 0000000000..4acfb0f138 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-async.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub async fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr new file mode 100644 index 0000000000..f57d8af29c --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr @@ -0,0 +1,5 @@ +error: ink! constructors must not be async + --> $DIR/constructor-async.rs:10:13 + | +10 | pub async fn constructor() -> Self { + | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-const.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-const.rs new file mode 100644 index 0000000000..dae9d73c0a --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-const.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub const fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr new file mode 100644 index 0000000000..ee2b07cb12 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr @@ -0,0 +1,5 @@ +error: ink! constructors must not be const + --> $DIR/constructor-const.rs:10:13 + | +10 | pub const fn constructor() -> Self { + | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.rs rename to crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr similarity index 92% rename from crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr rename to crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr index e3a81cc1f6..5cd8bece1d 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-15-non-codec-input.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/C-15-non-codec-input.rs:13:28 + --> $DIR/constructor-input-non-codec.rs:13:28 | 13 | pub fn constructor(_input: NonCodecType) -> Self { | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` @@ -12,7 +12,7 @@ note: required by a bound in `DispatchInput` | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/C-15-non-codec-input.rs:13:9 + --> $DIR/constructor-input-non-codec.rs:13:9 | 13 | / pub fn constructor(_input: NonCodecType) -> Self { 14 | | Self {} @@ -27,7 +27,7 @@ note: required by a bound in `parity_scale_codec::Decode::decode` | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/C-15-non-codec-input.rs:3:1 + --> $DIR/constructor-input-non-codec.rs:3:1 | 3 | #[ink::contract] | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.rs new file mode 100644 index 0000000000..d4ba3cf098 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor((_a, _b): (i32, i32)) -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr new file mode 100644 index 0000000000..093c9ac0a0 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr @@ -0,0 +1,5 @@ +error: ink! constructor arguments must have an identifier + --> $DIR/constructor-input-pattern.rs:10:28 + | +10 | pub fn constructor((_a, _b): (i32, i32)) -> Self { + | ^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.rs similarity index 51% rename from crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.rs rename to crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.rs index eeb4a12b43..48ac98ae44 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-03-constructor-missing-return.rs +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.rs @@ -1,16 +1,16 @@ use ink_lang as ink; #[ink::contract] -mod noop { +mod contract { #[ink(storage)] - pub struct Noop {} + pub struct Contract {} - impl Noop { + impl Contract { #[ink(constructor)] - pub fn missing_return() {} + pub fn constructor() {} #[ink(message)] - pub fn noop(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr new file mode 100644 index 0000000000..febb0d4b5a --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr @@ -0,0 +1,5 @@ +error: missing return for ink! constructor + --> $DIR/constructor-missing-return.rs:10:13 + | +10 | pub fn constructor() {} + | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-payable.rs similarity index 56% rename from crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/constructor-payable.rs index dcf230180d..b1a912857a 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.rs +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-payable.rs @@ -1,18 +1,18 @@ use ink_lang as ink; #[ink::contract] -mod noop { +mod contract { #[ink(storage)] - pub struct Noop {} + pub struct Contract {} - impl Noop { + impl Contract { #[ink(constructor, payable)] - pub fn abi_constructor() -> Self { + pub fn constructor() -> Self { Self {} } #[ink(message)] - pub fn noop(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr similarity index 75% rename from crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr index 159540e092..a423069ef1 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-14-payable-constructor.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr @@ -1,11 +1,11 @@ error: encountered conflicting ink! attribute argument - --> $DIR/C-14-payable-constructor.rs:9:28 + --> $DIR/constructor-payable.rs:9:28 | 9 | #[ink(constructor, payable)] | ^^^^^^^ error: constructors are implicitly payable - --> $DIR/C-14-payable-constructor.rs:9:28 + --> $DIR/constructor-payable.rs:9:28 | 9 | #[ink(constructor, payable)] | ^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.rs similarity index 54% rename from crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.rs index fa965eb0f7..f122061406 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-10-async-constructor.rs +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.rs @@ -1,18 +1,18 @@ use ink_lang as ink; #[ink::contract] -mod noop { +mod contract { #[ink(storage)] - pub struct Noop {} + pub struct Contract {} - impl Noop { + impl Contract { #[ink(constructor)] - pub async fn async_constructor() -> Self { + pub fn constructor(&self) -> Self { Self {} } #[ink(message)] - pub fn noop(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr new file mode 100644 index 0000000000..27847841dc --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr @@ -0,0 +1,5 @@ +error: ink! constructors must have no `self` receiver + --> $DIR/constructor-self-receiver-01.rs:10:28 + | +10 | pub fn constructor(&self) -> Self { + | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.rs new file mode 100644 index 0000000000..8e9701c69d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor(&mut self) -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr new file mode 100644 index 0000000000..30dc058141 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr @@ -0,0 +1,5 @@ +error: ink! constructors must have no `self` receiver + --> $DIR/constructor-self-receiver-02.rs:10:28 + | +10 | pub fn constructor(&mut self) -> Self { + | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.rs new file mode 100644 index 0000000000..1f7dd5890b --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor(this: &Self) -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr new file mode 100644 index 0000000000..644f4b384c --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr @@ -0,0 +1,18 @@ +error[E0411]: cannot find type `Self` in this scope + --> $DIR/constructor-self-receiver-03.rs:10:35 + | +10 | pub fn constructor(this: &Self) -> Self { + | ^^^^ `Self` is only available in impls, traits, and type definitions + +error[E0106]: missing lifetime specifier + --> $DIR/constructor-self-receiver-03.rs:10:34 + | +10 | pub fn constructor(this: &Self) -> Self { + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +10 ~ pub fn constructor(this: &'a Self) -> Self { +11 | Self {} +12 ~ }<'a> + | diff --git a/crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.rs similarity index 54% rename from crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.rs rename to crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.rs index eb82fee6e5..794be48114 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-01-constructor-self-mut.rs +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.rs @@ -1,18 +1,18 @@ use ink_lang as ink; #[ink::contract] -mod noop { +mod contract { #[ink(storage)] - pub struct Noop {} + pub struct Contract {} - impl Noop { + impl Contract { #[ink(constructor)] - pub fn self_mut_arg(&mut self) -> Self { + pub fn constructor(self) -> Self { Self {} } #[ink(message)] - pub fn noop(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr new file mode 100644 index 0000000000..31cb2f18d5 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr @@ -0,0 +1,5 @@ +error: ink! constructors must have no `self` receiver + --> $DIR/constructor-self-receiver-04.rs:10:28 + | +10 | pub fn constructor(self) -> Self { + | ^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.rs b/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.rs new file mode 100644 index 0000000000..c5c770520c --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub unsafe fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr new file mode 100644 index 0000000000..f46e07c71d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr @@ -0,0 +1,5 @@ +error: ink! constructors must not be unsafe + --> $DIR/constructor-unsafe.rs:10:13 + | +10 | pub unsafe fn constructor() -> Self { + | ^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.rs b/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.rs new file mode 100644 index 0000000000..4e126ecda3 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.rs @@ -0,0 +1,23 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event)] + #[ink(storage)] + pub struct Event {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr b/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr new file mode 100644 index 0000000000..1292e5f32b --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr @@ -0,0 +1,5 @@ +error: encountered conflicting ink! attribute argument + --> $DIR/event-conflicting-storage.rs:9:11 + | +9 | #[ink(storage)] + | ^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs new file mode 100644 index 0000000000..b21cbf0eec --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs @@ -0,0 +1,31 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } + + pub struct NonContract {} + + impl NonContract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr new file mode 100644 index 0000000000..24c5eb2abd --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr @@ -0,0 +1,12 @@ +error: encountered ink! messages with overlapping selectors (= [2E, 78, 36, CC]) +hint: use #[ink(selector = S:u32)] on the callable or #[ink(namespace = N:string)] on the implementation block to disambiguate overlapping selectors. + --> $DIR/impl-block-for-non-storage-01.rs:27:9 + | +27 | pub fn message(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: first ink! message with overlapping selector here + --> $DIR/impl-block-for-non-storage-01.rs:15:9 + | +15 | pub fn message(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.rs new file mode 100644 index 0000000000..779a431bb1 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.rs @@ -0,0 +1,24 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } + + pub struct NonContract {} + + #[ink(impl)] + impl NonContract {} +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr new file mode 100644 index 0000000000..08e93322ed --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr @@ -0,0 +1,15 @@ +error[E0271]: type mismatch resolving `::This == Contract` + --> $DIR/impl-block-for-non-storage-02.rs:21:10 + | +21 | impl NonContract {} + | ^^^^^^^^^^^ expected struct `Contract`, found struct `NonContract` + | +note: required by a bound in `contract::_::_::{closure#0}::assert_type_eq_all` + --> $DIR/impl-block-for-non-storage-02.rs:21:10 + | +21 | impl NonContract {} + | ^^^^^^^^^^^ + | | + | required by a bound in this + | required by this bound in `contract::_::_::{closure#0}::assert_type_eq_all` + = note: this error originates in the macro `::ink_lang::static_assertions::assert_type_eq_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs similarity index 77% rename from crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs rename to crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs index 21d08c2d3d..1151ef70f1 100644 --- a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.rs +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs @@ -1,12 +1,12 @@ use ink_lang as ink; #[ink::contract] -mod invalid_namespace_identifier { +mod contract { #[ink(storage)] - pub struct MyStorage {} + pub struct Contract {} #[ink(namespace = "::invalid_identifier")] - impl MyStorage { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr similarity index 74% rename from crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr rename to crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr index 8e3bacd08e..62c3572774 100644 --- a/crates/lang/macro/tests/ui/contract/fail/N-01-namespace-invalid-identifier.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr @@ -1,5 +1,5 @@ error: encountered invalid Rust identifier for namespace argument - --> $DIR/N-01-namespace-invalid-identifier.rs:8:23 + --> $DIR/impl-block-namespace-invalid-identifier.rs:8:23 | 8 | #[ink(namespace = "::invalid_identifier")] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs similarity index 76% rename from crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.rs rename to crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs index 60871df1e5..4a4decd71f 100644 --- a/crates/lang/macro/tests/ui/contract/fail/N-02-namespace-invalid-type.rs +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs @@ -1,12 +1,12 @@ use ink_lang as ink; #[ink::contract] -mod invalid_namespace_identifier { +mod contract { #[ink(storage)] - pub struct MyStorage {} + pub struct Contract {} #[ink(namespace = true)] - impl MyStorage { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr new file mode 100644 index 0000000000..f8f1be3916 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr @@ -0,0 +1,5 @@ +error: expected string type for `namespace` argument, e.g. #[ink(namespace = "hello")] + --> $DIR/impl-block-namespace-invalid-type.rs:8:11 + | +8 | #[ink(namespace = true)] + | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs similarity index 75% rename from crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.rs rename to crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs index a4af79c249..94bbf98b5b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.rs +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs @@ -1,12 +1,12 @@ use ink_lang as ink; #[ink::contract] -mod invalid_namespace_identifier { +mod contract { #[ink(storage)] - pub struct MyStorage {} + pub struct Contract {} #[ink(namespace)] - impl MyStorage { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr similarity index 75% rename from crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.stderr rename to crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr index e5298677d2..414c502fc7 100644 --- a/crates/lang/macro/tests/ui/contract/fail/N-03-namespace-missing-argument.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr @@ -1,5 +1,5 @@ error: encountered #[ink(namespace)] that is missing its string parameter. Did you mean #[ink(namespace = name: str)] ? - --> $DIR/N-03-namespace-missing-argument.rs:8:11 + --> $DIR/impl-block-namespace-missing-argument.rs:8:11 | 8 | #[ink(namespace)] | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.rs b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.rs rename to crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr similarity index 93% rename from crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr rename to crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr index 50797d22e1..82a13d95aa 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-07-message-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/M-07-message-input-non-codec.rs:18:31 + --> $DIR/message-input-non-codec.rs:18:31 | 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` @@ -12,7 +12,7 @@ note: required by a bound in `DispatchInput` | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/M-07-message-input-non-codec.rs:18:9 + --> $DIR/message-input-non-codec.rs:18:9 | 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` @@ -25,7 +25,7 @@ note: required by a bound in `parity_scale_codec::Decode::decode` | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/M-07-message-input-non-codec.rs:3:1 + --> $DIR/message-input-non-codec.rs:3:1 | 3 | #[ink::contract] | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` @@ -37,7 +37,7 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied - --> $DIR/M-07-message-input-non-codec.rs:18:9 + --> $DIR/message-input-non-codec.rs:18:9 | 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds diff --git a/crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.rs b/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.rs similarity index 60% rename from crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.rs rename to crates/lang/macro/tests/ui/contract/fail/message-input-pattern.rs index d60402a0b6..20d3863ead 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-02-message-missing-self-arg.rs +++ b/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.rs @@ -1,18 +1,18 @@ use ink_lang as ink; #[ink::contract] -mod missing_message_self_arg { +mod contract { #[ink(storage)] - pub struct MissingMessageSelfArg {} + pub struct Contract {} - impl MissingMessage { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} } #[ink(message)] - pub fn missing_self_arg() {} + pub fn message(&self, (_a, _b): (i32, i32)) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr b/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr new file mode 100644 index 0000000000..c12c1703c8 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr @@ -0,0 +1,5 @@ +error: ink! message arguments must have an identifier + --> $DIR/message-input-pattern.rs:15:31 + | +15 | pub fn message(&self, (_a, _b): (i32, i32)) {} + | ^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.rs rename to crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr similarity index 93% rename from crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr rename to crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr index 1f5f2cc433..e04cfba18f 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-04-message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/M-04-message-returns-non-codec.rs:18:34 + --> $DIR/message-returns-non-codec.rs:18:34 | 18 | pub fn message(&self) -> NonCodecType { | ^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` @@ -12,7 +12,7 @@ note: required by a bound in `DispatchOutput` | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/M-04-message-returns-non-codec.rs:18:9 + --> $DIR/message-returns-non-codec.rs:18:9 | 18 | / pub fn message(&self) -> NonCodecType { 19 | | NonCodecType @@ -27,7 +27,7 @@ note: required by a bound in `execute_message` | ^^^^^^^^^^^^^ required by this bound in `execute_message` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied - --> $DIR/M-04-message-returns-non-codec.rs:18:9 + --> $DIR/message-returns-non-codec.rs:18:9 | 6 | pub struct NonCodecType; | ------------------------ doesn't satisfy `NonCodecType: parity_scale_codec::Decode` diff --git a/crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.rs b/crates/lang/macro/tests/ui/contract/fail/message-returns-self.rs similarity index 72% rename from crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.rs rename to crates/lang/macro/tests/ui/contract/fail/message-returns-self.rs index 5361751ef3..a5f04da785 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.rs +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-self.rs @@ -1,11 +1,11 @@ use ink_lang as ink; #[ink::contract] -mod message_returns_self { +mod contract { #[ink(storage)] - pub struct MessageReturnsSelf {} + pub struct Contract {} - impl MessageReturnsSelf { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.stderr b/crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr similarity index 76% rename from crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.stderr rename to crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr index 1ce8a7adc7..3d3381238b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-03-message-returns-self.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr @@ -1,5 +1,5 @@ error: ink! messages must not return `Self` - --> $DIR/M-03-message-returns-self.rs:15:39 + --> $DIR/message-returns-self.rs:15:39 | 15 | pub fn returns_self(&self) -> Self {} | ^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.rs b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.rs similarity index 60% rename from crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.rs rename to crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.rs index ef0c35fefe..405486ce24 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.rs +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.rs @@ -1,18 +1,18 @@ use ink_lang as ink; #[ink::contract] -mod message_invalid_selector { +mod contract { #[ink(storage)] - pub struct MessageInvalidSelector {} + pub struct Contract {} - impl MessageInvalidSelector { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} } #[ink(message, selector = "0xC0DECAFE")] - pub fn invalid_selector(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.stderr b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr similarity index 83% rename from crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.stderr rename to crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr index ef29bddacc..60c05f90c5 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-05-message-invalid-selector.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr @@ -1,5 +1,5 @@ error: #[ink(selector = ..)] attributes with string inputs are deprecated. use an integer instead, e.g. #[ink(selector = 1)] or #[ink(selector = 0xC0DECAFE)]. - --> $DIR/M-05-message-invalid-selector.rs:14:24 + --> $DIR/message-selector-invalid-type-01.rs:14:24 | 14 | #[ink(message, selector = "0xC0DECAFE")] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-06-message-invalid-selector-type.rs b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.rs similarity index 59% rename from crates/lang/macro/tests/ui/contract/fail/M-06-message-invalid-selector-type.rs rename to crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.rs index 88348aa471..2c9c8a3dc5 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-06-message-invalid-selector-type.rs +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.rs @@ -1,18 +1,18 @@ use ink_lang as ink; #[ink::contract] -mod message_invalid_selector { +mod contract { #[ink(storage)] - pub struct MessageInvalidSelector {} + pub struct Contract {} - impl MessageInvalidSelector { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} } #[ink(message, selector = true)] - pub fn invalid_selector(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/M-06-message-invalid-selector-type.stderr b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr similarity index 77% rename from crates/lang/macro/tests/ui/contract/fail/M-06-message-invalid-selector-type.stderr rename to crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr index 45844a68a6..260667e14a 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-06-message-invalid-selector-type.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr @@ -1,5 +1,5 @@ error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE] - --> $DIR/M-06-message-invalid-selector-type.rs:14:24 + --> $DIR/message-selector-invalid-type-02.rs:14:24 | 14 | #[ink(message, selector = true)] | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.rs b/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.rs new file mode 100644 index 0000000000..e7c9697ae8 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message, selector)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr new file mode 100644 index 0000000000..5214ea4b75 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr @@ -0,0 +1,5 @@ +error: encountered #[ink(selector)] that is missing its u32 parameter. Did you mean #[ink(selector = value: u32)] ? + --> $DIR/message-selector-missing-arg.rs:14:24 + | +14 | #[ink(message, selector)] + | ^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.rs b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.rs new file mode 100644 index 0000000000..518f66e75b --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(this: &Self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr new file mode 100644 index 0000000000..352752bb69 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr @@ -0,0 +1,5 @@ +error: ink! messages must have `&self` or `&mut self` receiver + --> $DIR/message-self-receiver-invalid-01.rs:15:24 + | +15 | pub fn message(this: &Self) {} + | ^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.rs b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.rs new file mode 100644 index 0000000000..94ec0c3fb5 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(this: &mut Self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr new file mode 100644 index 0000000000..6643bf87a7 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr @@ -0,0 +1,5 @@ +error: ink! messages must have `&self` or `&mut self` receiver + --> $DIR/message-self-receiver-invalid-02.rs:15:24 + | +15 | pub fn message(this: &mut Self) {} + | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.rs b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.rs new file mode 100644 index 0000000000..c30aa771cc --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr new file mode 100644 index 0000000000..54b17afa2d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr @@ -0,0 +1,5 @@ +error: ink! messages must have `&self` or `&mut self` receiver + --> $DIR/message-self-receiver-invalid-03.rs:15:24 + | +15 | pub fn message(self) {} + | ^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.rs b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.rs new file mode 100644 index 0000000000..552c91c143 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.rs @@ -0,0 +1,19 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message() {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr new file mode 100644 index 0000000000..882afcf4cb --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr @@ -0,0 +1,6 @@ +error: ink! messages must have `&self` or `&mut self` receiver + --> $DIR/message-self-receiver-missing.rs:14:9 + | +14 | / #[ink(message)] +15 | | pub fn message() {} + | |___________________________^ diff --git a/crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs b/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.rs similarity index 65% rename from crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs rename to crates/lang/macro/tests/ui/contract/fail/message-unknown-property.rs index 22b188429a..e8e51eb8e4 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-10-method-unknown-ink-marker.rs +++ b/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.rs @@ -1,21 +1,19 @@ use ink_lang as ink; #[ink::contract] -mod unknown_method_ink_marker { +mod contract { #[ink(storage)] - pub struct UnknownMethodInkMarker {} + pub struct Contract {} - impl UnknownMethodInkMarker { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} } #[ink(message)] - pub fn message(&self) {} - #[ink(unknown_marker)] - pub fn method(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr b/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr new file mode 100644 index 0000000000..dc04994ebc --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr @@ -0,0 +1,5 @@ +error: unknown ink! attribute (path) + --> $DIR/message-unknown-property.rs:15:15 + | +15 | #[ink(unknown_marker)] + | ^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.rs b/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.rs similarity index 53% rename from crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.rs rename to crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.rs index 89d09bce04..5d7148422f 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.rs +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.rs @@ -1,13 +1,13 @@ use ink_lang as ink; #[ink::contract] -mod noop { +mod contact { #[ink(storage)] - pub struct Noop {} + pub struct Contract {} - impl Noop { + impl Contract { #[ink(message)] - pub fn noop(&self) {} + pub fn message(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr similarity index 52% rename from crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.stderr rename to crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr index ddcd3c1b98..bd8a62c5cb 100644 --- a/crates/lang/macro/tests/ui/contract/fail/C-04-missing-constructor.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr @@ -1,9 +1,9 @@ error: missing ink! constructor - --> $DIR/C-04-missing-constructor.rs:4:1 + --> $DIR/module-missing-constructor.rs:4:1 | -4 | / mod noop { +4 | / mod contact { 5 | | #[ink(storage)] -6 | | pub struct Noop {} +6 | | pub struct Contract {} 7 | | ... | 11 | | } diff --git a/crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.rs b/crates/lang/macro/tests/ui/contract/fail/module-missing-message.rs similarity index 68% rename from crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.rs rename to crates/lang/macro/tests/ui/contract/fail/module-missing-message.rs index 2a3d5f0b2a..6c0ad2a14e 100644 --- a/crates/lang/macro/tests/ui/contract/fail/M-01-missing-message.rs +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-message.rs @@ -1,11 +1,11 @@ use ink_lang as ink; #[ink::contract] -mod missing_message { +mod contract { #[ink(storage)] - pub struct MissingMessage {} + pub struct Contract {} - impl MissingMessage { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr b/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr new file mode 100644 index 0000000000..55307a51f6 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr @@ -0,0 +1,11 @@ +error: missing ink! message + --> $DIR/module-missing-message.rs:4:1 + | +4 | / mod contract { +5 | | #[ink(storage)] +6 | | pub struct Contract {} +7 | | +... | +13 | | } +14 | | } + | |_^ diff --git a/crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.rs b/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.rs similarity index 54% rename from crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.rs rename to crates/lang/macro/tests/ui/contract/fail/module-missing-storage.rs index b951ed06f6..02f0990249 100644 --- a/crates/lang/macro/tests/ui/contract/fail/S-01-missing-storage-struct.rs +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.rs @@ -1,11 +1,11 @@ use ink_lang as ink; #[ink::contract] -mod missing_storage_struct { - // We are missing the #[ink(storage)] attribute here - pub struct MissingStorageStruct {} +mod contract { + // #[ink(storage)] + pub struct Contract {} - impl MissingStorageStruct { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr b/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr new file mode 100644 index 0000000000..0b1ba684b6 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr @@ -0,0 +1,11 @@ +error: missing ink! storage struct + --> $DIR/module-missing-storage.rs:4:1 + | +4 | / mod contract { +5 | | // #[ink(storage)] +6 | | pub struct Contract {} +7 | | +... | +14 | | } +15 | | } + | |_^ diff --git a/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.rs b/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.rs new file mode 100644 index 0000000000..4a5f2ad816 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.rs @@ -0,0 +1,32 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } + + #[ink(storage)] + pub struct Contract2 {} + + impl Contract2 { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr b/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr new file mode 100644 index 0000000000..4876a882a0 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr @@ -0,0 +1,23 @@ +error: encountered multiple ink! storage structs, expected exactly one + --> $DIR/module-multiple-storages.rs:4:1 + | +4 | / mod contract { +5 | | #[ink(storage)] +6 | | pub struct Contract {} +7 | | +... | +29 | | } +30 | | } + | |_^ + +error: ink! storage struct here + --> $DIR/module-multiple-storages.rs:6:5 + | +6 | pub struct Contract {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: ink! storage struct here + --> $DIR/module-multiple-storages.rs:19:5 + | +19 | pub struct Contract2 {} + | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.rs b/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.rs new file mode 100644 index 0000000000..61416bf877 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.rs @@ -0,0 +1,25 @@ +use ink_lang as ink; + +#[ink::contract] +mod __ink_contract { + #[ink(storage)] + pub struct __ink_Contract {} + + const __ink_CONST: () = (); + static __ink_STATIC: () = (); + type __ink_Type = (); + + impl __ink_Contract { + #[ink(constructor)] + pub fn __ink_constructor(__ink_input: __ink_Type) -> Self { + Self {} + } + + #[ink(message)] + pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { + let __ink_first = (); + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr b/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr new file mode 100644 index 0000000000..2bd2d0b8b1 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr @@ -0,0 +1,83 @@ +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:4:5 + | +4 | mod __ink_contract { + | ^^^^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:6:16 + | +6 | pub struct __ink_Contract {} + | ^^^^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:8:11 + | +8 | const __ink_CONST: () = (); + | ^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:9:12 + | +9 | static __ink_STATIC: () = (); + | ^^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:10:10 + | +10 | type __ink_Type = (); + | ^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:12:10 + | +12 | impl __ink_Contract { + | ^^^^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:14:16 + | +14 | pub fn __ink_constructor(__ink_input: __ink_Type) -> Self { + | ^^^^^^^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:14:34 + | +14 | pub fn __ink_constructor(__ink_input: __ink_Type) -> Self { + | ^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:14:47 + | +14 | pub fn __ink_constructor(__ink_input: __ink_Type) -> Self { + | ^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:19:16 + | +19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { + | ^^^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:19:37 + | +19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { + | ^^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:19:50 + | +19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { + | ^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:19:65 + | +19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { + | ^^^^^^^^^^ + +error: encountered invalid identifier starting with __ink_ + --> $DIR/module-use-forbidden-idents.rs:20:17 + | +20 | let __ink_first = (); + | ^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.rs b/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.rs new file mode 100644 index 0000000000..af8635e42c --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.rs @@ -0,0 +1,20 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + #[ink(event)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr b/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr new file mode 100644 index 0000000000..ac89d8f635 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr @@ -0,0 +1,5 @@ +error: encountered conflicting ink! attribute argument + --> $DIR/storage-conflicting-event.rs:6:11 + | +6 | #[ink(event)] + | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.rs b/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.rs similarity index 64% rename from crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.rs rename to crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.rs index 8816f81729..748544af78 100644 --- a/crates/lang/macro/tests/ui/contract/fail/S-03-struct-unknown-ink-marker.rs +++ b/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.rs @@ -1,14 +1,12 @@ use ink_lang as ink; #[ink::contract] -mod unknown_ink_marker_on_struct { +mod contract { #[ink(storage)] - pub struct UnknownInkMarkerOnStruct {} - #[ink(unknown_or_unsupported)] - pub struct HasUnknownMarker {} + pub struct Contract {} - impl UnknownInkMarkerOnStruct { + impl Contract { #[ink(constructor)] pub fn constructor() -> Self { Self {} diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr new file mode 100644 index 0000000000..ceb8cea190 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr @@ -0,0 +1,5 @@ +error: unknown ink! attribute (path) + --> $DIR/storage-unknown-marker.rs:6:11 + | +6 | #[ink(unknown_or_unsupported)] + | ^^^^^^^^^^^^^^^^^^^^^^ From 74ec85eabed27cf601fce8aa908ddb170e647da2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 13:20:45 +0200 Subject: [PATCH 351/493] fix some UI tests --- ...mplicit-prelude.rs => no-implicit-prelude.rs.disabled} | 0 .../ui/trait_def/fail/config_namespace_invalid_2.stderr | 8 +++----- .../ui/trait_def/fail/message_selector_invalid_2.stderr | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) rename crates/lang/macro/tests/ui/contract/pass/{no-implicit-prelude.rs => no-implicit-prelude.rs.disabled} (100%) diff --git a/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs b/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs.disabled similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs rename to crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs.disabled diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr index 02cdce5c1a..d6bea37617 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr @@ -1,7 +1,5 @@ -error: expected `=` - --> $DIR/config_namespace_invalid_2.rs:3:1 +error: ink! config options require an argument separated by '=' + --> $DIR/config_namespace_invalid_2.rs:3:25 | 3 | #[ink::trait_definition(namespace)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the attribute macro `ink::trait_definition` (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr index 113f484512..aef66faddf 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr @@ -1,4 +1,4 @@ -error: unknown ink! attribute (path) +error: encountered #[ink(selector)] that is missing its u32 parameter. Did you mean #[ink(selector = value: u32)] ? --> $DIR/message_selector_invalid_2.rs:5:20 | 5 | #[ink(message, selector)] From 651d0b9dc9c8cf9683c5f2444c6909799af160c9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 13:21:05 +0200 Subject: [PATCH 352/493] use wildcards in UI test inclusion pattern --- crates/lang/macro/tests/compile_tests.rs | 148 ++--------------------- 1 file changed, 9 insertions(+), 139 deletions(-) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index f625e0d24c..18a09af9b8 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -16,155 +16,25 @@ fn contract() { let t = trybuild::TestCases::new(); - // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs"); - // t.pass("tests/ui/contract/pass/minimal-contract.rs"); - // t.pass("tests/ui/contract/pass/constructor-many-inputs.rs"); - // t.pass("tests/ui/contract/pass/constructor-selector.rs"); - // t.pass("tests/ui/contract/pass/message-many-inputs.rs"); - // t.pass("tests/ui/contract/pass/message-many-outputs.rs"); - // t.pass("tests/ui/contract/pass/message-payable.rs"); - // t.pass("tests/ui/contract/pass/message-selector.rs"); - // t.pass("tests/ui/contract/pass/storage-single-field.rs"); - // t.pass("tests/ui/contract/pass/storage-many-fields.rs"); - // t.pass("tests/ui/contract/pass/storage-packed-fields.rs"); - // t.pass("tests/ui/contract/pass/storage-with-derives.rs"); - // t.pass("tests/ui/contract/pass/event-single-definition.rs"); - // t.pass("tests/ui/contract/pass/event-many-definitions.rs"); - // t.pass("tests/ui/contract/pass/event-topics.rs"); - // t.pass("tests/ui/contract/pass/event-anonymous.rs"); - // t.pass("tests/ui/contract/pass/event-config-more-topics.rs"); - // t.pass("tests/ui/contract/pass/impl-alias-storage.rs"); - // t.pass("tests/ui/contract/pass/impl-with-property.rs"); - // t.pass("tests/ui/contract/pass/impl-block-namespace.rs"); - // t.pass("tests/ui/contract/pass/config-compile-as-dependency-true.rs"); - // t.pass("tests/ui/contract/pass/config-compile-as-dependency-false.rs"); - // t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs"); - // t.pass("tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs"); - // t.pass("tests/ui/contract/pass/config-custom-env.rs"); - // t.pass("tests/ui/contract/pass/env-access.rs"); - // t.pass("tests/ui/contract/pass/module-non-ink-items.rs"); - // t.pass("tests/ui/contract/pass/module-env-types.rs"); - // t.pass("tests/ui/contract/pass/trait-message-payable-guard.rs"); - // t.pass("tests/ui/contract/pass/trait-message-selector-guard.rs"); - // t.pass("tests/ui/contract/pass/example-flipper-works.rs"); - // t.pass("tests/ui/contract/pass/example-incrementer-works.rs"); - // t.pass("tests/ui/contract/pass/example-trait-flipper-works.rs"); - // t.pass("tests/ui/contract/pass/example-trait-incrementer-works.rs"); - // t.pass("tests/ui/contract/pass/example-erc20-works.rs"); - // t.pass("tests/ui/contract/pass/example-erc721-works.rs"); + // Optional test cases: + // + // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs.disabled"); - t.compile_fail( - "tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs", - ); - t.compile_fail( - "tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs", - ); - t.compile_fail( - "tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs", - ); - t.compile_fail( - "tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs", - ); - t.compile_fail( - "tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs", - ); - t.compile_fail("tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs"); - - t.compile_fail("tests/ui/contract/fail/module-use-forbidden-idents.rs"); - t.compile_fail("tests/ui/contract/fail/module-missing-constructor.rs"); - t.compile_fail("tests/ui/contract/fail/module-missing-message.rs"); - t.compile_fail("tests/ui/contract/fail/module-missing-storage.rs"); - t.compile_fail("tests/ui/contract/fail/module-multiple-storages.rs"); - - t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-01.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-02.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-03.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-self-receiver-04.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-missing-return.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-async.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-unsafe.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-const.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-abi.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-payable.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-input-non-codec.rs"); - t.compile_fail("tests/ui/contract/fail/constructor-input-pattern.rs"); - - t.compile_fail("tests/ui/contract/fail/message-input-pattern.rs"); - t.compile_fail("tests/ui/contract/fail/message-self-receiver-missing.rs"); - t.compile_fail("tests/ui/contract/fail/message-self-receiver-invalid-01.rs"); - t.compile_fail("tests/ui/contract/fail/message-self-receiver-invalid-02.rs"); - t.compile_fail("tests/ui/contract/fail/message-self-receiver-invalid-03.rs"); - t.compile_fail("tests/ui/contract/fail/message-returns-self.rs"); - t.compile_fail("tests/ui/contract/fail/message-returns-non-codec.rs"); - t.compile_fail("tests/ui/contract/fail/message-selector-invalid-type-01.rs"); - t.compile_fail("tests/ui/contract/fail/message-selector-invalid-type-02.rs"); - t.compile_fail("tests/ui/contract/fail/message-selector-missing-arg.rs"); - t.compile_fail("tests/ui/contract/fail/message-input-non-codec.rs"); - t.compile_fail("tests/ui/contract/fail/message-unknown-property.rs"); - - t.compile_fail("tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs"); - t.compile_fail("tests/ui/contract/fail/impl-block-namespace-invalid-type.rs"); - t.compile_fail("tests/ui/contract/fail/impl-block-namespace-missing-argument.rs"); - t.compile_fail("tests/ui/contract/fail/impl-block-for-non-storage-01.rs"); - t.compile_fail("tests/ui/contract/fail/impl-block-for-non-storage-02.rs"); - - t.compile_fail("tests/ui/contract/fail/trait-message-selector-mismatch.rs"); - t.compile_fail("tests/ui/contract/fail/trait-message-payable-mismatch.rs"); - t.compile_fail("tests/ui/contract/fail/trait-impl-namespace-invalid.rs"); - - t.compile_fail("tests/ui/contract/fail/storage-unknown-marker.rs"); - t.compile_fail("tests/ui/contract/fail/storage-conflicting-event.rs"); - - t.compile_fail("tests/ui/contract/fail/event-conflicting-storage.rs"); + t.pass("tests/ui/contract/pass/*.rs"); + t.compile_fail("tests/ui/contract/fail/*.rs"); } #[test] fn chain_extension() { let t = trybuild::TestCases::new(); + t.pass("tests/ui/chain_extension/E-01-simple.rs"); } #[test] fn trait_definition() { let t = trybuild::TestCases::new(); - t.pass("tests/ui/trait_def/pass/simple_definition.rs"); - // t.pass("tests/ui/trait_def/pass/no-implicit-prelude.rs"); - t.pass("tests/ui/trait_def/pass/many_inputs.rs"); - t.pass("tests/ui/trait_def/pass/many_outputs.rs"); - t.pass("tests/ui/trait_def/pass/payable_message.rs"); - t.pass("tests/ui/trait_def/pass/custom_selector.rs"); - t.pass("tests/ui/trait_def/pass/with_namespace.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_empty.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_constructor.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_rust_method.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_assoc_type.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_assoc_const.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_non_pub.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_unsafe.rs"); - t.compile_fail("tests/ui/trait_def/fail/definition_generic.rs"); - t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_3.rs"); - t.compile_fail("tests/ui/trait_def/fail/config_namespace_invalid_4.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_selector_overlap.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_selector_invalid_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_selector_invalid_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_payable_invalid_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_payable_invalid_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_receiver_missing.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_1.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_2.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_receiver_invalid_3.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_async_invalid.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_const_invalid.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_unsafe_invalid.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_abi_invalid.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_generic_invalid.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_input_pattern_invalid.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_input_non_codec.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_output_non_codec.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_default_impl.rs"); - t.compile_fail("tests/ui/trait_def/fail/message_constructor_conflict.rs"); + + t.pass("tests/ui/trait_def/pass/*.rs"); + t.compile_fail("tests/ui/trait_def/fail/*.rs"); } From 34e1daea784d061888673674707ee33ddaa013c9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 14:10:11 +0200 Subject: [PATCH 353/493] rename InkTraitDefinitionRegistry -> TraitDefinitionRegistry --- crates/lang/codegen/src/generator/arg_list.rs | 2 +- .../codegen/src/generator/as_dependency/call_builder.rs | 2 +- .../codegen/src/generator/as_dependency/contract_ref.rs | 2 +- crates/lang/codegen/src/generator/dispatch.rs | 6 +++--- crates/lang/codegen/src/generator/item_impls.rs | 6 +++--- crates/lang/codegen/src/generator/metadata.rs | 4 ++-- .../codegen/src/generator/trait_def/trait_registry.rs | 4 ++-- .../lang/macro/tests/ui/trait_def/pass/payable_message.rs | 8 ++++---- crates/lang/src/lib.rs | 2 +- crates/lang/src/traits.rs | 6 +++--- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 3722baa361..363fbb17e5 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -96,7 +96,7 @@ where pub fn generate_unique_trait_id(span: Span, trait_path: &syn::Path) -> TokenStream2 { quote_spanned!(span=> { - <<::ink_lang::InkTraitDefinitionRegistry + <<::ink_lang::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitUniqueId>::ID } diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 55f0839def..a193253ebf 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -246,7 +246,7 @@ impl CallBuilder<'_> { .map(|message| self.generate_ink_trait_impl_for_message(trait_path, message)); quote_spanned!(span=> impl #trait_path for #cb_ident { - type __ink_TraitInfo = <::ink_lang::InkTraitDefinitionRegistry + type __ink_TraitInfo = <::ink_lang::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #( #messages )* diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 21608f23c5..2acd7fe7be 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -210,7 +210,7 @@ impl ContractRef<'_> { #( #attrs )* impl #trait_path for #forwarder_ident { #[doc(hidden)] - type __ink_TraitInfo = <::ink_lang::InkTraitDefinitionRegistry + type __ink_TraitInfo = <::ink_lang::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #messages diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 8443dd0dad..0625be8a97 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -177,7 +177,7 @@ impl Dispatch<'_> { quote_spanned!(span=> { ::core::primitive::u32::from_be_bytes( - <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR ) @@ -343,12 +343,12 @@ impl Dispatch<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let payable = quote! {{ - <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR }}; diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 9db3bad39b..bf8466b41c 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -84,7 +84,7 @@ impl ItemImpls<'_> { let message_guard_payable = message.is_payable().then(|| { quote_spanned!(message_span=> const _: ::ink_lang::TraitMessagePayable<{ - <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#message_local_id>>::PAYABLE }> = ::ink_lang::TraitMessagePayable::; @@ -95,7 +95,7 @@ impl ItemImpls<'_> { quote_spanned!(message_span=> const _: ::ink_lang::TraitMessageSelector<{ ::core::primitive::u32::from_be_bytes( - <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#message_local_id>>::SELECTOR ) @@ -212,7 +212,7 @@ impl ItemImpls<'_> { quote_spanned!(span => #( #attrs )* impl #trait_path for #self_type { - type __ink_TraitInfo = <::ink_lang::InkTraitDefinitionRegistry + type __ink_TraitInfo = <::ink_lang::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #( #messages )* diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index e63b135fa8..db5e6ecb3e 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -267,12 +267,12 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let is_payable = quote! {{ - <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink_lang::InkTraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR }}; diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 8cc00afc2d..1e59d5c82a 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -94,7 +94,7 @@ impl TraitRegistry<'_> { /// call forwarder and call builder types as such for the ink! trait. /// /// This is done by the fact that ink! implements all ink! traits by the - /// [`ink_lang::InkTraitDefinitionRegistry`] type and uses the `__ink_ConcreteImplementer` + /// [`ink_lang::TraitDefinitionRegistry`] type and uses the `__ink_ConcreteImplementer` /// associated type to refer back to the actual call forwarder and call builder types. fn generate_registry_impl(&self) -> TokenStream2 { let span = self.span(); @@ -102,7 +102,7 @@ impl TraitRegistry<'_> { let trait_info_ident = self.trait_def.trait_info_ident(); let messages = self.generate_registry_messages(); quote_spanned!(span=> - impl #name for ::ink_lang::InkTraitDefinitionRegistry + impl #name for ::ink_lang::TraitDefinitionRegistry where E: ::ink_env::Environment, { diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 5c2e1ded4d..9996e29f29 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -45,23 +45,23 @@ fn main() { // println!("local_id(\"unpayable\") = {:X}", local_id("unpayable")); // println!("local_id(\"unpayable_mut\") = {:X}", local_id("unpayable_mut")); assert!( - <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, ); assert!( - <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, ); assert_eq!( - <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, false ); assert_eq!( - <<::ink_lang::InkTraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, false diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index ee2edf40a0..d2bf79b2d2 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -73,7 +73,7 @@ pub use self::{ DispatchableMessageInfo, ExecuteDispatchable, ImpliesReturn, - InkTraitDefinitionRegistry, + TraitDefinitionRegistry, TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 36cfff8f17..83398adcb9 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -96,18 +96,18 @@ pub trait True {} /// that ink! can serialize and deserialize as if it was an `AccountId` and call /// ink! messages on it according to the ink! trait definition interface. #[doc(hidden)] -pub struct InkTraitDefinitionRegistry { +pub struct TraitDefinitionRegistry { marker: PhantomData E>, } -impl crate::ContractEnv for InkTraitDefinitionRegistry +impl crate::ContractEnv for TraitDefinitionRegistry where E: ink_env::Environment, { type Env = E; } -unsafe impl TraitImplementer for InkTraitDefinitionRegistry {} +unsafe impl TraitImplementer for TraitDefinitionRegistry {} /// The global call builder type for an ink! trait definition. pub trait TraitCallBuilder { From 2b7b5289d9d01881cb2efaf26fd81aa9116eb7b4 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 14:17:29 +0200 Subject: [PATCH 354/493] fix some tests --- crates/lang/ir/src/ir/attrs.rs | 2 +- crates/lang/ir/src/ir/chain_extension.rs | 2 +- crates/lang/ir/src/ir/item_impl/callable.rs | 2 +- crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 83262d7c25..2e9e465d8c 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -1261,7 +1261,7 @@ mod tests { }, Err( "encountered #[ink(extension)] that is missing its N parameter. \ - Did you mean #[ink(extension = N: u32)] ?", + Did you mean #[ink(extension = id: u32)] ?", ), ); } diff --git a/crates/lang/ir/src/ir/chain_extension.rs b/crates/lang/ir/src/ir/chain_extension.rs index 90f83c5a59..8936fec3fb 100644 --- a/crates/lang/ir/src/ir/chain_extension.rs +++ b/crates/lang/ir/src/ir/chain_extension.rs @@ -783,7 +783,7 @@ mod tests { } ); assert_ink_chain_extension_eq_err!( - error: "encountered #[ink(extension)] that is missing its N parameter. Did you mean #[ink(extension = N: u32)] ?", + error: "encountered #[ink(extension)] that is missing its N parameter. Did you mean #[ink(extension = id: u32)] ?", pub trait MyChainExtension { #[ink(extension)] fn has_self_receiver(); diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index c8a7eaa2e8..7782d4d06d 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -406,7 +406,7 @@ pub(super) fn ensure_callable_invariants( if method_item.sig.abi.is_some() { return Err(format_err_spanned!( method_item.sig.abi, - "ink! {}s must have explicit ABI", + "ink! {}s must not have explicit ABI", kind, )) } diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr index a9f81663fd..1ad99ce813 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr @@ -1,4 +1,4 @@ -error: ink! constructors must have explicit ABI +error: ink! constructors must not have explicit ABI --> $DIR/constructor-abi.rs:10:13 | 10 | pub extern "C" fn constructor() -> Self { From 402921956282aa9539b3b1ba97f272d9fef5df17 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 14:48:11 +0200 Subject: [PATCH 355/493] apply rustfmt --- crates/lang/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index d2bf79b2d2..6ec52a9164 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -73,10 +73,10 @@ pub use self::{ DispatchableMessageInfo, ExecuteDispatchable, ImpliesReturn, - TraitDefinitionRegistry, TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, + TraitDefinitionRegistry, TraitImplementer, TraitMessageInfo, TraitMessagePayable, From dfd6404edc3a831c0482461e70b6056c3d943a6c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 14:49:00 +0200 Subject: [PATCH 356/493] rename ink_lang::type_check module to codegen and make it a folder --- .../lang/codegen/src/generator/item_impls.rs | 12 ++++----- .../codegen/src/generator/trait_def/mod.rs | 8 +++--- .../fail/constructor-input-non-codec.stderr | 2 +- .../fail/message-input-non-codec.stderr | 2 +- .../fail/message-returns-non-codec.stderr | 2 +- .../fail/message_input_non_codec.stderr | 2 +- .../fail/message_output_non_codec.stderr | 2 +- .../{type_check.rs => codegen/dispatch.rs} | 7 ----- crates/lang/src/codegen/mod.rs | 27 +++++++++++++++++++ crates/lang/src/lib.rs | 2 +- 10 files changed, 43 insertions(+), 23 deletions(-) rename crates/lang/src/{type_check.rs => codegen/dispatch.rs} (88%) create mode 100644 crates/lang/src/codegen/mod.rs diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index bf8466b41c..5de147d7ee 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -127,8 +127,8 @@ impl ItemImpls<'_> { let span = input.span(); let input_type = &*input.ty; quote_spanned!(span=> - let _: () = ::ink_lang::type_check::identity_type::< - ::ink_lang::type_check::DispatchInput<#input_type> + let _: () = ::ink_lang::codegen::identity_type::< + ::ink_lang::codegen::DispatchInput<#input_type> >(); ) }); @@ -148,16 +148,16 @@ impl ItemImpls<'_> { let span = input.span(); let input_type = &*input.ty; quote_spanned!(span=> - let _: () = ::ink_lang::type_check::identity_type::< - ::ink_lang::type_check::DispatchInput<#input_type> + let _: () = ::ink_lang::codegen::identity_type::< + ::ink_lang::codegen::DispatchInput<#input_type> >(); ) }); let message_output = message.output().map(|output_type| { let span = output_type.span(); quote_spanned!(span=> - let _: () = ::ink_lang::type_check::identity_type::< - ::ink_lang::type_check::DispatchOutput<#output_type> + let _: () = ::ink_lang::codegen::identity_type::< + ::ink_lang::codegen::DispatchOutput<#output_type> >(); ) }); diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index c238e3d92a..748d8efbe7 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -95,16 +95,16 @@ impl TraitDefinition<'_> { let input_span = input.span(); let input_type = &*input.ty; quote_spanned!(input_span=> - let _: () = ::ink_lang::type_check::identity_type::< - ::ink_lang::type_check::DispatchInput<#input_type> + let _: () = ::ink_lang::codegen::identity_type::< + ::ink_lang::codegen::DispatchInput<#input_type> >(); ) }); let message_output = message.output().map(|output_type| { let output_span = output_type.span(); quote_spanned!(output_span=> - let _: () = ::ink_lang::type_check::identity_type::< - ::ink_lang::type_check::DispatchOutput<#output_type> + let _: () = ::ink_lang::codegen::identity_type::< + ::ink_lang::codegen::DispatchOutput<#output_type> >(); ) }); diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr index 5cd8bece1d..1b869b39a7 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr @@ -6,7 +6,7 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $DIR/type_check.rs:23:8 + --> $DIR/dispatch.rs:23:8 | 23 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr index 82a13d95aa..8a9b301001 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr @@ -6,7 +6,7 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $DIR/type_check.rs:23:8 + --> $DIR/dispatch.rs:23:8 | 23 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr index e04cfba18f..0be536724d 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -6,7 +6,7 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `DispatchOutput` - --> $DIR/type_check.rs:33:8 + --> $DIR/dispatch.rs:33:8 | 33 | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr index 08f790909f..34de11ac4b 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr @@ -6,7 +6,7 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodec` note: required by a bound in `DispatchInput` - --> $DIR/type_check.rs:23:8 + --> $DIR/dispatch.rs:23:8 | 23 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr index ad73fae70f..651bae52d0 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr @@ -6,7 +6,7 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodec` note: required by a bound in `DispatchOutput` - --> $DIR/type_check.rs:33:8 + --> $DIR/dispatch.rs:33:8 | 33 | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` diff --git a/crates/lang/src/type_check.rs b/crates/lang/src/codegen/dispatch.rs similarity index 88% rename from crates/lang/src/type_check.rs rename to crates/lang/src/codegen/dispatch.rs index f564b79da7..ec4e79d8e2 100644 --- a/crates/lang/src/type_check.rs +++ b/crates/lang/src/codegen/dispatch.rs @@ -31,10 +31,3 @@ where pub struct DispatchOutput(T) where T: scale::Encode + 'static; - -/// Does nothing but takes a generic type as input. -/// -/// # Note -/// -/// Used to trigger some compile time checks. -pub const fn identity_type() {} diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs new file mode 100644 index 0000000000..e03057d519 --- /dev/null +++ b/crates/lang/src/codegen/mod.rs @@ -0,0 +1,27 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod dispatch; + +pub use self::dispatch::{ + DispatchInput, + DispatchOutput, +}; + +/// Takes a generic type as input and does nothing. +/// +/// # Note +/// +/// Used to trigger some compile time checks. +pub const fn identity_type() {} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 6ec52a9164..272c07f773 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -19,7 +19,7 @@ mod result_info; #[doc(hidden)] -pub mod type_check; +pub mod codegen; mod chain_extension; mod contract_ref; From dcad58818c249621cecdc22a412e110b0d2fd08e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 15:15:22 +0200 Subject: [PATCH 357/493] rename BaseEvent trait to ContractEventBase --- crates/lang/codegen/src/generator/events.rs | 6 +++--- crates/lang/src/events.rs | 6 +++--- crates/lang/src/lib.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index 245adf9485..1be0a271dc 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -62,11 +62,11 @@ impl<'a> Events<'a> { impl<'a> ::ink_lang::EmitEvent<#storage_ident> for ::ink_lang::EnvAccess<'a, Environment> { fn emit_event(self, event: E) where - E: Into<<#storage_ident as ::ink_lang::BaseEvent>::Type>, + E: Into<<#storage_ident as ::ink_lang::ContractEventBase>::Type>, { ::ink_env::emit_event::< Environment, - <#storage_ident as ::ink_lang::BaseEvent>::Type + <#storage_ident as ::ink_lang::ContractEventBase>::Type >(event.into()); } } @@ -94,7 +94,7 @@ impl<'a> Events<'a> { } const _: () = { - impl ::ink_lang::BaseEvent for #storage_ident { + impl ::ink_lang::ContractEventBase for #storage_ident { type Type = #base_event_ident; } }; diff --git a/crates/lang/src/events.rs b/crates/lang/src/events.rs index 69ede2223f..6780f96e19 100644 --- a/crates/lang/src/events.rs +++ b/crates/lang/src/events.rs @@ -22,18 +22,18 @@ /// define this trait here. pub trait EmitEvent where - C: BaseEvent, + C: ContractEventBase, { /// Emits an event that can be trivially converted into the base event. fn emit_event(self, event: E) where - E: Into<::Type>; + E: Into<::Type>; } /// Defines a base event type for the contract. /// /// This is usually the event enum that comprises all defined event types. -pub trait BaseEvent { +pub trait ContractEventBase { /// The generated base event enum. type Type; } diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 272c07f773..e02cd07bfb 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -60,7 +60,7 @@ pub use self::{ DispatchResult, }, events::{ - BaseEvent, + ContractEventBase, EmitEvent, }, traits::{ From c601e2397b8c51c3fa8657f156db566b23846b47 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 15:35:35 +0200 Subject: [PATCH 358/493] replace static_assertions usage by custom solution This leads to fewer dependencies and also to better error messages. --- .../lang/codegen/src/generator/item_impls.rs | 6 +-- .../fail/impl-block-for-non-storage-01.rs | 8 ++-- .../fail/impl-block-for-non-storage-01.stderr | 38 ++++++++++++++----- .../fail/impl-block-for-non-storage-02.stderr | 13 ++----- crates/lang/src/codegen/is_same_type.rs | 32 ++++++++++++++++ crates/lang/src/codegen/mod.rs | 2 + 6 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 crates/lang/src/codegen/is_same_type.rs diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 5de147d7ee..fde294e0ef 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -288,10 +288,8 @@ impl ItemImpls<'_> { let span = self_ty.span(); let storage_ident = self.contract.module().storage().ident(); quote_spanned!(span => - ::ink_lang::static_assertions::assert_type_eq_all!( - #self_ty, - #storage_ident, - ); + const _: ::ink_lang::codegen::IsSameType<#storage_ident> = + ::ink_lang::codegen::IsSameType::<#self_ty>::new(); ) } diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs index b21cbf0eec..1e648da4fa 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs @@ -7,24 +7,24 @@ mod contract { impl Contract { #[ink(constructor)] - pub fn constructor() -> Self { + pub fn constructor_1() -> Self { Self {} } #[ink(message)] - pub fn message(&self) {} + pub fn message_1(&self) {} } pub struct NonContract {} impl NonContract { #[ink(constructor)] - pub fn constructor() -> Self { + pub fn constructor_2() -> Self { Self {} } #[ink(message)] - pub fn message(&self) {} + pub fn message_2(&self) {} } } diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr index 24c5eb2abd..49bb9207d6 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr @@ -1,12 +1,32 @@ -error: encountered ink! messages with overlapping selectors (= [2E, 78, 36, CC]) -hint: use #[ink(selector = S:u32)] on the callable or #[ink(namespace = N:string)] on the implementation block to disambiguate overlapping selectors. - --> $DIR/impl-block-for-non-storage-01.rs:27:9 +error[E0308]: mismatched types + --> $DIR/impl-block-for-non-storage-01.rs:20:10 | -27 | pub fn message(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ +20 | impl NonContract { + | ^^^^^^^^^^^ expected struct `Contract`, found struct `NonContract` + | + = note: expected struct `IsSameType` + found struct `IsSameType` + +error[E0599]: no function or associated item named `constructor_2` found for struct `Contract` in the current scope + --> $DIR/impl-block-for-non-storage-01.rs:22:16 + | +6 | pub struct Contract {} + | ------------------- function or associated item `constructor_2` not found for this +... +22 | pub fn constructor_2() -> Self { + | ^^^^^^^^^^^^^ + | | + | function or associated item not found in `Contract` + | help: there is an associated function with a similar name: `constructor_1` -error: first ink! message with overlapping selector here - --> $DIR/impl-block-for-non-storage-01.rs:15:9 +error[E0599]: no function or associated item named `message_2` found for struct `Contract` in the current scope + --> $DIR/impl-block-for-non-storage-01.rs:27:16 | -15 | pub fn message(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ +6 | pub struct Contract {} + | ------------------- function or associated item `message_2` not found for this +... +27 | pub fn message_2(&self) {} + | ^^^^^^^^^ + | | + | function or associated item not found in `Contract` + | help: there is an associated function with a similar name: `message_1` diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr index 08e93322ed..71c7b05ee9 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr @@ -1,15 +1,8 @@ -error[E0271]: type mismatch resolving `::This == Contract` +error[E0308]: mismatched types --> $DIR/impl-block-for-non-storage-02.rs:21:10 | 21 | impl NonContract {} | ^^^^^^^^^^^ expected struct `Contract`, found struct `NonContract` | -note: required by a bound in `contract::_::_::{closure#0}::assert_type_eq_all` - --> $DIR/impl-block-for-non-storage-02.rs:21:10 - | -21 | impl NonContract {} - | ^^^^^^^^^^^ - | | - | required by a bound in this - | required by this bound in `contract::_::_::{closure#0}::assert_type_eq_all` - = note: this error originates in the macro `::ink_lang::static_assertions::assert_type_eq_all` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: expected struct `IsSameType` + found struct `IsSameType` diff --git a/crates/lang/src/codegen/is_same_type.rs b/crates/lang/src/codegen/is_same_type.rs new file mode 100644 index 0000000000..e98342d2b4 --- /dev/null +++ b/crates/lang/src/codegen/is_same_type.rs @@ -0,0 +1,32 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::marker::PhantomData; + +/// Used to check if `T` is allowed as ink! input parameter type. +/// +/// # Note +/// +/// An ink! input parameter type must implement [`scale::Decode`] +/// and must have a `'static` lifetime. +pub struct IsSameType { + _marker: PhantomData, +} + +impl IsSameType { + /// Creates a new const instance. + pub const fn new() -> Self { + Self { _marker: PhantomData } + } +} diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index e03057d519..132f84ac8f 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -13,11 +13,13 @@ // limitations under the License. mod dispatch; +mod is_same_type; pub use self::dispatch::{ DispatchInput, DispatchOutput, }; +pub use self::is_same_type::IsSameType; /// Takes a generic type as input and does nothing. /// From da4ccb2039ad54eb07c301d2a97831461f0dd7fa Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 15:46:32 +0200 Subject: [PATCH 359/493] remove static_assertions dependency from ink_lang --- crates/lang/Cargo.toml | 1 - crates/lang/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index 0a91a88fd4..d08a489342 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -24,7 +24,6 @@ ink_lang_macro = { version = "3.0.0-rc5", path = "macro", default-features = fal scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive", "full"] } derive_more = { version = "0.99", default-features = false, features = ["from"] } -static_assertions = "1.1" [dev-dependencies] # required for the doctest of `env_access::EnvAccess::instantiate_contract` diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index e02cd07bfb..e3504b82ba 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -86,7 +86,6 @@ pub use self::{ True, }, }; -pub use ::static_assertions; pub use ink_lang_macro::{ chain_extension, contract, From c081d4db5f10d5bea1d1ab36553d76bf44dc04f2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 15:55:37 +0200 Subject: [PATCH 360/493] apply rustfmt --- crates/lang/src/codegen/is_same_type.rs | 4 +++- crates/lang/src/codegen/mod.rs | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/lang/src/codegen/is_same_type.rs b/crates/lang/src/codegen/is_same_type.rs index e98342d2b4..e15130be13 100644 --- a/crates/lang/src/codegen/is_same_type.rs +++ b/crates/lang/src/codegen/is_same_type.rs @@ -27,6 +27,8 @@ pub struct IsSameType { impl IsSameType { /// Creates a new const instance. pub const fn new() -> Self { - Self { _marker: PhantomData } + Self { + _marker: PhantomData, + } } } diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 132f84ac8f..7de0947ad6 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -15,11 +15,13 @@ mod dispatch; mod is_same_type; -pub use self::dispatch::{ - DispatchInput, - DispatchOutput, +pub use self::{ + dispatch::{ + DispatchInput, + DispatchOutput, + }, + is_same_type::IsSameType, }; -pub use self::is_same_type::IsSameType; /// Takes a generic type as input and does nothing. /// From 871a0bdce706ce580e80f67316c6cc066cff7a05 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 16:03:46 +0200 Subject: [PATCH 361/493] fix some examples --- examples/erc20/lib.rs | 4 ++-- examples/trait-erc20/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/erc20/lib.rs b/examples/erc20/lib.rs index 755be1d6bb..5071496901 100644 --- a/examples/erc20/lib.rs +++ b/examples/erc20/lib.rs @@ -198,7 +198,7 @@ mod erc20 { /// Imports all the definitions from the outer scope so we can use them here. use super::*; - type Event = ::Type; + type Event = ::Type; use ink_lang as ink; @@ -518,7 +518,7 @@ mod erc20 { use ink_env::Clear; use ink_lang as ink; - type Event = ::Type; + type Event = ::Type; fn assert_transfer_event( event: &ink_env::test::EmittedEvent, diff --git a/examples/trait-erc20/lib.rs b/examples/trait-erc20/lib.rs index 7cc023aee1..1bdf9b1abb 100644 --- a/examples/trait-erc20/lib.rs +++ b/examples/trait-erc20/lib.rs @@ -255,7 +255,7 @@ mod erc20 { }; use ink_lang as ink; - type Event = ::Type; + type Event = ::Type; fn assert_transfer_event( event: &ink_env::test::EmittedEvent, From 2ae42590610ac43a287433986707bed0d96824c0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 16:16:11 +0200 Subject: [PATCH 362/493] move TraitMessage{Payable,Selector} into codegen submodule --- .../lang/codegen/src/generator/item_impls.rs | 8 ++--- crates/lang/src/codegen/mod.rs | 5 +++ crates/lang/src/codegen/trait_message.rs | 33 +++++++++++++++++++ crates/lang/src/lib.rs | 2 -- crates/lang/src/traits.rs | 20 ----------- 5 files changed, 42 insertions(+), 26 deletions(-) create mode 100644 crates/lang/src/codegen/trait_message.rs diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index fde294e0ef..f9cc232f7b 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -83,23 +83,23 @@ impl ItemImpls<'_> { let message_local_id = message.local_id().hex_padded_suffixed(); let message_guard_payable = message.is_payable().then(|| { quote_spanned!(message_span=> - const _: ::ink_lang::TraitMessagePayable<{ + const _: ::ink_lang::codegen::TraitMessagePayable<{ <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#message_local_id>>::PAYABLE - }> = ::ink_lang::TraitMessagePayable::; + }> = ::ink_lang::codegen::TraitMessagePayable::; ) }); let message_guard_selector = message.user_provided_selector().map(|selector| { let given_selector = selector.into_be_u32().hex_padded_suffixed(); quote_spanned!(message_span=> - const _: ::ink_lang::TraitMessageSelector<{ + const _: ::ink_lang::codegen::TraitMessageSelector<{ ::core::primitive::u32::from_be_bytes( <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#message_local_id>>::SELECTOR ) - }> = ::ink_lang::TraitMessageSelector::<#given_selector>; + }> = ::ink_lang::codegen::TraitMessageSelector::<#given_selector>; ) }); quote_spanned!(message_span=> diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 7de0947ad6..29dccfdcdd 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -14,6 +14,7 @@ mod dispatch; mod is_same_type; +mod trait_message; pub use self::{ dispatch::{ @@ -21,6 +22,10 @@ pub use self::{ DispatchOutput, }, is_same_type::IsSameType, + trait_message::{ + TraitMessagePayable, + TraitMessageSelector, + }, }; /// Takes a generic type as input and does nothing. diff --git a/crates/lang/src/codegen/trait_message.rs b/crates/lang/src/codegen/trait_message.rs new file mode 100644 index 0000000000..c541e3122b --- /dev/null +++ b/crates/lang/src/codegen/trait_message.rs @@ -0,0 +1,33 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Used as `payable` property guard for ink! trait messages. +/// +/// # Note +/// +/// When an ink! trait message is annotated with `#[ink(payable)]` +/// a compile time check is generated by ink! to guard that the +/// payability of the ink! trait message matches the payability of +/// the same ink! message as defined by the ink! trait message. +pub struct TraitMessagePayable; + +/// Used as `selector` property guard for ink! trait messages. +/// +/// # Note +/// +/// When an ink! trait message is annotated with `#[ink(selector = ..)]` +/// a compile time check is generated by ink! to guard that the +/// selector of the ink! trait message matches the selector of +/// the same ink! message as defined by the ink! trait message. +pub struct TraitMessageSelector; diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index e3504b82ba..f6cd907e5b 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -79,8 +79,6 @@ pub use self::{ TraitDefinitionRegistry, TraitImplementer, TraitMessageInfo, - TraitMessagePayable, - TraitMessageSelector, TraitModulePath, TraitUniqueId, True, diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 83398adcb9..2d11cc3137 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -343,23 +343,3 @@ pub trait ExecuteDispatchable { /// Executes the ink! smart contract message or constructor. fn execute_dispatchable(self) -> Result<(), DispatchError>; } - -/// Used as `payable` property guard for ink! trait messages. -/// -/// # Note -/// -/// When an ink! trait message is annotated with `#[ink(payable)]` -/// a compile time check is generated by ink! to guard that the -/// payability of the ink! trait message matches the payability of -/// the same ink! message as defined by the ink! trait message. -pub struct TraitMessagePayable; - -/// Used as `selector` property guard for ink! trait messages. -/// -/// # Note -/// -/// When an ink! trait message is annotated with `#[ink(selector = ..)]` -/// a compile time check is generated by ink! to guard that the -/// selector of the ink! trait message matches the selector of -/// the same ink! message as defined by the ink! trait message. -pub struct TraitMessageSelector; From 0115078c72ef40cd121a6d524c5377e541888497 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 16:29:40 +0200 Subject: [PATCH 363/493] remove superflous True trait from ink_lang --- crates/lang/codegen/src/generator/events.rs | 1 - crates/lang/src/lib.rs | 1 - crates/lang/src/traits.rs | 4 ---- 3 files changed, 6 deletions(-) diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index 1be0a271dc..a0e3688305 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -150,7 +150,6 @@ impl<'a> Events<'a> { #[allow(non_camel_case_types)] pub enum __ink_CheckSatisfied {} pub enum EventTopicsWithinBounds {} - impl ::ink_lang::True for __ink_CheckSatisfied {} #[doc(hidden)] pub trait CompliesWithTopicLimit {} impl CompliesWithTopicLimit for __ink_CheckSatisfied {} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index f6cd907e5b..fe8a81405b 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -81,7 +81,6 @@ pub use self::{ TraitMessageInfo, TraitModulePath, TraitUniqueId, - True, }, }; pub use ink_lang_macro::{ diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 2d11cc3137..dc7061e2f3 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -65,10 +65,6 @@ where { } -/// Indicates that some compile time expression is expected to be `true`. -#[doc(hidden)] -pub trait True {} - /// This type is known to ink! to implement all defined ink! trait definitions. /// This property can be guaranteed by `#[ink::trait_definition]` procedural macro. /// From 5b7b0203b287e98d29e490d75271c9f96296fea1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 17:01:58 +0200 Subject: [PATCH 364/493] add ExecuteMessageConfig --- crates/lang/codegen/src/generator/dispatch.rs | 10 +-- .../fail/message-returns-non-codec.stderr | 4 +- crates/lang/src/dispatcher.rs | 62 ++++++++++++------- crates/lang/src/lib.rs | 4 +- 4 files changed, 47 insertions(+), 33 deletions(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 0625be8a97..f9bca0bdcd 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -663,10 +663,12 @@ impl Dispatch<'_> { #message_output, _ >( - ::ink_lang::AcceptsPayments(#accepts_payment), - ::ink_lang::MutatesStorage(#mutates_storage), - ::ink_lang::MayRevert(#may_revert), - ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), + ::ink_lang::ExecuteMessageConfig { + payable: #accepts_payment, + mutates: #mutates_storage, + may_revert: #may_revert, + dynamic_storage_alloc: #is_dynamic_storage_allocation_enabled, + }, move |storage: &mut #storage_ident| { #message_callable(storage, input) } ) } diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr index 0be536724d..65df172332 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -21,9 +21,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `execute_message` - --> $DIR/dispatcher.rs:126:13 + --> $DIR/dispatcher.rs:140:13 | -126 | Output: scale::Encode + 'static, +140 | Output: scale::Encode + 'static, | ^^^^^^^^^^^^^ required by this bound in `execute_message` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/dispatcher.rs index 4f9c2597f2..356ba6b0d6 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/dispatcher.rs @@ -39,21 +39,6 @@ use ink_storage::{ #[doc(hidden)] pub type Result = core::result::Result; -/// Yields `true` if the message accepts payments. -#[derive(Copy, Clone)] -#[doc(hidden)] -pub struct AcceptsPayments(pub bool); - -/// Yields `true` if the associated ink! message may mutate contract storage. -#[derive(Copy, Clone)] -#[doc(hidden)] -pub struct MutatesStorage(pub bool); - -/// Yields `true` if the associated ink! message may revert execution. -#[derive(Copy, Clone)] -#[doc(hidden)] -pub struct MayRevert(pub bool); - /// Yields `true` if the dynamic storage allocator is enabled for the given call. #[derive(Copy, Clone)] #[doc(hidden)] @@ -106,6 +91,38 @@ where Ok(()) } +/// Configuration for execution of ink! messages. +#[derive(Debug, Copy, Clone)] +pub struct ExecuteMessageConfig { + /// Yields `true` if the ink! message accepts payment. + /// + /// # Note + /// + /// If no ink! message within the same ink! smart contract + /// is payable then this flag will be `true` since the check + /// then is moved before the message dispatch as an optimization. + pub payable: bool, + /// Yields `true` if the ink! message might mutate contract storage. + /// + /// # Note + /// + /// This is usually true for `&mut self` ink! messages. + pub mutates: bool, + /// Yields `true` if the ink! message execution might revert execution. + /// + /// # Note + /// + /// In ink! this is usually `true` for root ink! smart contracts and + /// `false` for dependency ink! smart contracts. + pub may_revert: bool, + /// Yields `true` if the dynamic storage allocator has been enabled. + /// + /// # Note + /// + /// Authors can enable it via `#[ink::contract(dynamic_storage_allocator = true)]`. + pub dynamic_storage_alloc: bool, +} + /// Executes the given `&mut self` message closure. /// /// # Note @@ -115,10 +132,7 @@ where #[inline] #[doc(hidden)] pub fn execute_message( - AcceptsPayments(accepts_payments): AcceptsPayments, - MutatesStorage(mutates_storage): MutatesStorage, - MayRevert(may_revert): MayRevert, - EnablesDynamicStorageAllocator(enables_dynamic_storage_allocator): EnablesDynamicStorageAllocator, + config: ExecuteMessageConfig, f: F, ) -> Result<()> where @@ -126,24 +140,24 @@ where Output: scale::Encode + 'static, F: FnOnce(&mut Storage) -> Output, { - if !accepts_payments { + if !config.payable { deny_payment::<::Env>()?; } - if enables_dynamic_storage_allocator { + if config.dynamic_storage_alloc { alloc::initialize(ContractPhase::Call); } let root_key = Key::from([0x00; 32]); let mut storage = ManuallyDrop::new(pull_spread_root::(&root_key)); let result = f(&mut storage); - if mutates_storage { + if config.mutates { push_spread_root::(&storage, &root_key); } - if enables_dynamic_storage_allocator { + if config.dynamic_storage_alloc { alloc::finalize(); } if TypeId::of::() != TypeId::of::<()>() { let revert_state = - may_revert && is_result_type!(Output) && is_result_err!(&result); + config.may_revert && is_result_type!(Output) && is_result_err!(&result); ink_env::return_value::( ReturnFlags::default().set_reverted(revert_state), &result, diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index fe8a81405b..9a8ca8d7ba 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -44,10 +44,8 @@ pub use self::{ deny_payment, execute_constructor, execute_message, - AcceptsPayments, EnablesDynamicStorageAllocator, - MayRevert, - MutatesStorage, + ExecuteMessageConfig, }, env_access::{ ContractEnv, From 41299a26b9cdad989b26420812161e23c92702d5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 17:19:06 +0200 Subject: [PATCH 365/493] refactor ink_lang dispatch definitions --- crates/lang/codegen/src/generator/dispatch.rs | 12 ++++--- .../dispatch/execution.rs} | 35 +++++++++---------- crates/lang/src/codegen/dispatch/mod.rs | 30 ++++++++++++++++ .../{dispatch.rs => dispatch/type_check.rs} | 0 crates/lang/src/codegen/mod.rs | 5 +++ crates/lang/src/error.rs | 5 --- crates/lang/src/lib.rs | 13 +------ 7 files changed, 60 insertions(+), 40 deletions(-) rename crates/lang/src/{dispatcher.rs => codegen/dispatch/execution.rs} (87%) create mode 100644 crates/lang/src/codegen/dispatch/mod.rs rename crates/lang/src/codegen/{dispatch.rs => dispatch/type_check.rs} (100%) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index f9bca0bdcd..5ae914b3c5 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -415,7 +415,7 @@ impl Dispatch<'_> { #[no_mangle] fn call() { if !#any_message_accept_payment { - ::ink_lang::deny_payment::<<#storage_ident as ::ink_lang::ContractEnv>::Env>() + ::ink_lang::codegen::deny_payment::<<#storage_ident as ::ink_lang::ContractEnv>::Env>() .unwrap_or_else(|error| ::core::panic!("{}", error)) } ::ink_env::decode_input::< @@ -510,8 +510,10 @@ impl Dispatch<'_> { .is_dynamic_storage_allocator_enabled(); quote_spanned!(constructor_span=> Self::#constructor_ident(input) => { - ::ink_lang::execute_constructor::<#storage_ident, _>( - ::ink_lang::EnablesDynamicStorageAllocator(#is_dynamic_storage_allocation_enabled), + ::ink_lang::codegen::execute_constructor::<#storage_ident, _>( + ::ink_lang::codegen::ExecuteConstructorConfig { + dynamic_storage_alloc: #is_dynamic_storage_allocation_enabled + }, move || { #constructor_callable(input) } ) } @@ -658,12 +660,12 @@ impl Dispatch<'_> { .is_dynamic_storage_allocator_enabled(); quote_spanned!(message_span=> Self::#message_ident(input) => { - ::ink_lang::execute_message::< + ::ink_lang::codegen::execute_message::< #storage_ident, #message_output, _ >( - ::ink_lang::ExecuteMessageConfig { + ::ink_lang::codegen::ExecuteMessageConfig { payable: #accepts_payment, mutates: #mutates_storage, may_revert: #may_revert, diff --git a/crates/lang/src/dispatcher.rs b/crates/lang/src/codegen/dispatch/execution.rs similarity index 87% rename from crates/lang/src/dispatcher.rs rename to crates/lang/src/codegen/dispatch/execution.rs index 356ba6b0d6..4739625c1a 100644 --- a/crates/lang/src/dispatcher.rs +++ b/crates/lang/src/codegen/dispatch/execution.rs @@ -35,23 +35,13 @@ use ink_storage::{ }, }; -/// Results of message handling operations. -#[doc(hidden)] -pub type Result = core::result::Result; - -/// Yields `true` if the dynamic storage allocator is enabled for the given call. -#[derive(Copy, Clone)] -#[doc(hidden)] -pub struct EnablesDynamicStorageAllocator(pub bool); - /// Returns `Ok` if the caller did not transfer additional value to the callee. /// /// # Errors /// /// If the caller did send some amount of transferred value to the callee. #[inline] -#[doc(hidden)] -pub fn deny_payment() -> Result<()> +pub fn deny_payment() -> Result<(), DispatchError> where E: Environment, { @@ -63,6 +53,17 @@ where Ok(()) } +/// Configuration for execution of ink! constructor. +#[derive(Debug, Copy, Clone)] +pub struct ExecuteConstructorConfig { + /// Yields `true` if the dynamic storage allocator has been enabled. + /// + /// # Note + /// + /// Authors can enable it via `#[ink::contract(dynamic_storage_allocator = true)]`. + pub dynamic_storage_alloc: bool, +} + /// Executes the given ink! constructor. /// /// # Note @@ -70,22 +71,21 @@ where /// The closure is supposed to already contain all the arguments that the real /// constructor message requires and forwards them. #[inline] -#[doc(hidden)] pub fn execute_constructor( - EnablesDynamicStorageAllocator(uses_dynamic_storage_allocator): EnablesDynamicStorageAllocator, + config: ExecuteConstructorConfig, f: F, -) -> Result<()> +) -> Result<(), DispatchError> where S: ink_storage::traits::SpreadLayout, F: FnOnce() -> S, { - if uses_dynamic_storage_allocator { + if config.dynamic_storage_alloc { alloc::initialize(ContractPhase::Deploy); } let storage = ManuallyDrop::new(f()); let root_key = Key::from([0x00; 32]); push_spread_root::(&storage, &root_key); - if uses_dynamic_storage_allocator { + if config.dynamic_storage_alloc { alloc::finalize(); } Ok(()) @@ -130,11 +130,10 @@ pub struct ExecuteMessageConfig { /// The closure is supposed to already contain all the arguments that the real /// message requires and forwards them. #[inline] -#[doc(hidden)] pub fn execute_message( config: ExecuteMessageConfig, f: F, -) -> Result<()> +) -> Result<(), DispatchError> where Storage: SpreadLayout + ContractEnv, Output: scale::Encode + 'static, diff --git a/crates/lang/src/codegen/dispatch/mod.rs b/crates/lang/src/codegen/dispatch/mod.rs new file mode 100644 index 0000000000..ea8bdc37fd --- /dev/null +++ b/crates/lang/src/codegen/dispatch/mod.rs @@ -0,0 +1,30 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod execution; +mod type_check; + +pub use self::{ + execution::{ + deny_payment, + execute_constructor, + execute_message, + ExecuteConstructorConfig, + ExecuteMessageConfig, + }, + type_check::{ + DispatchInput, + DispatchOutput, + }, +}; diff --git a/crates/lang/src/codegen/dispatch.rs b/crates/lang/src/codegen/dispatch/type_check.rs similarity index 100% rename from crates/lang/src/codegen/dispatch.rs rename to crates/lang/src/codegen/dispatch/type_check.rs diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 29dccfdcdd..7444b041ff 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -18,8 +18,13 @@ mod trait_message; pub use self::{ dispatch::{ + deny_payment, + execute_constructor, + execute_message, DispatchInput, DispatchOutput, + ExecuteConstructorConfig, + ExecuteMessageConfig, }, is_same_type::IsSameType, trait_message::{ diff --git a/crates/lang/src/error.rs b/crates/lang/src/error.rs index 6f336c382d..5d73dc48fc 100644 --- a/crates/lang/src/error.rs +++ b/crates/lang/src/error.rs @@ -14,13 +14,8 @@ use derive_more::Display; -/// A dispatch result. -#[doc(hidden)] -pub type DispatchResult = core::result::Result<(), DispatchError>; - /// A dispatch error. #[derive(Debug, Copy, Clone, Display)] -#[doc(hidden)] pub enum DispatchError { #[display(fmt = "unknown selector")] UnknownSelector, diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 9a8ca8d7ba..1370cf2af9 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -23,7 +23,6 @@ pub mod codegen; mod chain_extension; mod contract_ref; -mod dispatcher; mod env_access; mod error; mod events; @@ -40,23 +39,13 @@ pub use self::{ ContractReference, ToAccountId, }, - dispatcher::{ - deny_payment, - execute_constructor, - execute_message, - EnablesDynamicStorageAllocator, - ExecuteMessageConfig, - }, env_access::{ ContractEnv, Env, EnvAccess, StaticEnv, }, - error::{ - DispatchError, - DispatchResult, - }, + error::DispatchError, events::{ ContractEventBase, EmitEvent, From 852496f5e2c74f2351223af5401b81353e84e197 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 30 Sep 2021 17:28:26 +0200 Subject: [PATCH 366/493] add show-codegen-docs crate feature to ink_lang to unhide the codegen module --- crates/lang/Cargo.toml | 1 + crates/lang/src/codegen/mod.rs | 2 ++ crates/lang/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index d08a489342..dd22ef7b80 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -41,3 +41,4 @@ std = [ "ink_lang_macro/std", "scale/std", ] +show-codegen-docs = [] diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 7444b041ff..021ea9f7d9 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Definitions and facilities mainly used by the ink! codegen. + mod dispatch; mod is_same_type; mod trait_message; diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 1370cf2af9..2cbe5dd196 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -18,7 +18,7 @@ #[doc(hidden)] mod result_info; -#[doc(hidden)] +#[cfg_attr(not(feature = "show-codegen-docs"), doc(hidden))] pub mod codegen; mod chain_extension; From 1f7347fd4b673cf0ab4492398d2fabfb4a5cb7cb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 09:32:31 +0200 Subject: [PATCH 367/493] fix docs and add doc example tests to IsSameType --- crates/lang/src/codegen/is_same_type.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/lang/src/codegen/is_same_type.rs b/crates/lang/src/codegen/is_same_type.rs index e15130be13..dedfcd4bd9 100644 --- a/crates/lang/src/codegen/is_same_type.rs +++ b/crates/lang/src/codegen/is_same_type.rs @@ -14,12 +14,23 @@ use core::marker::PhantomData; -/// Used to check if `T` is allowed as ink! input parameter type. +/// Can be used to check equality of types. /// -/// # Note +/// # Example /// -/// An ink! input parameter type must implement [`scale::Decode`] -/// and must have a `'static` lifetime. +/// This code compiles: +/// +/// ``` +/// # use ink_lang::codegen::IsSameType; +/// const _: IsSameType = IsSameType::::new(); +/// ``` +/// +/// While this code does not: +/// +/// ```compile_fail +/// # use ink_lang::codegen::IsSameType; +/// const _: IsSameType = IsSameType::::new(); +/// ``` pub struct IsSameType { _marker: PhantomData, } From e6f155631745832ff8b1abc42e24f9cd5ba1cd80 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 09:32:54 +0200 Subject: [PATCH 368/493] add doc example tests to DispatchInput and DispatchOutput types --- .../lang/src/codegen/dispatch/type_check.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/crates/lang/src/codegen/dispatch/type_check.rs b/crates/lang/src/codegen/dispatch/type_check.rs index ec4e79d8e2..2f21a41899 100644 --- a/crates/lang/src/codegen/dispatch/type_check.rs +++ b/crates/lang/src/codegen/dispatch/type_check.rs @@ -18,6 +18,24 @@ /// /// An ink! input parameter type must implement [`scale::Decode`] /// and must have a `'static` lifetime. +/// +/// # Example +/// +/// This compiles since `i32` fullfills the requirements of an ink! input. +/// +/// ``` +/// # use ink_lang::codegen::DispatchInput; +/// const _: () = ink_lang::codegen::identity_type::>(); +/// ``` +/// +/// This fails to compile since `Foo` does not fullfil all requirements. +/// +/// ```compile_fail +/// # use ink_lang::codegen::DispatchInput; +/// // Foo is missing scale codec implementations. +/// struct Foo {} +/// const _: () = ink_lang::codegen::identity_type::>(); +/// ``` pub struct DispatchInput(T) where T: scale::Decode + 'static; @@ -28,6 +46,24 @@ where /// /// An ink! input parameter type must implement [`scale::Encode`] /// and must have a `'static` lifetime. +/// +/// # Example +/// +/// This compiles since `i32` fullfills the requirements of an ink! output. +/// +/// ``` +/// # use ink_lang::codegen::DispatchOutput; +/// const _: () = ink_lang::codegen::identity_type::>(); +/// ``` +/// +/// This fails to compile since `Foo` does not fullfil all requirements. +/// +/// ```compile_fail +/// # use ink_lang::codegen::DispatchOutput; +/// // Foo is missing scale codec implementations. +/// struct Foo {} +/// const _: () = ink_lang::codegen::identity_type::>(); +/// ``` pub struct DispatchOutput(T) where T: scale::Encode + 'static; From d94f06ac80e23cf30c3f6a5e5dabd2127ef50c1d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 10:17:28 +0200 Subject: [PATCH 369/493] fix spelling issues --- crates/lang/src/codegen/dispatch/type_check.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/codegen/dispatch/type_check.rs b/crates/lang/src/codegen/dispatch/type_check.rs index 2f21a41899..20198a13a6 100644 --- a/crates/lang/src/codegen/dispatch/type_check.rs +++ b/crates/lang/src/codegen/dispatch/type_check.rs @@ -21,7 +21,7 @@ /// /// # Example /// -/// This compiles since `i32` fullfills the requirements of an ink! input. +/// This compiles since `i32` fulfills the requirements of an ink! input. /// /// ``` /// # use ink_lang::codegen::DispatchInput; @@ -49,7 +49,7 @@ where /// /// # Example /// -/// This compiles since `i32` fullfills the requirements of an ink! output. +/// This compiles since `i32` fulfills the requirements of an ink! output. /// /// ``` /// # use ink_lang::codegen::DispatchOutput; From dc6e0dcb12233c5092127d16e5813a44a89bc640 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 10:21:49 +0200 Subject: [PATCH 370/493] fix trait definition UI tests --- .../tests/ui/trait_def/fail/message_input_non_codec.stderr | 4 ++-- .../tests/ui/trait_def/fail/message_output_non_codec.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr index 34de11ac4b..e0b5b92f14 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodec` note: required by a bound in `DispatchInput` - --> $DIR/dispatch.rs:23:8 + --> $DIR/type_check.rs:41:8 | -23 | T: scale::Decode + 'static; +41 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr index 651bae52d0..b89f1a353d 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodec` note: required by a bound in `DispatchOutput` - --> $DIR/dispatch.rs:33:8 + --> $DIR/type_check.rs:69:8 | -33 | T: scale::Encode + 'static; +69 | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>`, but its trait bounds were not satisfied From 5095b81d04c80e80c00063f42d7826db6b39a05a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 10:34:05 +0200 Subject: [PATCH 371/493] rename TraitImplementer -> TraitImplementedById and move into codegen module --- .../src/generator/trait_def/definition.rs | 2 +- .../src/generator/trait_def/trait_registry.rs | 4 +-- crates/lang/src/codegen/mod.rs | 2 ++ crates/lang/src/codegen/trait_def.rs | 31 +++++++++++++++++++ crates/lang/src/lib.rs | 1 - crates/lang/src/traits.rs | 12 +++---- 6 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 crates/lang/src/codegen/trait_def.rs diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 4532b51619..0b50d5648a 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -66,7 +66,7 @@ impl TraitDefinition<'_> { #[allow(non_camel_case_types)] type __ink_TraitInfo: ::ink_lang::TraitUniqueId + ::ink_lang::TraitCallForwarder - + ::ink_lang::TraitImplementer<#unique_trait_id>; + + ::ink_lang::codegen::TraitImplementedById<#unique_trait_id>; #(#messages)* } diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 1e59d5c82a..146016f249 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -208,7 +208,7 @@ impl TraitRegistry<'_> { /// Phantom type that implements the following traits for every ink! trait: /// - /// - `ink_lang::TraitImplementer` (unsafe implementation) + /// - `ink_lang::codegen::TraitImplementedById` (unsafe implementation) /// - `ink_lang::TraitUniqueId` /// - `ink_lang::TraitCallForwarder` /// @@ -229,7 +229,7 @@ impl TraitRegistry<'_> { #trait_message_info - unsafe impl ::ink_lang::TraitImplementer<#unique_id> + unsafe impl ::ink_lang::codegen::TraitImplementedById<#unique_id> for #trait_info_ident where E: ::ink_env::Environment, diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 021ea9f7d9..f4fc3576a2 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -17,8 +17,10 @@ mod dispatch; mod is_same_type; mod trait_message; +mod trait_def; pub use self::{ + trait_def::TraitImplementedById, dispatch::{ deny_payment, execute_constructor, diff --git a/crates/lang/src/codegen/trait_def.rs b/crates/lang/src/codegen/trait_def.rs new file mode 100644 index 0000000000..166f85e01d --- /dev/null +++ b/crates/lang/src/codegen/trait_def.rs @@ -0,0 +1,31 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Marker trait required by info objects of ink! trait definitions. +/// +/// - Automatically implemented for the trait info object of an ink! trait +/// definition by the `#[ink::trait_definition]` procedural macro. +/// +/// # Note +/// +/// The `GLOBAL_TRAIT_ID` is a `u32` value uniquely identifying the +/// ink! trait definition. Every implementer of an ink! trait definition +/// is required to implement this trait given the correct `GLOBAL_TRAIT_ID`. +/// +/// # Safety +/// +/// The trait is marked as `unsafe` to signal to ink! smart contract authors +/// that manually implementing an ink! trait definition is unsafe to do and +/// may potentially lead to unwanted behavior. +pub unsafe trait TraitImplementedById {} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 2cbe5dd196..8718ff17a0 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -64,7 +64,6 @@ pub use self::{ TraitCallForwarder, TraitCallForwarderFor, TraitDefinitionRegistry, - TraitImplementer, TraitMessageInfo, TraitModulePath, TraitUniqueId, diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index dc7061e2f3..b500ed97cf 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -12,7 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::DispatchError; +use crate::{ + codegen::TraitImplementedById, + DispatchError, +}; use core::marker::PhantomData; use ink_env::{ call::{ @@ -26,11 +29,6 @@ use ink_env::{ Environment, }; -/// Trait used to indicate that an ink! trait definition has been checked -/// by the `#[ink::trait_definition]` procedural macro. -#[doc(hidden)] -pub unsafe trait TraitImplementer {} - /// Trait used by `#[ink::trait_definition]` to ensure that the associated /// return type for each trait message is correct. #[doc(hidden)] @@ -103,7 +101,7 @@ where type Env = E; } -unsafe impl TraitImplementer for TraitDefinitionRegistry {} +unsafe impl TraitImplementedById for TraitDefinitionRegistry {} /// The global call builder type for an ink! trait definition. pub trait TraitCallBuilder { From 7822260a25853780f15263a21396fa9768842cbb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 10:42:46 +0200 Subject: [PATCH 372/493] apply rustfmt --- crates/lang/src/codegen/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index f4fc3576a2..88c23172b7 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -16,11 +16,10 @@ mod dispatch; mod is_same_type; -mod trait_message; mod trait_def; +mod trait_message; pub use self::{ - trait_def::TraitImplementedById, dispatch::{ deny_payment, execute_constructor, @@ -31,6 +30,7 @@ pub use self::{ ExecuteMessageConfig, }, is_same_type::IsSameType, + trait_def::TraitImplementedById, trait_message::{ TraitMessagePayable, TraitMessageSelector, From d33c0ffd455327be5c0cc8b39adf8fd264b28701 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 10:43:15 +0200 Subject: [PATCH 373/493] move ImpliesReturn to ink_lang::codegen module and improve doc comments --- .../src/generator/trait_def/definition.rs | 2 +- crates/lang/src/codegen/implies_return.rs | 66 +++++++++++++++++++ crates/lang/src/codegen/mod.rs | 2 + crates/lang/src/traits.rs | 45 ------------- 4 files changed, 69 insertions(+), 46 deletions(-) create mode 100644 crates/lang/src/codegen/implies_return.rs diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 0b50d5648a..e4dfaf4a6e 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -38,7 +38,7 @@ impl<'a> TraitDefinition<'a> { let output_ident = format_ident!("{}Output", ident.to_string().to_camel_case()); quote_spanned!(span => /// Output type of the respective trait message. - type #output_ident: ::ink_lang::ImpliesReturn<#output>; + type #output_ident: ::ink_lang::codegen::ImpliesReturn<#output>; #(#attrs)* fn #ident(#inputs) -> Self::#output_ident; diff --git a/crates/lang/src/codegen/implies_return.rs b/crates/lang/src/codegen/implies_return.rs new file mode 100644 index 0000000000..eacdbbc139 --- /dev/null +++ b/crates/lang/src/codegen/implies_return.rs @@ -0,0 +1,66 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use ink_env::{ + call::{ + utils::{ + ReturnType, + Set, + }, + CallBuilder, + ExecutionInput, + }, + Environment, +}; + +/// Trait used as bound for the outputs of ink! trait definition messages. +/// +/// # Note +/// +/// Indicates that a value of type `T` or an equivalent `CallBuilder` +/// instantiation of an ink! message returning a value of type `T` are +/// returned by the respective ink! trait message. +/// +/// The bounds are automatically generated by the `#[ink::trait_definition]` +/// procedural macro. +pub trait ImpliesReturn {} + +impl ImpliesReturn for T {} +impl ImpliesReturn + for CallBuilder< + E, + Callee, + GasCost, + TransferredValue, + Set>, + Set>, + > +where + E: Environment, +{ +} + +impl ImpliesReturn<()> + for CallBuilder< + E, + Callee, + GasCost, + TransferredValue, + Set>, + Set<()>, + > +where + E: Environment, +{ +} diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 88c23172b7..afa160e507 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -15,6 +15,7 @@ //! Definitions and facilities mainly used by the ink! codegen. mod dispatch; +mod implies_return; mod is_same_type; mod trait_def; mod trait_message; @@ -29,6 +30,7 @@ pub use self::{ ExecuteConstructorConfig, ExecuteMessageConfig, }, + implies_return::ImpliesReturn, is_same_type::IsSameType, trait_def::TraitImplementedById, trait_message::{ diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index b500ed97cf..ff5ea4771a 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -17,51 +17,6 @@ use crate::{ DispatchError, }; use core::marker::PhantomData; -use ink_env::{ - call::{ - utils::{ - ReturnType, - Set, - }, - CallBuilder, - ExecutionInput, - }, - Environment, -}; - -/// Trait used by `#[ink::trait_definition]` to ensure that the associated -/// return type for each trait message is correct. -#[doc(hidden)] -pub trait ImpliesReturn {} - -impl ImpliesReturn for T {} -impl ImpliesReturn - for CallBuilder< - E, - Callee, - GasCost, - TransferredValue, - Set>, - Set>, - > -where - E: Environment, -{ -} - -impl ImpliesReturn<()> - for CallBuilder< - E, - Callee, - GasCost, - TransferredValue, - Set>, - Set<()>, - > -where - E: Environment, -{ -} /// This type is known to ink! to implement all defined ink! trait definitions. /// This property can be guaranteed by `#[ink::trait_definition]` procedural macro. From 012e9f1bf3511939807682d88f79854e102c5f9a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 10:43:47 +0200 Subject: [PATCH 374/493] remove re-export of ImpliesReturn from ink_lang It is now exported from the ink_lang::codegen sub module. --- crates/lang/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 8718ff17a0..1ffc27dc79 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -59,7 +59,6 @@ pub use self::{ DispatchableConstructorInfo, DispatchableMessageInfo, ExecuteDispatchable, - ImpliesReturn, TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, From c650b7db3ef416f37d85851392e4bb4da9fdd0c9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 11:26:47 +0200 Subject: [PATCH 375/493] fix spelling issues --- crates/lang/src/codegen/dispatch/type_check.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/codegen/dispatch/type_check.rs b/crates/lang/src/codegen/dispatch/type_check.rs index 20198a13a6..0d86096726 100644 --- a/crates/lang/src/codegen/dispatch/type_check.rs +++ b/crates/lang/src/codegen/dispatch/type_check.rs @@ -28,7 +28,7 @@ /// const _: () = ink_lang::codegen::identity_type::>(); /// ``` /// -/// This fails to compile since `Foo` does not fullfil all requirements. +/// This fails to compile since `Foo` does not fulfill all requirements. /// /// ```compile_fail /// # use ink_lang::codegen::DispatchInput; @@ -56,7 +56,7 @@ where /// const _: () = ink_lang::codegen::identity_type::>(); /// ``` /// -/// This fails to compile since `Foo` does not fullfil all requirements. +/// This fails to compile since `Foo` does not fulfill all requirements. /// /// ```compile_fail /// # use ink_lang::codegen::DispatchOutput; From 78edcae3cf3b979d5502339250f61c0f744f47a8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 11:38:09 +0200 Subject: [PATCH 376/493] fix UI tests --- .../ui/contract/fail/constructor-input-non-codec.stderr | 4 ++-- .../tests/ui/contract/fail/message-input-non-codec.stderr | 4 ++-- .../ui/contract/fail/message-returns-non-codec.stderr | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr index 1b869b39a7..03bd3ac4e1 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $DIR/dispatch.rs:23:8 + --> $DIR/type_check.rs:41:8 | -23 | T: scale::Decode + 'static; +41 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr index 8a9b301001..7629695388 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $DIR/dispatch.rs:23:8 + --> $DIR/type_check.rs:41:8 | -23 | T: scale::Decode + 'static; +41 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr index 65df172332..bec9e51efd 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `DispatchOutput` - --> $DIR/dispatch.rs:33:8 + --> $DIR/type_check.rs:69:8 | -33 | T: scale::Encode + 'static; +69 | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied @@ -21,9 +21,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `execute_message` - --> $DIR/dispatcher.rs:140:13 + --> $DIR/execution.rs:139:13 | -140 | Output: scale::Encode + 'static, +139 | Output: scale::Encode + 'static, | ^^^^^^^^^^^^^ required by this bound in `execute_message` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied From c6562bce48eeb6ce5f5f22c0e916c591ccbfd5dd Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 11:51:55 +0200 Subject: [PATCH 377/493] move ink! trait definition codegen definitions into trait_def submodule --- crates/lang/src/codegen/mod.rs | 5 ++-- .../implemented_by.rs} | 0 crates/lang/src/codegen/trait_def/mod.rs | 24 +++++++++++++++++++ .../codegen/{ => trait_def}/trait_message.rs | 0 4 files changed, 26 insertions(+), 3 deletions(-) rename crates/lang/src/codegen/{trait_def.rs => trait_def/implemented_by.rs} (100%) create mode 100644 crates/lang/src/codegen/trait_def/mod.rs rename crates/lang/src/codegen/{ => trait_def}/trait_message.rs (100%) diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index afa160e507..54fda52fd3 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -18,7 +18,6 @@ mod dispatch; mod implies_return; mod is_same_type; mod trait_def; -mod trait_message; pub use self::{ dispatch::{ @@ -32,8 +31,8 @@ pub use self::{ }, implies_return::ImpliesReturn, is_same_type::IsSameType, - trait_def::TraitImplementedById, - trait_message::{ + trait_def::{ + TraitImplementedById, TraitMessagePayable, TraitMessageSelector, }, diff --git a/crates/lang/src/codegen/trait_def.rs b/crates/lang/src/codegen/trait_def/implemented_by.rs similarity index 100% rename from crates/lang/src/codegen/trait_def.rs rename to crates/lang/src/codegen/trait_def/implemented_by.rs diff --git a/crates/lang/src/codegen/trait_def/mod.rs b/crates/lang/src/codegen/trait_def/mod.rs new file mode 100644 index 0000000000..7f569d662f --- /dev/null +++ b/crates/lang/src/codegen/trait_def/mod.rs @@ -0,0 +1,24 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod implemented_by; +mod trait_message; + +pub use self::{ + implemented_by::TraitImplementedById, + trait_message::{ + TraitMessagePayable, + TraitMessageSelector, + }, +}; diff --git a/crates/lang/src/codegen/trait_message.rs b/crates/lang/src/codegen/trait_def/trait_message.rs similarity index 100% rename from crates/lang/src/codegen/trait_message.rs rename to crates/lang/src/codegen/trait_def/trait_message.rs From 3e1fb5445e5a1f001dd7eb0144a8763ef72bf8b1 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 11:59:42 +0200 Subject: [PATCH 378/493] move TraitDefinitionRegistry into new ink_lang::reflect module --- crates/lang/codegen/src/generator/arg_list.rs | 2 +- .../generator/as_dependency/call_builder.rs | 2 +- .../generator/as_dependency/contract_ref.rs | 2 +- crates/lang/codegen/src/generator/dispatch.rs | 6 +- .../lang/codegen/src/generator/item_impls.rs | 6 +- crates/lang/codegen/src/generator/metadata.rs | 4 +- .../src/generator/trait_def/trait_registry.rs | 2 +- .../ui/trait_def/pass/payable_message.rs | 8 +-- crates/lang/src/lib.rs | 3 +- crates/lang/src/reflect/mod.rs | 17 ++++++ crates/lang/src/reflect/trait_def/mod.rs | 17 ++++++ crates/lang/src/reflect/trait_def/registry.rs | 56 +++++++++++++++++++ crates/lang/src/traits.rs | 46 +-------------- 13 files changed, 109 insertions(+), 62 deletions(-) create mode 100644 crates/lang/src/reflect/mod.rs create mode 100644 crates/lang/src/reflect/trait_def/mod.rs create mode 100644 crates/lang/src/reflect/trait_def/registry.rs diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 363fbb17e5..4593a7e69a 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -96,7 +96,7 @@ where pub fn generate_unique_trait_id(span: Span, trait_path: &syn::Path) -> TokenStream2 { quote_spanned!(span=> { - <<::ink_lang::TraitDefinitionRegistry + <<::ink_lang::reflect::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitUniqueId>::ID } diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index a193253ebf..50ce755918 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -246,7 +246,7 @@ impl CallBuilder<'_> { .map(|message| self.generate_ink_trait_impl_for_message(trait_path, message)); quote_spanned!(span=> impl #trait_path for #cb_ident { - type __ink_TraitInfo = <::ink_lang::TraitDefinitionRegistry + type __ink_TraitInfo = <::ink_lang::reflect::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #( #messages )* diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 2acd7fe7be..8e19b3a75d 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -210,7 +210,7 @@ impl ContractRef<'_> { #( #attrs )* impl #trait_path for #forwarder_ident { #[doc(hidden)] - type __ink_TraitInfo = <::ink_lang::TraitDefinitionRegistry + type __ink_TraitInfo = <::ink_lang::reflect::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #messages diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 5ae914b3c5..afe580a05d 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -177,7 +177,7 @@ impl Dispatch<'_> { quote_spanned!(span=> { ::core::primitive::u32::from_be_bytes( - <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR ) @@ -343,12 +343,12 @@ impl Dispatch<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let payable = quote! {{ - <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR }}; diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index f9cc232f7b..fa6be8a367 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -84,7 +84,7 @@ impl ItemImpls<'_> { let message_guard_payable = message.is_payable().then(|| { quote_spanned!(message_span=> const _: ::ink_lang::codegen::TraitMessagePayable<{ - <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#message_local_id>>::PAYABLE }> = ::ink_lang::codegen::TraitMessagePayable::; @@ -95,7 +95,7 @@ impl ItemImpls<'_> { quote_spanned!(message_span=> const _: ::ink_lang::codegen::TraitMessageSelector<{ ::core::primitive::u32::from_be_bytes( - <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#message_local_id>>::SELECTOR ) @@ -212,7 +212,7 @@ impl ItemImpls<'_> { quote_spanned!(span => #( #attrs )* impl #trait_path for #self_type { - type __ink_TraitInfo = <::ink_lang::TraitDefinitionRegistry + type __ink_TraitInfo = <::ink_lang::reflect::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo; #( #messages )* diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index db5e6ecb3e..a7f4314492 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -267,12 +267,12 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let is_payable = quote! {{ - <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink_lang::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR }}; diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 146016f249..a77bd05c79 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -102,7 +102,7 @@ impl TraitRegistry<'_> { let trait_info_ident = self.trait_def.trait_info_ident(); let messages = self.generate_registry_messages(); quote_spanned!(span=> - impl #name for ::ink_lang::TraitDefinitionRegistry + impl #name for ::ink_lang::reflect::TraitDefinitionRegistry where E: ::ink_env::Environment, { diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 9996e29f29..7901d53d11 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -45,23 +45,23 @@ fn main() { // println!("local_id(\"unpayable\") = {:X}", local_id("unpayable")); // println!("local_id(\"unpayable_mut\") = {:X}", local_id("unpayable_mut")); assert!( - <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, ); assert!( - <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, ); assert_eq!( - <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, false ); assert_eq!( - <<::ink_lang::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo as ::ink_lang::TraitMessageInfo>::PAYABLE, false diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 1ffc27dc79..55b2e77a4b 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -21,6 +21,8 @@ mod result_info; #[cfg_attr(not(feature = "show-codegen-docs"), doc(hidden))] pub mod codegen; +pub mod reflect; + mod chain_extension; mod contract_ref; mod env_access; @@ -62,7 +64,6 @@ pub use self::{ TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, - TraitDefinitionRegistry, TraitMessageInfo, TraitModulePath, TraitUniqueId, diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs new file mode 100644 index 0000000000..25f1bdbafd --- /dev/null +++ b/crates/lang/src/reflect/mod.rs @@ -0,0 +1,17 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod trait_def; + +pub use self::trait_def::TraitDefinitionRegistry; diff --git a/crates/lang/src/reflect/trait_def/mod.rs b/crates/lang/src/reflect/trait_def/mod.rs new file mode 100644 index 0000000000..ee8db133d3 --- /dev/null +++ b/crates/lang/src/reflect/trait_def/mod.rs @@ -0,0 +1,17 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod registry; + +pub use self::registry::TraitDefinitionRegistry; diff --git a/crates/lang/src/reflect/trait_def/registry.rs b/crates/lang/src/reflect/trait_def/registry.rs new file mode 100644 index 0000000000..b11ec20427 --- /dev/null +++ b/crates/lang/src/reflect/trait_def/registry.rs @@ -0,0 +1,56 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::codegen::TraitImplementedById; +use core::marker::PhantomData; + +/// This type is known to ink! to implement all defined ink! trait definitions. +/// This property can be guaranteed by `#[ink::trait_definition]` procedural macro. +/// +/// By the introduction of an new internal and hidden associated type called +/// `__ink_DynamicCallForwarder` for all ink! trait definitions it is possible +/// for ink! to map from any given ink! trait definition back to a concrete +/// Rust type. +/// Whenever the `ChainExtensionRegistry` implements an ink! trait definition +/// all calls are defaulted to produce linker errors (ideally compiler errors +/// if that was possible) and the only relevant implementation is the new +/// `__ink_DynamicCallForwarder` associated type that links to a concrete +/// type implementing `FromAccountId` and the ink! trait definition with +/// proper implementations. +/// +/// Then ink! can map from the ink! trait definition `MyTrait` to this concrete +/// dynamic call forwarder type by: +/// ```no_compile +/// <::ink_lang::reflect::TraitDefinitionRegistry as MyTrait>::__ink_DynamicCallForwarder +/// ``` +/// Normal implementations of ink! trait definitions default the new +/// `__ink_DynamicCallForwarder` associated type to `::ink_lang::NoDynamicCallForwarder`. +/// +/// This is the technique used by ink! to resolve `&dyn MyTrait`, `&mut dyn MyTrait` +/// in message parameters or `dyn MyTrait` in ink! storage fields to concrete types +/// that ink! can serialize and deserialize as if it was an `AccountId` and call +/// ink! messages on it according to the ink! trait definition interface. +#[doc(hidden)] +pub struct TraitDefinitionRegistry { + marker: PhantomData E>, +} + +impl crate::ContractEnv for TraitDefinitionRegistry +where + E: ink_env::Environment, +{ + type Env = E; +} + +unsafe impl TraitImplementedById for TraitDefinitionRegistry {} diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index ff5ea4771a..66110baf21 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -12,51 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - codegen::TraitImplementedById, - DispatchError, -}; -use core::marker::PhantomData; - -/// This type is known to ink! to implement all defined ink! trait definitions. -/// This property can be guaranteed by `#[ink::trait_definition]` procedural macro. -/// -/// By the introduction of an new internal and hidden associated type called -/// `__ink_DynamicCallForwarder` for all ink! trait definitions it is possible -/// for ink! to map from any given ink! trait definition back to a concrete -/// Rust type. -/// Whenever the `ChainExtensionRegistry` implements an ink! trait definition -/// all calls are defaulted to produce linker errors (ideally compiler errors -/// if that was possible) and the only relevant implementation is the new -/// `__ink_DynamicCallForwarder` associated type that links to a concrete -/// type implementing `FromAccountId` and the ink! trait definition with -/// proper implementations. -/// -/// Then ink! can map from the ink! trait definition `MyTrait` to this concrete -/// dynamic call forwarder type by: -/// ```no_compile -/// <::ink_lang::TraitDefinitionRegistry as MyTrait>::__ink_DynamicCallForwarder -/// ``` -/// Normal implementations of ink! trait definitions default the new -/// `__ink_DynamicCallForwarder` associated type to `::ink_lang::NoDynamicCallForwarder`. -/// -/// This is the technique used by ink! to resolve `&dyn MyTrait`, `&mut dyn MyTrait` -/// in message parameters or `dyn MyTrait` in ink! storage fields to concrete types -/// that ink! can serialize and deserialize as if it was an `AccountId` and call -/// ink! messages on it according to the ink! trait definition interface. -#[doc(hidden)] -pub struct TraitDefinitionRegistry { - marker: PhantomData E>, -} - -impl crate::ContractEnv for TraitDefinitionRegistry -where - E: ink_env::Environment, -{ - type Env = E; -} - -unsafe impl TraitImplementedById for TraitDefinitionRegistry {} +use crate::DispatchError; /// The global call builder type for an ink! trait definition. pub trait TraitCallBuilder { From 5db1bf31302079587770334a8ead23d8e71a43ca Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 12:01:29 +0200 Subject: [PATCH 379/493] unhide docs for TraitDefinitionRegistry --- crates/lang/src/reflect/trait_def/registry.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/lang/src/reflect/trait_def/registry.rs b/crates/lang/src/reflect/trait_def/registry.rs index b11ec20427..aabd1855ab 100644 --- a/crates/lang/src/reflect/trait_def/registry.rs +++ b/crates/lang/src/reflect/trait_def/registry.rs @@ -41,7 +41,6 @@ use core::marker::PhantomData; /// in message parameters or `dyn MyTrait` in ink! storage fields to concrete types /// that ink! can serialize and deserialize as if it was an `AccountId` and call /// ink! messages on it according to the ink! trait definition interface. -#[doc(hidden)] pub struct TraitDefinitionRegistry { marker: PhantomData E>, } From 9ac99c05763ab51df4067e313306feb31fed8f54 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 12:38:02 +0200 Subject: [PATCH 380/493] enable no-implicit-prelude UI test --- .../{no-implicit-prelude.rs.disabled => no-implicit-prelude.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/lang/macro/tests/ui/contract/pass/{no-implicit-prelude.rs.disabled => no-implicit-prelude.rs} (100%) diff --git a/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs.disabled b/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs.disabled rename to crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs From 486fe918b18eb7750a76e204646bf313460714b6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 12:49:28 +0200 Subject: [PATCH 381/493] add doc comment to reflect module --- crates/lang/src/reflect/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index 25f1bdbafd..ecf854bcfd 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -12,6 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! Definitions and utilities for ink! smart contract static reflection. +//! +//! # Note +//! +//! The ink! smart contract codegen uses these reflections in order to +//! structure, solidify and manage the generated code. +//! +//! However, the definitions in this module might be useful to ink! smart +//! contract authors as well as they allow to inspect compile time information +//! about the ink! smart contract at hand. + mod trait_def; pub use self::trait_def::TraitDefinitionRegistry; From fd649c4c05813cdb33136130b5a90b271c287a96 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:00:26 +0200 Subject: [PATCH 382/493] update docs of TraitDefinitionRegistry --- crates/lang/src/reflect/trait_def/registry.rs | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/crates/lang/src/reflect/trait_def/registry.rs b/crates/lang/src/reflect/trait_def/registry.rs index aabd1855ab..b7030c9815 100644 --- a/crates/lang/src/reflect/trait_def/registry.rs +++ b/crates/lang/src/reflect/trait_def/registry.rs @@ -15,32 +15,42 @@ use crate::codegen::TraitImplementedById; use core::marker::PhantomData; -/// This type is known to ink! to implement all defined ink! trait definitions. -/// This property can be guaranteed by `#[ink::trait_definition]` procedural macro. +/// Type that is guaranteed by ink! to implement all ink! trait definitions. /// -/// By the introduction of an new internal and hidden associated type called -/// `__ink_DynamicCallForwarder` for all ink! trait definitions it is possible -/// for ink! to map from any given ink! trait definition back to a concrete -/// Rust type. -/// Whenever the `ChainExtensionRegistry` implements an ink! trait definition -/// all calls are defaulted to produce linker errors (ideally compiler errors -/// if that was possible) and the only relevant implementation is the new -/// `__ink_DynamicCallForwarder` associated type that links to a concrete -/// type implementing `FromAccountId` and the ink! trait definition with -/// proper implementations. +/// This guarantee is used by ink! itself and can be used by ink! smart contract +/// authors to query static information about known ink! trait definitions. +/// +/// # Codegen +/// +/// - The `#[ink::trait_definition]` procedural macro generates an associated type +/// called `__ink_TraitInfo` for each ink! trait definition. +/// - Furthermore the ink! codegen implements the ink! trait definition for the +/// `TraitDefinitionRegistry` with stub implementations for all methods that +/// guarantee that they are never called. +/// - For every implemented ink! trait definition an ink! trait info object type +/// is generated that is linked to the global `TraitDefinitionRegistry` through +/// the aforementioned `__ink_TraitInfo` associated type. +/// - This trait info object type itself implements various traits each providing +/// useful static reflection information to the rest of the codegen about the ink! +/// trait definition. +/// +/// # Usage /// -/// Then ink! can map from the ink! trait definition `MyTrait` to this concrete -/// dynamic call forwarder type by: -/// ```no_compile -/// <::ink_lang::reflect::TraitDefinitionRegistry as MyTrait>::__ink_DynamicCallForwarder /// ``` -/// Normal implementations of ink! trait definitions default the new -/// `__ink_DynamicCallForwarder` associated type to `::ink_lang::NoDynamicCallForwarder`. +/// # use ink_lang as ink; +/// # use ink_lang::reflect::TraitDefinitionRegistry; +/// use ink_env::DefaultEnvironment; /// -/// This is the technique used by ink! to resolve `&dyn MyTrait`, `&mut dyn MyTrait` -/// in message parameters or `dyn MyTrait` in ink! storage fields to concrete types -/// that ink! can serialize and deserialize as if it was an `AccountId` and call -/// ink! messages on it according to the ink! trait definition interface. +/// #[ink::trait_definition] +/// pub trait TraitDefinition { +/// #[ink(message)] +/// fn message(&self); +/// } +/// +/// /// Access the generated ink! trait info object type like this: +/// type TraitInfo = +/// as TraitDefinition>::__ink_TraitInfo; +/// ``` pub struct TraitDefinitionRegistry { marker: PhantomData E>, } From 1efe6af09935352af7cbabbd935e17bb30856d4a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:11:50 +0200 Subject: [PATCH 383/493] move definitions for dispatch reflections into reflect submodule --- crates/lang/codegen/src/generator/dispatch.rs | 100 +++++++-------- .../ui/contract/pass/constructor-selector.rs | 18 +-- .../tests/ui/contract/pass/message-payable.rs | 4 +- .../ui/contract/pass/message-selector.rs | 18 +-- crates/lang/src/lib.rs | 8 -- crates/lang/src/reflect/dispatch.rs | 117 ++++++++++++++++++ crates/lang/src/reflect/mod.rs | 15 ++- crates/lang/src/traits.rs | 104 ---------------- 8 files changed, 201 insertions(+), 183 deletions(-) create mode 100644 crates/lang/src/reflect/dispatch.rs diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index afe580a05d..ccc5fb3826 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -124,7 +124,7 @@ impl Dispatch<'_> { let count_messages = self.query_amount_messages(); let count_constructors = self.query_amount_constructors(); quote_spanned!(span=> - impl ::ink_lang::ContractAmountDispatchables for #storage_ident { + impl ::ink_lang::reflect::ContractAmountDispatchables for #storage_ident { const MESSAGES: ::core::primitive::usize = #count_messages; const CONSTRUCTORS: ::core::primitive::usize = #count_constructors; } @@ -185,12 +185,12 @@ impl Dispatch<'_> { ) }); quote_spanned!(span=> - impl ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + impl ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }> for #storage_ident { const IDS: [ ::core::primitive::u32; - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES ] = [ #( #inherent_ids , )* #( #trait_ids ),* @@ -225,12 +225,12 @@ impl Dispatch<'_> { quote_spanned!(span=> #id) }); quote_spanned!(span=> - impl ::ink_lang::ContractDispatchableConstructors<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + impl ::ink_lang::reflect::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::CONSTRUCTORS }> for #storage_ident { const IDS: [ ::core::primitive::u32; - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::CONSTRUCTORS ] = [ #( #constructor_ids ),* ]; @@ -260,7 +260,7 @@ impl Dispatch<'_> { let input_tuple_type = generator::input_types_tuple(constructor.inputs()); let input_tuple_bindings = generator::input_bindings_tuple(constructor.inputs()); quote_spanned!(constructor_span=> - impl ::ink_lang::DispatchableConstructorInfo<#selector_id> for #storage_ident { + impl ::ink_lang::reflect::DispatchableConstructorInfo<#selector_id> for #storage_ident { type Input = #input_tuple_type; type Storage = #storage_ident; @@ -306,7 +306,7 @@ impl Dispatch<'_> { let input_tuple_type = generator::input_types_tuple(message.inputs()); let input_tuple_bindings = generator::input_bindings_tuple(message.inputs()); quote_spanned!(message_span=> - impl ::ink_lang::DispatchableMessageInfo<#selector_id> for #storage_ident { + impl ::ink_lang::reflect::DispatchableMessageInfo<#selector_id> for #storage_ident { type Input = #input_tuple_type; type Output = #output_tuple_type; type Storage = #storage_ident; @@ -364,7 +364,7 @@ impl Dispatch<'_> { let input_tuple_bindings = generator::input_bindings_tuple(message.inputs()); let label = format!("{}::{}", trait_ident, message_ident); quote_spanned!(message_span=> - impl ::ink_lang::DispatchableMessageInfo<#selector_id> for #storage_ident { + impl ::ink_lang::reflect::DispatchableMessageInfo<#selector_id> for #storage_ident { type Input = #input_tuple_type; type Output = #output_tuple_type; type Storage = #storage_ident; @@ -400,11 +400,11 @@ impl Dispatch<'_> { #[no_mangle] fn deploy() { ::ink_env::decode_input::< - <#storage_ident as ::ink_lang::ContractConstructorDecoder>::Type>() + <#storage_ident as ::ink_lang::reflect::ContractConstructorDecoder>::Type>() .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput) .and_then(|decoder| { - <<#storage_ident as ::ink_lang::ContractConstructorDecoder>::Type - as ::ink_lang::ExecuteDispatchable>::execute_dispatchable(decoder) + <<#storage_ident as ::ink_lang::reflect::ContractConstructorDecoder>::Type + as ::ink_lang::reflect::ExecuteDispatchable>::execute_dispatchable(decoder) }) .unwrap_or_else(|error| { ::core::panic!("dispatching ink! constructor failed: {}", error) @@ -419,11 +419,11 @@ impl Dispatch<'_> { .unwrap_or_else(|error| ::core::panic!("{}", error)) } ::ink_env::decode_input::< - <#storage_ident as ::ink_lang::ContractMessageDecoder>::Type>() + <#storage_ident as ::ink_lang::reflect::ContractMessageDecoder>::Type>() .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput) .and_then(|decoder| { - <<#storage_ident as ::ink_lang::ContractMessageDecoder>::Type - as ::ink_lang::ExecuteDispatchable>::execute_dispatchable(decoder) + <<#storage_ident as ::ink_lang::reflect::ContractMessageDecoder>::Type + as ::ink_lang::reflect::ExecuteDispatchable>::execute_dispatchable(decoder) }) .unwrap_or_else(|error| { ::core::panic!("dispatching ink! message failed: {}", error) @@ -450,9 +450,9 @@ impl Dispatch<'_> { constructor_index: usize, ) -> TokenStream2 { quote_spanned!(span=> - <#storage_ident as ::ink_lang::DispatchableConstructorInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableConstructors<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + <#storage_ident as ::ink_lang::reflect::DispatchableConstructorInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::CONSTRUCTORS }>>::IDS[#constructor_index] }>>::Input ) @@ -479,9 +479,9 @@ impl Dispatch<'_> { let constructor_span = constructor_spans[index]; let constructor_ident = constructor_variant_ident(index); let constructor_selector = quote_spanned!(span=> - <#storage_ident as ::ink_lang::DispatchableConstructorInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableConstructors<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + <#storage_ident as ::ink_lang::reflect::DispatchableConstructorInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::CONSTRUCTORS }>>::IDS[#index] }>>::SELECTOR ); @@ -498,9 +498,9 @@ impl Dispatch<'_> { let constructor_span = constructor_spans[index]; let constructor_ident = constructor_variant_ident(index); let constructor_callable = quote_spanned!(constructor_span=> - <#storage_ident as ::ink_lang::DispatchableConstructorInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableConstructors<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::CONSTRUCTORS + <#storage_ident as ::ink_lang::reflect::DispatchableConstructorInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableConstructors<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::CONSTRUCTORS }>>::IDS[#index] }>>::CALLABLE ); @@ -542,7 +542,7 @@ impl Dispatch<'_> { } } - impl ::ink_lang::ExecuteDispatchable for __ink_ConstructorDecoder { + impl ::ink_lang::reflect::ExecuteDispatchable for __ink_ConstructorDecoder { fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { match self { #( #constructor_execute ),* @@ -550,7 +550,7 @@ impl Dispatch<'_> { } } - impl ::ink_lang::ContractConstructorDecoder for #storage_ident { + impl ::ink_lang::reflect::ContractConstructorDecoder for #storage_ident { type Type = __ink_ConstructorDecoder; } }; @@ -575,9 +575,9 @@ impl Dispatch<'_> { message_index: usize, ) -> TokenStream2 { quote_spanned!(span=> - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }>>::IDS[#message_index] }>>::Input ) @@ -603,9 +603,9 @@ impl Dispatch<'_> { let message_span = message_spans[index]; let message_ident = message_variant_ident(index); let message_selector = quote_spanned!(span=> - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }>>::IDS[#index] }>>::SELECTOR ); @@ -624,32 +624,32 @@ impl Dispatch<'_> { let message_span = message_spans[index]; let message_ident = message_variant_ident(index); let message_callable = quote_spanned!(message_span=> - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }>>::IDS[#index] }>>::CALLABLE ); let message_output = quote_spanned!(message_span=> - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }>>::IDS[#index] }>>::Output ); let accepts_payment = quote_spanned!(message_span=> false || !#any_message_accept_payment || - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }>>::IDS[#index] }>>::PAYABLE ); let mutates_storage = quote_spanned!(message_span=> - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }>>::IDS[#index] }>>::MUTATES ); @@ -700,7 +700,7 @@ impl Dispatch<'_> { } } - impl ::ink_lang::ExecuteDispatchable for __ink_MessageDecoder { + impl ::ink_lang::reflect::ExecuteDispatchable for __ink_MessageDecoder { #[allow(clippy::nonminimal_bool)] fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { match self { @@ -709,7 +709,7 @@ impl Dispatch<'_> { } } - impl ::ink_lang::ContractMessageDecoder for #storage_ident { + impl ::ink_lang::reflect::ContractMessageDecoder for #storage_ident { type Type = __ink_MessageDecoder; } }; @@ -733,9 +733,9 @@ impl Dispatch<'_> { let message_is_payable = (0..count_messages).map(|index| { let message_span = message_spans[index]; quote_spanned!(message_span=> - <#storage_ident as ::ink_lang::DispatchableMessageInfo<{ - <#storage_ident as ::ink_lang::ContractDispatchableMessages<{ - <#storage_ident as ::ink_lang::ContractAmountDispatchables>::MESSAGES + <#storage_ident as ::ink_lang::reflect::DispatchableMessageInfo<{ + <#storage_ident as ::ink_lang::reflect::ContractDispatchableMessages<{ + <#storage_ident as ::ink_lang::reflect::ContractAmountDispatchables>::MESSAGES }>>::IDS[#index] }>>::PAYABLE ) diff --git a/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs b/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs index 0e45b36751..64e446c303 100644 --- a/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs +++ b/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs @@ -29,11 +29,11 @@ mod contract { fn main() { assert_eq!( - ::CONSTRUCTORS + ::CONSTRUCTORS }, >>::IDS[0] }, @@ -41,11 +41,11 @@ fn main() { [0x5C, 0x5D, 0x42, 0x89], ); assert_eq!( - ::CONSTRUCTORS + ::CONSTRUCTORS }, >>::IDS[1] }, @@ -53,11 +53,11 @@ fn main() { 1_u32.to_be_bytes(), ); assert_eq!( - ::CONSTRUCTORS + ::CONSTRUCTORS }, >>::IDS[2] }, diff --git a/crates/lang/macro/tests/ui/contract/pass/message-payable.rs b/crates/lang/macro/tests/ui/contract/pass/message-payable.rs index 2463460d5a..74f5035c7a 100644 --- a/crates/lang/macro/tests/ui/contract/pass/message-payable.rs +++ b/crates/lang/macro/tests/ui/contract/pass/message-payable.rs @@ -22,6 +22,6 @@ mod contract { use contract::Contract; fn main() { - assert!(>::PAYABLE); - assert!(!>::PAYABLE); + assert!(>::PAYABLE); + assert!(!>::PAYABLE); } diff --git a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs index 26dd166da8..aab4e056b1 100644 --- a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs +++ b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs @@ -25,30 +25,30 @@ mod contract { fn main() { assert_eq!( - ::MESSAGES }, + ::MESSAGES }, >>::IDS[0] }, >>::SELECTOR, [0x5A, 0x6A, 0xC1, 0x5D], ); assert_eq!( - ::MESSAGES }, + ::MESSAGES }, >>::IDS[1] }, >>::SELECTOR, 1_u32.to_be_bytes(), ); assert_eq!( - ::MESSAGES }, + ::MESSAGES }, >>::IDS[2] }, >>::SELECTOR, diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 55b2e77a4b..993ed6dc05 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -53,14 +53,6 @@ pub use self::{ EmitEvent, }, traits::{ - ContractAmountDispatchables, - ContractConstructorDecoder, - ContractDispatchableConstructors, - ContractDispatchableMessages, - ContractMessageDecoder, - DispatchableConstructorInfo, - DispatchableMessageInfo, - ExecuteDispatchable, TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs new file mode 100644 index 0000000000..de583369d0 --- /dev/null +++ b/crates/lang/src/reflect/dispatch.rs @@ -0,0 +1,117 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::DispatchError; + +/// Implemented by all ink! smart contracts. +/// +/// Reflects the number of dispatchable ink! messages and constructors respectively. +pub trait ContractAmountDispatchables { + /// The number of dispatchable ink! messages. + const MESSAGES: usize; + /// The number of dispatchable ink! constructors. + const CONSTRUCTORS: usize; +} + +/// Implemented by all ink! smart contracts. +/// +/// Stores a sequence of all dispatchable ink! message of the ink! smart contract. +/// +/// # Note +/// +/// Implemented for the amount of dispatchable ink! messages of the ink! smart contract. +pub trait ContractDispatchableMessages { + /// The sequence stores selector IDs of all ink! messages dispatchable by the ink! smart contract. + const IDS: [u32; AMOUNT]; +} + +/// Implemented by all ink! smart contracts. +/// +/// Stores a sequence of all dispatchable ink! constructors of the ink! smart contract. +/// +/// # Note +/// +/// Implemented for the amount of dispatchable ink! constructors of the ink! smart contract. +pub trait ContractDispatchableConstructors { + /// The sequence stores selector IDs of all ink! constructors dispatchable by the ink! smart contract. + const IDS: [u32; AMOUNT]; +} + +/// Implemented by the ink! message namespace type for every ink! message selector ID. +/// +/// Stores various information properties of the respective dispatchable ink! message. +pub trait DispatchableMessageInfo { + /// Reflects the input types of the dispatchable ink! message. + type Input; + /// Reflects the output type of the dispatchable ink! message. + type Output; + /// The ink! storage struct type. + type Storage; + + /// The closure that can be used to dispatch into the dispatchable ink! message. + /// + /// # Note + /// + /// We unify `&self` and `&mut self` ink! messages here and always take a `&mut self`. + /// This is mainly done for simplification but also because we can easily convert from + /// `&mut self` to `&self` with our current dispatch codegen architecture. + const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output; + + /// Yields `true` if the dispatchable ink! message mutates the ink! storage. + const MUTATES: bool; + /// Yields `true` if the dispatchable ink! message is payable. + const PAYABLE: bool; + /// The selectors of the dispatchable ink! message. + const SELECTOR: [u8; 4]; + /// The label of the dispatchable ink! message. + const LABEL: &'static str; +} + +/// Implemented by the ink! constructor namespace type for every ink! constructor selector ID. +/// +/// Stores various information of the respective dispatchable ink! constructor. +pub trait DispatchableConstructorInfo { + /// Reflects the input types of the dispatchable ink! constructor. + type Input; + /// The ink! storage struct type. + type Storage; + + /// The closure that can be used to dispatch into the dispatchable ink! constructor. + const CALLABLE: fn(Self::Input) -> Self::Storage; + + /// The selectors of the dispatchable ink! constructor. + const SELECTOR: [u8; 4]; + /// The label of the dispatchable ink! constructor. + const LABEL: &'static str; +} + +/// Generated type used to decode all dispatchable ink! messages of the ink! smart contract. +pub trait ContractMessageDecoder { + /// The ink! smart contract message decoder type. + type Type: scale::Decode + ExecuteDispatchable; +} + +/// Generated type used to decode all dispatchable ink! constructors of the ink! smart contract. +pub trait ContractConstructorDecoder { + /// The ink! smart contract constructor decoder type. + type Type: scale::Decode + ExecuteDispatchable; +} + +/// Implemented by the ink! smart contract message or constructor decoder. +/// +/// Starts the execution of the respective ink! message or constructor call. +pub trait ExecuteDispatchable { + /// Executes the ink! smart contract message or constructor. + fn execute_dispatchable(self) -> Result<(), DispatchError>; +} diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index ecf854bcfd..1ef68f9274 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -23,6 +23,19 @@ //! contract authors as well as they allow to inspect compile time information //! about the ink! smart contract at hand. +mod dispatch; mod trait_def; -pub use self::trait_def::TraitDefinitionRegistry; +pub use self::{ + dispatch::{ + ContractAmountDispatchables, + ContractConstructorDecoder, + ContractDispatchableConstructors, + ContractDispatchableMessages, + ContractMessageDecoder, + DispatchableConstructorInfo, + DispatchableMessageInfo, + ExecuteDispatchable, + }, + trait_def::TraitDefinitionRegistry, +}; diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 66110baf21..e52b7c6051 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::DispatchError; - /// The global call builder type for an ink! trait definition. pub trait TraitCallBuilder { /// The call builder type. @@ -146,105 +144,3 @@ pub trait TraitMessageInfo { /// ink! trait definition site. const SELECTOR: [u8; 4]; } - -/// Implemented by all ink! smart contracts. -/// -/// Reflects the number of dispatchable ink! messages and constructors respectively. -pub trait ContractAmountDispatchables { - /// The number of dispatchable ink! messages. - const MESSAGES: usize; - /// The number of dispatchable ink! constructors. - const CONSTRUCTORS: usize; -} - -/// Implemented by all ink! smart contracts. -/// -/// Stores a sequence of all dispatchable ink! message of the ink! smart contract. -/// -/// # Note -/// -/// Implemented for the amount of dispatchable ink! messages of the ink! smart contract. -pub trait ContractDispatchableMessages { - /// The sequence stores selector IDs of all ink! messages dispatchable by the ink! smart contract. - const IDS: [u32; AMOUNT]; -} - -/// Implemented by all ink! smart contracts. -/// -/// Stores a sequence of all dispatchable ink! constructors of the ink! smart contract. -/// -/// # Note -/// -/// Implemented for the amount of dispatchable ink! constructors of the ink! smart contract. -pub trait ContractDispatchableConstructors { - /// The sequence stores selector IDs of all ink! constructors dispatchable by the ink! smart contract. - const IDS: [u32; AMOUNT]; -} - -/// Implemented by the ink! message namespace type for every ink! message selector ID. -/// -/// Stores various information properties of the respective dispatchable ink! message. -pub trait DispatchableMessageInfo { - /// Reflects the input types of the dispatchable ink! message. - type Input; - /// Reflects the output type of the dispatchable ink! message. - type Output; - /// The ink! storage struct type. - type Storage; - - /// The closure that can be used to dispatch into the dispatchable ink! message. - /// - /// # Note - /// - /// We unify `&self` and `&mut self` ink! messages here and always take a `&mut self`. - /// This is mainly done for simplification but also because we can easily convert from - /// `&mut self` to `&self` with our current dispatch codegen architecture. - const CALLABLE: fn(&mut Self::Storage, Self::Input) -> Self::Output; - - /// Yields `true` if the dispatchable ink! message mutates the ink! storage. - const MUTATES: bool; - /// Yields `true` if the dispatchable ink! message is payable. - const PAYABLE: bool; - /// The selectors of the dispatchable ink! message. - const SELECTOR: [u8; 4]; - /// The label of the dispatchable ink! message. - const LABEL: &'static str; -} - -/// Implemented by the ink! constructor namespace type for every ink! constructor selector ID. -/// -/// Stores various information of the respective dispatchable ink! constructor. -pub trait DispatchableConstructorInfo { - /// Reflects the input types of the dispatchable ink! constructor. - type Input; - /// The ink! storage struct type. - type Storage; - - /// The closure that can be used to dispatch into the dispatchable ink! constructor. - const CALLABLE: fn(Self::Input) -> Self::Storage; - - /// The selectors of the dispatchable ink! constructor. - const SELECTOR: [u8; 4]; - /// The label of the dispatchable ink! constructor. - const LABEL: &'static str; -} - -/// Generated type used to decode all dispatchable ink! messages of the ink! smart contract. -pub trait ContractMessageDecoder { - /// The ink! smart contract message decoder type. - type Type: scale::Decode + ExecuteDispatchable; -} - -/// Generated type used to decode all dispatchable ink! constructors of the ink! smart contract. -pub trait ContractConstructorDecoder { - /// The ink! smart contract constructor decoder type. - type Type: scale::Decode + ExecuteDispatchable; -} - -/// Implemented by the ink! smart contract message or constructor decoder. -/// -/// Starts the execution of the respective ink! message or constructor call. -pub trait ExecuteDispatchable { - /// Executes the ink! smart contract message or constructor. - fn execute_dispatchable(self) -> Result<(), DispatchError>; -} From 0fa014178244e417978c47d39d4f4226115523be Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:21:51 +0200 Subject: [PATCH 384/493] add usage example to COntractAmountDispatchables reflect trait --- crates/lang/src/reflect/dispatch.rs | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index de583369d0..38b0db7735 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -17,6 +17,43 @@ use crate::DispatchError; /// Implemented by all ink! smart contracts. /// /// Reflects the number of dispatchable ink! messages and constructors respectively. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::ContractAmountDispatchables; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor1() -> Self { Contract {} } +/// +/// #[ink(constructor)] +/// pub fn constructor2() -> Self { Contract {} } +/// +/// #[ink(message)] +/// pub fn message1(&self) {} +/// +/// #[ink(message)] +/// pub fn message2(&self) {} +/// +/// #[ink(message)] +/// pub fn message3(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// assert_eq!(::CONSTRUCTORS, 2); +/// assert_eq!(::MESSAGES, 3); +/// } +/// ``` pub trait ContractAmountDispatchables { /// The number of dispatchable ink! messages. const MESSAGES: usize; From 0a05e39a4ec70b50ac13839199232991b64508e7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:25:04 +0200 Subject: [PATCH 385/493] add doc comment note to ContractAmountDispatchables trait --- crates/lang/src/reflect/dispatch.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 38b0db7735..e2d1c5a0f2 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -18,6 +18,11 @@ use crate::DispatchError; /// /// Reflects the number of dispatchable ink! messages and constructors respectively. /// +/// # Note +/// +/// All ink! constructors and ink! messages of an ink! smart contract are dispatchables. +/// This explicitly includes ink! messages from ink! trait implementations. +/// /// # Usage /// /// ``` From 00d81d4841aa8ab0f7092e4cfd3ec5fbde80200a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:28:20 +0200 Subject: [PATCH 386/493] add enforced newline to docs --- crates/lang/src/reflect/dispatch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index e2d1c5a0f2..b5c44da18e 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -20,7 +20,7 @@ use crate::DispatchError; /// /// # Note /// -/// All ink! constructors and ink! messages of an ink! smart contract are dispatchables. +/// All ink! constructors and ink! messages of an ink! smart contract are dispatchables. /// This explicitly includes ink! messages from ink! trait implementations. /// /// # Usage From e5ba75fa15e78363b6111ae139dcfdd4a37a58b0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:29:43 +0200 Subject: [PATCH 387/493] improve docs --- crates/lang/src/reflect/dispatch.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index b5c44da18e..b1ee6fcae6 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -14,14 +14,13 @@ use crate::DispatchError; -/// Implemented by all ink! smart contracts. -/// /// Reflects the number of dispatchable ink! messages and constructors respectively. /// /// # Note /// -/// All ink! constructors and ink! messages of an ink! smart contract are dispatchables. -/// This explicitly includes ink! messages from ink! trait implementations. +/// - This is automatically implemented by all ink! smart contracts. +/// - All ink! constructors and ink! messages of an ink! smart contract are dispatchables. +/// This explicitly includes ink! messages from ink! trait implementations. /// /// # Usage /// From 55e1728a927388418b69d77d43fd5ae1c77fa4b5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:39:56 +0200 Subject: [PATCH 388/493] update docs for ContractDispatchableMessages trait --- crates/lang/src/reflect/dispatch.rs | 45 ++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index b1ee6fcae6..f54f1b9699 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -65,13 +65,50 @@ pub trait ContractAmountDispatchables { const CONSTRUCTORS: usize; } -/// Implemented by all ink! smart contracts. -/// -/// Stores a sequence of all dispatchable ink! message of the ink! smart contract. +/// Reflects the sequence of all dispatchable ink! messages of the ink! smart contract. /// /// # Note /// -/// Implemented for the amount of dispatchable ink! messages of the ink! smart contract. +/// This is automatically implemented by all ink! smart contracts. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::ContractAmountDispatchables; +/// # use ink_lang::reflect::ContractDispatchableMessages; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor1() -> Self { Contract {} } +/// +/// #[ink(message, selector = 1234)] +/// pub fn message1(&self) {} +/// +/// #[ink(message, selector = 0xC0DECAFE)] +/// pub fn message2(&self) {} +/// +/// #[ink(message, selector = 42)] +/// pub fn message3(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// assert_eq!( +/// ::MESSAGES +/// }>>::IDS, +/// [1234, 0xC0DECAFE, 42], +/// ); +/// } +/// ``` pub trait ContractDispatchableMessages { /// The sequence stores selector IDs of all ink! messages dispatchable by the ink! smart contract. const IDS: [u32; AMOUNT]; From 52cb2e8efed54a455f2336e9f44c57831631025b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:41:24 +0200 Subject: [PATCH 389/493] improve doc test --- crates/lang/src/reflect/dispatch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index f54f1b9699..1cf09493b1 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -93,7 +93,7 @@ pub trait ContractAmountDispatchables { /// #[ink(message, selector = 0xC0DECAFE)] /// pub fn message2(&self) {} /// -/// #[ink(message, selector = 42)] +/// #[ink(message)] /// pub fn message3(&self) {} /// } /// } @@ -105,7 +105,7 @@ pub trait ContractAmountDispatchables { /// ::MESSAGES /// }>>::IDS, -/// [1234, 0xC0DECAFE, 42], +/// [1234, 0xC0DECAFE, 606597556], /// ); /// } /// ``` From 69a12da14f34c827830627a60968a50d428db86c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:43:36 +0200 Subject: [PATCH 390/493] update docs of ContractDispatchableConstructors trait --- crates/lang/src/reflect/dispatch.rs | 45 ++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 1cf09493b1..efdc66e7ed 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -114,13 +114,50 @@ pub trait ContractDispatchableMessages { const IDS: [u32; AMOUNT]; } -/// Implemented by all ink! smart contracts. -/// -/// Stores a sequence of all dispatchable ink! constructors of the ink! smart contract. +/// Reflects the sequence of all dispatchable ink! constructors of the ink! smart contract. /// /// # Note /// -/// Implemented for the amount of dispatchable ink! constructors of the ink! smart contract. +/// This is automatically implemented by all ink! smart contracts. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::ContractAmountDispatchables; +/// # use ink_lang::reflect::ContractDispatchableConstructors; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor, selector = 1234)] +/// pub fn constructor1() -> Self { Contract {} } +/// +/// #[ink(constructor, selector = 0xC0DECAFE)] +/// pub fn constructor2() -> Self { Contract {} } +/// +/// #[ink(constructor)] +/// pub fn constructor3() -> Self { Contract {} } +/// +/// #[ink(message)] +/// pub fn message1(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// assert_eq!( +/// ::CONSTRUCTORS +/// }>>::IDS, +/// [1234, 0xC0DECAFE, 1555172939], +/// ); +/// } +/// ``` pub trait ContractDispatchableConstructors { /// The sequence stores selector IDs of all ink! constructors dispatchable by the ink! smart contract. const IDS: [u32; AMOUNT]; From 3320918ba4c31cbd26e8a4221b40ee11b92b21c0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:55:36 +0200 Subject: [PATCH 391/493] apply rustfmt --- .../macro/tests/ui/contract/pass/message-selector.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs index aab4e056b1..303c699076 100644 --- a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs +++ b/crates/lang/macro/tests/ui/contract/pass/message-selector.rs @@ -28,7 +28,9 @@ fn main() { ::MESSAGES }, + { + ::MESSAGES + }, >>::IDS[0] }, >>::SELECTOR, @@ -38,7 +40,9 @@ fn main() { ::MESSAGES }, + { + ::MESSAGES + }, >>::IDS[1] }, >>::SELECTOR, @@ -48,7 +52,9 @@ fn main() { ::MESSAGES }, + { + ::MESSAGES + }, >>::IDS[2] }, >>::SELECTOR, From ab7f9ec1e4147772bebf6b8aa40c308a1d20788c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Fri, 1 Oct 2021 13:56:27 +0200 Subject: [PATCH 392/493] fix hunspell dict --- .config/cargo_spellcheck.dic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.config/cargo_spellcheck.dic b/.config/cargo_spellcheck.dic index b17314829a..05f9b5aad9 100644 --- a/.config/cargo_spellcheck.dic +++ b/.config/cargo_spellcheck.dic @@ -35,7 +35,7 @@ defragmentation deploy dereferencing deserialize/S -dispatchable +dispatchable/S encodable evaluable fuzzer From c44c79e725807f70a03bb049cef9fc4b5d4efe19 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 2 Oct 2021 19:18:46 +0200 Subject: [PATCH 393/493] remove non-existing optional UI test comments --- crates/lang/macro/tests/compile_tests.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 18a09af9b8..31d0d2f976 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -16,10 +16,6 @@ fn contract() { let t = trybuild::TestCases::new(); - // Optional test cases: - // - // t.pass("tests/ui/contract/pass/no-implicit-prelude.rs.disabled"); - t.pass("tests/ui/contract/pass/*.rs"); t.compile_fail("tests/ui/contract/fail/*.rs"); } From c6be743f57e7d2e837c74ff5451d542d321ba2d6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 2 Oct 2021 19:19:42 +0200 Subject: [PATCH 394/493] merge UI tests into one fat one This (hopefully) fixes the flaky codecov CI for now ... --- crates/lang/macro/tests/compile_tests.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/macro/tests/compile_tests.rs index 31d0d2f976..1f84bf3897 100644 --- a/crates/lang/macro/tests/compile_tests.rs +++ b/crates/lang/macro/tests/compile_tests.rs @@ -13,24 +13,14 @@ // limitations under the License. #[test] -fn contract() { +fn ui_tests() { let t = trybuild::TestCases::new(); t.pass("tests/ui/contract/pass/*.rs"); t.compile_fail("tests/ui/contract/fail/*.rs"); -} - -#[test] -fn chain_extension() { - let t = trybuild::TestCases::new(); - - t.pass("tests/ui/chain_extension/E-01-simple.rs"); -} - -#[test] -fn trait_definition() { - let t = trybuild::TestCases::new(); t.pass("tests/ui/trait_def/pass/*.rs"); t.compile_fail("tests/ui/trait_def/fail/*.rs"); + + t.pass("tests/ui/chain_extension/E-01-simple.rs"); } From ada8b610bc31d9073dcc7ab0cd3fee6ec8f4de47 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 12:31:05 +0200 Subject: [PATCH 395/493] use new selector_id! macro instead of raw values in doc tests --- crates/lang/src/reflect/dispatch.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index efdc66e7ed..76ad99b659 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -77,6 +77,7 @@ pub trait ContractAmountDispatchables { /// use ink_lang as ink; /// # use ink_lang::reflect::ContractAmountDispatchables; /// # use ink_lang::reflect::ContractDispatchableMessages; +/// # use ink_lang::selector_id; /// /// #[ink::contract] /// pub mod contract { @@ -105,7 +106,7 @@ pub trait ContractAmountDispatchables { /// ::MESSAGES /// }>>::IDS, -/// [1234, 0xC0DECAFE, 606597556], +/// [1234, 0xC0DECAFE, selector_id!("message3")], /// ); /// } /// ``` @@ -126,6 +127,7 @@ pub trait ContractDispatchableMessages { /// use ink_lang as ink; /// # use ink_lang::reflect::ContractAmountDispatchables; /// # use ink_lang::reflect::ContractDispatchableConstructors; +/// # use ink_lang::selector_id; /// /// #[ink::contract] /// pub mod contract { @@ -154,7 +156,7 @@ pub trait ContractDispatchableMessages { /// ::CONSTRUCTORS /// }>>::IDS, -/// [1234, 0xC0DECAFE, 1555172939], +/// [1234, 0xC0DECAFE, selector_id!("constructor3")], /// ); /// } /// ``` From 8fb55b892cce30cea244dc1aa8339095266d5417 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 13:20:39 +0200 Subject: [PATCH 396/493] add usage docs to DispatchableMessageInfo trait --- crates/lang/src/reflect/dispatch.rs | 59 +++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 76ad99b659..9763727b25 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -168,6 +168,65 @@ pub trait ContractDispatchableConstructors { /// Implemented by the ink! message namespace type for every ink! message selector ID. /// /// Stores various information properties of the respective dispatchable ink! message. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::DispatchableMessageInfo; +/// # use ink_lang::{selector_id, selector_bytes}; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Contract {} } +/// +/// #[ink(message)] +/// pub fn message1(&self) {} +/// +/// #[ink(message, payable, selector = 0xC0DECAFE)] +/// pub fn message2(&mut self, input1: i32, input2: i64) -> (bool, i32) { +/// unimplemented!() +/// } +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn assert_message_info( +/// mutates: bool, +/// payable: bool, +/// selector: [u8; 4], +/// label: &str, +/// ) +/// where +/// Contract: DispatchableMessageInfo<{ID}, Input = In, Output = Out>, +/// { +/// assert_eq!(>::MUTATES, mutates); +/// assert_eq!(>::PAYABLE, payable); +/// assert_eq!( +/// >::SELECTOR, +/// selector, +/// ); +/// assert_eq!( +/// >::LABEL, +/// label, +/// ); +/// } +/// +/// fn main() { +/// assert_message_info::<(), (), {selector_id!("message1")}>( +/// false, false, selector_bytes!("message1"), "message1" +/// ); +/// assert_message_info::<(i32, i64), (bool, i32), 0xC0DECAFE_u32>( +/// true, true, [0xC0, 0xDE, 0xCA, 0xFE], "message2" +/// ); +/// } +/// ``` pub trait DispatchableMessageInfo { /// Reflects the input types of the dispatchable ink! message. type Input; From 1ebf078c3a4567ceb28f080a8fece91ea6273aaa Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 13:25:13 +0200 Subject: [PATCH 397/493] improve doc test --- crates/lang/src/reflect/dispatch.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 9763727b25..774bb13407 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -197,6 +197,11 @@ pub trait ContractDispatchableConstructors { /// /// use contract::Contract; /// +/// /// Asserts that the message with the selector `ID` has the following properties. +/// /// +/// /// # Note +/// /// +/// /// The `In` and `Out` generic parameters describe the input and output types. /// fn assert_message_info( /// mutates: bool, /// payable: bool, From dca78042859856ba7f48615dbbebce7901fdb946 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 13:30:32 +0200 Subject: [PATCH 398/493] add usage example to DispatchableConstructorInfo trait docs --- crates/lang/src/reflect/dispatch.rs | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 774bb13407..57f89d60da 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -262,6 +262,66 @@ pub trait DispatchableMessageInfo { /// Implemented by the ink! constructor namespace type for every ink! constructor selector ID. /// /// Stores various information of the respective dispatchable ink! constructor. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::DispatchableConstructorInfo; +/// # use ink_lang::{selector_id, selector_bytes}; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor1() -> Self { Contract {} } +/// +/// #[ink(constructor, selector = 0xC0DECAFE)] +/// pub fn constructor2(input1: i32, input2: i64) -> Self { +/// Contract {} +/// } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// /// Asserts that the constructor with the selector `ID` has the following properties. +/// /// +/// /// # Note +/// /// +/// /// The `In` and `Out` generic parameters describe the input and output types. +/// fn assert_constructor_info( +/// selector: [u8; 4], +/// label: &str, +/// ) +/// where +/// Contract: DispatchableConstructorInfo<{ID}, Input = In>, +/// { +/// assert_eq!( +/// >::SELECTOR, +/// selector, +/// ); +/// assert_eq!( +/// >::LABEL, +/// label, +/// ); +/// } +/// +/// fn main() { +/// assert_constructor_info::<(), {selector_id!("constructor1")}>( +/// selector_bytes!("constructor1"), "constructor1" +/// ); +/// assert_constructor_info::<(i32, i64), 0xC0DECAFE_u32>( +/// [0xC0, 0xDE, 0xCA, 0xFE], "constructor2" +/// ); +/// } +/// ``` pub trait DispatchableConstructorInfo { /// Reflects the input types of the dispatchable ink! constructor. type Input; From ebfa89ebadf00a79728aa5b4389faaa59f129b0c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 13:54:45 +0200 Subject: [PATCH 399/493] add note and usage example for ContractMessageDecoder docs --- crates/lang/src/reflect/dispatch.rs | 79 +++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 57f89d60da..00cfeec2c2 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -338,12 +338,91 @@ pub trait DispatchableConstructorInfo { } /// Generated type used to decode all dispatchable ink! messages of the ink! smart contract. +/// +/// # Note +/// +/// The decoder follows the ink! calling ABI where all ink! message calls start with +/// 4 bytes dedicated to the ink! message selector followed by the SCALE encoded parameters. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::ContractMessageDecoder; +/// # use ink_lang::selector_bytes; +/// # use scale::{Encode, Decode}; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message1(&self) {} +/// +/// #[ink(message)] +/// pub fn message2(&self, input1: bool, input2: i32) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// // Call to `message1` without input parameters. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("message1")); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_ok() +/// ); +/// } +/// // Call to `message2` with 2 parameters. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("message2")); +/// input_bytes.extend(true.encode()); +/// input_bytes.extend(42i32.encode()); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_ok() +/// ); +/// } +/// // Call with invalid ink! message selector. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("non_existing_message")); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_err() +/// ); +/// } +/// // Call with invalid ink! message parameters. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("message2")); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_err() +/// ); +/// } +/// } +/// ``` pub trait ContractMessageDecoder { /// The ink! smart contract message decoder type. type Type: scale::Decode + ExecuteDispatchable; } /// Generated type used to decode all dispatchable ink! constructors of the ink! smart contract. +/// +/// # Note +/// +/// The decoder follows the ink! calling ABI where all ink! constructor calls start with +/// 4 bytes dedicated to the ink! constructor selector followed by the SCALE encoded parameters. pub trait ContractConstructorDecoder { /// The ink! smart contract constructor decoder type. type Type: scale::Decode + ExecuteDispatchable; From 9b59754228ec7ef3a771fb092daf0afcb333fd1f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 14:15:11 +0200 Subject: [PATCH 400/493] add usage example to ContractConstructorDecoder docs --- crates/lang/src/reflect/dispatch.rs | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 00cfeec2c2..0d2a90be40 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -423,6 +423,75 @@ pub trait ContractMessageDecoder { /// /// The decoder follows the ink! calling ABI where all ink! constructor calls start with /// 4 bytes dedicated to the ink! constructor selector followed by the SCALE encoded parameters. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::ContractConstructorDecoder; +/// # use ink_lang::selector_bytes; +/// # use scale::{Encode, Decode}; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor1() -> Self { Self {} } +/// +/// #[ink(constructor)] +/// pub fn constructor2(input1: bool, input2: i32) -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// // Call to `constructor1` without input parameters. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("constructor1")); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_ok() +/// ); +/// } +/// // Call to `constructor2` with 2 parameters. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("constructor2")); +/// input_bytes.extend(true.encode()); +/// input_bytes.extend(42i32.encode()); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_ok() +/// ); +/// } +/// // Call with invalid ink! constructor selector. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("non_existing_constructor")); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_err() +/// ); +/// } +/// // Call with invalid ink! constructor parameters. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("constructor2")); +/// assert!( +/// <::Type as Decode>::decode( +/// &mut &input_bytes[..]).is_err() +/// ); +/// } +/// } +/// ``` pub trait ContractConstructorDecoder { /// The ink! smart contract constructor decoder type. type Type: scale::Decode + ExecuteDispatchable; From 95388bbe680ea2a584d6174b28f37aeb41ef3214 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 19:36:09 +0200 Subject: [PATCH 401/493] improve docs of some reflect types in ink_lang --- crates/lang/src/reflect/dispatch.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 0d2a90be40..33aa554ea1 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -165,9 +165,13 @@ pub trait ContractDispatchableConstructors { const IDS: [u32; AMOUNT]; } -/// Implemented by the ink! message namespace type for every ink! message selector ID. +/// Stores various information of the respective dispatchable ink! message. /// -/// Stores various information properties of the respective dispatchable ink! message. +/// # Note +/// +/// This trait is implemented by ink! for every dispatchable ink! message +/// of the root ink! smart contract. The `ID` used in the trait reflects the +/// chosen or derived selector of the dispatchable ink! message. /// /// # Usage /// @@ -259,10 +263,14 @@ pub trait DispatchableMessageInfo { const LABEL: &'static str; } -/// Implemented by the ink! constructor namespace type for every ink! constructor selector ID. -/// /// Stores various information of the respective dispatchable ink! constructor. /// +/// # Note +/// +/// This trait is implemented by ink! for every dispatchable ink! constructor +/// of the root ink! smart contract. The `ID` used in the trait reflects the +/// chosen or derived selector of the dispatchable ink! constructor. +/// /// # Usage /// /// ``` From cad68767940bf39672803ba91f842cc44874764e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 19:37:11 +0200 Subject: [PATCH 402/493] improve docs --- crates/lang/src/reflect/dispatch.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 33aa554ea1..71c79f4470 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -505,9 +505,11 @@ pub trait ContractConstructorDecoder { type Type: scale::Decode + ExecuteDispatchable; } -/// Implemented by the ink! smart contract message or constructor decoder. -/// /// Starts the execution of the respective ink! message or constructor call. +/// +/// # Note +/// +/// Implemented by the ink! smart contract message or constructor decoder. pub trait ExecuteDispatchable { /// Executes the ink! smart contract message or constructor. fn execute_dispatchable(self) -> Result<(), DispatchError>; From ce59d8f7bf488bd8a6c9153fbe3a20cdcb4c24d2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:20:47 +0200 Subject: [PATCH 403/493] move TraitMessageInfo into reflect submodule --- crates/lang/codegen/src/generator/dispatch.rs | 6 +-- .../lang/codegen/src/generator/item_impls.rs | 4 +- crates/lang/codegen/src/generator/metadata.rs | 4 +- .../src/generator/trait_def/trait_registry.rs | 6 +-- .../ui/trait_def/pass/payable_message.rs | 8 +-- crates/lang/src/lib.rs | 1 - crates/lang/src/reflect/mod.rs | 5 +- crates/lang/src/reflect/trait_def/info.rs | 52 +++++++++++++++++++ crates/lang/src/reflect/trait_def/mod.rs | 6 ++- crates/lang/src/traits.rs | 39 -------------- 10 files changed, 75 insertions(+), 56 deletions(-) create mode 100644 crates/lang/src/reflect/trait_def/info.rs diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index ccc5fb3826..aed9546e62 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -179,7 +179,7 @@ impl Dispatch<'_> { ::core::primitive::u32::from_be_bytes( <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR + as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::SELECTOR ) } ) @@ -345,12 +345,12 @@ impl Dispatch<'_> { let payable = quote! {{ <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE + as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR + as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; let selector_id = quote! {{ ::core::primitive::u32::from_be_bytes(#selector) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index fa6be8a367..775128810f 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -86,7 +86,7 @@ impl ItemImpls<'_> { const _: ::ink_lang::codegen::TraitMessagePayable<{ <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo<#message_local_id>>::PAYABLE + as ::ink_lang::reflect::TraitMessageInfo<#message_local_id>>::PAYABLE }> = ::ink_lang::codegen::TraitMessagePayable::; ) }); @@ -97,7 +97,7 @@ impl ItemImpls<'_> { ::core::primitive::u32::from_be_bytes( <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo<#message_local_id>>::SELECTOR + as ::ink_lang::reflect::TraitMessageInfo<#message_local_id>>::SELECTOR ) }> = ::ink_lang::codegen::TraitMessageSelector::<#given_selector>; ) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index a7f4314492..8599e3b721 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -269,12 +269,12 @@ impl Metadata<'_> { let is_payable = quote! {{ <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo<#local_id>>::PAYABLE + as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo<#local_id>>::SELECTOR + as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; let ret_ty = Self::generate_return_type(message.output()); quote_spanned!(message_span=> diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index a77bd05c79..f7b9ee84e8 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -261,7 +261,7 @@ impl TraitRegistry<'_> { ) } - /// Generates the [`::ink_lang::TraitMessageInfo`] implementations for all + /// Generates the [`::ink_lang::reflect::TraitMessageInfo`] implementations for all /// ink! messages defined by the ink! trait definition. fn generate_info_for_trait_messages(&self) -> TokenStream2 { let span = self.span(); @@ -277,7 +277,7 @@ impl TraitRegistry<'_> { ) } - /// Generates the [`::ink_lang::TraitMessageInfo`] implementation for a single + /// Generates the [`::ink_lang::reflect::TraitMessageInfo`] implementation for a single /// ink! message defined by the ink! trait definition. fn generate_info_for_trait_for_message( &self, @@ -290,7 +290,7 @@ impl TraitRegistry<'_> { let selector_bytes = selector.hex_lits(); let is_payable = message.ink_attrs().is_payable(); quote_spanned!(span=> - impl ::ink_lang::TraitMessageInfo<#local_id> for #trait_info_ident { + impl ::ink_lang::reflect::TraitMessageInfo<#local_id> for #trait_info_ident { const PAYABLE: ::core::primitive::bool = #is_payable; const SELECTOR: [::core::primitive::u8; 4usize] = [ #( #selector_bytes ),* ]; diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 7901d53d11..40aee51633 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -47,23 +47,23 @@ fn main() { assert!( <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo>::PAYABLE, + as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, ); assert!( <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo>::PAYABLE, + as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, ); assert_eq!( <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo>::PAYABLE, + as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, false ); assert_eq!( <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::TraitMessageInfo>::PAYABLE, + as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, false ); } diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 1a9721441b..e66a812982 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -56,7 +56,6 @@ pub use self::{ TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, - TraitMessageInfo, TraitModulePath, TraitUniqueId, }, diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index 1ef68f9274..89ca3a9704 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -37,5 +37,8 @@ pub use self::{ DispatchableMessageInfo, ExecuteDispatchable, }, - trait_def::TraitDefinitionRegistry, + trait_def::{ + TraitDefinitionRegistry, + TraitMessageInfo, + }, }; diff --git a/crates/lang/src/reflect/trait_def/info.rs b/crates/lang/src/reflect/trait_def/info.rs new file mode 100644 index 0000000000..c377a9ce3d --- /dev/null +++ b/crates/lang/src/reflect/trait_def/info.rs @@ -0,0 +1,52 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Stores information for every ink! trait message of an ink! trait definition. +/// +/// This information includes if the ink! trait message is payable +/// as well as its derived or manually specified selector. +/// +/// In the future this info trait might be extended to contain +/// more information about a single ink! trait message. +/// +/// The information provided through this trait can be used on the +/// implementer side of an ink! trait to check and guard certain +/// properties on a Rust type system level. This is important since +/// ink! cannot be guaranteed to have both the ink! trait definition +/// and all of its implementers under its scope and radar. +/// +/// # Note +/// +/// - The `TraitMessageInfo` is implemented by the +/// automatically generated ink! trait definition information object +/// associated to the ink! trait definition at hand. +/// - For every ink! trait message defined by the ink! trait definition +/// the associated ink! trait definition information object implements +/// this trait given the `TRAIT_LOCAL_MESSAGE_ID` of each ink! trait +/// message respectively. +/// - The local IDs uniquely identifying all the ink! trait messages +/// of the ink! trait definition are computed solely using the Rust +/// identifier of the ink! trait message which can be derived from +/// ink! implementation blocks in order to query the information +/// stored by this ink! trait information object trait implementation. +pub trait TraitMessageInfo { + /// Is `true` if the ink! trait message has been annotated with `#[ink(payable)]`. + const PAYABLE: bool; + + /// The unique selector of the ink! trait message. + /// + /// This might have been adjusted using `#[ink(selector = N:u32)]` at the + /// ink! trait definition site. + const SELECTOR: [u8; 4]; +} diff --git a/crates/lang/src/reflect/trait_def/mod.rs b/crates/lang/src/reflect/trait_def/mod.rs index ee8db133d3..cf496d7292 100644 --- a/crates/lang/src/reflect/trait_def/mod.rs +++ b/crates/lang/src/reflect/trait_def/mod.rs @@ -12,6 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod info; mod registry; -pub use self::registry::TraitDefinitionRegistry; +pub use self::{ + info::TraitMessageInfo, + registry::TraitDefinitionRegistry, +}; diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index e52b7c6051..2a24bd7d90 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -105,42 +105,3 @@ pub trait TraitCallForwarderFor { /// This is used for the long-hand calling syntax. fn build_mut(&mut self) -> &mut ::Builder; } - -/// Stores information for every ink! trait message of an ink! trait definition. -/// -/// This information includes if the ink! trait message is payable -/// as well as its derived or manually specified selector. -/// -/// In the future this info trait might be extended to contain -/// more information about a single ink! trait message. -/// -/// The information provided through this trait can be used on the -/// implementer side of an ink! trait to check and guard certain -/// properties on a Rust type system level. This is important since -/// ink! cannot be guaranteed to have both the ink! trait definition -/// and all of its implementers under its scope and radar. -/// -/// # Note -/// -/// - The `TraitMessageInfo` is implemented by the -/// automatically generated ink! trait definition information object -/// associated to the ink! trait definition at hand. -/// - For every ink! trait message defined by the ink! trait definition -/// the associated ink! trait definition information object implements -/// this trait given the `TRAIT_LOCAL_MESSAGE_ID` of each ink! trait -/// message respectively. -/// - The local IDs uniquely identifying all the ink! trait messages -/// of the ink! trait definition are computed solely using the Rust -/// identifier of the ink! trait message which can be derived from -/// ink! implementation blocks in order to query the information -/// stored by this ink! trait information object trait implementation. -pub trait TraitMessageInfo { - /// Is `true` if the ink! trait message has been annotated with `#[ink(payable)]`. - const PAYABLE: bool; - - /// The unique selector of the ink! trait message. - /// - /// This might have been adjusted using `#[ink(selector = N:u32)]` at the - /// ink! trait definition site. - const SELECTOR: [u8; 4]; -} From b2696eefa0053d91bda2df118ccdbf29a375e8f0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:21:05 +0200 Subject: [PATCH 404/493] remove invalid static_assertions imports --- crates/metadata/src/layout/tests.rs | 1 - crates/metadata/src/tests.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/crates/metadata/src/layout/tests.rs b/crates/metadata/src/layout/tests.rs index 4137f63119..fe8a25339d 100644 --- a/crates/metadata/src/layout/tests.rs +++ b/crates/metadata/src/layout/tests.rs @@ -14,7 +14,6 @@ use super::*; use ink_primitives::KeyPtr; -use pretty_assertions::assert_eq; #[test] fn layout_key_works() { diff --git a/crates/metadata/src/tests.rs b/crates/metadata/src/tests.rs index 91a5991ec6..47a03814d8 100644 --- a/crates/metadata/src/tests.rs +++ b/crates/metadata/src/tests.rs @@ -13,7 +13,6 @@ // limitations under the License. use super::*; -use pretty_assertions::assert_eq; use scale_info::{ IntoPortable, Registry, From 5b44a9381c218a6d16d49e8e689b27f98dfe89fc Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:45:04 +0200 Subject: [PATCH 405/493] take &mut [u8; 32] instead of &mut [u8] for blake2b output --- crates/lang/ir/src/ir/blake2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/blake2.rs b/crates/lang/ir/src/ir/blake2.rs index 46bf73d0c6..43bd5f6b83 100644 --- a/crates/lang/ir/src/ir/blake2.rs +++ b/crates/lang/ir/src/ir/blake2.rs @@ -17,7 +17,7 @@ use proc_macro2::TokenStream as TokenStream2; use syn::spanned::Spanned as _; /// Computes the BLAKE-2b 256-bit hash for the given input and stores it in output. -pub fn blake2b_256(input: &[u8], output: &mut [u8]) { +pub fn blake2b_256(input: &[u8], output: &mut [u8; 32]) { use ::blake2::digest::{ Update as _, VariableOutput as _, From d06ae5d6528aae828d24c1a7a7c80a1c4bb7bdba Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:45:32 +0200 Subject: [PATCH 406/493] make local_id of trait_def equal to selector of the message identifier --- crates/lang/ir/src/ir/utils.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/lang/ir/src/ir/utils.rs b/crates/lang/ir/src/ir/utils.rs index 64985e90cd..b69558da9b 100644 --- a/crates/lang/ir/src/ir/utils.rs +++ b/crates/lang/ir/src/ir/utils.rs @@ -13,6 +13,7 @@ // limitations under the License. use crate::format_err; +use super::Selector; use proc_macro2::Span; use syn::spanned::Spanned as _; @@ -47,11 +48,10 @@ pub fn ensure_pub_visibility( /// /// # Note /// -/// Used from within ink! trait definitions as well as ink! trait implementation blocks. +/// - The returned value is equal to the selector of the message identifier. +/// - Used from within ink! trait definitions as well as ink! trait implementation blocks. pub fn local_message_id(ident: &syn::Ident) -> u32 { - let buffer = format!("message::{}", ident).into_bytes(); - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = ::digest(&buffer).split(); - let head_32: [u8; 4] = head_32.into(); - u32::from_be_bytes(head_32) + let input = ident.to_string().into_bytes(); + let selector = Selector::new(&input); + selector.into_be_u32() } From 95604c1aaca96d179b0667843a17a63c3f250281 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:45:59 +0200 Subject: [PATCH 407/493] modernize payable_message UI trait_def passing test --- .../ui/trait_def/pass/payable_message.rs | 52 +++++++------------ 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs index 40aee51633..6f05e8574b 100644 --- a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs +++ b/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs @@ -15,55 +15,39 @@ pub trait PayableDefinition { fn unpayable_mut(&mut self); } -/// Computed using `local_id("payable")`. -const PAYABLE_ID: u32 = 0xFDDBE704; +use ink_lang::selector_id; -/// Computed using `local_id("payable_mut")`. -const PAYABLE_MUT_ID: u32 = 0x1CE6275F; - -/// Computed using `local_id("unpayable")`. -const UNPAYABLE_ID: u32 = 0x511647A5; - -/// Computed using `local_id("unpayable_mut")`. -const UNPAYABLE_MUT_ID: u32 = 0x4A60F1E1; +const PAYABLE_ID: u32 = selector_id!("payable"); +const PAYABLE_MUT_ID: u32 = selector_id!("payable_mut"); +const UNPAYABLE_ID: u32 = selector_id!("unpayable"); +const UNPAYABLE_MUT_ID: u32 = selector_id!("unpayable_mut"); fn main() { - use ink_lang_ir as ir; - /// Returns the local ID for the given name. - #[allow(dead_code)] - fn local_id(name: &str) -> u32 { - ir::utils::local_message_id(&syn::Ident::new( - name, - proc_macro2::Span::call_site(), - )) - } - // Uncomment these in order to print out the local IDs of - // all the ink! trait messages for this test. - // - // println!("local_id(\"payable\") = {:X}", local_id("payable")); - // println!("local_id(\"payable_mut\") = {:X}", local_id("payable_mut")); - // println!("local_id(\"unpayable\") = {:X}", local_id("unpayable")); - // println!("local_id(\"unpayable_mut\") = {:X}", local_id("unpayable_mut")); + use ink_env::DefaultEnvironment; + use ink_lang::reflect::{ + TraitDefinitionRegistry, + TraitMessageInfo, + }; assert!( - <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + < as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, + as TraitMessageInfo>::PAYABLE, ); assert!( - <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + < as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, + as TraitMessageInfo>::PAYABLE, ); assert_eq!( - <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + < as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, + as TraitMessageInfo>::PAYABLE, false ); assert_eq!( - <<::ink_lang::reflect::TraitDefinitionRegistry<::ink_env::DefaultEnvironment> + < as PayableDefinition>::__ink_TraitInfo - as ::ink_lang::reflect::TraitMessageInfo>::PAYABLE, + as TraitMessageInfo>::PAYABLE, false ); } From f579a9f1830d9be17c48345f6fdfc748b8f84e58 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:46:30 +0200 Subject: [PATCH 408/493] add usage example to TraitMessageInfo trait --- crates/lang/src/reflect/trait_def/info.rs | 49 +++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/crates/lang/src/reflect/trait_def/info.rs b/crates/lang/src/reflect/trait_def/info.rs index c377a9ce3d..5aabce2fcb 100644 --- a/crates/lang/src/reflect/trait_def/info.rs +++ b/crates/lang/src/reflect/trait_def/info.rs @@ -40,6 +40,55 @@ /// identifier of the ink! trait message which can be derived from /// ink! implementation blocks in order to query the information /// stored by this ink! trait information object trait implementation. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// +/// #[ink::trait_definition] +/// pub trait InkTrait { +/// #[ink(message)] +/// fn trait_message_1(&self); +/// +/// #[ink(message, payable, selector = 0xC0DECAFE)] +/// fn trait_message_2(&mut self); +/// } +/// +/// #[ink::contract] +/// pub mod contract { +/// use super::InkTrait; +/// +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Contract {} } +/// } +/// +/// impl InkTrait for Contract { +/// #[ink(message)] +/// fn trait_message_1(&self) {} +/// +/// #[ink(message)] +/// fn trait_message_2(&mut self) {} +/// } +/// } +/// +/// # use ink_lang::reflect::TraitDefinitionRegistry; +/// # use ink_lang::reflect::TraitMessageInfo; +/// # use ink_env::DefaultEnvironment; +/// # use ink_lang::selector_id; +/// +/// fn main() { +/// assert_eq!( +/// < as InkTrait>::__ink_TraitInfo +/// as TraitMessageInfo<{selector_id!("trait_message_1")}>>::PAYABLE, +/// false, +/// ); +/// } +/// ``` pub trait TraitMessageInfo { /// Is `true` if the ink! trait message has been annotated with `#[ink(payable)]`. const PAYABLE: bool; From 466eaa74652a3db2604942a26aec52a608604262 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:59:07 +0200 Subject: [PATCH 409/493] fix composed selector calculation for empty ink! trait namespaces --- crates/lang/ir/src/ir/selector.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index b4151b77ea..d0443cc514 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -121,7 +121,11 @@ impl Selector { let namespace = trait_prefix.namespace_bytes(); let trait_ident = trait_prefix.trait_ident().to_string().into_bytes(); let separator = &b"::"[..]; - [namespace, &trait_ident, &fn_ident].join(separator) + if namespace.is_empty() { + [&trait_ident[..], &fn_ident[..]].join(separator) + } else { + [namespace, &trait_ident[..], &fn_ident[..]].join(separator) + } } None => fn_ident.to_vec(), }; From 21a613f20d406261ac8f16d72a8a920199b529ca Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:59:22 +0200 Subject: [PATCH 410/493] apply rustfmt --- crates/lang/ir/src/ir/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/utils.rs b/crates/lang/ir/src/ir/utils.rs index b69558da9b..9ffefbd8c5 100644 --- a/crates/lang/ir/src/ir/utils.rs +++ b/crates/lang/ir/src/ir/utils.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::format_err; use super::Selector; +use crate::format_err; use proc_macro2::Span; use syn::spanned::Spanned as _; From 8a14d3795c87a45b504c429eed682f27aea4f0fc Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 22:59:41 +0200 Subject: [PATCH 411/493] extend usage example for TraitMessageInfo trait docs --- crates/lang/src/reflect/trait_def/info.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/lang/src/reflect/trait_def/info.rs b/crates/lang/src/reflect/trait_def/info.rs index 5aabce2fcb..30def4b3d1 100644 --- a/crates/lang/src/reflect/trait_def/info.rs +++ b/crates/lang/src/reflect/trait_def/info.rs @@ -79,7 +79,7 @@ /// # use ink_lang::reflect::TraitDefinitionRegistry; /// # use ink_lang::reflect::TraitMessageInfo; /// # use ink_env::DefaultEnvironment; -/// # use ink_lang::selector_id; +/// # use ink_lang::{selector_id, selector_bytes}; /// /// fn main() { /// assert_eq!( @@ -87,6 +87,21 @@ /// as TraitMessageInfo<{selector_id!("trait_message_1")}>>::PAYABLE, /// false, /// ); +/// assert_eq!( +/// < as InkTrait>::__ink_TraitInfo +/// as TraitMessageInfo<{selector_id!("trait_message_2")}>>::PAYABLE, +/// true, +/// ); +/// assert_eq!( +/// < as InkTrait>::__ink_TraitInfo +/// as TraitMessageInfo<{selector_id!("trait_message_1")}>>::SELECTOR, +/// selector_bytes!("InkTrait::trait_message_1") +/// ); +/// assert_eq!( +/// < as InkTrait>::__ink_TraitInfo +/// as TraitMessageInfo<{selector_id!("trait_message_2")}>>::SELECTOR, +/// [0xC0, 0xDE, 0xCA, 0xFE] +/// ); /// } /// ``` pub trait TraitMessageInfo { From 216865644cca7cf6877897128030d5b1374118e0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Mon, 4 Oct 2021 23:40:45 +0200 Subject: [PATCH 412/493] hopefully fix some weird spelling issues --- crates/lang/ir/src/ir/item_impl/callable.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index 7782d4d06d..5f4723c646 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -182,8 +182,9 @@ pub trait Callable { /// # Details /// /// Given -/// - the callable's identifier `i` -/// - the optionally set callable's selector `s` +/// +/// - the identifier `i` of the callable +/// - the optionally set selector `s` of the callable /// - the `impl` blocks trait path in case it implements a trait, `P` /// - 16 kB blocks optional user provided namespace `S` /// From 3139e705b25c49003b34ecb941abdc33af6e0e9f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 00:09:19 +0200 Subject: [PATCH 413/493] make ink! trait definitions actually use the namespace config --- crates/lang/ir/src/ir/selector.rs | 17 ++++++------- crates/lang/ir/src/ir/trait_def/item/mod.rs | 28 ++++++++++++++------- crates/lang/ir/src/ir/trait_def/mod.rs | 2 +- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index d0443cc514..cf4df3235c 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -13,10 +13,7 @@ // limitations under the License. use super::blake2::blake2b_256; -use crate::{ - literal::HexLiteral, - Namespace, -}; +use crate::literal::HexLiteral; use core::convert::TryFrom; use proc_macro2::TokenStream as TokenStream2; use std::marker::PhantomData; @@ -40,14 +37,14 @@ pub struct TraitPrefix<'a> { /// By default this is equal to the `module_path!` at the ink! trait definition site. /// It can be customized by the ink! trait definition author using `#[ink(namespace = N)]` /// ink! attribute. - namespace: &'a Namespace, + namespace: Option<&'a syn::LitStr>, /// The Rust identifier of the ink! trait definition. trait_ident: &'a syn::Ident, } impl<'a> TraitPrefix<'a> { /// Creates a new trait prefix. - pub fn new(trait_ident: &'a syn::Ident, namespace: &'a Namespace) -> Self { + pub fn new(trait_ident: &'a syn::Ident, namespace: Option<&'a syn::LitStr>) -> Self { Self { namespace, trait_ident, @@ -55,8 +52,10 @@ impl<'a> TraitPrefix<'a> { } /// Returns a shared slice over the bytes of the namespace. - pub fn namespace_bytes(&self) -> &[u8] { - self.namespace.as_bytes() + pub fn namespace_bytes(&self) -> Vec { + self.namespace + .map(|namespace| namespace.value().into_bytes()) + .unwrap_or_default() } /// Returns a shared reference to the Rust identifier of the trait. @@ -124,7 +123,7 @@ impl Selector { if namespace.is_empty() { [&trait_ident[..], &fn_ident[..]].join(separator) } else { - [namespace, &trait_ident[..], &fn_ident[..]].join(separator) + [&namespace[..], &trait_ident[..], &fn_ident[..]].join(separator) } } None => fn_ident.to_vec(), diff --git a/crates/lang/ir/src/ir/trait_def/item/mod.rs b/crates/lang/ir/src/ir/trait_def/item/mod.rs index 0ee8eb6f34..eb6882f6ef 100644 --- a/crates/lang/ir/src/ir/trait_def/item/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/item/mod.rs @@ -23,12 +23,13 @@ pub use self::{ InkTraitMessage, }, }; -use super::InkAttribute; +use super::TraitDefinitionConfig; use crate::{ ir, ir::idents_lint, Selector, }; +#[cfg(test)] use core::convert::TryFrom; use ir::TraitPrefix; use proc_macro2::{ @@ -48,15 +49,27 @@ pub struct InkItemTrait { message_selectors: HashMap, } +#[cfg(test)] impl TryFrom for InkItemTrait { type Error = syn::Error; fn try_from(item_trait: syn::ItemTrait) -> core::result::Result { + let config = TraitDefinitionConfig::default(); + Self::new(&config, item_trait) + } +} + +impl InkItemTrait { + /// Creates a new ink! item trait from the given config and trait definition. + pub fn new( + config: &TraitDefinitionConfig, + item_trait: syn::ItemTrait, + ) -> Result { idents_lint::ensure_no_ink_identifiers(&item_trait)?; Self::analyse_properties(&item_trait)?; Self::analyse_items(&item_trait)?; let mut message_selectors = >::new(); - Self::extract_selectors(&item_trait, &mut message_selectors)?; + Self::extract_selectors(config, &item_trait, &mut message_selectors)?; if message_selectors.is_empty() { return Err(format_err!( item_trait.span(), @@ -320,11 +333,12 @@ impl InkItemTrait { /// or ink! messages. Note that overlaps between ink! constructor and message /// selectors are allowed. fn extract_selectors( + config: &TraitDefinitionConfig, item_trait: &syn::ItemTrait, message_selectors: &mut HashMap, ) -> Result<()> { let mut seen_message_selectors = >::new(); - let (ink_attrs, _) = ir::sanitize_optional_attributes( + let (_ink_attrs, _) = ir::sanitize_optional_attributes( item_trait.span(), item_trait.attrs.iter().cloned(), |arg| { @@ -335,13 +349,9 @@ impl InkItemTrait { }, ) .expect("encountered unexpected invalid attributes on ink! trait definition"); - let namespace = ink_attrs - .as_ref() - .map(InkAttribute::namespace) - .flatten() - .unwrap_or_default(); + let namespace = config.namespace(); let ident = &item_trait.ident; - let trait_prefix = TraitPrefix::new(ident, &namespace); + let trait_prefix = TraitPrefix::new(ident, namespace); for callable in IterInkTraitItemsRaw::from_raw(item_trait) { let ident = callable.ident(); let ink_attrs = callable.ink_attrs(); diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index b2bf05d6d8..c0998fe187 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -45,7 +45,7 @@ impl InkTraitDefinition { let parsed_config = syn::parse2::(config)?; let parsed_item = syn::parse2::(input)?; let config = TraitDefinitionConfig::try_from(parsed_config)?; - let item = InkItemTrait::try_from(parsed_item)?; + let item = InkItemTrait::new(&config, parsed_item)?; Ok(Self { config, item }) } From 8c3a5cbadf17a25512f34314143b8fe99f94e1c9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 00:09:41 +0200 Subject: [PATCH 414/493] extend usage example for TraitMessageInfo docs --- crates/lang/src/reflect/trait_def/info.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/crates/lang/src/reflect/trait_def/info.rs b/crates/lang/src/reflect/trait_def/info.rs index 30def4b3d1..c0e8d3ee0b 100644 --- a/crates/lang/src/reflect/trait_def/info.rs +++ b/crates/lang/src/reflect/trait_def/info.rs @@ -55,9 +55,15 @@ /// fn trait_message_2(&mut self); /// } /// +/// #[ink::trait_definition(namespace = "foo")] +/// pub trait InkTrait2 { +/// #[ink(message)] +/// fn trait_message(&self); +/// } +/// /// #[ink::contract] /// pub mod contract { -/// use super::InkTrait; +/// use super::{InkTrait, InkTrait2}; /// /// #[ink(storage)] /// pub struct Contract {} @@ -74,6 +80,11 @@ /// #[ink(message)] /// fn trait_message_2(&mut self) {} /// } +/// +/// impl InkTrait2 for Contract { +/// #[ink(message)] +/// fn trait_message(&self) {} +/// } /// } /// /// # use ink_lang::reflect::TraitDefinitionRegistry; @@ -93,6 +104,11 @@ /// true, /// ); /// assert_eq!( +/// < as InkTrait2>::__ink_TraitInfo +/// as TraitMessageInfo<{selector_id!("trait_message")}>>::PAYABLE, +/// false, +/// ); +/// assert_eq!( /// < as InkTrait>::__ink_TraitInfo /// as TraitMessageInfo<{selector_id!("trait_message_1")}>>::SELECTOR, /// selector_bytes!("InkTrait::trait_message_1") @@ -102,6 +118,11 @@ /// as TraitMessageInfo<{selector_id!("trait_message_2")}>>::SELECTOR, /// [0xC0, 0xDE, 0xCA, 0xFE] /// ); +/// assert_eq!( +/// < as InkTrait2>::__ink_TraitInfo +/// as TraitMessageInfo<{selector_id!("trait_message")}>>::SELECTOR, +/// selector_bytes!("foo::InkTrait2::trait_message") +/// ); /// } /// ``` pub trait TraitMessageInfo { From f980060677d52d52cf94530e14bbb1a3f3a4d6b9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 18:46:05 +0200 Subject: [PATCH 415/493] rework some ink! trait definition passing UI tests --- .../ui/trait_def/pass/custom_selector.rs | 16 ------- .../ui/trait_def/pass/invalid_selector_3.rs | 9 ---- .../ui/trait_def/pass/valid_selectors.rs | 39 +++++++++++++++++ .../pass/valid_selectors_namespace.rs | 42 +++++++++++++++++++ 4 files changed, 81 insertions(+), 25 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs delete mode 100644 crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/valid_selectors.rs create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/valid_selectors_namespace.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs b/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs deleted file mode 100644 index 6cb9dbaff7..0000000000 --- a/crates/lang/macro/tests/ui/trait_def/pass/custom_selector.rs +++ /dev/null @@ -1,16 +0,0 @@ -use ink_lang as ink; - -#[ink::trait_definition] -pub trait CustomSelector { - #[ink(message, selector = 1)] - fn selector1(&self); - #[ink(message, selector = 2)] - fn selector1_mut(&mut self); - - #[ink(message, selector = 0x0000_0003)] - fn selector2(&self); - #[ink(message, selector = 0x0000_0004)] - fn selector2_mut(&mut self); -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs b/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs deleted file mode 100644 index bb8f866246..0000000000 --- a/crates/lang/macro/tests/ui/trait_def/pass/invalid_selector_3.rs +++ /dev/null @@ -1,9 +0,0 @@ -use ink_lang as ink; - -#[ink::trait_definition] -pub trait TraitDefinition { - #[ink(message, selector = 0xC0DECAFE)] - fn message(&self); -} - -fn main() {} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors.rs b/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors.rs new file mode 100644 index 0000000000..fc00d76e05 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors.rs @@ -0,0 +1,39 @@ +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message1(&self); + + #[ink(message, selector = 42)] + fn message2(&self); + + #[ink(message, selector = 0xC0DECAFE)] + fn message3(&mut self); +} + +use ink_env::DefaultEnvironment; +use ink_lang::{ + reflect::{ + TraitDefinitionRegistry, + TraitMessageInfo, + }, + selector_bytes, + selector_id, +}; + +fn main() { + macro_rules! assert_selector_eq { + ( $message_id:literal, $expected_selector:expr $(,)? ) => { + assert_eq!( + < as TraitDefinition>::__ink_TraitInfo + as TraitMessageInfo<{selector_id!($message_id)}>>::SELECTOR, + $expected_selector + ); + } + } + + assert_selector_eq!("message1", selector_bytes!("TraitDefinition::message1"),); + assert_selector_eq!("message2", [0, 0, 0, 42],); + assert_selector_eq!("message3", [0xC0, 0xDE, 0xCA, 0xFE],); +} diff --git a/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors_namespace.rs b/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors_namespace.rs new file mode 100644 index 0000000000..402ee89682 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors_namespace.rs @@ -0,0 +1,42 @@ +use ink_lang as ink; + +#[ink::trait_definition(namespace = "foo")] +pub trait TraitDefinition { + #[ink(message)] + fn message1(&self); + + #[ink(message, selector = 42)] + fn message2(&self); + + #[ink(message, selector = 0xC0DECAFE)] + fn message3(&mut self); +} + +use ink_env::DefaultEnvironment; +use ink_lang::{ + reflect::{ + TraitDefinitionRegistry, + TraitMessageInfo, + }, + selector_bytes, + selector_id, +}; + +fn main() { + macro_rules! assert_selector_eq { + ( $message_id:literal, $expected_selector:expr $(,)? ) => { + assert_eq!( + < as TraitDefinition>::__ink_TraitInfo + as TraitMessageInfo<{selector_id!($message_id)}>>::SELECTOR, + $expected_selector + ); + } + } + + assert_selector_eq!( + "message1", + selector_bytes!("foo::TraitDefinition::message1"), + ); + assert_selector_eq!("message2", [0, 0, 0, 42],); + assert_selector_eq!("message3", [0xC0, 0xDE, 0xCA, 0xFE],); +} From cfbc35440c35beab5f1603ed1a0dfd84a7533c06 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 18:46:27 +0200 Subject: [PATCH 416/493] add new passing UI test for ink! trait definitions concerning namespaces --- .../pass/avoid_overlap_with_namespace.rs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs b/crates/lang/macro/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs new file mode 100644 index 0000000000..8c92867e21 --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs @@ -0,0 +1,54 @@ +mod foo { + use ink_lang as ink; + + #[ink::trait_definition(namespace = "foo")] + pub trait TraitDefinition { + #[ink(message)] + fn message(&self); + } +} + +mod bar { + use ink_lang as ink; + + #[ink::trait_definition(namespace = "bar")] + pub trait TraitDefinition { + #[ink(message)] + fn message(&self); + } +} + +use bar::TraitDefinition as TraitDefinition2; +use foo::TraitDefinition as TraitDefinition1; +use ink_env::DefaultEnvironment; +use ink_lang::{ + reflect::{ + TraitDefinitionRegistry, + TraitMessageInfo, + }, + selector_bytes, + selector_id, +}; + +fn main() { + macro_rules! assert_selector_eq { + ( $trait_ident:path, $message_id:literal, $expected_selector:expr $(,)? ) => { + assert_eq!( + < as $trait_ident>::__ink_TraitInfo + as TraitMessageInfo<{selector_id!($message_id)}>>::SELECTOR, + $expected_selector + ); + } + } + + assert_selector_eq!( + TraitDefinition1, + "message", + selector_bytes!("foo::TraitDefinition::message"), + ); + assert_selector_eq!( + TraitDefinition2, + "message", + selector_bytes!("bar::TraitDefinition::message"), + ); +} From 60de455164240cc16479627c4809ee1fc8b4ae0f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 18:46:56 +0200 Subject: [PATCH 417/493] add fail UI tests for ink! trait definitions concerning overlapping selectors --- .../fail/trait-message-selector-overlap-1.rs | 51 +++++++++++++++++++ .../trait-message-selector-overlap-1.stderr | 17 +++++++ .../fail/trait-message-selector-overlap-2.rs | 51 +++++++++++++++++++ .../trait-message-selector-overlap-2.stderr | 17 +++++++ 4 files changed, 136 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs new file mode 100644 index 0000000000..f402c766d1 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs @@ -0,0 +1,51 @@ +mod foo { + use ink_lang as ink; + + #[ink::trait_definition] + pub trait TraitDefinition { + #[ink(message)] + fn message(&self); + } +} + +mod bar { + use ink_lang as ink; + + #[ink::trait_definition] + pub trait TraitDefinition { + #[ink(message)] + fn message(&self); + } +} + +use ink_lang as ink; + +#[ink::contract] +pub mod contract { + use super::{ + bar::TraitDefinition as TraitDefinition2, + foo::TraitDefinition as TraitDefinition1, + }; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl TraitDefinition1 for Contract { + #[ink(message)] + fn message(&self) {} + } + + impl TraitDefinition2 for Contract { + #[ink(message)] + fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr new file mode 100644 index 0000000000..faa5bac123 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr @@ -0,0 +1,17 @@ +error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1083895717_u32>` for type `contract::Contract` + --> $DIR/trait-message-selector-overlap-1.rs:47:9 + | +42 | fn message(&self) {} + | ----------------- first implementation here +... +47 | fn message(&self) {} + | ^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::Contract` + +error[E0119]: conflicting implementations of trait `ink_lang::TraitCallForwarderFor<3872610552_u32>` for type `contract::_::CallBuilder` + --> $DIR/trait-message-selector-overlap-1.rs:45:5 + | +40 | impl TraitDefinition1 for Contract { + | ---------------------------------- first implementation here +... +45 | impl TraitDefinition2 for Contract { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs new file mode 100644 index 0000000000..8bcb70f49d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs @@ -0,0 +1,51 @@ +mod foo { + use ink_lang as ink; + + #[ink::trait_definition(namespace = "same")] + pub trait TraitDefinition { + #[ink(message)] + fn message(&self); + } +} + +mod bar { + use ink_lang as ink; + + #[ink::trait_definition(namespace = "same")] + pub trait TraitDefinition { + #[ink(message)] + fn message(&self); + } +} + +use ink_lang as ink; + +#[ink::contract] +pub mod contract { + use super::{ + bar::TraitDefinition as TraitDefinition2, + foo::TraitDefinition as TraitDefinition1, + }; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl TraitDefinition1 for Contract { + #[ink(message)] + fn message(&self) {} + } + + impl TraitDefinition2 for Contract { + #[ink(message)] + fn message(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr new file mode 100644 index 0000000000..be529d1f89 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr @@ -0,0 +1,17 @@ +error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1518209067_u32>` for type `contract::Contract` + --> $DIR/trait-message-selector-overlap-2.rs:47:9 + | +42 | fn message(&self) {} + | ----------------- first implementation here +... +47 | fn message(&self) {} + | ^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::Contract` + +error[E0119]: conflicting implementations of trait `ink_lang::TraitCallForwarderFor<687202556_u32>` for type `contract::_::CallBuilder` + --> $DIR/trait-message-selector-overlap-2.rs:45:5 + | +40 | impl TraitDefinition1 for Contract { + | ---------------------------------- first implementation here +... +45 | impl TraitDefinition2 for Contract { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` From 6ab791256c32c80d1487d518bd92b2d03814f1ff Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 19:02:38 +0200 Subject: [PATCH 418/493] move ContractName into reflect sub-module and add docs and usage example --- crates/lang/codegen/src/generator/storage.rs | 2 +- crates/lang/src/contract_ref.rs | 6 --- crates/lang/src/lib.rs | 1 - crates/lang/src/reflect/contract.rs | 53 ++++++++++++++++++++ crates/lang/src/reflect/mod.rs | 2 + 5 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 crates/lang/src/reflect/contract.rs diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index 4b835e7508..da39f06d60 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -103,7 +103,7 @@ impl Storage<'_> { } const _: () = { - impl ::ink_lang::ContractName for #ident { + impl ::ink_lang::reflect::ContractName for #ident { const NAME: &'static str = ::core::stringify!(#ident); } }; diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index f1124c79fe..77213f156b 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -39,9 +39,3 @@ pub trait ContractCallBuilder { /// The generated contract call builder type. type Type; } - -/// Trait to inform about the name of an ink! smart contract. -pub trait ContractName { - /// The name of the ink! smart contract. - const NAME: &'static str; -} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index e66a812982..2da318ea82 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -37,7 +37,6 @@ pub use self::{ }, contract_ref::{ ContractCallBuilder, - ContractName, ContractReference, ToAccountId, }, diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs new file mode 100644 index 0000000000..6bae2c85d6 --- /dev/null +++ b/crates/lang/src/reflect/contract.rs @@ -0,0 +1,53 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Stores the name of the ink! smart contract. +/// +/// # Note +/// +/// The name is the identifier of the `#[ink(storage)]` annotated `struct`. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// # use ink_lang::reflect::ContractName; +/// assert_eq!( +/// ::NAME, +/// "Contract", +/// ); +/// } +/// ``` +pub trait ContractName { + /// The name of the ink! smart contract. + const NAME: &'static str; +} diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index 89ca3a9704..d2e0d60760 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -23,10 +23,12 @@ //! contract authors as well as they allow to inspect compile time information //! about the ink! smart contract at hand. +mod contract; mod dispatch; mod trait_def; pub use self::{ + contract::ContractName, dispatch::{ ContractAmountDispatchables, ContractConstructorDecoder, From 03e8fb3c74e530c846acb7417480dc41d46ef90d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:05:32 +0200 Subject: [PATCH 419/493] move ContractEnv trait to reflect module and add extensive docs and usage examples --- .../generator/as_dependency/call_builder.rs | 4 +- .../generator/as_dependency/contract_ref.rs | 4 +- crates/lang/codegen/src/generator/dispatch.rs | 8 +- crates/lang/codegen/src/generator/env.rs | 14 +-- crates/lang/codegen/src/generator/events.rs | 2 +- .../lang/codegen/src/generator/item_impls.rs | 4 +- crates/lang/codegen/src/generator/metadata.rs | 4 +- crates/lang/codegen/src/generator/storage.rs | 4 +- .../src/generator/trait_def/call_builder.rs | 2 +- .../src/generator/trait_def/call_forwarder.rs | 2 +- .../src/generator/trait_def/definition.rs | 2 +- crates/lang/src/codegen/dispatch/execution.rs | 2 +- crates/lang/src/env_access.rs | 6 -- crates/lang/src/lib.rs | 1 - crates/lang/src/reflect/contract.rs | 92 +++++++++++++++++++ crates/lang/src/reflect/mod.rs | 5 +- crates/lang/src/reflect/trait_def/registry.rs | 7 +- examples/multisig_plain/lib.rs | 4 +- 18 files changed, 129 insertions(+), 38 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 50ce755918..b28160bc11 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -106,8 +106,8 @@ impl CallBuilder<'_> { type Type = #cb_ident; } - impl ::ink_lang::ContractEnv for #cb_ident { - type Env = <#storage_ident as ::ink_lang::ContractEnv>::Env; + impl ::ink_lang::reflect::ContractEnv for #cb_ident { + type Env = <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env; } }; ) diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 8e19b3a75d..e3a2a2d30c 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -111,8 +111,8 @@ impl ContractRef<'_> { type Type = #ref_ident; } - impl ::ink_lang::ContractEnv for #ref_ident { - type Env = <#storage_ident as ::ink_lang::ContractEnv>::Env; + impl ::ink_lang::reflect::ContractEnv for #ref_ident { + type Env = <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env; } }; ) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index aed9546e62..5e8b519a2e 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -177,7 +177,7 @@ impl Dispatch<'_> { quote_spanned!(span=> { ::core::primitive::u32::from_be_bytes( - <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::SELECTOR ) @@ -343,12 +343,12 @@ impl Dispatch<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let payable = quote! {{ - <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; @@ -415,7 +415,7 @@ impl Dispatch<'_> { #[no_mangle] fn call() { if !#any_message_accept_payment { - ::ink_lang::codegen::deny_payment::<<#storage_ident as ::ink_lang::ContractEnv>::Env>() + ::ink_lang::codegen::deny_payment::<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env>() .unwrap_or_else(|error| ::core::panic!("{}", error)) } ::ink_env::decode_input::< diff --git a/crates/lang/codegen/src/generator/env.rs b/crates/lang/codegen/src/generator/env.rs index bb9682f1cd..e1396b016f 100644 --- a/crates/lang/codegen/src/generator/env.rs +++ b/crates/lang/codegen/src/generator/env.rs @@ -28,17 +28,17 @@ impl GenerateCode for Env<'_> { let env = self.contract.config().env(); let storage_ident = self.contract.module().storage().ident(); quote! { - impl ::ink_lang::ContractEnv for #storage_ident { + impl ::ink_lang::reflect::ContractEnv for #storage_ident { type Env = #env; } - type Environment = <#storage_ident as ::ink_lang::ContractEnv>::Env; + type Environment = <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env; - type AccountId = <<#storage_ident as ::ink_lang::ContractEnv>::Env as ::ink_env::Environment>::AccountId; - type Balance = <<#storage_ident as ::ink_lang::ContractEnv>::Env as ::ink_env::Environment>::Balance; - type Hash = <<#storage_ident as ::ink_lang::ContractEnv>::Env as ::ink_env::Environment>::Hash; - type Timestamp = <<#storage_ident as ::ink_lang::ContractEnv>::Env as ::ink_env::Environment>::Timestamp; - type BlockNumber = <<#storage_ident as ::ink_lang::ContractEnv>::Env as ::ink_env::Environment>::BlockNumber; + type AccountId = <<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env as ::ink_env::Environment>::AccountId; + type Balance = <<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env as ::ink_env::Environment>::Balance; + type Hash = <<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env as ::ink_env::Environment>::Hash; + type Timestamp = <<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env as ::ink_env::Environment>::Timestamp; + type BlockNumber = <<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env as ::ink_env::Environment>::BlockNumber; } } } diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index a0e3688305..c8b1b30232 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -167,7 +167,7 @@ impl<'a> Events<'a> { #[allow(non_upper_case_globals)] const __ink_MAX_EVENT_TOPICS: usize = < - <#storage_ident as ::ink_lang::ContractEnv>::Env as ::ink_env::Environment + <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env as ::ink_env::Environment >::MAX_EVENT_TOPICS; fn __ink_ensure_max_event_topics(_: T) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 775128810f..231ba5d7ab 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -84,7 +84,7 @@ impl ItemImpls<'_> { let message_guard_payable = message.is_payable().then(|| { quote_spanned!(message_span=> const _: ::ink_lang::codegen::TraitMessagePayable<{ - <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::reflect::TraitMessageInfo<#message_local_id>>::PAYABLE }> = ::ink_lang::codegen::TraitMessagePayable::; @@ -95,7 +95,7 @@ impl ItemImpls<'_> { quote_spanned!(message_span=> const _: ::ink_lang::codegen::TraitMessageSelector<{ ::core::primitive::u32::from_be_bytes( - <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::reflect::TraitMessageInfo<#message_local_id>>::SELECTOR ) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index 833e74c301..b2f0f0adfb 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -265,12 +265,12 @@ impl Metadata<'_> { let mutates = message.receiver().is_ref_mut(); let local_id = message.local_id().hex_padded_suffixed(); let is_payable = quote! {{ - <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::PAYABLE }}; let selector = quote! {{ - <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::ContractEnv>::Env> + <<::ink_lang::reflect::TraitDefinitionRegistry<<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env> as #trait_path>::__ink_TraitInfo as ::ink_lang::reflect::TraitMessageInfo<#local_id>>::SELECTOR }}; diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index da39f06d60..614edc2329 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -62,7 +62,7 @@ impl Storage<'_> { const _: () = { impl<'a> ::ink_lang::Env for &'a #storage_ident { type EnvAccess = ::ink_lang::EnvAccess< - 'a, <#storage_ident as ::ink_lang::ContractEnv>::Env>; + 'a, <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env>; fn env(self) -> Self::EnvAccess { <::EnvAccess @@ -72,7 +72,7 @@ impl Storage<'_> { impl<'a> ::ink_lang::StaticEnv for #storage_ident { type EnvAccess = ::ink_lang::EnvAccess< - 'static, <#storage_ident as ::ink_lang::ContractEnv>::Env>; + 'static, <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env>; fn env() -> Self::EnvAccess { <::EnvAccess diff --git a/crates/lang/codegen/src/generator/trait_def/call_builder.rs b/crates/lang/codegen/src/generator/trait_def/call_builder.rs index e5e9b2fc25..11d484ccc7 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_builder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_builder.rs @@ -315,7 +315,7 @@ impl CallBuilder<'_> { let builder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - impl ::ink_lang::ContractEnv for #builder_ident + impl ::ink_lang::reflect::ContractEnv for #builder_ident where E: ::ink_env::Environment, { diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index fa7b24a158..52f36d4238 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -343,7 +343,7 @@ impl CallForwarder<'_> { let forwarder_ident = self.ident(); let message_impls = self.generate_ink_trait_impl_messages(); quote_spanned!(span=> - impl ::ink_lang::ContractEnv for #forwarder_ident + impl ::ink_lang::reflect::ContractEnv for #forwarder_ident where E: ::ink_env::Environment, { diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index e4dfaf4a6e..c8e6f77424 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -60,7 +60,7 @@ impl TraitDefinition<'_> { .map(Self::generate_for_message); quote_spanned!(span => #(#attrs)* - pub trait #ident: ::ink_lang::ContractEnv { + pub trait #ident: ::ink_lang::reflect::ContractEnv { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] diff --git a/crates/lang/src/codegen/dispatch/execution.rs b/crates/lang/src/codegen/dispatch/execution.rs index 4739625c1a..36625b2952 100644 --- a/crates/lang/src/codegen/dispatch/execution.rs +++ b/crates/lang/src/codegen/dispatch/execution.rs @@ -13,7 +13,7 @@ // limitations under the License. use crate::{ - ContractEnv, + reflect::ContractEnv, DispatchError, }; use core::{ diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs index 9dabe722c9..e7180f192c 100644 --- a/crates/lang/src/env_access.rs +++ b/crates/lang/src/env_access.rs @@ -31,12 +31,6 @@ use ink_env::{ }; use ink_primitives::Key; -/// The environment of the compiled ink! smart contract. -pub trait ContractEnv { - /// The environment type. - type Env: ::ink_env::Environment; -} - /// Simplifies interaction with the host environment via `self`. /// /// # Note diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 2da318ea82..19d7689299 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -41,7 +41,6 @@ pub use self::{ ToAccountId, }, env_access::{ - ContractEnv, Env, EnvAccess, StaticEnv, diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs index 6bae2c85d6..9b9182ec90 100644 --- a/crates/lang/src/reflect/contract.rs +++ b/crates/lang/src/reflect/contract.rs @@ -51,3 +51,95 @@ pub trait ContractName { /// The name of the ink! smart contract. const NAME: &'static str; } + +/// Stores the used host environment type of the ink! smart contract. +/// +/// # Note +/// +/// The used host environment can be altered using the `env` configuration +/// parameter in the `#[ink::contract]` parameters. For example if the user +/// wanted to use an environment type definition called `MyEnvironment` they +/// issue the ink! smart contract as follows: +/// +/// ``` +/// #[ink::contract(env = MyEnvironment)] +/// ``` +/// +/// # Usage: Default Environment +/// +/// ``` +/// use ink_lang as ink; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// # use ink_lang::reflect::ContractEnv; +/// assert_eq!( +/// ::Env, +/// ink_env::DefaultEnvironment, +/// ); +/// } +/// ``` +/// +/// # Usage: Custom Environment +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_env::Environment; +/// +/// pub struct CustomEnvironment {} +/// +/// impl Environment for CustomEnvironment { +/// const MAX_EVENT_TOPICS: usize = 4; +/// +/// type AccountId = ::AccountId; +/// type Balance = u64; +/// type Hash = ::Hash; +/// type BlockNumber = u32; +/// type Timestamp = u64; +/// type RentFraction = ::RentFraction; +/// type ChainExtension = ::ChainExtension; +/// } +/// +/// #[ink::contract(env = super::CustomEnvironment)] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// # use ink_lang::reflect::ContractEnv; +/// assert_eq!( +/// ::Env, +/// CustomEnvironment +/// ); +/// } +/// ``` +pub trait ContractEnv { + /// The environment type. + type Env: ::ink_env::Environment; +} diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index d2e0d60760..e1647a117d 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -28,7 +28,10 @@ mod dispatch; mod trait_def; pub use self::{ - contract::ContractName, + contract::{ + ContractEnv, + ContractName, + }, dispatch::{ ContractAmountDispatchables, ContractConstructorDecoder, diff --git a/crates/lang/src/reflect/trait_def/registry.rs b/crates/lang/src/reflect/trait_def/registry.rs index b7030c9815..136ea38559 100644 --- a/crates/lang/src/reflect/trait_def/registry.rs +++ b/crates/lang/src/reflect/trait_def/registry.rs @@ -12,7 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::codegen::TraitImplementedById; +use crate::{ + codegen::TraitImplementedById, + reflect::ContractEnv, +}; use core::marker::PhantomData; /// Type that is guaranteed by ink! to implement all ink! trait definitions. @@ -55,7 +58,7 @@ pub struct TraitDefinitionRegistry { marker: PhantomData E>, } -impl crate::ContractEnv for TraitDefinitionRegistry +impl ContractEnv for TraitDefinitionRegistry where E: ink_env::Environment, { diff --git a/examples/multisig_plain/lib.rs b/examples/multisig_plain/lib.rs index 20570a45ff..426a2c08dc 100755 --- a/examples/multisig_plain/lib.rs +++ b/examples/multisig_plain/lib.rs @@ -484,7 +484,7 @@ mod multisig_plain { self.ensure_confirmed(trans_id); let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); assert!(self.env().transferred_balance() == t.transferred_value); - let result = build_call::<::Env>() + let result = build_call::<::Env>() .callee(t.callee) .gas_limit(t.gas_limit) .transferred_value(t.transferred_value) @@ -513,7 +513,7 @@ mod multisig_plain { ) -> Result, Error> { self.ensure_confirmed(trans_id); let t = self.take_transaction(trans_id).expect(WRONG_TRANSACTION_ID); - let result = build_call::<::Env>() + let result = build_call::<::Env>() .callee(t.callee) .gas_limit(t.gas_limit) .transferred_value(t.transferred_value) From f05ddd27df96037d7c87f468f9aa3bfafe0710ad Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:12:49 +0200 Subject: [PATCH 420/493] apply clippy suggestions --- crates/lang/codegen/src/generator/metadata.rs | 2 +- crates/lang/ir/src/ir/attrs.rs | 4 +-- crates/lang/src/reflect/contract.rs | 36 ++++++++----------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index b2f0f0adfb..fcf4fe95fe 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -125,7 +125,7 @@ impl Metadata<'_> { let ident = constructor.ident(); let args = constructor .inputs() - .map(|arg| Self::generate_dispatch_argument(arg)); + .map(Self::generate_dispatch_argument); quote_spanned!(span=> ::ink_metadata::ConstructorSpec::from_name(::core::stringify!(#ident)) .selector([ diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index e7352913d4..6c07101c1f 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -661,7 +661,7 @@ where pub fn sanitize_optional_attributes( parent_span: Span, attrs: I, - mut is_conflicting_attr: C, + is_conflicting_attr: C, ) -> Result<(Option, Vec), syn::Error> where I: IntoIterator, @@ -674,7 +674,7 @@ where let normalized = ir::InkAttribute::from_expanded(ink_attrs).map_err(|err| { err.into_combine(format_err!(parent_span, "at this invocation",)) })?; - normalized.ensure_no_conflicts(|arg| is_conflicting_attr(arg))?; + normalized.ensure_no_conflicts(is_conflicting_attr)?; Ok((Some(normalized), rust_attrs)) } diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs index 9b9182ec90..b90a360f63 100644 --- a/crates/lang/src/reflect/contract.rs +++ b/crates/lang/src/reflect/contract.rs @@ -39,13 +39,11 @@ /// /// use contract::Contract; /// -/// fn main() { -/// # use ink_lang::reflect::ContractName; -/// assert_eq!( -/// ::NAME, -/// "Contract", -/// ); -/// } +/// # use ink_lang::reflect::ContractName; +/// assert_eq!( +/// ::NAME, +/// "Contract", +/// ); /// ``` pub trait ContractName { /// The name of the ink! smart contract. @@ -86,13 +84,11 @@ pub trait ContractName { /// /// use contract::Contract; /// -/// fn main() { -/// # use ink_lang::reflect::ContractEnv; -/// assert_eq!( -/// ::Env, -/// ink_env::DefaultEnvironment, -/// ); -/// } +/// # use ink_lang::reflect::ContractEnv; +/// assert_eq!( +/// ::Env, +/// ink_env::DefaultEnvironment, +/// ); /// ``` /// /// # Usage: Custom Environment @@ -131,13 +127,11 @@ pub trait ContractName { /// /// use contract::Contract; /// -/// fn main() { -/// # use ink_lang::reflect::ContractEnv; -/// assert_eq!( -/// ::Env, -/// CustomEnvironment -/// ); -/// } +/// # use ink_lang::reflect::ContractEnv; +/// assert_eq!( +/// ::Env, +/// CustomEnvironment +/// ); /// ``` pub trait ContractEnv { /// The environment type. From e8d410f0d0e47f2ea0cc2a78762b23b0ea77e333 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:28:47 +0200 Subject: [PATCH 421/493] move ContractReference trait to reflect module --- .../codegen/src/generator/as_dependency/contract_ref.rs | 2 +- crates/lang/src/contract_ref.rs | 6 ------ crates/lang/src/lib.rs | 1 - crates/lang/src/reflect/contract.rs | 6 ++++++ crates/lang/src/reflect/mod.rs | 1 + 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index e3a2a2d30c..e8a6bda839 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -107,7 +107,7 @@ impl ContractRef<'_> { } const _: () = { - impl ::ink_lang::ContractReference for #storage_ident { + impl ::ink_lang::reflect::ContractReference for #storage_ident { type Type = #ref_ident; } diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index 77213f156b..a0f350abd6 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -25,12 +25,6 @@ where fn to_account_id(&self) -> ::AccountId; } -/// Used to refer to the generated contract reference from the given contract storage struct. -pub trait ContractReference { - /// The generated contract reference type. - type Type; -} - /// Used to refer to the generated contract call builder. /// /// The generated contract call builder implements the long-hand calling API diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 19d7689299..ee8a286d6c 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -37,7 +37,6 @@ pub use self::{ }, contract_ref::{ ContractCallBuilder, - ContractReference, ToAccountId, }, env_access::{ diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs index b90a360f63..3ae1c29800 100644 --- a/crates/lang/src/reflect/contract.rs +++ b/crates/lang/src/reflect/contract.rs @@ -137,3 +137,9 @@ pub trait ContractEnv { /// The environment type. type Env: ::ink_env::Environment; } + +/// Used to refer to the generated contract reference from the given contract storage struct. +pub trait ContractReference { + /// The generated contract reference type. + type Type; +} diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index e1647a117d..e2c3e8d623 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -31,6 +31,7 @@ pub use self::{ contract::{ ContractEnv, ContractName, + ContractReference, }, dispatch::{ ContractAmountDispatchables, From b2904e6d0f443d46a97a7c1a0c45f3d1025be39b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:46:30 +0200 Subject: [PATCH 422/493] apply rustfmt --- crates/lang/codegen/src/generator/metadata.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/metadata.rs b/crates/lang/codegen/src/generator/metadata.rs index fcf4fe95fe..d4ca3a854f 100644 --- a/crates/lang/codegen/src/generator/metadata.rs +++ b/crates/lang/codegen/src/generator/metadata.rs @@ -123,9 +123,7 @@ impl Metadata<'_> { let selector_bytes = constructor.composed_selector().hex_lits(); let constructor = constructor.callable(); let ident = constructor.ident(); - let args = constructor - .inputs() - .map(Self::generate_dispatch_argument); + let args = constructor.inputs().map(Self::generate_dispatch_argument); quote_spanned!(span=> ::ink_metadata::ConstructorSpec::from_name(::core::stringify!(#ident)) .selector([ From 368558ece4c83b742a3b693eb89257297fbe0a2b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:46:48 +0200 Subject: [PATCH 423/493] fix some usage doc tests --- crates/lang/src/reflect/contract.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs index 3ae1c29800..982e4e92bf 100644 --- a/crates/lang/src/reflect/contract.rs +++ b/crates/lang/src/reflect/contract.rs @@ -59,7 +59,7 @@ pub trait ContractName { /// wanted to use an environment type definition called `MyEnvironment` they /// issue the ink! smart contract as follows: /// -/// ``` +/// ```no_compile /// #[ink::contract(env = MyEnvironment)] /// ``` /// @@ -85,17 +85,20 @@ pub trait ContractName { /// use contract::Contract; /// /// # use ink_lang::reflect::ContractEnv; -/// assert_eq!( -/// ::Env, -/// ink_env::DefaultEnvironment, -/// ); +/// # use ink_lang::codegen::IsSameType; +/// +/// // The following line only compiles successfully if both +/// // `ink_env::DefaultEnvironment` and `::Env` +/// // are of the same type. +/// const _: IsSameType<::Env> = +/// >::new(); /// ``` /// /// # Usage: Custom Environment /// /// ``` /// use ink_lang as ink; -/// # use ink_env::Environment; +/// # use ink_env::{Environment, DefaultEnvironment}; /// /// pub struct CustomEnvironment {} /// @@ -126,12 +129,16 @@ pub trait ContractName { /// } /// /// use contract::Contract; -/// /// # use ink_lang::reflect::ContractEnv; -/// assert_eq!( -/// ::Env, -/// CustomEnvironment -/// ); +/// # use ink_lang::codegen::IsSameType; +/// +/// // The following line only compiles successfully if both +/// // `CustomEnvironment` and `::Env` +/// // are of the same type. +/// const _: IsSameType<::Env> = +/// >::new(); +/// +/// fn main() {} /// ``` pub trait ContractEnv { /// The environment type. From c01355301106e6b46c0e52aaf4bb27196390f227 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:47:01 +0200 Subject: [PATCH 424/493] add extensive docs and usage example to ContractReference trait --- crates/lang/src/reflect/contract.rs | 40 ++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs index 982e4e92bf..486d449f32 100644 --- a/crates/lang/src/reflect/contract.rs +++ b/crates/lang/src/reflect/contract.rs @@ -145,7 +145,45 @@ pub trait ContractEnv { type Env: ::ink_env::Environment; } -/// Used to refer to the generated contract reference from the given contract storage struct. +/// Refers to the generated ink! smart contract reference type. +/// +/// # Note +/// +/// Given an ink! storage struct with identifier `Contract` the ink! codegen produces +/// the ink! root type `Contract` and the ink! reference type `ContractRef`. +/// +/// This trait exists so that users can avoid using a generated identifier to refer to +/// the generated reference type of the ink! smart contract. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::{Contract, ContractRef}; +/// # use ink_lang::codegen::IsSameType; +/// # use ink_lang::reflect::ContractReference; +/// +/// // The following line only compiles successfully if both +/// // `ContractReference` and `::Type` +/// // are of the same type. +/// const _: IsSameType<::Type> = +/// >::new(); +/// ``` pub trait ContractReference { /// The generated contract reference type. type Type; From 4f9efdfa0dd9fd84ac614632b7155abf0c9a77f6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:50:41 +0200 Subject: [PATCH 425/493] improve docs --- crates/lang/src/env_access.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs index e7180f192c..90ce32dc4d 100644 --- a/crates/lang/src/env_access.rs +++ b/crates/lang/src/env_access.rs @@ -61,7 +61,7 @@ pub trait StaticEnv { fn env() -> Self::EnvAccess; } -/// A typed accessor to the environment. +/// The API behind the `self.env()` syntax in ink!. /// /// This allows ink! messages to make use of the environment efficiently /// and user friendly while also maintaining access invariants. From 004d517eb361fc7e981dd301e6282779a26877d2 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:51:11 +0200 Subject: [PATCH 426/493] improve docs (2) --- crates/lang/src/env_access.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs index 90ce32dc4d..2c57202b68 100644 --- a/crates/lang/src/env_access.rs +++ b/crates/lang/src/env_access.rs @@ -61,7 +61,7 @@ pub trait StaticEnv { fn env() -> Self::EnvAccess; } -/// The API behind the `self.env()` syntax in ink!. +/// The API behind the `self.env()` and `Self::env()` syntax in ink!. /// /// This allows ink! messages to make use of the environment efficiently /// and user friendly while also maintaining access invariants. From 86c296854db40a3e1229ed05bc36070ab1315aa7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 5 Oct 2021 22:58:49 +0200 Subject: [PATCH 427/493] move DispatchError to the reflect submodule --- crates/lang/codegen/src/generator/dispatch.rs | 8 ++-- crates/lang/src/codegen/dispatch/execution.rs | 4 +- crates/lang/src/error.rs | 38 ------------------- crates/lang/src/lib.rs | 2 - crates/lang/src/reflect/dispatch.rs | 25 +++++++++++- crates/lang/src/reflect/mod.rs | 1 + 6 files changed, 31 insertions(+), 47 deletions(-) delete mode 100644 crates/lang/src/error.rs diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 5e8b519a2e..8dd19678c3 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -401,7 +401,7 @@ impl Dispatch<'_> { fn deploy() { ::ink_env::decode_input::< <#storage_ident as ::ink_lang::reflect::ContractConstructorDecoder>::Type>() - .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput) + .map_err(|_| ::ink_lang::reflect::DispatchError::CouldNotReadInput) .and_then(|decoder| { <<#storage_ident as ::ink_lang::reflect::ContractConstructorDecoder>::Type as ::ink_lang::reflect::ExecuteDispatchable>::execute_dispatchable(decoder) @@ -420,7 +420,7 @@ impl Dispatch<'_> { } ::ink_env::decode_input::< <#storage_ident as ::ink_lang::reflect::ContractMessageDecoder>::Type>() - .map_err(|_| ::ink_lang::DispatchError::CouldNotReadInput) + .map_err(|_| ::ink_lang::reflect::DispatchError::CouldNotReadInput) .and_then(|decoder| { <<#storage_ident as ::ink_lang::reflect::ContractMessageDecoder>::Type as ::ink_lang::reflect::ExecuteDispatchable>::execute_dispatchable(decoder) @@ -543,7 +543,7 @@ impl Dispatch<'_> { } impl ::ink_lang::reflect::ExecuteDispatchable for __ink_ConstructorDecoder { - fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { + fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::reflect::DispatchError> { match self { #( #constructor_execute ),* } @@ -702,7 +702,7 @@ impl Dispatch<'_> { impl ::ink_lang::reflect::ExecuteDispatchable for __ink_MessageDecoder { #[allow(clippy::nonminimal_bool)] - fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::DispatchError> { + fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::reflect::DispatchError> { match self { #( #message_execute ),* } diff --git a/crates/lang/src/codegen/dispatch/execution.rs b/crates/lang/src/codegen/dispatch/execution.rs index 36625b2952..2631dcbe29 100644 --- a/crates/lang/src/codegen/dispatch/execution.rs +++ b/crates/lang/src/codegen/dispatch/execution.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - reflect::ContractEnv, +use crate::reflect::{ + ContractEnv, DispatchError, }; use core::{ diff --git a/crates/lang/src/error.rs b/crates/lang/src/error.rs deleted file mode 100644 index 5d73dc48fc..0000000000 --- a/crates/lang/src/error.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use derive_more::Display; - -/// A dispatch error. -#[derive(Debug, Copy, Clone, Display)] -pub enum DispatchError { - #[display(fmt = "unknown selector")] - UnknownSelector, - #[display(fmt = "unknown constructor selector")] - UnknownInstantiateSelector, - #[display(fmt = "unknown message selector")] - UnknownCallSelector, - - #[display(fmt = "unable to decoded input parameter bytes")] - InvalidParameters, - #[display(fmt = "unable to decoded input parameter bytes for constructor")] - InvalidInstantiateParameters, - #[display(fmt = "unable to decoded input parameter bytes for message")] - InvalidCallParameters, - - #[display(fmt = "could not read input parameters")] - CouldNotReadInput, - #[display(fmt = "paid an unpayable message")] - PaidUnpayableMessage, -} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index ee8a286d6c..572b0fcd4c 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -26,7 +26,6 @@ pub mod reflect; mod chain_extension; mod contract_ref; mod env_access; -mod error; mod events; mod traits; @@ -44,7 +43,6 @@ pub use self::{ EnvAccess, StaticEnv, }, - error::DispatchError, events::{ ContractEventBase, EmitEvent, diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index 71c79f4470..bc7a811d0d 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::DispatchError; +use derive_more::Display; /// Reflects the number of dispatchable ink! messages and constructors respectively. /// @@ -514,3 +514,26 @@ pub trait ExecuteDispatchable { /// Executes the ink! smart contract message or constructor. fn execute_dispatchable(self) -> Result<(), DispatchError>; } + +/// An error that can occur during dispatch of ink! dispatchables. +#[derive(Debug, Copy, Clone, Display)] +pub enum DispatchError { + #[display(fmt = "unknown selector")] + UnknownSelector, + #[display(fmt = "unknown constructor selector")] + UnknownInstantiateSelector, + #[display(fmt = "unknown message selector")] + UnknownCallSelector, + + #[display(fmt = "unable to decoded input parameter bytes")] + InvalidParameters, + #[display(fmt = "unable to decoded input parameter bytes for constructor")] + InvalidInstantiateParameters, + #[display(fmt = "unable to decoded input parameter bytes for message")] + InvalidCallParameters, + + #[display(fmt = "could not read input parameters")] + CouldNotReadInput, + #[display(fmt = "paid an unpayable message")] + PaidUnpayableMessage, +} diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index e2c3e8d623..dcabc24c98 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -39,6 +39,7 @@ pub use self::{ ContractDispatchableConstructors, ContractDispatchableMessages, ContractMessageDecoder, + DispatchError, DispatchableConstructorInfo, DispatchableMessageInfo, ExecuteDispatchable, From 51a64a75cee34161c39330b95f8bca5afa21b092 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 11:23:19 +0200 Subject: [PATCH 428/493] add new event topic guards codegen to ink! codegen --- crates/lang/codegen/src/generator/events.rs | 45 +++------ .../fail/event-too-many-topics-anonymous.rs | 62 +++++++++++++ .../event-too-many-topics-anonymous.stderr | 23 +++++ .../ui/contract/fail/event-too-many-topics.rs | 58 ++++++++++++ .../fail/event-too-many-topics.stderr | 23 +++++ crates/lang/src/codegen/event.rs | 91 +++++++++++++++++++ crates/lang/src/codegen/mod.rs | 6 ++ 7 files changed, 277 insertions(+), 31 deletions(-) create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr create mode 100644 crates/lang/src/codegen/event.rs diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index c8b1b30232..e7025bb197 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -141,42 +141,25 @@ impl<'a> Events<'a> { /// Generate checks to guard against too many topics in event definitions. fn generate_topics_guard(&self, event: &ir::Event) -> TokenStream2 { + let span = event.span(); let storage_ident = self.contract.module().storage().ident(); let event_ident = event.ident(); let len_topics = event.fields().filter(|event| event.is_topic).count(); - let span = event.span(); + let max_len_topics = quote_spanned!(span=> + <<#storage_ident as ::ink_lang::reflect::ContractEnv>::Env + as ::ink_env::Environment>::MAX_EVENT_TOPICS + ); quote_spanned!(span=> - const _: () = { - #[allow(non_camel_case_types)] - pub enum __ink_CheckSatisfied {} - pub enum EventTopicsWithinBounds {} - #[doc(hidden)] - pub trait CompliesWithTopicLimit {} - impl CompliesWithTopicLimit for __ink_CheckSatisfied {} - - #[allow(non_camel_case_types)] - pub trait __ink_RenameBool { - type Type; - } - impl __ink_RenameBool for [(); true as usize] { - type Type = __ink_CheckSatisfied; - } - impl __ink_RenameBool for [(); false as usize] { - type Type = #event_ident; - } - - #[allow(non_upper_case_globals)] - const __ink_MAX_EVENT_TOPICS: usize = < - <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env as ::ink_env::Environment - >::MAX_EVENT_TOPICS; + impl ::ink_lang::codegen::EventLenTopics for #event_ident { + type LenTopics = ::ink_lang::codegen::EventTopics<#len_topics>; + } - fn __ink_ensure_max_event_topics(_: T) - where - T: __ink_RenameBool, - ::Type: CompliesWithTopicLimit, - {} - let _ = __ink_ensure_max_event_topics::<[(); (#len_topics <= __ink_MAX_EVENT_TOPICS) as usize]>; - }; + const _: () = ::ink_lang::codegen::identity_type::< + ::ink_lang::codegen::EventRespectsTopicLimit< + #event_ident, + { #max_len_topics }, + > + >(); ) } diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.rs b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.rs new file mode 100644 index 0000000000..7ef6b7499e --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.rs @@ -0,0 +1,62 @@ +use ink_env::{ + DefaultEnvironment, + Environment, +}; +use ink_lang as ink; + +pub struct EnvironmentMoreTopics; + +impl ink_env::Environment for EnvironmentMoreTopics { + const MAX_EVENT_TOPICS: usize = 2; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Hash = ::Hash; + type Timestamp = ::Timestamp; + type BlockNumber = ::BlockNumber; + type ChainExtension = (); + type RentFraction = ::RentFraction; +} + +#[ink::contract(env = super::EnvironmentMoreTopics)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event, anonymous)] + pub struct Event { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + #[ink(topic)] + arg_4: i32, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::env().emit_event(Event { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + Self {} + } + + #[ink(message)] + pub fn message(&self) { + self.env().emit_event(Event { + arg_1: 1, + arg_2: 2, + arg_3: 3, + arg_4: 4, + }); + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr new file mode 100644 index 0000000000..42ad1797be --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `EventTopics<4_usize>: codegen::event::RespectTopicLimit<2_usize>` is not satisfied + --> $DIR/event-too-many-topics-anonymous.rs:27:5 + | +27 | / pub struct Event { +28 | | #[ink(topic)] +29 | | arg_1: i8, +30 | | #[ink(topic)] +... | +35 | | arg_4: i32, +36 | | } + | |_____^ the trait `codegen::event::RespectTopicLimit<2_usize>` is not implemented for `EventTopics<4_usize>` + | + = help: the following implementations were found: + as codegen::event::RespectTopicLimit<0_usize>> + as codegen::event::RespectTopicLimit<10_usize>> + as codegen::event::RespectTopicLimit<11_usize>> + as codegen::event::RespectTopicLimit<12_usize>> + and 87 others +note: required by a bound in `EventRespectsTopicLimit` + --> $DIR/event.rs:48:43 + | +48 | ::LenTopics: RespectTopicLimit, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.rs b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.rs new file mode 100644 index 0000000000..c3834db8d9 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.rs @@ -0,0 +1,58 @@ +use ink_env::{ + DefaultEnvironment, + Environment, +}; +use ink_lang as ink; + +pub struct EnvironmentMoreTopics; + +impl ink_env::Environment for EnvironmentMoreTopics { + const MAX_EVENT_TOPICS: usize = 2; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Hash = ::Hash; + type Timestamp = ::Timestamp; + type BlockNumber = ::BlockNumber; + type ChainExtension = (); + type RentFraction = ::RentFraction; +} + +#[ink::contract(env = super::EnvironmentMoreTopics)] +mod contract { + #[ink(storage)] + pub struct Contract {} + + #[ink(event)] + pub struct Event { + #[ink(topic)] + arg_1: i8, + #[ink(topic)] + arg_2: i16, + #[ink(topic)] + arg_3: i32, + } + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::env().emit_event(Event { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + Self {} + } + + #[ink(message)] + pub fn message(&self) { + self.env().emit_event(Event { + arg_1: 1, + arg_2: 2, + arg_3: 3, + }); + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr new file mode 100644 index 0000000000..18636cb541 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `EventTopics<3_usize>: codegen::event::RespectTopicLimit<2_usize>` is not satisfied + --> $DIR/event-too-many-topics.rs:27:5 + | +27 | / pub struct Event { +28 | | #[ink(topic)] +29 | | arg_1: i8, +30 | | #[ink(topic)] +... | +33 | | arg_3: i32, +34 | | } + | |_____^ the trait `codegen::event::RespectTopicLimit<2_usize>` is not implemented for `EventTopics<3_usize>` + | + = help: the following implementations were found: + as codegen::event::RespectTopicLimit<0_usize>> + as codegen::event::RespectTopicLimit<10_usize>> + as codegen::event::RespectTopicLimit<11_usize>> + as codegen::event::RespectTopicLimit<12_usize>> + and 87 others +note: required by a bound in `EventRespectsTopicLimit` + --> $DIR/event.rs:48:43 + | +48 | ::LenTopics: RespectTopicLimit, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/src/codegen/event.rs b/crates/lang/src/codegen/event.rs new file mode 100644 index 0000000000..0639acd7ab --- /dev/null +++ b/crates/lang/src/codegen/event.rs @@ -0,0 +1,91 @@ +use std::marker::PhantomData; + +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Guards that an ink! event definitions respects the topic limit. +/// +/// # Usage +/// +/// ``` +/// // #[ink(event)] +/// pub struct ExampleEvent {} +/// +/// /// The amount of the topics of the example event struct. +/// const LEN_TOPICS: usize = 3; +/// +/// /// The limit for the amount of topics per ink! event definition. +/// const TOPICS_LIMIT: usize = 4; +/// +/// impl ::ink_lang::codegen::EventLenTopics for ExampleEvent { +/// type LenTopics = ::ink_lang::codegen::EventTopics; +/// } +/// +/// // The below code only compiles successfully if the example ink! event +/// // definitions respects the topic limitation: it must have an amount of +/// // topics less than or equal to the topic limit. +/// const _: () = ::ink_lang::codegen::identity_type::< +/// ::ink_lang::codegen::EventRespectsTopicLimit< +/// ExampleEvent, +/// TOPICS_LIMIT, +/// > +/// >(); +/// ``` +pub struct EventRespectsTopicLimit +where + Event: EventLenTopics, + ::LenTopics: RespectTopicLimit, +{ + marker: PhantomData Event>, +} + +/// Guards that an amount of event topics respects the event topic limit. +/// +/// # Note +/// +/// Implemented by `EventTopics` if M is less or equal to N. +/// Automatically implemented for up to 12 event topics. +pub trait RespectTopicLimit {} + +/// Represents an the amount of topics for an ink! event definition. +pub struct EventTopics; + +macro_rules! impl_is_smaller_or_equals { + ( $first:literal $( , $rest:literal )* $(,)? ) => { + impl RespectTopicLimit<$first> for EventTopics<$first> {} + $( + impl RespectTopicLimit<$rest> for EventTopics<$first> {} + )* + + impl_is_smaller_or_equals! { $( $rest ),* } + }; + ( ) => {}; +} +impl_is_smaller_or_equals! { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 +} + +/// Stores the number of event topics of the ink! event definition. +pub trait EventLenTopics { + /// Type denoting the number of event topics. + /// + /// # Note + /// + /// We use an associated type instead of an associated constant here + /// because Rust does not yet allow for generics in constant parameter + /// position which would be required in the `EventRespectsTopicLimit` + /// trait definition. + /// As soon as this is possible in Rust we might change this to a constant. + type LenTopics; +} diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 54fda52fd3..7329753772 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -15,6 +15,7 @@ //! Definitions and facilities mainly used by the ink! codegen. mod dispatch; +mod event; mod implies_return; mod is_same_type; mod trait_def; @@ -29,6 +30,11 @@ pub use self::{ ExecuteConstructorConfig, ExecuteMessageConfig, }, + event::{ + EventRespectsTopicLimit, + EventTopics, + EventLenTopics, + }, implies_return::ImpliesReturn, is_same_type::IsSameType, trait_def::{ From f6aa4fdce5ec8eca6a95fe6b0cda3e747abb9940 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 11:24:09 +0200 Subject: [PATCH 429/493] apply rustfmt and fix PhantomData import --- crates/lang/src/codegen/event.rs | 4 ++-- crates/lang/src/codegen/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/lang/src/codegen/event.rs b/crates/lang/src/codegen/event.rs index 0639acd7ab..b75e02a0dc 100644 --- a/crates/lang/src/codegen/event.rs +++ b/crates/lang/src/codegen/event.rs @@ -1,5 +1,3 @@ -use std::marker::PhantomData; - // Copyright 2018-2021 Parity Technologies (UK) Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,6 +12,8 @@ use std::marker::PhantomData; // See the License for the specific language governing permissions and // limitations under the License. +use core::marker::PhantomData; + /// Guards that an ink! event definitions respects the topic limit. /// /// # Usage diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 7329753772..274bec8d92 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -31,9 +31,9 @@ pub use self::{ ExecuteMessageConfig, }, event::{ + EventLenTopics, EventRespectsTopicLimit, EventTopics, - EventLenTopics, }, implies_return::ImpliesReturn, is_same_type::IsSameType, From 7d8c419f78808871b64585786f79a677238e2731 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 13:16:14 +0200 Subject: [PATCH 430/493] re-export RespectTopicLimit trait --- crates/lang/src/codegen/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 274bec8d92..08f5e79409 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -34,6 +34,7 @@ pub use self::{ EventLenTopics, EventRespectsTopicLimit, EventTopics, + RespectTopicLimit, }, implies_return::ImpliesReturn, is_same_type::IsSameType, From 23ff499617dbf64c31fb168b45106030cea5046a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 13:55:25 +0200 Subject: [PATCH 431/493] modernize trait_erc20 example contract --- examples/trait-erc20/lib.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/examples/trait-erc20/lib.rs b/examples/trait-erc20/lib.rs index 1bdf9b1abb..65a9265172 100644 --- a/examples/trait-erc20/lib.rs +++ b/examples/trait-erc20/lib.rs @@ -4,16 +4,7 @@ use ink_lang as ink; #[ink::contract] mod erc20 { - #[cfg(not(feature = "ink-as-dependency"))] use ink_lang as ink; - - #[cfg(not(feature = "ink-as-dependency"))] - use ink_lang::{ - EmitEvent, - Env, - }; - - #[cfg(not(feature = "ink-as-dependency"))] use ink_storage::{ collections::HashMap as StorageHashMap, lazy::Lazy, @@ -209,6 +200,7 @@ mod erc20 { } } + #[ink(impl)] impl Erc20 { /// Transfers `value` amount of tokens from the caller's account to account `to`. /// From 7399ea2dfd303368bfa1d7f2250c34548352094a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:08:12 +0200 Subject: [PATCH 432/493] move Env and StaticEnv into ink_lang::codegen module --- .../lang/codegen/src/generator/item_impls.rs | 3 +- crates/lang/codegen/src/generator/storage.rs | 12 +++--- crates/lang/src/codegen/env.rs | 43 +++++++++++++++++++ crates/lang/src/codegen/mod.rs | 5 +++ crates/lang/src/env_access.rs | 30 ------------- crates/lang/src/lib.rs | 6 +-- 6 files changed, 57 insertions(+), 42 deletions(-) create mode 100644 crates/lang/src/codegen/env.rs diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 231ba5d7ab..05ab492bea 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -48,7 +48,8 @@ impl GenerateCode for ItemImpls<'_> { let trait_message_property_guards = self.generate_trait_message_property_guards(); quote! { const _: () = { - use ::ink_lang::{Env as _, EmitEvent as _, StaticEnv as _}; + // Required to make `self.env()` and `Self::env()` syntax available. + use ::ink_lang::codegen::{Env as _, StaticEnv as _}; #( #item_impls )* #inout_guards diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index 614edc2329..61ccac6de0 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -43,9 +43,9 @@ impl GenerateCode for Storage<'_> { #storage_struct const _: () = { - // Used to make `self.env()` available in message code. + // Used to make `self.env()` and `Self::env()` available in message code. #[allow(unused_imports)] - use ::ink_lang::{ + use ::ink_lang::codegen::{ Env as _, StaticEnv as _, }; @@ -60,22 +60,22 @@ impl Storage<'_> { let storage_ident = &self.contract.module().storage().ident(); quote! { const _: () = { - impl<'a> ::ink_lang::Env for &'a #storage_ident { + impl<'a> ::ink_lang::codegen::Env for &'a #storage_ident { type EnvAccess = ::ink_lang::EnvAccess< 'a, <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env>; fn env(self) -> Self::EnvAccess { - <::EnvAccess + <::EnvAccess as ::core::default::Default>::default() } } - impl<'a> ::ink_lang::StaticEnv for #storage_ident { + impl<'a> ::ink_lang::codegen::StaticEnv for #storage_ident { type EnvAccess = ::ink_lang::EnvAccess< 'static, <#storage_ident as ::ink_lang::reflect::ContractEnv>::Env>; fn env() -> Self::EnvAccess { - <::EnvAccess + <::EnvAccess as ::core::default::Default>::default() } } diff --git a/crates/lang/src/codegen/env.rs b/crates/lang/src/codegen/env.rs new file mode 100644 index 0000000000..0d34828c61 --- /dev/null +++ b/crates/lang/src/codegen/env.rs @@ -0,0 +1,43 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Simplifies interaction with the host environment via `self`. +/// +/// # Note +/// +/// This is generally implemented for storage structs that include +/// their environment in order to allow the different dispatch functions +/// to use it for returning the contract's output. +pub trait Env { + /// The access wrapper. + type EnvAccess; + + /// Accesses the host environment with `self.env()` syntax. + fn env(self) -> Self::EnvAccess; +} + +/// Simplifies interaction with the host environment via `Self`. +/// +/// # Note +/// +/// This is generally implemented for storage structs that include +/// their environment in order to allow the different dispatch functions +/// to use it for returning the contract's output. +pub trait StaticEnv { + /// The access wrapper. + type EnvAccess; + + /// Accesses the host environment with `Self::env()` syntax. + fn env() -> Self::EnvAccess; +} diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 08f5e79409..9b11147c32 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -15,6 +15,7 @@ //! Definitions and facilities mainly used by the ink! codegen. mod dispatch; +mod env; mod event; mod implies_return; mod is_same_type; @@ -30,6 +31,10 @@ pub use self::{ ExecuteConstructorConfig, ExecuteMessageConfig, }, + env::{ + Env, + StaticEnv, + }, event::{ EventLenTopics, EventRespectsTopicLimit, diff --git a/crates/lang/src/env_access.rs b/crates/lang/src/env_access.rs index 2c57202b68..472e796bca 100644 --- a/crates/lang/src/env_access.rs +++ b/crates/lang/src/env_access.rs @@ -31,36 +31,6 @@ use ink_env::{ }; use ink_primitives::Key; -/// Simplifies interaction with the host environment via `self`. -/// -/// # Note -/// -/// This is generally implemented for storage structs that include -/// their environment in order to allow the different dispatch functions -/// to use it for returning the contract's output. -pub trait Env { - /// The access wrapper. - type EnvAccess; - - /// Accesses the environment with predefined environmental types. - fn env(self) -> Self::EnvAccess; -} - -/// Simplifies interaction with the host environment via `Self`. -/// -/// # Note -/// -/// This is generally implemented for storage structs that include -/// their environment in order to allow the different dispatch functions -/// to use it for returning the contract's output. -pub trait StaticEnv { - /// The access wrapper. - type EnvAccess; - - /// Accesses the environment with predefined environmental types. - fn env() -> Self::EnvAccess; -} - /// The API behind the `self.env()` and `Self::env()` syntax in ink!. /// /// This allows ink! messages to make use of the environment efficiently diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 572b0fcd4c..8bf7a3ac0e 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -38,11 +38,7 @@ pub use self::{ ContractCallBuilder, ToAccountId, }, - env_access::{ - Env, - EnvAccess, - StaticEnv, - }, + env_access::EnvAccess, events::{ ContractEventBase, EmitEvent, From b590a35c1b06eadf2a8ce5fe2e7df016e76e2bd6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:08:49 +0200 Subject: [PATCH 433/493] conditionally import EmitEvent trait anonymously for ink! impl blocks --- crates/lang/codegen/src/generator/item_impls.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 05ab492bea..6718649142 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -46,10 +46,16 @@ impl GenerateCode for ItemImpls<'_> { .map(|item_impl| self.generate_item_impl(item_impl)); let inout_guards = self.generate_input_output_guards(); let trait_message_property_guards = self.generate_trait_message_property_guards(); + let use_emit_event = + self.contract.module().events().next().is_some().then(|| { + // Required to make `self.env().emit_event(..)` syntax available. + quote! { use ::ink_lang::EmitEvent as _; } + }); quote! { const _: () = { // Required to make `self.env()` and `Self::env()` syntax available. use ::ink_lang::codegen::{Env as _, StaticEnv as _}; + #use_emit_event #( #item_impls )* #inout_guards From 1a6748c52e3df12fe6af76d5796b6bc73b1601b7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:08:57 +0200 Subject: [PATCH 434/493] fix some UI tests --- .../fail/event-too-many-topics-anonymous.stderr | 12 ++++++------ .../ui/contract/fail/event-too-many-topics.stderr | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr index 42ad1797be..3dd1b1d2e4 100644 --- a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `EventTopics<4_usize>: codegen::event::RespectTopicLimit<2_usize>` is not satisfied +error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>` is not satisfied --> $DIR/event-too-many-topics-anonymous.rs:27:5 | 27 | / pub struct Event { @@ -8,13 +8,13 @@ error[E0277]: the trait bound `EventTopics<4_usize>: codegen::event::RespectTopi ... | 35 | | arg_4: i32, 36 | | } - | |_____^ the trait `codegen::event::RespectTopicLimit<2_usize>` is not implemented for `EventTopics<4_usize>` + | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<4_usize>` | = help: the following implementations were found: - as codegen::event::RespectTopicLimit<0_usize>> - as codegen::event::RespectTopicLimit<10_usize>> - as codegen::event::RespectTopicLimit<11_usize>> - as codegen::event::RespectTopicLimit<12_usize>> + as RespectTopicLimit<0_usize>> + as RespectTopicLimit<10_usize>> + as RespectTopicLimit<11_usize>> + as RespectTopicLimit<12_usize>> and 87 others note: required by a bound in `EventRespectsTopicLimit` --> $DIR/event.rs:48:43 diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr index 18636cb541..d6a1546ca9 100644 --- a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr @@ -1,4 +1,4 @@ -error[E0277]: the trait bound `EventTopics<3_usize>: codegen::event::RespectTopicLimit<2_usize>` is not satisfied +error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>` is not satisfied --> $DIR/event-too-many-topics.rs:27:5 | 27 | / pub struct Event { @@ -8,13 +8,13 @@ error[E0277]: the trait bound `EventTopics<3_usize>: codegen::event::RespectTopi ... | 33 | | arg_3: i32, 34 | | } - | |_____^ the trait `codegen::event::RespectTopicLimit<2_usize>` is not implemented for `EventTopics<3_usize>` + | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<3_usize>` | = help: the following implementations were found: - as codegen::event::RespectTopicLimit<0_usize>> - as codegen::event::RespectTopicLimit<10_usize>> - as codegen::event::RespectTopicLimit<11_usize>> - as codegen::event::RespectTopicLimit<12_usize>> + as RespectTopicLimit<0_usize>> + as RespectTopicLimit<10_usize>> + as RespectTopicLimit<11_usize>> + as RespectTopicLimit<12_usize>> and 87 others note: required by a bound in `EventRespectsTopicLimit` --> $DIR/event.rs:48:43 From f94130d9bf752af7ea0d31c07eae5146d32a544b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:20:16 +0200 Subject: [PATCH 435/493] move EmitEvent trait to ink_lang::codegen module --- crates/lang/codegen/src/generator/events.rs | 2 +- .../lang/codegen/src/generator/item_impls.rs | 2 +- crates/lang/codegen/src/generator/storage.rs | 2 +- crates/lang/src/codegen/event/emit.rs | 26 +++++++++++++++++++ crates/lang/src/codegen/event/mod.rs | 26 +++++++++++++++++++ .../src/codegen/{event.rs => event/topics.rs} | 0 crates/lang/src/codegen/mod.rs | 1 + crates/lang/src/events.rs | 18 ------------- crates/lang/src/lib.rs | 5 +--- 9 files changed, 57 insertions(+), 25 deletions(-) create mode 100644 crates/lang/src/codegen/event/emit.rs create mode 100644 crates/lang/src/codegen/event/mod.rs rename crates/lang/src/codegen/{event.rs => event/topics.rs} (100%) diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index e7025bb197..3f7ba42155 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -59,7 +59,7 @@ impl<'a> Events<'a> { let storage_ident = &self.contract.module().storage().ident(); quote! { const _: () = { - impl<'a> ::ink_lang::EmitEvent<#storage_ident> for ::ink_lang::EnvAccess<'a, Environment> { + impl<'a> ::ink_lang::codegen::EmitEvent<#storage_ident> for ::ink_lang::EnvAccess<'a, Environment> { fn emit_event(self, event: E) where E: Into<<#storage_ident as ::ink_lang::ContractEventBase>::Type>, diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 6718649142..9592c6ce87 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -49,7 +49,7 @@ impl GenerateCode for ItemImpls<'_> { let use_emit_event = self.contract.module().events().next().is_some().then(|| { // Required to make `self.env().emit_event(..)` syntax available. - quote! { use ::ink_lang::EmitEvent as _; } + quote! { use ::ink_lang::codegen::EmitEvent as _; } }); quote! { const _: () = { diff --git a/crates/lang/codegen/src/generator/storage.rs b/crates/lang/codegen/src/generator/storage.rs index 61ccac6de0..c68e29824a 100644 --- a/crates/lang/codegen/src/generator/storage.rs +++ b/crates/lang/codegen/src/generator/storage.rs @@ -36,7 +36,7 @@ impl GenerateCode for Storage<'_> { let use_emit_event = self.contract.module().events().next().is_some().then(|| { // Required to allow for `self.env().emit_event(..)` in messages and constructors. - quote! { use ::ink_lang::EmitEvent as _; } + quote! { use ::ink_lang::codegen::EmitEvent as _; } }); quote_spanned!(storage_span => #access_env_impls diff --git a/crates/lang/src/codegen/event/emit.rs b/crates/lang/src/codegen/event/emit.rs new file mode 100644 index 0000000000..40bb4c4f1f --- /dev/null +++ b/crates/lang/src/codegen/event/emit.rs @@ -0,0 +1,26 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::ContractEventBase; + +/// Allows for `self.env().emit_event(..)` syntax in ink! implementation blocks. +pub trait EmitEvent +where + C: ContractEventBase, +{ + /// Emits an event that can be trivially converted into the base event. + fn emit_event(self, event: E) + where + E: Into<::Type>; +} diff --git a/crates/lang/src/codegen/event/mod.rs b/crates/lang/src/codegen/event/mod.rs new file mode 100644 index 0000000000..ec78bb811f --- /dev/null +++ b/crates/lang/src/codegen/event/mod.rs @@ -0,0 +1,26 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod emit; +mod topics; + +pub use self::{ + emit::EmitEvent, + topics::{ + EventLenTopics, + EventRespectsTopicLimit, + EventTopics, + RespectTopicLimit, + }, +}; diff --git a/crates/lang/src/codegen/event.rs b/crates/lang/src/codegen/event/topics.rs similarity index 100% rename from crates/lang/src/codegen/event.rs rename to crates/lang/src/codegen/event/topics.rs diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 9b11147c32..305bf8711a 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -36,6 +36,7 @@ pub use self::{ StaticEnv, }, event::{ + EmitEvent, EventLenTopics, EventRespectsTopicLimit, EventTopics, diff --git a/crates/lang/src/events.rs b/crates/lang/src/events.rs index 6780f96e19..ab7e12d568 100644 --- a/crates/lang/src/events.rs +++ b/crates/lang/src/events.rs @@ -12,24 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// Implemented by contracts in order to override `env().emit_event(..)` -/// syntax for emitting of ink! contract events. -/// -/// # Developer Note -/// -/// Normally we'd try to define traits like these in the companion -/// `ink_lang` crate, however, due to Rust's orphan rules we must -/// define this trait here. -pub trait EmitEvent -where - C: ContractEventBase, -{ - /// Emits an event that can be trivially converted into the base event. - fn emit_event(self, event: E) - where - E: Into<::Type>; -} - /// Defines a base event type for the contract. /// /// This is usually the event enum that comprises all defined event types. diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 8bf7a3ac0e..8405a713af 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -39,10 +39,7 @@ pub use self::{ ToAccountId, }, env_access::EnvAccess, - events::{ - ContractEventBase, - EmitEvent, - }, + events::ContractEventBase, traits::{ TraitCallBuilder, TraitCallForwarder, From 0a984a18838db0b34131482ec2a0f5092b8c1c9a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:20:34 +0200 Subject: [PATCH 436/493] fix UI tests --- .../event-too-many-topics-anonymous.stderr | 23 ------------------- .../fail/event-too-many-topics.stderr | 23 ------------------- 2 files changed, 46 deletions(-) delete mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr delete mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr deleted file mode 100644 index 3dd1b1d2e4..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>` is not satisfied - --> $DIR/event-too-many-topics-anonymous.rs:27:5 - | -27 | / pub struct Event { -28 | | #[ink(topic)] -29 | | arg_1: i8, -30 | | #[ink(topic)] -... | -35 | | arg_4: i32, -36 | | } - | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<4_usize>` - | - = help: the following implementations were found: - as RespectTopicLimit<0_usize>> - as RespectTopicLimit<10_usize>> - as RespectTopicLimit<11_usize>> - as RespectTopicLimit<12_usize>> - and 87 others -note: required by a bound in `EventRespectsTopicLimit` - --> $DIR/event.rs:48:43 - | -48 | ::LenTopics: RespectTopicLimit, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr deleted file mode 100644 index d6a1546ca9..0000000000 --- a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>` is not satisfied - --> $DIR/event-too-many-topics.rs:27:5 - | -27 | / pub struct Event { -28 | | #[ink(topic)] -29 | | arg_1: i8, -30 | | #[ink(topic)] -... | -33 | | arg_3: i32, -34 | | } - | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<3_usize>` - | - = help: the following implementations were found: - as RespectTopicLimit<0_usize>> - as RespectTopicLimit<10_usize>> - as RespectTopicLimit<11_usize>> - as RespectTopicLimit<12_usize>> - and 87 others -note: required by a bound in `EventRespectsTopicLimit` - --> $DIR/event.rs:48:43 - | -48 | ::LenTopics: RespectTopicLimit, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` From 03e2a0a04d0840a2e18c8332c5a615acdca36dea Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:30:21 +0200 Subject: [PATCH 437/493] fix UI tests --- .../event-too-many-topics-anonymous.stderr | 23 +++++++++++++++++++ .../fail/event-too-many-topics.stderr | 23 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr new file mode 100644 index 0000000000..1900ad503d --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>` is not satisfied + --> $DIR/event-too-many-topics-anonymous.rs:27:5 + | +27 | / pub struct Event { +28 | | #[ink(topic)] +29 | | arg_1: i8, +30 | | #[ink(topic)] +... | +35 | | arg_4: i32, +36 | | } + | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<4_usize>` + | + = help: the following implementations were found: + as RespectTopicLimit<0_usize>> + as RespectTopicLimit<10_usize>> + as RespectTopicLimit<11_usize>> + as RespectTopicLimit<12_usize>> + and 87 others +note: required by a bound in `EventRespectsTopicLimit` + --> $DIR/topics.rs:48:43 + | +48 | ::LenTopics: RespectTopicLimit, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr new file mode 100644 index 0000000000..50f783b605 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>` is not satisfied + --> $DIR/event-too-many-topics.rs:27:5 + | +27 | / pub struct Event { +28 | | #[ink(topic)] +29 | | arg_1: i8, +30 | | #[ink(topic)] +... | +33 | | arg_3: i32, +34 | | } + | |_____^ the trait `RespectTopicLimit<2_usize>` is not implemented for `EventTopics<3_usize>` + | + = help: the following implementations were found: + as RespectTopicLimit<0_usize>> + as RespectTopicLimit<10_usize>> + as RespectTopicLimit<11_usize>> + as RespectTopicLimit<12_usize>> + and 87 others +note: required by a bound in `EventRespectsTopicLimit` + --> $DIR/topics.rs:48:43 + | +48 | ::LenTopics: RespectTopicLimit, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` From f6b714be5a63d0e5b63082d1d996f4b41fd619c0 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:30:33 +0200 Subject: [PATCH 438/493] add passing UI test for self.env() and Self::env() syntax --- .../ui/contract/pass/impl-block-using-env.rs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/pass/impl-block-using-env.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-block-using-env.rs b/crates/lang/macro/tests/ui/contract/pass/impl-block-using-env.rs new file mode 100644 index 0000000000..6c58107d94 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/impl-block-using-env.rs @@ -0,0 +1,35 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::constructor_impl() + } + } + + impl Contract { + #[ink(message)] + pub fn message(&self) { + self.message_impl(); + } + } + + #[ink(impl)] + impl Contract { + fn constructor_impl() -> Self { + let _ = Self::env().caller(); + Self {} + } + + fn message_impl(&self) { + let _ = self.env().caller(); + } + } +} + +fn main() {} From e24f65111d8e96d16d4fdf586af86f6865c4f860 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:34:20 +0200 Subject: [PATCH 439/493] add failing UI tests for missing #[ink(impl)] annotation --- .../fail/impl-block-using-env-no-marker.rs | 29 +++++++++++++++++++ .../impl-block-using-env-no-marker.stderr | 11 +++++++ .../impl-block-using-static-env-no-marker.rs | 28 ++++++++++++++++++ ...pl-block-using-static-env-no-marker.stderr | 14 +++++++++ 4 files changed, 82 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.rs new file mode 100644 index 0000000000..0b51814af7 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.rs @@ -0,0 +1,29 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl Contract { + #[ink(message)] + pub fn message(&self) { + self.message_impl(); + } + } + + impl Contract { + fn message_impl(&self) { + let _ = self.env().caller(); + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr new file mode 100644 index 0000000000..c68e582000 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr @@ -0,0 +1,11 @@ +error[E0599]: no method named `env` found for reference `&Contract` in the current scope + --> $DIR/impl-block-using-env-no-marker.rs:24:26 + | +24 | let _ = self.env().caller(); + | ^^^ method not found in `&Contract` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +6 | use ink_lang::codegen::Env; + | diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs new file mode 100644 index 0000000000..0aace2aac9 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs @@ -0,0 +1,28 @@ +use ink_lang as ink; + +#[ink::contract] +mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self::constructor_impl() + } + } + + impl Contract { + #[ink(message)] + pub fn message(&self) {} + } + + impl Contract { + fn constructor_impl() -> Self { + let _ = Self::env().caller(); + Self {} + } + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr new file mode 100644 index 0000000000..09f63cdf55 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr @@ -0,0 +1,14 @@ +error[E0599]: no function or associated item named `env` found for struct `Contract` in the current scope + --> $DIR/impl-block-using-static-env-no-marker.rs:22:27 + | +6 | pub struct Contract {} + | ------------------- function or associated item `env` not found for this +... +22 | let _ = Self::env().caller(); + | ^^^ function or associated item not found in `Contract` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +6 | use ink_lang::codegen::StaticEnv; + | From 8eb1be8a4d0b40f7e2b4e66f870b53dfcfb71975 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 14:57:04 +0200 Subject: [PATCH 440/493] move ContractEventBase trait to ink_lang::reflect submodule --- crates/lang/codegen/src/generator/events.rs | 6 +++--- crates/lang/src/codegen/event/emit.rs | 2 +- crates/lang/src/lib.rs | 2 -- crates/lang/src/{events.rs => reflect/event.rs} | 0 crates/lang/src/reflect/mod.rs | 2 ++ examples/erc20/lib.rs | 4 ++-- examples/trait-erc20/lib.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) rename crates/lang/src/{events.rs => reflect/event.rs} (100%) diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index 3f7ba42155..85905e26ad 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -62,11 +62,11 @@ impl<'a> Events<'a> { impl<'a> ::ink_lang::codegen::EmitEvent<#storage_ident> for ::ink_lang::EnvAccess<'a, Environment> { fn emit_event(self, event: E) where - E: Into<<#storage_ident as ::ink_lang::ContractEventBase>::Type>, + E: Into<<#storage_ident as ::ink_lang::reflect::ContractEventBase>::Type>, { ::ink_env::emit_event::< Environment, - <#storage_ident as ::ink_lang::ContractEventBase>::Type + <#storage_ident as ::ink_lang::reflect::ContractEventBase>::Type >(event.into()); } } @@ -94,7 +94,7 @@ impl<'a> Events<'a> { } const _: () = { - impl ::ink_lang::ContractEventBase for #storage_ident { + impl ::ink_lang::reflect::ContractEventBase for #storage_ident { type Type = #base_event_ident; } }; diff --git a/crates/lang/src/codegen/event/emit.rs b/crates/lang/src/codegen/event/emit.rs index 40bb4c4f1f..e47980e8b1 100644 --- a/crates/lang/src/codegen/event/emit.rs +++ b/crates/lang/src/codegen/event/emit.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::ContractEventBase; +use crate::reflect::ContractEventBase; /// Allows for `self.env().emit_event(..)` syntax in ink! implementation blocks. pub trait EmitEvent diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 8405a713af..32b34a7438 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -26,7 +26,6 @@ pub mod reflect; mod chain_extension; mod contract_ref; mod env_access; -mod events; mod traits; pub use self::{ @@ -39,7 +38,6 @@ pub use self::{ ToAccountId, }, env_access::EnvAccess, - events::ContractEventBase, traits::{ TraitCallBuilder, TraitCallForwarder, diff --git a/crates/lang/src/events.rs b/crates/lang/src/reflect/event.rs similarity index 100% rename from crates/lang/src/events.rs rename to crates/lang/src/reflect/event.rs diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index dcabc24c98..65612684a5 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -26,8 +26,10 @@ mod contract; mod dispatch; mod trait_def; +mod event; pub use self::{ + event::ContractEventBase, contract::{ ContractEnv, ContractName, diff --git a/examples/erc20/lib.rs b/examples/erc20/lib.rs index 5071496901..ad05e33d59 100644 --- a/examples/erc20/lib.rs +++ b/examples/erc20/lib.rs @@ -198,7 +198,7 @@ mod erc20 { /// Imports all the definitions from the outer scope so we can use them here. use super::*; - type Event = ::Type; + type Event = ::Type; use ink_lang as ink; @@ -518,7 +518,7 @@ mod erc20 { use ink_env::Clear; use ink_lang as ink; - type Event = ::Type; + type Event = ::Type; fn assert_transfer_event( event: &ink_env::test::EmittedEvent, diff --git a/examples/trait-erc20/lib.rs b/examples/trait-erc20/lib.rs index 65a9265172..383eab63af 100644 --- a/examples/trait-erc20/lib.rs +++ b/examples/trait-erc20/lib.rs @@ -247,7 +247,7 @@ mod erc20 { }; use ink_lang as ink; - type Event = ::Type; + type Event = ::Type; fn assert_transfer_event( event: &ink_env::test::EmittedEvent, From 18a6ec439a9ac54964a0ad4db2f711542dcaffba Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:00:35 +0200 Subject: [PATCH 441/493] apply rustfmt --- crates/lang/src/reflect/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index 65612684a5..a5f268ef48 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -25,11 +25,10 @@ mod contract; mod dispatch; -mod trait_def; mod event; +mod trait_def; pub use self::{ - event::ContractEventBase, contract::{ ContractEnv, ContractName, @@ -46,6 +45,7 @@ pub use self::{ DispatchableMessageInfo, ExecuteDispatchable, }, + event::ContractEventBase, trait_def::{ TraitDefinitionRegistry, TraitMessageInfo, From b3294ed0fdff324f771cbff34737a20eb959bd61 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:00:45 +0200 Subject: [PATCH 442/493] add usage example to ContractEventBase docs --- crates/lang/src/reflect/event.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/lang/src/reflect/event.rs b/crates/lang/src/reflect/event.rs index ab7e12d568..f3befcf704 100644 --- a/crates/lang/src/reflect/event.rs +++ b/crates/lang/src/reflect/event.rs @@ -15,6 +15,37 @@ /// Defines a base event type for the contract. /// /// This is usually the event enum that comprises all defined event types. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// #[ink(event)] +/// pub struct Event1 {} +/// +/// #[ink(event)] +/// pub struct Event2 {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self) {} +/// } +/// } +/// +/// use contract::Contract; +/// # use ink_lang::reflect::ContractEventBase; +/// +/// type BaseEvent = ::Type; +/// ``` pub trait ContractEventBase { /// The generated base event enum. type Type; From 23c0e6caaeb0ef60d68541504b21a4eb1b1de40a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:13:55 +0200 Subject: [PATCH 443/493] move TraitModulePath to ink_lang::reflect submodule --- .../src/generator/trait_def/trait_registry.rs | 2 +- crates/lang/src/lib.rs | 1 - crates/lang/src/reflect/mod.rs | 1 + crates/lang/src/reflect/trait_def/info.rs | 17 +++++++++++++++++ crates/lang/src/reflect/trait_def/mod.rs | 5 ++++- crates/lang/src/traits.rs | 17 ----------------- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index f7b9ee84e8..1df7733075 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -243,7 +243,7 @@ impl TraitRegistry<'_> { const ID: ::core::primitive::u32 = #unique_id; } - impl ::ink_lang::TraitModulePath for #trait_info_ident + impl ::ink_lang::reflect::TraitModulePath for #trait_info_ident where E: ::ink_env::Environment, { diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 32b34a7438..0a8ea7e5a2 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -42,7 +42,6 @@ pub use self::{ TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, - TraitModulePath, TraitUniqueId, }, }; diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index a5f268ef48..43c39bda1c 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -49,5 +49,6 @@ pub use self::{ trait_def::{ TraitDefinitionRegistry, TraitMessageInfo, + TraitModulePath, }, }; diff --git a/crates/lang/src/reflect/trait_def/info.rs b/crates/lang/src/reflect/trait_def/info.rs index c0e8d3ee0b..8745c1b2da 100644 --- a/crates/lang/src/reflect/trait_def/info.rs +++ b/crates/lang/src/reflect/trait_def/info.rs @@ -135,3 +135,20 @@ pub trait TraitMessageInfo { /// ink! trait definition site. const SELECTOR: [u8; 4]; } + +/// Captures the module path of the ink! trait definition. +/// +/// This can be used to differentiate between two equally named +/// ink! trait definitions and also for metadata. +pub trait TraitModulePath { + /// The module path of the ink! trait definition. + /// + /// This is equivalent to Rust's builtin `module_path!` macro + /// invocation at the definition site of the ink! trait. + const PATH: &'static str; + + /// The name of the ink! trait. + /// + /// This is just for convenience. + const NAME: &'static str; +} diff --git a/crates/lang/src/reflect/trait_def/mod.rs b/crates/lang/src/reflect/trait_def/mod.rs index cf496d7292..f28cf9be17 100644 --- a/crates/lang/src/reflect/trait_def/mod.rs +++ b/crates/lang/src/reflect/trait_def/mod.rs @@ -16,6 +16,9 @@ mod info; mod registry; pub use self::{ - info::TraitMessageInfo, + info::{ + TraitMessageInfo, + TraitModulePath, + }, registry::TraitDefinitionRegistry, }; diff --git a/crates/lang/src/traits.rs b/crates/lang/src/traits.rs index 2a24bd7d90..601824e2b1 100644 --- a/crates/lang/src/traits.rs +++ b/crates/lang/src/traits.rs @@ -48,23 +48,6 @@ pub trait TraitCallForwarder { type Forwarder: TraitCallBuilder; } -/// Captures the module path of the ink! trait definition. -/// -/// This can be used to differentiate between two equally named -/// ink! trait definitions and also for metadata. -pub trait TraitModulePath { - /// The module path of the ink! trait definition. - /// - /// This is equivalent to Rust's builtin `module_path!` macro - /// invocation at the definition site of the ink! trait. - const PATH: &'static str; - - /// The name of the ink! trait. - /// - /// This is just for convenience. - const NAME: &'static str; -} - /// Implemented by call builders of smart contracts. /// /// These might be implementing multiple different ink! traits. From 716e275fd91e851326819d06c657f78818be05f7 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:26:06 +0200 Subject: [PATCH 444/493] move ink! trait call builder codegen facilities to ink_lang::codegen submodule --- crates/lang/codegen/src/generator/arg_list.rs | 2 +- .../generator/as_dependency/call_builder.rs | 22 ++++++++-------- .../generator/as_dependency/contract_ref.rs | 10 +++---- .../src/generator/trait_def/call_forwarder.rs | 26 +++++++++---------- .../src/generator/trait_def/definition.rs | 4 +-- .../src/generator/trait_def/trait_registry.rs | 4 +-- .../trait-message-selector-overlap-1.stderr | 18 ++++++------- .../trait-message-selector-overlap-2.stderr | 18 ++++++------- crates/lang/src/codegen/mod.rs | 4 +++ .../trait_def/call_builder.rs} | 0 crates/lang/src/codegen/trait_def/mod.rs | 7 +++++ crates/lang/src/lib.rs | 7 ----- 12 files changed, 63 insertions(+), 59 deletions(-) rename crates/lang/src/{traits.rs => codegen/trait_def/call_builder.rs} (100%) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 4593a7e69a..f1a66822b5 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -98,7 +98,7 @@ pub fn generate_unique_trait_id(span: Span, trait_path: &syn::Path) -> TokenStre { <<::ink_lang::reflect::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo - as ::ink_lang::TraitUniqueId>::ID + as ::ink_lang::codegen::TraitUniqueId>::ID } ) } diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index b28160bc11..5d9d72671d 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -185,8 +185,8 @@ impl CallBuilder<'_> { let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); quote_spanned!(span=> #[doc(hidden)] - impl ::ink_lang::TraitCallForwarderFor<#unique_trait_id> for #cb_ident { - type Forwarder = <::__ink_TraitInfo as ::ink_lang::TraitCallForwarder>::Forwarder; + impl ::ink_lang::codegen::TraitCallForwarderFor<#unique_trait_id> for #cb_ident { + type Forwarder = <::__ink_TraitInfo as ::ink_lang::codegen::TraitCallForwarder>::Forwarder; #[inline(always)] fn forward(&self) -> &Self::Forwarder { @@ -215,18 +215,18 @@ impl CallBuilder<'_> { } #[inline(always)] - fn build(&self) -> &::Builder { - <_ as ::ink_lang::TraitCallBuilder>::call( - >::forward(self) + fn build(&self) -> &::Builder { + <_ as ::ink_lang::codegen::TraitCallBuilder>::call( + >::forward(self) ) } #[inline(always)] fn build_mut(&mut self) - -> &mut ::Builder + -> &mut ::Builder { - <_ as ::ink_lang::TraitCallBuilder>::call_mut( - >::forward_mut(self) + <_ as ::ink_lang::codegen::TraitCallBuilder>::call_mut( + >::forward_mut(self) ) } } @@ -288,8 +288,8 @@ impl CallBuilder<'_> { quote_spanned!(span=> type #output_ident = <<< Self - as ::ink_lang::TraitCallForwarderFor<#unique_trait_id>>::Forwarder - as ::ink_lang::TraitCallBuilder>::Builder + as ::ink_lang::codegen::TraitCallForwarderFor<#unique_trait_id>>::Forwarder + as ::ink_lang::codegen::TraitCallBuilder>::Builder as #trait_path>::#output_ident; #[inline] @@ -299,7 +299,7 @@ impl CallBuilder<'_> { #( , #input_bindings: #input_types )* ) -> Self::#output_ident { <_ as #trait_path>::#message_ident( - >::#build_cmd(self) + >::#build_cmd(self) #( , #input_bindings )* ) } diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index e8a6bda839..00e24329a0 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -157,7 +157,7 @@ impl ContractRef<'_> { let storage_ident = self.contract.module().storage().ident(); quote_spanned!(span=> const _: () = { - impl ::ink_lang::TraitCallBuilder for #ref_ident { + impl ::ink_lang::codegen::TraitCallBuilder for #ref_ident { type Builder = <#storage_ident as ::ink_lang::ContractCallBuilder>::Type; #[inline] @@ -258,7 +258,7 @@ impl ContractRef<'_> { let input_types = message.inputs().map(|input| &input.ty).collect::>(); quote_spanned!(span=> type #output_ident = - <::Forwarder as #trait_path>::#output_ident; + <::Forwarder as #trait_path>::#output_ident; #[inline] fn #message_ident( @@ -266,8 +266,8 @@ impl ContractRef<'_> { #( , #input_bindings : #input_types )* ) -> Self::#output_ident { <_ as #trait_path>::#message_ident( - <_ as ::ink_lang::TraitCallForwarderFor<#unique_trait_id>>::#forward_operator( - ::#call_operator(self), + <_ as ::ink_lang::codegen::TraitCallForwarderFor<#unique_trait_id>>::#forward_operator( + ::#call_operator(self), ) #( , #input_bindings )* ) @@ -350,7 +350,7 @@ impl ContractRef<'_> { & #mut_token self #( , #input_bindings : #input_types )* ) #output_type { - ::#call_operator(self) + ::#call_operator(self) .#message_ident( #( #input_bindings ),* ) .fire() .unwrap_or_else(|error| ::core::panic!( diff --git a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs index 52f36d4238..26003527c0 100644 --- a/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs +++ b/crates/lang/codegen/src/generator/trait_def/call_forwarder.rs @@ -120,7 +120,7 @@ impl CallForwarder<'_> { where E: ::ink_env::Environment, { - builder: ::Builder, + builder: ::Builder, } ) } @@ -145,7 +145,7 @@ impl CallForwarder<'_> { fn layout( __key_ptr: &mut ::ink_storage::traits::KeyPtr, ) -> ::ink_metadata::layout::Layout { - <::Builder + <::Builder as ::ink_storage::traits::StorageLayout>::layout(__key_ptr) } } @@ -174,20 +174,20 @@ impl CallForwarder<'_> { #[inline] fn pull_spread(ptr: &mut ::ink_primitives::KeyPtr) -> Self { Self { - builder: <::Builder + builder: <::Builder as ::ink_storage::traits::SpreadLayout>::pull_spread(ptr) } } #[inline] fn push_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { - <::Builder + <::Builder as ::ink_storage::traits::SpreadLayout>::push_spread(&self.builder, ptr) } #[inline] fn clear_spread(&self, ptr: &mut ::ink_primitives::KeyPtr) { - <::Builder + <::Builder as ::ink_storage::traits::SpreadLayout>::clear_spread(&self.builder, ptr) } } @@ -240,7 +240,7 @@ impl CallForwarder<'_> { #[inline] fn clone(&self) -> Self { Self { - builder: <::Builder + builder: <::Builder as ::core::clone::Clone>::clone(&self.builder), } } @@ -277,7 +277,7 @@ impl CallForwarder<'_> { { #[inline] fn from_account_id(account_id: ::AccountId) -> Self { - Self { builder: <::Builder + Self { builder: <::Builder as ::ink_env::call::FromAccountId>::from_account_id(account_id) } } } @@ -288,7 +288,7 @@ impl CallForwarder<'_> { { #[inline] fn to_account_id(&self) -> ::AccountId { - <::Builder + <::Builder as ::ink_lang::ToAccountId>::to_account_id(&self.builder) } } @@ -311,19 +311,19 @@ impl CallForwarder<'_> { /// Also this explains why we designed the generated code so that we have /// both types and why the forwarder is a thin-wrapper around the builder /// as this allows to perform this operation safely. - impl ::ink_lang::TraitCallBuilder for #call_forwarder_ident + impl ::ink_lang::codegen::TraitCallBuilder for #call_forwarder_ident where E: ::ink_env::Environment, { type Builder = #call_builder_ident; #[inline] - fn call(&self) -> &::Builder { + fn call(&self) -> &::Builder { &self.builder } #[inline] - fn call_mut(&mut self) -> &mut ::Builder { + fn call_mut(&mut self) -> &mut ::Builder { &mut self.builder } } @@ -414,8 +414,8 @@ impl CallForwarder<'_> { & #mut_tok self #( , #input_bindings : #input_types )* ) -> Self::#output_ident { - <::Builder as #trait_ident>::#message_ident( - ::#call_op(self) + <::Builder as #trait_ident>::#message_ident( + ::#call_op(self) #( , #input_bindings )* diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index c8e6f77424..51b1e8fd0c 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -64,8 +64,8 @@ impl TraitDefinition<'_> { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] - type __ink_TraitInfo: ::ink_lang::TraitUniqueId - + ::ink_lang::TraitCallForwarder + type __ink_TraitInfo: ::ink_lang::codegen::TraitUniqueId + + ::ink_lang::codegen::TraitCallForwarder + ::ink_lang::codegen::TraitImplementedById<#unique_trait_id>; #(#messages)* diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 1df7733075..256ce03d3f 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -236,7 +236,7 @@ impl TraitRegistry<'_> { { } - impl ::ink_lang::TraitUniqueId for #trait_info_ident + impl ::ink_lang::codegen::TraitUniqueId for #trait_info_ident where E: ::ink_env::Environment, { @@ -252,7 +252,7 @@ impl TraitRegistry<'_> { const NAME: &'static ::core::primitive::str = ::core::stringify!(#trait_ident); } - impl ::ink_lang::TraitCallForwarder for #trait_info_ident + impl ::ink_lang::codegen::TraitCallForwarder for #trait_info_ident where E: ::ink_env::Environment, { diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr index faa5bac123..7bd54816b7 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `ink_lang::codegen::TraitCallForwarderFor<3872610552_u32>` for type `contract::_::CallBuilder` + --> $DIR/trait-message-selector-overlap-1.rs:45:5 + | +40 | impl TraitDefinition1 for Contract { + | ---------------------------------- first implementation here +... +45 | impl TraitDefinition2 for Contract { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` + error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1083895717_u32>` for type `contract::Contract` --> $DIR/trait-message-selector-overlap-1.rs:47:9 | @@ -6,12 +15,3 @@ error[E0119]: conflicting implementations of trait `ink_lang::reflect::Dispatcha ... 47 | fn message(&self) {} | ^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::Contract` - -error[E0119]: conflicting implementations of trait `ink_lang::TraitCallForwarderFor<3872610552_u32>` for type `contract::_::CallBuilder` - --> $DIR/trait-message-selector-overlap-1.rs:45:5 - | -40 | impl TraitDefinition1 for Contract { - | ---------------------------------- first implementation here -... -45 | impl TraitDefinition2 for Contract { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr index be529d1f89..60c1e1a67e 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr @@ -1,3 +1,12 @@ +error[E0119]: conflicting implementations of trait `ink_lang::codegen::TraitCallForwarderFor<687202556_u32>` for type `contract::_::CallBuilder` + --> $DIR/trait-message-selector-overlap-2.rs:45:5 + | +40 | impl TraitDefinition1 for Contract { + | ---------------------------------- first implementation here +... +45 | impl TraitDefinition2 for Contract { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` + error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1518209067_u32>` for type `contract::Contract` --> $DIR/trait-message-selector-overlap-2.rs:47:9 | @@ -6,12 +15,3 @@ error[E0119]: conflicting implementations of trait `ink_lang::reflect::Dispatcha ... 47 | fn message(&self) {} | ^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::Contract` - -error[E0119]: conflicting implementations of trait `ink_lang::TraitCallForwarderFor<687202556_u32>` for type `contract::_::CallBuilder` - --> $DIR/trait-message-selector-overlap-2.rs:45:5 - | -40 | impl TraitDefinition1 for Contract { - | ---------------------------------- first implementation here -... -45 | impl TraitDefinition2 for Contract { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 305bf8711a..8ab3cb5938 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -45,9 +45,13 @@ pub use self::{ implies_return::ImpliesReturn, is_same_type::IsSameType, trait_def::{ + TraitCallBuilder, + TraitCallForwarder, + TraitCallForwarderFor, TraitImplementedById, TraitMessagePayable, TraitMessageSelector, + TraitUniqueId, }, }; diff --git a/crates/lang/src/traits.rs b/crates/lang/src/codegen/trait_def/call_builder.rs similarity index 100% rename from crates/lang/src/traits.rs rename to crates/lang/src/codegen/trait_def/call_builder.rs diff --git a/crates/lang/src/codegen/trait_def/mod.rs b/crates/lang/src/codegen/trait_def/mod.rs index 7f569d662f..d3f3c42fcf 100644 --- a/crates/lang/src/codegen/trait_def/mod.rs +++ b/crates/lang/src/codegen/trait_def/mod.rs @@ -12,10 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod call_builder; mod implemented_by; mod trait_message; pub use self::{ + call_builder::{ + TraitCallBuilder, + TraitCallForwarder, + TraitCallForwarderFor, + TraitUniqueId, + }, implemented_by::TraitImplementedById, trait_message::{ TraitMessagePayable, diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 0a8ea7e5a2..e24aaa0107 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -26,7 +26,6 @@ pub mod reflect; mod chain_extension; mod contract_ref; mod env_access; -mod traits; pub use self::{ chain_extension::{ @@ -38,12 +37,6 @@ pub use self::{ ToAccountId, }, env_access::EnvAccess, - traits::{ - TraitCallBuilder, - TraitCallForwarder, - TraitCallForwarderFor, - TraitUniqueId, - }, }; pub use ink_lang_macro::{ blake2x256, From 4febf9662205aa40d4bd29cbe591b20a1f7f68ed Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:30:06 +0200 Subject: [PATCH 445/493] move ContractCallBuilder to ink_lang::codegen submodule --- .../generator/as_dependency/call_builder.rs | 2 +- .../generator/as_dependency/contract_ref.rs | 8 +++---- crates/lang/src/codegen/dispatch/info.rs | 22 +++++++++++++++++++ crates/lang/src/codegen/dispatch/mod.rs | 2 ++ crates/lang/src/codegen/mod.rs | 1 + crates/lang/src/contract_ref.rs | 9 -------- crates/lang/src/lib.rs | 5 +---- 7 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 crates/lang/src/codegen/dispatch/info.rs diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 5d9d72671d..7edbfae33a 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -102,7 +102,7 @@ impl CallBuilder<'_> { } const _: () = { - impl ::ink_lang::ContractCallBuilder for #storage_ident { + impl ::ink_lang::codegen::ContractCallBuilder for #storage_ident { type Type = #cb_ident; } diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index 00e24329a0..ef5c5785a7 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -103,7 +103,7 @@ impl ContractRef<'_> { )] #( #doc_attrs )* pub struct #ref_ident { - inner: <#storage_ident as ::ink_lang::ContractCallBuilder>::Type, + inner: <#storage_ident as ::ink_lang::codegen::ContractCallBuilder>::Type, } const _: () = { @@ -131,7 +131,7 @@ impl ContractRef<'_> { #[inline] fn from_account_id(account_id: AccountId) -> Self { Self { inner: <<#storage_ident - as ::ink_lang::ContractCallBuilder>::Type + as ::ink_lang::codegen::ContractCallBuilder>::Type as ::ink_env::call::FromAccountId>::from_account_id(account_id) } } @@ -140,7 +140,7 @@ impl ContractRef<'_> { impl ::ink_lang::ToAccountId for #ref_ident { #[inline] fn to_account_id(&self) -> AccountId { - <<#storage_ident as ::ink_lang::ContractCallBuilder>::Type + <<#storage_ident as ::ink_lang::codegen::ContractCallBuilder>::Type as ::ink_lang::ToAccountId>::to_account_id(&self.inner) } } @@ -158,7 +158,7 @@ impl ContractRef<'_> { quote_spanned!(span=> const _: () = { impl ::ink_lang::codegen::TraitCallBuilder for #ref_ident { - type Builder = <#storage_ident as ::ink_lang::ContractCallBuilder>::Type; + type Builder = <#storage_ident as ::ink_lang::codegen::ContractCallBuilder>::Type; #[inline] fn call(&self) -> &Self::Builder { diff --git a/crates/lang/src/codegen/dispatch/info.rs b/crates/lang/src/codegen/dispatch/info.rs new file mode 100644 index 0000000000..c7843d1ca3 --- /dev/null +++ b/crates/lang/src/codegen/dispatch/info.rs @@ -0,0 +1,22 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Used to refer to the generated contract call builder. +/// +/// The generated contract call builder implements the long-hand calling API +/// for all inherent or trait ink! messages. +pub trait ContractCallBuilder { + /// The generated contract call builder type. + type Type; +} diff --git a/crates/lang/src/codegen/dispatch/mod.rs b/crates/lang/src/codegen/dispatch/mod.rs index ea8bdc37fd..d94871aa2a 100644 --- a/crates/lang/src/codegen/dispatch/mod.rs +++ b/crates/lang/src/codegen/dispatch/mod.rs @@ -13,6 +13,7 @@ // limitations under the License. mod execution; +mod info; mod type_check; pub use self::{ @@ -23,6 +24,7 @@ pub use self::{ ExecuteConstructorConfig, ExecuteMessageConfig, }, + info::ContractCallBuilder, type_check::{ DispatchInput, DispatchOutput, diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 8ab3cb5938..0091be2c00 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -26,6 +26,7 @@ pub use self::{ deny_payment, execute_constructor, execute_message, + ContractCallBuilder, DispatchInput, DispatchOutput, ExecuteConstructorConfig, diff --git a/crates/lang/src/contract_ref.rs b/crates/lang/src/contract_ref.rs index a0f350abd6..fa62e87375 100644 --- a/crates/lang/src/contract_ref.rs +++ b/crates/lang/src/contract_ref.rs @@ -24,12 +24,3 @@ where /// Returns the underlying account identifier of the instantiated contract. fn to_account_id(&self) -> ::AccountId; } - -/// Used to refer to the generated contract call builder. -/// -/// The generated contract call builder implements the long-hand calling API -/// for all inherent or trait ink! messages. -pub trait ContractCallBuilder { - /// The generated contract call builder type. - type Type; -} diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index e24aaa0107..a833252b74 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -32,10 +32,7 @@ pub use self::{ ChainExtensionInstance, IsResultType, }, - contract_ref::{ - ContractCallBuilder, - ToAccountId, - }, + contract_ref::ToAccountId, env_access::EnvAccess, }; pub use ink_lang_macro::{ From bc92311bc9ce66a8a6672c043017a0452c8c363a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:43:12 +0200 Subject: [PATCH 446/493] move IsSameType and identity_type into ink_lang::codegen::utils module --- crates/lang/codegen/src/generator/events.rs | 2 +- .../lang/codegen/src/generator/item_impls.rs | 10 ++--- .../codegen/src/generator/trait_def/mod.rs | 4 +- .../lang/src/codegen/dispatch/type_check.rs | 8 ++-- crates/lang/src/codegen/event/topics.rs | 2 +- crates/lang/src/codegen/mod.rs | 10 +---- .../lang/src/codegen/utils/identity_type.rs | 20 +++++++++ crates/lang/src/codegen/utils/mod.rs | 23 ++++++++++ crates/lang/src/codegen/utils/same_type.rs | 45 +++++++++++++++++++ crates/lang/src/reflect/contract.rs | 6 +-- 10 files changed, 105 insertions(+), 25 deletions(-) create mode 100644 crates/lang/src/codegen/utils/identity_type.rs create mode 100644 crates/lang/src/codegen/utils/mod.rs create mode 100644 crates/lang/src/codegen/utils/same_type.rs diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index 85905e26ad..ce3b106bd3 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -154,7 +154,7 @@ impl<'a> Events<'a> { type LenTopics = ::ink_lang::codegen::EventTopics<#len_topics>; } - const _: () = ::ink_lang::codegen::identity_type::< + const _: () = ::ink_lang::codegen::utils::identity_type::< ::ink_lang::codegen::EventRespectsTopicLimit< #event_ident, { #max_len_topics }, diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 9592c6ce87..57565ad75a 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -134,7 +134,7 @@ impl ItemImpls<'_> { let span = input.span(); let input_type = &*input.ty; quote_spanned!(span=> - let _: () = ::ink_lang::codegen::identity_type::< + let _: () = ::ink_lang::codegen::utils::identity_type::< ::ink_lang::codegen::DispatchInput<#input_type> >(); ) @@ -155,7 +155,7 @@ impl ItemImpls<'_> { let span = input.span(); let input_type = &*input.ty; quote_spanned!(span=> - let _: () = ::ink_lang::codegen::identity_type::< + let _: () = ::ink_lang::codegen::utils::identity_type::< ::ink_lang::codegen::DispatchInput<#input_type> >(); ) @@ -163,7 +163,7 @@ impl ItemImpls<'_> { let message_output = message.output().map(|output_type| { let span = output_type.span(); quote_spanned!(span=> - let _: () = ::ink_lang::codegen::identity_type::< + let _: () = ::ink_lang::codegen::utils::identity_type::< ::ink_lang::codegen::DispatchOutput<#output_type> >(); ) @@ -295,8 +295,8 @@ impl ItemImpls<'_> { let span = self_ty.span(); let storage_ident = self.contract.module().storage().ident(); quote_spanned!(span => - const _: ::ink_lang::codegen::IsSameType<#storage_ident> = - ::ink_lang::codegen::IsSameType::<#self_ty>::new(); + const _: ::ink_lang::codegen::utils::IsSameType<#storage_ident> = + ::ink_lang::codegen::utils::IsSameType::<#self_ty>::new(); ) } diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 748d8efbe7..1ec5b2651a 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -95,7 +95,7 @@ impl TraitDefinition<'_> { let input_span = input.span(); let input_type = &*input.ty; quote_spanned!(input_span=> - let _: () = ::ink_lang::codegen::identity_type::< + let _: () = ::ink_lang::codegen::utils::identity_type::< ::ink_lang::codegen::DispatchInput<#input_type> >(); ) @@ -103,7 +103,7 @@ impl TraitDefinition<'_> { let message_output = message.output().map(|output_type| { let output_span = output_type.span(); quote_spanned!(output_span=> - let _: () = ::ink_lang::codegen::identity_type::< + let _: () = ::ink_lang::codegen::utils::identity_type::< ::ink_lang::codegen::DispatchOutput<#output_type> >(); ) diff --git a/crates/lang/src/codegen/dispatch/type_check.rs b/crates/lang/src/codegen/dispatch/type_check.rs index 0d86096726..e121c5c116 100644 --- a/crates/lang/src/codegen/dispatch/type_check.rs +++ b/crates/lang/src/codegen/dispatch/type_check.rs @@ -25,7 +25,7 @@ /// /// ``` /// # use ink_lang::codegen::DispatchInput; -/// const _: () = ink_lang::codegen::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::identity_type::>(); /// ``` /// /// This fails to compile since `Foo` does not fulfill all requirements. @@ -34,7 +34,7 @@ /// # use ink_lang::codegen::DispatchInput; /// // Foo is missing scale codec implementations. /// struct Foo {} -/// const _: () = ink_lang::codegen::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::identity_type::>(); /// ``` pub struct DispatchInput(T) where @@ -53,7 +53,7 @@ where /// /// ``` /// # use ink_lang::codegen::DispatchOutput; -/// const _: () = ink_lang::codegen::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::identity_type::>(); /// ``` /// /// This fails to compile since `Foo` does not fulfill all requirements. @@ -62,7 +62,7 @@ where /// # use ink_lang::codegen::DispatchOutput; /// // Foo is missing scale codec implementations. /// struct Foo {} -/// const _: () = ink_lang::codegen::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::identity_type::>(); /// ``` pub struct DispatchOutput(T) where diff --git a/crates/lang/src/codegen/event/topics.rs b/crates/lang/src/codegen/event/topics.rs index b75e02a0dc..7b68bf87a5 100644 --- a/crates/lang/src/codegen/event/topics.rs +++ b/crates/lang/src/codegen/event/topics.rs @@ -35,7 +35,7 @@ use core::marker::PhantomData; /// // The below code only compiles successfully if the example ink! event /// // definitions respects the topic limitation: it must have an amount of /// // topics less than or equal to the topic limit. -/// const _: () = ::ink_lang::codegen::identity_type::< +/// const _: () = ::ink_lang::codegen::utils::identity_type::< /// ::ink_lang::codegen::EventRespectsTopicLimit< /// ExampleEvent, /// TOPICS_LIMIT, diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 0091be2c00..811f00063a 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -18,8 +18,8 @@ mod dispatch; mod env; mod event; mod implies_return; -mod is_same_type; mod trait_def; +pub mod utils; pub use self::{ dispatch::{ @@ -44,7 +44,6 @@ pub use self::{ RespectTopicLimit, }, implies_return::ImpliesReturn, - is_same_type::IsSameType, trait_def::{ TraitCallBuilder, TraitCallForwarder, @@ -55,10 +54,3 @@ pub use self::{ TraitUniqueId, }, }; - -/// Takes a generic type as input and does nothing. -/// -/// # Note -/// -/// Used to trigger some compile time checks. -pub const fn identity_type() {} diff --git a/crates/lang/src/codegen/utils/identity_type.rs b/crates/lang/src/codegen/utils/identity_type.rs new file mode 100644 index 0000000000..fa0d290245 --- /dev/null +++ b/crates/lang/src/codegen/utils/identity_type.rs @@ -0,0 +1,20 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Takes a generic type as input and does nothing. +/// +/// # Note +/// +/// Used to trigger some compile time checks. +pub const fn identity_type() {} diff --git a/crates/lang/src/codegen/utils/mod.rs b/crates/lang/src/codegen/utils/mod.rs new file mode 100644 index 0000000000..cac1d2841e --- /dev/null +++ b/crates/lang/src/codegen/utils/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Utility types and definitions used by the ink! codegen. + +mod same_type; +mod identity_type; + +pub use self::{ + same_type::IsSameType, + identity_type::identity_type, +}; diff --git a/crates/lang/src/codegen/utils/same_type.rs b/crates/lang/src/codegen/utils/same_type.rs new file mode 100644 index 0000000000..44fbba5438 --- /dev/null +++ b/crates/lang/src/codegen/utils/same_type.rs @@ -0,0 +1,45 @@ +// Copyright 2018-2021 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use core::marker::PhantomData; + +/// Can be used to check equality of types. +/// +/// # Example +/// +/// This code compiles: +/// +/// ``` +/// # use ink_lang::codegen::utils::IsSameType; +/// const _: IsSameType = IsSameType::::new(); +/// ``` +/// +/// While this code does not: +/// +/// ```compile_fail +/// # use ink_lang::codegen::utils::IsSameType; +/// const _: IsSameType = IsSameType::::new(); +/// ``` +pub struct IsSameType { + _marker: PhantomData, +} + +impl IsSameType { + /// Creates a new const instance. + pub const fn new() -> Self { + Self { + _marker: PhantomData, + } + } +} diff --git a/crates/lang/src/reflect/contract.rs b/crates/lang/src/reflect/contract.rs index 486d449f32..7083f56f8b 100644 --- a/crates/lang/src/reflect/contract.rs +++ b/crates/lang/src/reflect/contract.rs @@ -85,7 +85,7 @@ pub trait ContractName { /// use contract::Contract; /// /// # use ink_lang::reflect::ContractEnv; -/// # use ink_lang::codegen::IsSameType; +/// # use ink_lang::codegen::utils::IsSameType; /// /// // The following line only compiles successfully if both /// // `ink_env::DefaultEnvironment` and `::Env` @@ -130,7 +130,7 @@ pub trait ContractName { /// /// use contract::Contract; /// # use ink_lang::reflect::ContractEnv; -/// # use ink_lang::codegen::IsSameType; +/// # use ink_lang::codegen::utils::IsSameType; /// /// // The following line only compiles successfully if both /// // `CustomEnvironment` and `::Env` @@ -175,7 +175,7 @@ pub trait ContractEnv { /// } /// /// use contract::{Contract, ContractRef}; -/// # use ink_lang::codegen::IsSameType; +/// # use ink_lang::codegen::utils::IsSameType; /// # use ink_lang::reflect::ContractReference; /// /// // The following line only compiles successfully if both From 3eec2e3e1cb30d1430b13ad10e523190e226eace Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:52:34 +0200 Subject: [PATCH 447/493] rename identity_type to consume_type --- crates/lang/codegen/src/generator/events.rs | 2 +- crates/lang/codegen/src/generator/item_impls.rs | 6 +++--- crates/lang/codegen/src/generator/trait_def/mod.rs | 4 ++-- crates/lang/src/codegen/dispatch/type_check.rs | 8 ++++---- crates/lang/src/codegen/event/topics.rs | 2 +- crates/lang/src/codegen/utils/mod.rs | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/lang/codegen/src/generator/events.rs b/crates/lang/codegen/src/generator/events.rs index ce3b106bd3..3401da156b 100644 --- a/crates/lang/codegen/src/generator/events.rs +++ b/crates/lang/codegen/src/generator/events.rs @@ -154,7 +154,7 @@ impl<'a> Events<'a> { type LenTopics = ::ink_lang::codegen::EventTopics<#len_topics>; } - const _: () = ::ink_lang::codegen::utils::identity_type::< + const _: () = ::ink_lang::codegen::utils::consume_type::< ::ink_lang::codegen::EventRespectsTopicLimit< #event_ident, { #max_len_topics }, diff --git a/crates/lang/codegen/src/generator/item_impls.rs b/crates/lang/codegen/src/generator/item_impls.rs index 57565ad75a..28fe7fb6cc 100644 --- a/crates/lang/codegen/src/generator/item_impls.rs +++ b/crates/lang/codegen/src/generator/item_impls.rs @@ -134,7 +134,7 @@ impl ItemImpls<'_> { let span = input.span(); let input_type = &*input.ty; quote_spanned!(span=> - let _: () = ::ink_lang::codegen::utils::identity_type::< + let _: () = ::ink_lang::codegen::utils::consume_type::< ::ink_lang::codegen::DispatchInput<#input_type> >(); ) @@ -155,7 +155,7 @@ impl ItemImpls<'_> { let span = input.span(); let input_type = &*input.ty; quote_spanned!(span=> - let _: () = ::ink_lang::codegen::utils::identity_type::< + let _: () = ::ink_lang::codegen::utils::consume_type::< ::ink_lang::codegen::DispatchInput<#input_type> >(); ) @@ -163,7 +163,7 @@ impl ItemImpls<'_> { let message_output = message.output().map(|output_type| { let span = output_type.span(); quote_spanned!(span=> - let _: () = ::ink_lang::codegen::utils::identity_type::< + let _: () = ::ink_lang::codegen::utils::consume_type::< ::ink_lang::codegen::DispatchOutput<#output_type> >(); ) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 1ec5b2651a..2144d926de 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -95,7 +95,7 @@ impl TraitDefinition<'_> { let input_span = input.span(); let input_type = &*input.ty; quote_spanned!(input_span=> - let _: () = ::ink_lang::codegen::utils::identity_type::< + let _: () = ::ink_lang::codegen::utils::consume_type::< ::ink_lang::codegen::DispatchInput<#input_type> >(); ) @@ -103,7 +103,7 @@ impl TraitDefinition<'_> { let message_output = message.output().map(|output_type| { let output_span = output_type.span(); quote_spanned!(output_span=> - let _: () = ::ink_lang::codegen::utils::identity_type::< + let _: () = ::ink_lang::codegen::utils::consume_type::< ::ink_lang::codegen::DispatchOutput<#output_type> >(); ) diff --git a/crates/lang/src/codegen/dispatch/type_check.rs b/crates/lang/src/codegen/dispatch/type_check.rs index e121c5c116..fe25341d50 100644 --- a/crates/lang/src/codegen/dispatch/type_check.rs +++ b/crates/lang/src/codegen/dispatch/type_check.rs @@ -25,7 +25,7 @@ /// /// ``` /// # use ink_lang::codegen::DispatchInput; -/// const _: () = ink_lang::codegen::utils::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::consume_type::>(); /// ``` /// /// This fails to compile since `Foo` does not fulfill all requirements. @@ -34,7 +34,7 @@ /// # use ink_lang::codegen::DispatchInput; /// // Foo is missing scale codec implementations. /// struct Foo {} -/// const _: () = ink_lang::codegen::utils::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::consume_type::>(); /// ``` pub struct DispatchInput(T) where @@ -53,7 +53,7 @@ where /// /// ``` /// # use ink_lang::codegen::DispatchOutput; -/// const _: () = ink_lang::codegen::utils::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::consume_type::>(); /// ``` /// /// This fails to compile since `Foo` does not fulfill all requirements. @@ -62,7 +62,7 @@ where /// # use ink_lang::codegen::DispatchOutput; /// // Foo is missing scale codec implementations. /// struct Foo {} -/// const _: () = ink_lang::codegen::utils::identity_type::>(); +/// const _: () = ink_lang::codegen::utils::consume_type::>(); /// ``` pub struct DispatchOutput(T) where diff --git a/crates/lang/src/codegen/event/topics.rs b/crates/lang/src/codegen/event/topics.rs index 7b68bf87a5..36bc36d9e1 100644 --- a/crates/lang/src/codegen/event/topics.rs +++ b/crates/lang/src/codegen/event/topics.rs @@ -35,7 +35,7 @@ use core::marker::PhantomData; /// // The below code only compiles successfully if the example ink! event /// // definitions respects the topic limitation: it must have an amount of /// // topics less than or equal to the topic limit. -/// const _: () = ::ink_lang::codegen::utils::identity_type::< +/// const _: () = ::ink_lang::codegen::utils::consume_type::< /// ::ink_lang::codegen::EventRespectsTopicLimit< /// ExampleEvent, /// TOPICS_LIMIT, diff --git a/crates/lang/src/codegen/utils/mod.rs b/crates/lang/src/codegen/utils/mod.rs index cac1d2841e..acb58233bb 100644 --- a/crates/lang/src/codegen/utils/mod.rs +++ b/crates/lang/src/codegen/utils/mod.rs @@ -19,5 +19,5 @@ mod identity_type; pub use self::{ same_type::IsSameType, - identity_type::identity_type, + identity_type::consume_type, }; From 0b1c17ace3254349e37792b086233446bd310af8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:52:48 +0200 Subject: [PATCH 448/493] apply rustfmt --- crates/lang/src/codegen/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/src/codegen/utils/mod.rs b/crates/lang/src/codegen/utils/mod.rs index acb58233bb..5ed73ba58e 100644 --- a/crates/lang/src/codegen/utils/mod.rs +++ b/crates/lang/src/codegen/utils/mod.rs @@ -14,10 +14,10 @@ //! Utility types and definitions used by the ink! codegen. -mod same_type; mod identity_type; +mod same_type; pub use self::{ - same_type::IsSameType, identity_type::consume_type, + same_type::IsSameType, }; From 048ce448ec5063c768d321733d7748ece7c74d5c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 15:53:05 +0200 Subject: [PATCH 449/493] add usage examples to consume_type docs (+ missing rename) --- .../lang/src/codegen/utils/identity_type.rs | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/crates/lang/src/codegen/utils/identity_type.rs b/crates/lang/src/codegen/utils/identity_type.rs index fa0d290245..fffc5ce543 100644 --- a/crates/lang/src/codegen/utils/identity_type.rs +++ b/crates/lang/src/codegen/utils/identity_type.rs @@ -12,9 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// Takes a generic type as input and does nothing. +/// Takes a generic type as input and just consumes it while doing nothing. /// /// # Note /// -/// Used to trigger some compile time checks. -pub const fn identity_type() {} +/// This can be used to trigger some compile time checks due to the fact +/// that the type consumed this way is type checked. We usually use this +/// to make the Rust compiler check the trait bounds in particular. +/// +/// # Usage: Compiles +/// +/// ``` +/// # use ink_lang::codegen::utils::consume_type; +/// # use core::marker::PhantomData; +/// # +/// pub struct RequiresCopy(PhantomData); +/// +/// // The following line of code works because `i32: Copy`. +/// let _: () = consume_type::>(); +/// ``` +/// +/// # Usage: Compile Error +/// +/// ```compile_fail +/// # use ink_lang::codegen::utils::consume_type; +/// # use core::marker::PhantomData; +/// # +/// pub struct RequiresCopy(PhantomData); +/// +/// // The following line of code fails to compile because +/// // `String` does not implement `Copy`. +/// let _: () = consume_type::>(); +/// ``` +pub const fn consume_type() {} From b74772b6711a92caf1aee183b3ea7127e38f8bc9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:02:48 +0200 Subject: [PATCH 450/493] fix codegen to allow for environmental type usage in ink! trait definitions --- .../codegen/src/generator/trait_def/mod.rs | 42 ------------------- .../src/generator/trait_def/trait_registry.rs | 35 +++++++++++++++- 2 files changed, 34 insertions(+), 43 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index 2144d926de..d21b6b31aa 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -27,7 +27,6 @@ use quote::{ format_ident, quote_spanned, }; -use syn::spanned::Spanned as _; /// Generator to create the ink! storage struct and important trait implementations. #[derive(From, Copy, Clone)] @@ -67,54 +66,13 @@ impl GenerateCode for TraitDefinition<'_> { let trait_registry = self.generate_trait_registry_impl(); let trait_call_builder = self.generate_call_builder(); let trait_call_forwarder = self.generate_call_forwarder(); - let input_output_guards = self.generate_input_output_guards(); quote_spanned!(span => #trait_definition const _: () = { #trait_registry #trait_call_builder #trait_call_forwarder - #input_output_guards }; ) } } - -impl TraitDefinition<'_> { - /// Generates code to assert that ink! input and output types meet certain properties. - fn generate_input_output_guards(&self) -> TokenStream2 { - let storage_span = self.trait_def.item().span(); - let message_inout_guards = self - .trait_def - .item() - .iter_items() - .filter_map(|(impl_item, _)| impl_item.filter_map_message()) - .map(|message| { - let message_span = message.span(); - let message_inputs = message.inputs().map(|input| { - let input_span = input.span(); - let input_type = &*input.ty; - quote_spanned!(input_span=> - let _: () = ::ink_lang::codegen::utils::consume_type::< - ::ink_lang::codegen::DispatchInput<#input_type> - >(); - ) - }); - let message_output = message.output().map(|output_type| { - let output_span = output_type.span(); - quote_spanned!(output_span=> - let _: () = ::ink_lang::codegen::utils::consume_type::< - ::ink_lang::codegen::DispatchOutput<#output_type> - >(); - ) - }); - quote_spanned!(message_span=> - #( #message_inputs )* - #message_output - ) - }); - quote_spanned!(storage_span=> - #( #message_inout_guards )* - ) - } -} diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 256ce03d3f..2a3ae4dd89 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -36,7 +36,10 @@ use quote::{ quote, quote_spanned, }; -use syn::parse_quote; +use syn::{ + parse_quote, + spanned::Spanned, +}; impl<'a> TraitDefinition<'a> { /// Generates the code for the global trait registry implementation. @@ -129,6 +132,34 @@ impl TraitRegistry<'_> { } } + /// Generates code to assert that ink! input and output types meet certain properties. + fn generate_inout_guards_for_message( + message: &ir::InkTraitMessage, + ) -> TokenStream2 { + let message_span = message.span(); + let message_inputs = message.inputs().map(|input| { + let input_span = input.span(); + let input_type = &*input.ty; + quote_spanned!(input_span=> + let _: () = ::ink_lang::codegen::utils::consume_type::< + ::ink_lang::codegen::DispatchInput<#input_type> + >(); + ) + }); + let message_output = message.output().map(|output_type| { + let output_span = output_type.span(); + quote_spanned!(output_span=> + let _: () = ::ink_lang::codegen::utils::consume_type::< + ::ink_lang::codegen::DispatchOutput<#output_type> + >(); + ) + }); + quote_spanned!(message_span=> + #( #message_inputs )* + #message_output + ) + } + /// Generate the code for a single ink! trait message implemented by the trait registry. /// /// Generally the implementation of any ink! trait of the ink! trait registry @@ -154,6 +185,7 @@ impl TraitRegistry<'_> { selector, message.mutates(), ); + let inout_guards = Self::generate_inout_guards_for_message(message); let impl_body = match option_env!("INK_COVERAGE_REPORTING") { Some("true") => { quote! { @@ -187,6 +219,7 @@ impl TraitRegistry<'_> { & #mut_token self #( , #input_bindings : #input_types )* ) -> Self::#output_ident { + #inout_guards #impl_body } ) From e368bf8213092eb361dccc19c9bc2a694346d8b8 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:03:09 +0200 Subject: [PATCH 451/493] add UI test that uses environmental types in ink! trait definition --- .../tests/ui/trait_def/pass/using-env-types.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 crates/lang/macro/tests/ui/trait_def/pass/using-env-types.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/using-env-types.rs b/crates/lang/macro/tests/ui/trait_def/pass/using-env-types.rs new file mode 100644 index 0000000000..21500739bf --- /dev/null +++ b/crates/lang/macro/tests/ui/trait_def/pass/using-env-types.rs @@ -0,0 +1,14 @@ +use ink_env::Environment; +use ink_lang::reflect::ContractEnv; + +use ink_lang as ink; + +#[ink::trait_definition] +pub trait TraitDefinition { + #[ink(message)] + fn message_1(&self) -> <::Env as Environment>::AccountId; + #[ink(message)] + fn message_2(&self, input: <::Env as Environment>::Balance); +} + +fn main() {} From 46accafeafec3623a2fb9bfd4240de92d2829986 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:03:34 +0200 Subject: [PATCH 452/493] apply rustfmt --- crates/lang/codegen/src/generator/trait_def/trait_registry.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 2a3ae4dd89..ec40160ef1 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -133,9 +133,7 @@ impl TraitRegistry<'_> { } /// Generates code to assert that ink! input and output types meet certain properties. - fn generate_inout_guards_for_message( - message: &ir::InkTraitMessage, - ) -> TokenStream2 { + fn generate_inout_guards_for_message(message: &ir::InkTraitMessage) -> TokenStream2 { let message_span = message.span(); let message_inputs = message.inputs().map(|input| { let input_span = input.span(); From 4ab8a86daaa72c00d3e274c8cab5e26c70f39bf9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:19:26 +0200 Subject: [PATCH 453/493] remove unused Selector::unique_id method --- crates/lang/ir/src/ir/selector.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index cf4df3235c..d858953c11 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -136,11 +136,6 @@ impl Selector { &self.bytes } - /// Returns a unique identifier as `usize`. - pub fn unique_id(self) -> usize { - self.into_be_u32() as usize - } - /// Returns the big-endian `u32` representation of the selector bytes. pub fn into_be_u32(self) -> u32 { u32::from_be_bytes(self.bytes) From 7b978c2235dd41d289d3b0091432b250f25eb07c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:25:04 +0200 Subject: [PATCH 454/493] remove Selector::from_bytes Users should use Selector's From<[u8;4]> implementation instead. --- crates/lang/ir/src/ir/attrs.rs | 6 +++--- crates/lang/ir/src/ir/item_impl/callable.rs | 2 +- crates/lang/ir/src/ir/selector.rs | 11 +++-------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index 6c07101c1f..cbf3144b56 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -818,7 +818,7 @@ impl TryFrom for AttributeFrag { error ) })?; - let selector = Selector::from_bytes(selector_u32.to_be_bytes()); + let selector = Selector::from(selector_u32.to_be_bytes()); return Ok(AttributeFrag { ast: meta, arg: AttributeArg::Selector(selector), @@ -1116,7 +1116,7 @@ mod tests { #[ink(selector = 42)] }, Ok(test::Attribute::Ink(vec![AttributeArg::Selector( - Selector::from_bytes([0, 0, 0, 42]), + Selector::from([0, 0, 0, 42]), )])), ); assert_attribute_try_from( @@ -1124,7 +1124,7 @@ mod tests { #[ink(selector = 0xDEADBEEF)] }, Ok(test::Attribute::Ink(vec![AttributeArg::Selector( - Selector::from_bytes([0xDE, 0xAD, 0xBE, 0xEF]), + Selector::from([0xDE, 0xAD, 0xBE, 0xEF]), )])), ); } diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index 5f4723c646..0c3f1c68f5 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -554,7 +554,7 @@ mod tests { impl ExpectedSelector { pub fn expected_selector(self) -> ir::Selector { match self { - Self::Raw(raw_selector) => ir::Selector::from_bytes(raw_selector), + Self::Raw(raw_selector) => ir::Selector::from(raw_selector), Self::Blake2(blake2_input) => ir::Selector::new(&blake2_input), } } diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index d858953c11..170a70319f 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -65,16 +65,11 @@ impl<'a> TraitPrefix<'a> { } impl Selector { - /// Creates a new selector from the given raw bytes. - pub fn from_bytes(bytes: [u8; 4]) -> Self { - Self { bytes } - } - /// Computes the BLAKE-2 256-bit based selector from the given input bytes. pub fn new(input: &[u8]) -> Self { let mut output = [0; 32]; blake2b_256(input, &mut output); - Self::from_bytes([output[0], output[1], output[2], output[3]]) + Self::from([output[0], output[1], output[2], output[3]]) } /// # Note @@ -149,7 +144,7 @@ impl Selector { impl From<[u8; 4]> for Selector { fn from(bytes: [u8; 4]) -> Self { - Self::from_bytes(bytes) + Self { bytes } } } @@ -221,7 +216,7 @@ mod tests { #[test] fn hex_lits_works() { - let hex_lits = Selector::from_bytes([0xC0, 0xDE, 0xCA, 0xFE]).hex_lits(); + let hex_lits = Selector::from([0xC0, 0xDE, 0xCA, 0xFE]).hex_lits(); assert_eq!( hex_lits, [ From aa545761eb3ad8d617289fc6cf854a3a60084d43 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:26:21 +0200 Subject: [PATCH 455/493] rename Selector::new -> Selector::compute --- crates/lang/ir/src/ir/item_impl/callable.rs | 4 ++-- crates/lang/ir/src/ir/selector.rs | 6 +++--- crates/lang/ir/src/ir/utils.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/lang/ir/src/ir/item_impl/callable.rs b/crates/lang/ir/src/ir/item_impl/callable.rs index 0c3f1c68f5..d7ab1bca1c 100644 --- a/crates/lang/ir/src/ir/item_impl/callable.rs +++ b/crates/lang/ir/src/ir/item_impl/callable.rs @@ -344,7 +344,7 @@ where } } }; - ir::Selector::new(&joined) + ir::Selector::compute(&joined) } /// Ensures that common invariants of externally callable ink! entities are met. @@ -555,7 +555,7 @@ mod tests { pub fn expected_selector(self) -> ir::Selector { match self { Self::Raw(raw_selector) => ir::Selector::from(raw_selector), - Self::Blake2(blake2_input) => ir::Selector::new(&blake2_input), + Self::Blake2(blake2_input) => ir::Selector::compute(&blake2_input), } } } diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 170a70319f..0f1707f7c2 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -66,7 +66,7 @@ impl<'a> TraitPrefix<'a> { impl Selector { /// Computes the BLAKE-2 256-bit based selector from the given input bytes. - pub fn new(input: &[u8]) -> Self { + pub fn compute(input: &[u8]) -> Self { let mut output = [0; 32]; blake2b_256(input, &mut output); Self::from([output[0], output[1], output[2], output[3]]) @@ -123,7 +123,7 @@ impl Selector { } None => fn_ident.to_vec(), }; - Self::new(&input_bytes) + Self::compute(&input_bytes) } /// Returns the underlying four bytes. @@ -201,7 +201,7 @@ impl TryFrom for SelectorMacro { )) } }; - let selector = Selector::new(&input_bytes); + let selector = Selector::compute(&input_bytes); Ok(Self { selector, input: lit, diff --git a/crates/lang/ir/src/ir/utils.rs b/crates/lang/ir/src/ir/utils.rs index 9ffefbd8c5..a075f9432c 100644 --- a/crates/lang/ir/src/ir/utils.rs +++ b/crates/lang/ir/src/ir/utils.rs @@ -52,6 +52,6 @@ pub fn ensure_pub_visibility( /// - Used from within ink! trait definitions as well as ink! trait implementation blocks. pub fn local_message_id(ident: &syn::Ident) -> u32 { let input = ident.to_string().into_bytes(); - let selector = Selector::new(&input); + let selector = Selector::compute(&input); selector.into_be_u32() } From 8d4f3adfe3ca196a0efb1f076cbc3867532292eb Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:34:56 +0200 Subject: [PATCH 456/493] fix some UI tests for rename --- .../lang/macro/tests/ui/selector_bytes/pass/bytestring_input.rs | 2 +- crates/lang/macro/tests/ui/selector_bytes/pass/string_input.rs | 2 +- crates/lang/macro/tests/ui/selector_id/pass/bytestring_input.rs | 2 +- crates/lang/macro/tests/ui/selector_id/pass/string_input.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/lang/macro/tests/ui/selector_bytes/pass/bytestring_input.rs b/crates/lang/macro/tests/ui/selector_bytes/pass/bytestring_input.rs index 03e7731d98..19d956bece 100644 --- a/crates/lang/macro/tests/ui/selector_bytes/pass/bytestring_input.rs +++ b/crates/lang/macro/tests/ui/selector_bytes/pass/bytestring_input.rs @@ -7,7 +7,7 @@ macro_rules! assert_macro_eq { const HASH: [u8; 4] = ink::selector_bytes!($input); assert_eq!( HASH, - *ir::Selector::new($input).as_bytes(), + ir::Selector::compute($input).to_bytes(), ); }}; } diff --git a/crates/lang/macro/tests/ui/selector_bytes/pass/string_input.rs b/crates/lang/macro/tests/ui/selector_bytes/pass/string_input.rs index 0291b2d4b1..fb9aa25507 100644 --- a/crates/lang/macro/tests/ui/selector_bytes/pass/string_input.rs +++ b/crates/lang/macro/tests/ui/selector_bytes/pass/string_input.rs @@ -7,7 +7,7 @@ macro_rules! assert_macro_eq { const HASH: [u8; 4] = ink::selector_bytes!($input); assert_eq!( HASH, - *ir::Selector::new($input.as_bytes()).as_bytes(), + ir::Selector::compute($input.as_bytes()).to_bytes(), ); }}; } diff --git a/crates/lang/macro/tests/ui/selector_id/pass/bytestring_input.rs b/crates/lang/macro/tests/ui/selector_id/pass/bytestring_input.rs index 9e837be2e0..8136c259ac 100644 --- a/crates/lang/macro/tests/ui/selector_id/pass/bytestring_input.rs +++ b/crates/lang/macro/tests/ui/selector_id/pass/bytestring_input.rs @@ -7,7 +7,7 @@ macro_rules! assert_macro_eq { const HASH: u32 = ink::selector_id!($input); assert_eq!( HASH, - ir::Selector::new($input).into_be_u32(), + ir::Selector::compute($input).into_be_u32(), ); }}; } diff --git a/crates/lang/macro/tests/ui/selector_id/pass/string_input.rs b/crates/lang/macro/tests/ui/selector_id/pass/string_input.rs index 21d98a37a1..ca7eb30e25 100644 --- a/crates/lang/macro/tests/ui/selector_id/pass/string_input.rs +++ b/crates/lang/macro/tests/ui/selector_id/pass/string_input.rs @@ -7,7 +7,7 @@ macro_rules! assert_macro_eq { const HASH: u32 = ink::selector_id!($input); assert_eq!( HASH, - ir::Selector::new($input.as_bytes()).into_be_u32(), + ir::Selector::compute($input.as_bytes()).into_be_u32(), ); }}; } From a406b8449af8b21fbd39dec3b15a4bb542e537f9 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 6 Oct 2021 22:35:24 +0200 Subject: [PATCH 457/493] change API: Selector::as_bytes -> Selector::to_bytes and return by value --- crates/lang/codegen/src/enforced_error.rs | 2 +- crates/lang/ir/src/ir/attrs.rs | 2 +- crates/lang/ir/src/ir/item_mod.rs | 2 +- crates/lang/ir/src/ir/selector.rs | 4 ++-- crates/lang/ir/src/ir/trait_def/item/mod.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/lang/codegen/src/enforced_error.rs b/crates/lang/codegen/src/enforced_error.rs index 982f40ab66..635daa8d47 100644 --- a/crates/lang/codegen/src/enforced_error.rs +++ b/crates/lang/codegen/src/enforced_error.rs @@ -74,7 +74,7 @@ impl EnforcedErrors { Self::CannotCallTraitMessage { trait_ident: trait_ident.to_string(), message_ident: message_ident.to_string(), - message_selector: *message_selector.as_bytes(), + message_selector: message_selector.to_bytes(), message_is_mut, } .into_ident() diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index cbf3144b56..a0b7c377d1 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -496,7 +496,7 @@ impl core::fmt::Display for AttributeArg { Self::Constructor => write!(f, "constructor"), Self::Payable => write!(f, "payable"), Self::Selector(selector) => { - write!(f, "selector = {:?}", selector.as_bytes()) + write!(f, "selector = {:?}", selector.to_bytes()) } Self::Extension(extension) => { write!(f, "extension = {:?}", extension.into_u32()) diff --git a/crates/lang/ir/src/ir/item_mod.rs b/crates/lang/ir/src/ir/item_mod.rs index 6472fdce55..858035889d 100644 --- a/crates/lang/ir/src/ir/item_mod.rs +++ b/crates/lang/ir/src/ir/item_mod.rs @@ -196,7 +196,7 @@ impl ItemMod { #[ink(namespace = N:string)] on the implementation block to \ disambiguate overlapping selectors.", kind, - selector.as_bytes(), + selector.to_bytes(), ) .into_combine(format_err!( first_span, diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 0f1707f7c2..8bdcded304 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -127,8 +127,8 @@ impl Selector { } /// Returns the underlying four bytes. - pub fn as_bytes(&self) -> &[u8; 4] { - &self.bytes + pub fn to_bytes(&self) -> [u8; 4] { + self.bytes } /// Returns the big-endian `u32` representation of the selector bytes. diff --git a/crates/lang/ir/src/ir/trait_def/item/mod.rs b/crates/lang/ir/src/ir/trait_def/item/mod.rs index eb6882f6ef..fe347ec640 100644 --- a/crates/lang/ir/src/ir/trait_def/item/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/item/mod.rs @@ -373,7 +373,7 @@ impl InkItemTrait { return Err(format_err_spanned!( ident, "encountered duplicate selector ({:x?}) in the same ink! trait definition", - selector.as_bytes(), + selector.to_bytes(), ).into_combine(format_err_spanned!( duplicate_selector, "first ink! trait constructor or message with same selector found here", From ca9fa3c11bf6f35f0c7e14e9ce19ca09562af376 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 7 Oct 2021 08:24:51 +0200 Subject: [PATCH 458/493] add payability to hunspell dict --- .config/cargo_spellcheck.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/cargo_spellcheck.dic b/.config/cargo_spellcheck.dic index ceb311eb87..d08d2fd453 100644 --- a/.config/cargo_spellcheck.dic +++ b/.config/cargo_spellcheck.dic @@ -95,3 +95,4 @@ vector/S implementer/S deduplicated wildcard/S +payability From 49b1340f674f0ac179da4140f40b1d044075a489 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 7 Oct 2021 11:51:15 +0200 Subject: [PATCH 459/493] use ink! trait info object instead of uniqe trait ID for TraitCallForwarderFor trait --- crates/lang/codegen/src/generator/arg_list.rs | 9 +++------ .../src/generator/as_dependency/call_builder.rs | 14 +++++++------- .../src/generator/as_dependency/contract_ref.rs | 4 ++-- crates/lang/codegen/src/generator/mod.rs | 2 +- crates/lang/src/codegen/trait_def/call_builder.rs | 2 +- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index f1a66822b5..12a5e5b2e4 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -93,12 +93,9 @@ where /// /// As with all Rust macros identifiers can shadow each other so the given identifier /// needs to be valid for the scope in which the returned code is generated. -pub fn generate_unique_trait_id(span: Span, trait_path: &syn::Path) -> TokenStream2 { +pub fn generate_reference_to_trait_info(span: Span, trait_path: &syn::Path) -> TokenStream2 { quote_spanned!(span=> - { - <<::ink_lang::reflect::TraitDefinitionRegistry - as #trait_path>::__ink_TraitInfo - as ::ink_lang::codegen::TraitUniqueId>::ID - } + <::ink_lang::reflect::TraitDefinitionRegistry + as #trait_path>::__ink_TraitInfo ) } diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 7edbfae33a..9666b942c7 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -182,10 +182,10 @@ impl CallBuilder<'_> { ) -> TokenStream2 { let span = impl_block.span(); let cb_ident = Self::call_builder_ident(); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); + let trait_info = generator::generate_reference_to_trait_info(span, trait_path); quote_spanned!(span=> #[doc(hidden)] - impl ::ink_lang::codegen::TraitCallForwarderFor<#unique_trait_id> for #cb_ident { + impl ::ink_lang::codegen::TraitCallForwarderFor<#trait_info> for #cb_ident { type Forwarder = <::__ink_TraitInfo as ::ink_lang::codegen::TraitCallForwarder>::Forwarder; #[inline(always)] @@ -217,7 +217,7 @@ impl CallBuilder<'_> { #[inline(always)] fn build(&self) -> &::Builder { <_ as ::ink_lang::codegen::TraitCallBuilder>::call( - >::forward(self) + >::forward(self) ) } @@ -226,7 +226,7 @@ impl CallBuilder<'_> { -> &mut ::Builder { <_ as ::ink_lang::codegen::TraitCallBuilder>::call_mut( - >::forward_mut(self) + >::forward_mut(self) ) } } @@ -265,7 +265,7 @@ impl CallBuilder<'_> { let span = message.span(); let message_ident = message.ident(); let output_ident = generator::output_ident(message_ident); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); + let trait_info = generator::generate_reference_to_trait_info(span, trait_path); let input_bindings = message .callable() .inputs() @@ -288,7 +288,7 @@ impl CallBuilder<'_> { quote_spanned!(span=> type #output_ident = <<< Self - as ::ink_lang::codegen::TraitCallForwarderFor<#unique_trait_id>>::Forwarder + as ::ink_lang::codegen::TraitCallForwarderFor<#trait_info>>::Forwarder as ::ink_lang::codegen::TraitCallBuilder>::Builder as #trait_path>::#output_ident; @@ -299,7 +299,7 @@ impl CallBuilder<'_> { #( , #input_bindings: #input_types )* ) -> Self::#output_ident { <_ as #trait_path>::#message_ident( - >::#build_cmd(self) + >::#build_cmd(self) #( , #input_bindings )* ) } diff --git a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs index ef5c5785a7..d9c724f716 100644 --- a/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs +++ b/crates/lang/codegen/src/generator/as_dependency/contract_ref.rs @@ -242,7 +242,7 @@ impl ContractRef<'_> { ) -> TokenStream2 { use ir::Callable as _; let span = message.span(); - let unique_trait_id = generator::generate_unique_trait_id(span, trait_path); + let trait_info = generator::generate_reference_to_trait_info(span, trait_path); let message_ident = message.ident(); let output_ident = generator::output_ident(message_ident); let call_operator = match message.receiver() { @@ -266,7 +266,7 @@ impl ContractRef<'_> { #( , #input_bindings : #input_types )* ) -> Self::#output_ident { <_ as #trait_path>::#message_ident( - <_ as ::ink_lang::codegen::TraitCallForwarderFor<#unique_trait_id>>::#forward_operator( + <_ as ::ink_lang::codegen::TraitCallForwarderFor<#trait_info>>::#forward_operator( ::#call_operator(self), ) #( , #input_bindings )* diff --git a/crates/lang/codegen/src/generator/mod.rs b/crates/lang/codegen/src/generator/mod.rs index 360d900719..1130957265 100644 --- a/crates/lang/codegen/src/generator/mod.rs +++ b/crates/lang/codegen/src/generator/mod.rs @@ -44,7 +44,7 @@ mod trait_def; pub use self::{ arg_list::{ generate_argument_list, - generate_unique_trait_id, + generate_reference_to_trait_info, input_bindings, input_bindings_tuple, input_types, diff --git a/crates/lang/src/codegen/trait_def/call_builder.rs b/crates/lang/src/codegen/trait_def/call_builder.rs index 601824e2b1..8c25c5c64c 100644 --- a/crates/lang/src/codegen/trait_def/call_builder.rs +++ b/crates/lang/src/codegen/trait_def/call_builder.rs @@ -57,7 +57,7 @@ pub trait TraitCallForwarder { /// While the trait is not necessary it encapsulates a lot of /// utility and auxiliary code required for the actual ink! trait /// implementations. -pub trait TraitCallForwarderFor { +pub trait TraitCallForwarderFor { type Forwarder: TraitCallBuilder; /// Forwards the `&self` call. From 88995a95a01a7caf57e865de612e17f11d1fd88d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 7 Oct 2021 11:51:40 +0200 Subject: [PATCH 460/493] adjust UI tests --- .../fail/trait-message-selector-overlap-1.stderr | 9 --------- .../fail/trait-message-selector-overlap-2.stderr | 9 --------- 2 files changed, 18 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr index 7bd54816b7..2974adf324 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr @@ -1,12 +1,3 @@ -error[E0119]: conflicting implementations of trait `ink_lang::codegen::TraitCallForwarderFor<3872610552_u32>` for type `contract::_::CallBuilder` - --> $DIR/trait-message-selector-overlap-1.rs:45:5 - | -40 | impl TraitDefinition1 for Contract { - | ---------------------------------- first implementation here -... -45 | impl TraitDefinition2 for Contract { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` - error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1083895717_u32>` for type `contract::Contract` --> $DIR/trait-message-selector-overlap-1.rs:47:9 | diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr index 60c1e1a67e..cd76925773 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr @@ -1,12 +1,3 @@ -error[E0119]: conflicting implementations of trait `ink_lang::codegen::TraitCallForwarderFor<687202556_u32>` for type `contract::_::CallBuilder` - --> $DIR/trait-message-selector-overlap-2.rs:45:5 - | -40 | impl TraitDefinition1 for Contract { - | ---------------------------------- first implementation here -... -45 | impl TraitDefinition2 for Contract { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::_::CallBuilder` - error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1518209067_u32>` for type `contract::Contract` --> $DIR/trait-message-selector-overlap-2.rs:47:9 | From 3a701662992ae79c209416c7f8d53eab8b4141cd Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 7 Oct 2021 11:52:18 +0200 Subject: [PATCH 461/493] apply rustfmt --- crates/lang/codegen/src/generator/arg_list.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/arg_list.rs b/crates/lang/codegen/src/generator/arg_list.rs index 12a5e5b2e4..c239f4b2e6 100644 --- a/crates/lang/codegen/src/generator/arg_list.rs +++ b/crates/lang/codegen/src/generator/arg_list.rs @@ -93,7 +93,10 @@ where /// /// As with all Rust macros identifiers can shadow each other so the given identifier /// needs to be valid for the scope in which the returned code is generated. -pub fn generate_reference_to_trait_info(span: Span, trait_path: &syn::Path) -> TokenStream2 { +pub fn generate_reference_to_trait_info( + span: Span, + trait_path: &syn::Path, +) -> TokenStream2 { quote_spanned!(span=> <::ink_lang::reflect::TraitDefinitionRegistry as #trait_path>::__ink_TraitInfo From 1b71efd9309a36c30f81a61856483e723cb91774 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 7 Oct 2021 12:13:38 +0200 Subject: [PATCH 462/493] remove TraitUniqueId trait --- .../lang/codegen/src/generator/trait_def/definition.rs | 3 +-- .../codegen/src/generator/trait_def/trait_registry.rs | 8 -------- crates/lang/src/codegen/mod.rs | 1 - crates/lang/src/codegen/trait_def/call_builder.rs | 9 --------- crates/lang/src/codegen/trait_def/mod.rs | 1 - 5 files changed, 1 insertion(+), 21 deletions(-) diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 51b1e8fd0c..2c4843e842 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -64,8 +64,7 @@ impl TraitDefinition<'_> { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] - type __ink_TraitInfo: ::ink_lang::codegen::TraitUniqueId - + ::ink_lang::codegen::TraitCallForwarder + type __ink_TraitInfo: ::ink_lang::codegen::TraitCallForwarder + ::ink_lang::codegen::TraitImplementedById<#unique_trait_id>; #(#messages)* diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index ec40160ef1..623cb6dfe8 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -240,7 +240,6 @@ impl TraitRegistry<'_> { /// Phantom type that implements the following traits for every ink! trait: /// /// - `ink_lang::codegen::TraitImplementedById` (unsafe implementation) - /// - `ink_lang::TraitUniqueId` /// - `ink_lang::TraitCallForwarder` /// /// It is mainly used to access global information about the ink! trait. @@ -267,13 +266,6 @@ impl TraitRegistry<'_> { { } - impl ::ink_lang::codegen::TraitUniqueId for #trait_info_ident - where - E: ::ink_env::Environment, - { - const ID: ::core::primitive::u32 = #unique_id; - } - impl ::ink_lang::reflect::TraitModulePath for #trait_info_ident where E: ::ink_env::Environment, diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 811f00063a..26d0926441 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -51,6 +51,5 @@ pub use self::{ TraitImplementedById, TraitMessagePayable, TraitMessageSelector, - TraitUniqueId, }, }; diff --git a/crates/lang/src/codegen/trait_def/call_builder.rs b/crates/lang/src/codegen/trait_def/call_builder.rs index 8c25c5c64c..846d2502a0 100644 --- a/crates/lang/src/codegen/trait_def/call_builder.rs +++ b/crates/lang/src/codegen/trait_def/call_builder.rs @@ -28,15 +28,6 @@ pub trait TraitCallBuilder { fn call_mut(&mut self) -> &mut Self::Builder; } -/// Implemented by the global trait info provider. -/// -/// This communicates the `u32` number that uniquely identifies -/// the ink! trait definition. -pub trait TraitUniqueId { - /// The unique trait `u32` identifier. - const ID: u32; -} - /// Implemented by the global trait info provider. /// /// It is used to query the global trait call forwarder. diff --git a/crates/lang/src/codegen/trait_def/mod.rs b/crates/lang/src/codegen/trait_def/mod.rs index d3f3c42fcf..30680e4899 100644 --- a/crates/lang/src/codegen/trait_def/mod.rs +++ b/crates/lang/src/codegen/trait_def/mod.rs @@ -21,7 +21,6 @@ pub use self::{ TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, - TraitUniqueId, }, implemented_by::TraitImplementedById, trait_message::{ From 2106c4426c36960d247df2a45f43449ccfabb657 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 7 Oct 2021 13:10:13 +0200 Subject: [PATCH 463/493] remove TraitImplementedById and utilities to compute ink! trait verify hash --- .../src/generator/trait_def/definition.rs | 5 +- .../codegen/src/generator/trait_def/mod.rs | 11 +--- .../src/generator/trait_def/trait_registry.rs | 10 ---- crates/lang/ir/src/ir/trait_def/mod.rs | 29 ---------- crates/lang/ir/src/ir/trait_def/tests.rs | 58 ------------------- crates/lang/src/codegen/mod.rs | 1 - .../src/codegen/trait_def/implemented_by.rs | 31 ---------- crates/lang/src/codegen/trait_def/mod.rs | 2 - crates/lang/src/reflect/trait_def/registry.rs | 7 +-- 9 files changed, 3 insertions(+), 151 deletions(-) delete mode 100644 crates/lang/src/codegen/trait_def/implemented_by.rs diff --git a/crates/lang/codegen/src/generator/trait_def/definition.rs b/crates/lang/codegen/src/generator/trait_def/definition.rs index 2c4843e842..230b0b9c21 100644 --- a/crates/lang/codegen/src/generator/trait_def/definition.rs +++ b/crates/lang/codegen/src/generator/trait_def/definition.rs @@ -16,7 +16,6 @@ use super::TraitDefinition; use heck::CamelCase as _; -use ir::HexLiteral; use proc_macro2::TokenStream as TokenStream2; use quote::{ format_ident, @@ -52,7 +51,6 @@ impl TraitDefinition<'_> { let span = item.span(); let attrs = item.attrs(); let ident = item.ident(); - let unique_trait_id = self.trait_def.id().hex_padded_suffixed(); let messages = item .iter_items() .map(|(item, _)| item) @@ -64,8 +62,7 @@ impl TraitDefinition<'_> { /// Holds general and global information about the trait. #[doc(hidden)] #[allow(non_camel_case_types)] - type __ink_TraitInfo: ::ink_lang::codegen::TraitCallForwarder - + ::ink_lang::codegen::TraitImplementedById<#unique_trait_id>; + type __ink_TraitInfo: ::ink_lang::codegen::TraitCallForwarder; #(#messages)* } diff --git a/crates/lang/codegen/src/generator/trait_def/mod.rs b/crates/lang/codegen/src/generator/trait_def/mod.rs index d21b6b31aa..f9e53bec31 100644 --- a/crates/lang/codegen/src/generator/trait_def/mod.rs +++ b/crates/lang/codegen/src/generator/trait_def/mod.rs @@ -41,16 +41,7 @@ impl<'a> TraitDefinition<'a> { /// were `$NAME` is the non-unique name of the trait and `$TRAIT_ID` /// is the hex representation of the unique 4-byte trait identifier. fn append_trait_suffix(&self, prefix: &str) -> syn::Ident { - let unique_id = self.trait_def.id().to_be_bytes(); - format_ident!( - "__ink_{}_{}_0x{:X}{:X}{:X}{:X}", - prefix, - self.trait_def.item().ident(), - unique_id[0], - unique_id[1], - unique_id[2], - unique_id[3] - ) + format_ident!("__ink_{}{}", prefix, self.trait_def.item().ident(),) } /// Returns the span of the underlying ink! trait definition. diff --git a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs index 623cb6dfe8..0ddda31854 100644 --- a/crates/lang/codegen/src/generator/trait_def/trait_registry.rs +++ b/crates/lang/codegen/src/generator/trait_def/trait_registry.rs @@ -26,7 +26,6 @@ use crate::{ EnforcedErrors, }; use derive_more::From; -use ir::HexLiteral; use proc_macro2::{ Span, TokenStream as TokenStream2, @@ -239,14 +238,12 @@ impl TraitRegistry<'_> { /// Phantom type that implements the following traits for every ink! trait: /// - /// - `ink_lang::codegen::TraitImplementedById` (unsafe implementation) /// - `ink_lang::TraitCallForwarder` /// /// It is mainly used to access global information about the ink! trait. fn generate_trait_info_object(&self) -> TokenStream2 { let span = self.span(); let trait_ident = self.trait_ident(); - let unique_id = self.trait_def.trait_def.id().hex_padded_suffixed(); let trait_info_ident = self.trait_def.trait_info_ident(); let trait_call_forwarder = self.trait_def.call_forwarder_ident(); let trait_message_info = self.generate_info_for_trait_messages(); @@ -259,13 +256,6 @@ impl TraitRegistry<'_> { #trait_message_info - unsafe impl ::ink_lang::codegen::TraitImplementedById<#unique_id> - for #trait_info_ident - where - E: ::ink_env::Environment, - { - } - impl ::ink_lang::reflect::TraitModulePath for #trait_info_ident where E: ::ink_env::Environment, diff --git a/crates/lang/ir/src/ir/trait_def/mod.rs b/crates/lang/ir/src/ir/trait_def/mod.rs index c0998fe187..220038af0d 100644 --- a/crates/lang/ir/src/ir/trait_def/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/mod.rs @@ -70,33 +70,4 @@ impl InkTraitDefinition { pub fn item(&self) -> &InkItemTrait { &self.item } - - /// Returns the hash to verify that the trait definition has been checked. - pub fn verify_hash(&self) -> [u8; 32] { - let trait_ident = self.item().ident().to_string(); - let buffer = match self.config.namespace() { - Some(lit_str) => { - format!("{}::{}", lit_str.value(), trait_ident) - } - None => trait_ident, - }; - let buffer = buffer.into_bytes(); - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&buffer).split(); - head_32.into() - } - - /// Returns an identifier (uniquely) representing the ink! trait definition. - /// - /// # Note - /// - /// Identifiers generated by this routine might overlap with each other - /// if ink! trait definitions have equal namespaces and identifiers. - /// Users can use the `namespace` configuration parameter in order to - /// disambiguate ink! trait definitions. - pub fn id(&self) -> u32 { - let [h1, h2, h3, h4, ..] = self.verify_hash(); - u32::from_be_bytes([h1, h2, h3, h4]) - } } diff --git a/crates/lang/ir/src/ir/trait_def/tests.rs b/crates/lang/ir/src/ir/trait_def/tests.rs index 882352e064..40caa5249b 100644 --- a/crates/lang/ir/src/ir/trait_def/tests.rs +++ b/crates/lang/ir/src/ir/trait_def/tests.rs @@ -444,61 +444,3 @@ fn iter_messages_works() { let expected = vec!["message_1".to_string(), "message_2".to_string()]; assert_eq!(actual, expected); } - -fn assert_verify_hash_works_with( - config: TraitDefinitionConfig, - ink_trait: InkItemTrait, - expected: &str, -) { - let expected = expected.to_string().into_bytes(); - let trait_definition = InkTraitDefinition::from_raw_parts(config, ink_trait); - let actual = trait_definition.verify_hash(); - let expected: [u8; 32] = { - use blake2::digest::generic_array::sequence::Split as _; - let (head_32, _rest) = - ::digest(&expected).split(); - head_32.into() - }; - assert_eq!(actual, expected); -} - -macro_rules! ink_trait { - ( $($tt:tt)* ) => {{ - >::try_from(syn::parse_quote! { - $( $tt )* - }) - .unwrap() - }}; -} - -fn dummy_trait_definition() -> InkItemTrait { - ink_trait! { - pub trait MyTrait { - #[ink(message)] - fn message_1(&self); - #[ink(message)] - fn message_2(&mut self, a: i32, b: i32) -> i32; - } - } -} - -#[test] -fn verify_hash_works() { - let ink_trait = dummy_trait_definition(); - let config = TraitDefinitionConfig::default(); - assert_verify_hash_works_with(config, ink_trait, "MyTrait"); -} - -#[test] -fn verify_hash_works_with_empty_namespace() { - let ink_trait = dummy_trait_definition(); - let config = TraitDefinitionConfig::default().with_namespace(""); - assert_verify_hash_works_with(config, ink_trait, "::MyTrait"); -} - -#[test] -fn verify_hash_works_with_namespace() { - let ink_trait = dummy_trait_definition(); - let config = TraitDefinitionConfig::default().with_namespace("my_custom_namespace"); - assert_verify_hash_works_with(config, ink_trait, "my_custom_namespace::MyTrait"); -} diff --git a/crates/lang/src/codegen/mod.rs b/crates/lang/src/codegen/mod.rs index 26d0926441..a296549909 100644 --- a/crates/lang/src/codegen/mod.rs +++ b/crates/lang/src/codegen/mod.rs @@ -48,7 +48,6 @@ pub use self::{ TraitCallBuilder, TraitCallForwarder, TraitCallForwarderFor, - TraitImplementedById, TraitMessagePayable, TraitMessageSelector, }, diff --git a/crates/lang/src/codegen/trait_def/implemented_by.rs b/crates/lang/src/codegen/trait_def/implemented_by.rs deleted file mode 100644 index 166f85e01d..0000000000 --- a/crates/lang/src/codegen/trait_def/implemented_by.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018-2021 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/// Marker trait required by info objects of ink! trait definitions. -/// -/// - Automatically implemented for the trait info object of an ink! trait -/// definition by the `#[ink::trait_definition]` procedural macro. -/// -/// # Note -/// -/// The `GLOBAL_TRAIT_ID` is a `u32` value uniquely identifying the -/// ink! trait definition. Every implementer of an ink! trait definition -/// is required to implement this trait given the correct `GLOBAL_TRAIT_ID`. -/// -/// # Safety -/// -/// The trait is marked as `unsafe` to signal to ink! smart contract authors -/// that manually implementing an ink! trait definition is unsafe to do and -/// may potentially lead to unwanted behavior. -pub unsafe trait TraitImplementedById {} diff --git a/crates/lang/src/codegen/trait_def/mod.rs b/crates/lang/src/codegen/trait_def/mod.rs index 30680e4899..f3b18af8fb 100644 --- a/crates/lang/src/codegen/trait_def/mod.rs +++ b/crates/lang/src/codegen/trait_def/mod.rs @@ -13,7 +13,6 @@ // limitations under the License. mod call_builder; -mod implemented_by; mod trait_message; pub use self::{ @@ -22,7 +21,6 @@ pub use self::{ TraitCallForwarder, TraitCallForwarderFor, }, - implemented_by::TraitImplementedById, trait_message::{ TraitMessagePayable, TraitMessageSelector, diff --git a/crates/lang/src/reflect/trait_def/registry.rs b/crates/lang/src/reflect/trait_def/registry.rs index 136ea38559..5f33d2323e 100644 --- a/crates/lang/src/reflect/trait_def/registry.rs +++ b/crates/lang/src/reflect/trait_def/registry.rs @@ -12,10 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - codegen::TraitImplementedById, - reflect::ContractEnv, -}; +use crate::reflect::ContractEnv; use core::marker::PhantomData; /// Type that is guaranteed by ink! to implement all ink! trait definitions. @@ -64,5 +61,3 @@ where { type Env = E; } - -unsafe impl TraitImplementedById for TraitDefinitionRegistry {} From 41b36525b5e3de5dec170bd22a6e13b60238f511 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 09:06:45 +0200 Subject: [PATCH 464/493] remove unused CannotCallTraitConstructor variant --- crates/lang/codegen/src/enforced_error.rs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/crates/lang/codegen/src/enforced_error.rs b/crates/lang/codegen/src/enforced_error.rs index 635daa8d47..ea92e2b8a5 100644 --- a/crates/lang/codegen/src/enforced_error.rs +++ b/crates/lang/codegen/src/enforced_error.rs @@ -38,20 +38,6 @@ pub enum EnforcedErrors { /// Is `true` if the `self` receiver of the ink! message is `&mut self`. message_is_mut: bool, }, - /// The below error represents calling a constructor in a context that does - /// not allow calling it. This may happen when the constructor defined in a - /// trait is cross-called in another contract. - /// This is not allowed since the contract to which a call is forwarded must - /// already exist at the point when the call to it is made. - #[codec(index = 2)] - CannotCallTraitConstructor { - /// The trait that defines the called constructor. - trait_ident: String, - /// The name of the called constructor. - constructor_ident: String, - /// The selector of the called constructor. - constructor_selector: [u8; 4], - }, } impl EnforcedErrors { From 061b4c75d9d8a5d0ed3a205e8a1ef2ba663c3602 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 09:46:07 +0200 Subject: [PATCH 465/493] Update to using trybuild version 1.0.49 This forces most or all of the failure UI tests to be adjusted slightly. --- crates/lang/macro/Cargo.toml | 2 +- .../fail/invalid_parameter_type_01.stderr | 2 +- .../fail/invalid_parameter_type_02.stderr | 2 +- .../ui/blake2b/fail/missing_parameter.stderr | 2 +- .../blake2b/fail/non_literal_parameter.stderr | 2 +- ...mpile-as-dependency-invalid-type-01.stderr | 2 +- ...mpile-as-dependency-invalid-type-02.stderr | 2 +- ...g-compile-as-dependency-missing-arg.stderr | 2 +- ...c-storage-allocator-invalid-type-01.stderr | 2 +- ...c-storage-allocator-invalid-type-02.stderr | 2 +- ...namic-storage-allocator-missing-arg.stderr | 2 +- .../ui/contract/fail/constructor-abi.stderr | 2 +- .../ui/contract/fail/constructor-async.stderr | 2 +- .../ui/contract/fail/constructor-const.stderr | 2 +- .../fail/constructor-input-non-codec.stderr | 14 +++--- .../fail/constructor-input-pattern.stderr | 2 +- .../fail/constructor-missing-return.stderr | 2 +- .../contract/fail/constructor-payable.stderr | 4 +- .../fail/constructor-self-receiver-01.stderr | 2 +- .../fail/constructor-self-receiver-02.stderr | 2 +- .../fail/constructor-self-receiver-03.stderr | 4 +- .../fail/constructor-self-receiver-04.stderr | 2 +- .../contract/fail/constructor-unsafe.stderr | 2 +- .../fail/event-conflicting-storage.stderr | 2 +- .../event-too-many-topics-anonymous.stderr | 6 +-- .../fail/event-too-many-topics.stderr | 6 +-- .../fail/impl-block-for-non-storage-01.stderr | 6 +-- .../fail/impl-block-for-non-storage-02.stderr | 2 +- ...-block-namespace-invalid-identifier.stderr | 2 +- .../impl-block-namespace-invalid-type.stderr | 2 +- ...pl-block-namespace-missing-argument.stderr | 2 +- .../impl-block-using-env-no-marker.stderr | 2 +- ...pl-block-using-static-env-no-marker.stderr | 2 +- .../fail/message-input-non-codec.stderr | 16 +++---- .../fail/message-input-pattern.stderr | 2 +- .../fail/message-returns-non-codec.stderr | 45 ++++++++++++------- .../contract/fail/message-returns-self.stderr | 2 +- .../message-selector-invalid-type-01.stderr | 2 +- .../message-selector-invalid-type-02.stderr | 2 +- .../fail/message-selector-missing-arg.stderr | 2 +- .../message-self-receiver-invalid-01.stderr | 2 +- .../message-self-receiver-invalid-02.stderr | 2 +- .../message-self-receiver-invalid-03.stderr | 2 +- .../fail/message-self-receiver-missing.stderr | 2 +- .../fail/message-unknown-property.stderr | 2 +- .../fail/module-missing-constructor.stderr | 2 +- .../fail/module-missing-message.stderr | 2 +- .../fail/module-missing-storage.stderr | 2 +- .../fail/module-multiple-storages.stderr | 6 +-- .../fail/module-use-forbidden-idents.stderr | 28 ++++++------ .../fail/storage-conflicting-event.stderr | 2 +- .../fail/storage-unknown-marker.stderr | 2 +- .../fail/trait-impl-namespace-invalid.stderr | 2 +- .../trait-message-payable-mismatch.stderr | 2 +- .../trait-message-selector-mismatch.stderr | 2 +- .../trait-message-selector-overlap-1.stderr | 2 +- .../trait-message-selector-overlap-2.stderr | 2 +- .../fail/invalid_parameter_type_01.stderr | 2 +- .../fail/invalid_parameter_type_02.stderr | 2 +- .../fail/missing_parameter.stderr | 2 +- .../fail/non_literal_parameter.stderr | 2 +- .../fail/invalid_parameter_type_01.stderr | 2 +- .../fail/invalid_parameter_type_02.stderr | 2 +- .../selector_id/fail/missing_parameter.stderr | 2 +- .../fail/non_literal_parameter.stderr | 2 +- .../fail/config_namespace_invalid_1.stderr | 2 +- .../fail/config_namespace_invalid_2.stderr | 2 +- .../fail/config_namespace_invalid_3.stderr | 2 +- .../fail/config_namespace_invalid_4.stderr | 2 +- .../fail/definition_assoc_const.stderr | 2 +- .../fail/definition_assoc_type.stderr | 2 +- .../fail/definition_constructor.stderr | 2 +- .../ui/trait_def/fail/definition_empty.stderr | 2 +- .../trait_def/fail/definition_generic.stderr | 2 +- .../trait_def/fail/definition_non_pub.stderr | 2 +- .../fail/definition_rust_method.stderr | 2 +- .../definition_super_trait_invalid_1.stderr | 2 +- .../definition_super_trait_invalid_2.stderr | 2 +- .../trait_def/fail/definition_unsafe.stderr | 2 +- .../trait_def/fail/message_abi_invalid.stderr | 2 +- .../fail/message_async_invalid.stderr | 2 +- .../fail/message_const_invalid.stderr | 2 +- .../fail/message_constructor_conflict.stderr | 2 +- .../fail/message_default_impl.stderr | 2 +- .../fail/message_generic_invalid.stderr | 2 +- .../fail/message_input_non_codec.stderr | 10 ++--- .../fail/message_input_pattern_invalid.stderr | 2 +- .../fail/message_output_non_codec.stderr | 37 +++++++++------ .../fail/message_payable_invalid_1.stderr | 2 +- .../fail/message_payable_invalid_2.stderr | 2 +- .../fail/message_receiver_invalid_1.stderr | 2 +- .../fail/message_receiver_invalid_2.stderr | 2 +- .../fail/message_receiver_invalid_3.stderr | 2 +- .../fail/message_receiver_missing.stderr | 2 +- .../fail/message_selector_invalid_1.stderr | 2 +- .../fail/message_selector_invalid_2.stderr | 2 +- .../fail/message_selector_overlap.stderr | 4 +- .../fail/message_unsafe_invalid.stderr | 2 +- 98 files changed, 189 insertions(+), 167 deletions(-) diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index e781982f6f..b00bdb77ad 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -30,7 +30,7 @@ ink_storage = { version = "3.0.0-rc5", path = "../../storage/" } ink_lang = { version = "3.0.0-rc5", path = ".." } ink_prelude = { version = "3.0.0-rc5", path = "../../prelude/" } -trybuild = { version = "1", features = ["diff"] } +trybuild = { version = "1.0.49", features = ["diff"] } scale-info = { version = "0.6", default-features = false, features = ["derive"] } [lib] diff --git a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr b/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr index da36a72ec4..4d1451ec43 100644 --- a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr +++ b/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input. found Bool(LitBool { value: true }) - --> $DIR/invalid_parameter_type_01.rs:3:38 + --> tests/ui/blake2b/fail/invalid_parameter_type_01.rs:3:38 | 3 | const _: [u8; 32] = ink::blake2x256!(true); | ^^^^ diff --git a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr b/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr index 96d1399302..19c784fa44 100644 --- a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr +++ b/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input. found Int(LitInt { token: 42 }) - --> $DIR/invalid_parameter_type_02.rs:3:38 + --> tests/ui/blake2b/fail/invalid_parameter_type_02.rs:3:38 | 3 | const _: [u8; 32] = ink::blake2x256!(42); | ^^ diff --git a/crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.stderr b/crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.stderr index 172fbee0df..952d1515ba 100644 --- a/crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.stderr +++ b/crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input: unexpected end of input, expected literal - --> $DIR/missing_parameter.rs:3:21 + --> tests/ui/blake2b/fail/missing_parameter.rs:3:21 | 3 | const _: [u8; 32] = ink::blake2x256!(); | ^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.stderr b/crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.stderr index 95f6bf75b2..0c6f18647e 100644 --- a/crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.stderr +++ b/crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input: expected literal - --> $DIR/non_literal_parameter.rs:4:38 + --> tests/ui/blake2b/fail/non_literal_parameter.rs:4:38 | 4 | const _: [u8; 32] = ink::blake2x256!(INPUT); | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr index deb458b804..6aa45e18c3 100644 --- a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr @@ -1,5 +1,5 @@ error: expected a bool literal for `compile_as_dependency` ink! configuration argument - --> $DIR/config-compile-as-dependency-invalid-type-01.rs:3:17 + --> tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs:3:17 | 3 | #[ink::contract(compile_as_dependency = "yes")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr index 9ac7a98793..270aee2699 100644 --- a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr @@ -1,5 +1,5 @@ error: expected a bool literal for `compile_as_dependency` ink! configuration argument - --> $DIR/config-compile-as-dependency-invalid-type-02.rs:3:17 + --> tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs:3:17 | 3 | #[ink::contract(compile_as_dependency = 42)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr index dc3eb26675..8a0176d6d9 100644 --- a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr @@ -1,5 +1,5 @@ error: ink! config options require an argument separated by '=' - --> $DIR/config-compile-as-dependency-missing-arg.rs:3:17 + --> tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs:3:17 | 3 | #[ink::contract(compile_as_dependency)] | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr index 6e1c181f0f..51071b94c3 100644 --- a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr @@ -1,5 +1,5 @@ error: expected a bool literal for `dynamic_storage_allocator` ink! configuration argument - --> $DIR/config-dynamic-storage-allocator-invalid-type-01.rs:3:17 + --> tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs:3:17 | 3 | #[ink::contract(dynamic_storage_allocator = "foo")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr index cdf39f773b..63b1373fb1 100644 --- a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr @@ -1,5 +1,5 @@ error: expected a bool literal for `dynamic_storage_allocator` ink! configuration argument - --> $DIR/config-dynamic-storage-allocator-invalid-type-02.rs:3:17 + --> tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs:3:17 | 3 | #[ink::contract(dynamic_storage_allocator = 42)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr index 2d9108bc12..b19ec2b427 100644 --- a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr @@ -1,5 +1,5 @@ error: ink! config options require an argument separated by '=' - --> $DIR/config-dynamic-storage-allocator-missing-arg.rs:3:17 + --> tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs:3:17 | 3 | #[ink::contract(dynamic_storage_allocator)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr index 1ad99ce813..ac69b6edc5 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr @@ -1,5 +1,5 @@ error: ink! constructors must not have explicit ABI - --> $DIR/constructor-abi.rs:10:13 + --> tests/ui/contract/fail/constructor-abi.rs:10:13 | 10 | pub extern "C" fn constructor() -> Self { | ^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr index f57d8af29c..86a797e0c1 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr @@ -1,5 +1,5 @@ error: ink! constructors must not be async - --> $DIR/constructor-async.rs:10:13 + --> tests/ui/contract/fail/constructor-async.rs:10:13 | 10 | pub async fn constructor() -> Self { | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr index ee2b07cb12..4a4b2399fd 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr @@ -1,5 +1,5 @@ error: ink! constructors must not be const - --> $DIR/constructor-const.rs:10:13 + --> tests/ui/contract/fail/constructor-const.rs:10:13 | 10 | pub const fn constructor() -> Self { | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr index 03bd3ac4e1..4e16403b25 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/constructor-input-non-codec.rs:13:28 + --> tests/ui/contract/fail/constructor-input-non-codec.rs:13:28 | 13 | pub fn constructor(_input: NonCodecType) -> Self { | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $DIR/type_check.rs:41:8 + --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs | -41 | T: scale::Decode + 'static; + | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/constructor-input-non-codec.rs:13:9 + --> tests/ui/contract/fail/constructor-input-non-codec.rs:13:9 | 13 | / pub fn constructor(_input: NonCodecType) -> Self { 14 | | Self {} @@ -21,13 +21,13 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `parity_scale_codec::Decode::decode` - --> $DIR/codec.rs:284:15 + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs | -284 | fn decode(input: &mut I) -> Result; + | fn decode(input: &mut I) -> Result; | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/constructor-input-non-codec.rs:3:1 + --> tests/ui/contract/fail/constructor-input-non-codec.rs:3:1 | 3 | #[ink::contract] | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr index 093c9ac0a0..59def8bc72 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr @@ -1,5 +1,5 @@ error: ink! constructor arguments must have an identifier - --> $DIR/constructor-input-pattern.rs:10:28 + --> tests/ui/contract/fail/constructor-input-pattern.rs:10:28 | 10 | pub fn constructor((_a, _b): (i32, i32)) -> Self { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr index febb0d4b5a..fda3fa61b5 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr @@ -1,5 +1,5 @@ error: missing return for ink! constructor - --> $DIR/constructor-missing-return.rs:10:13 + --> tests/ui/contract/fail/constructor-missing-return.rs:10:13 | 10 | pub fn constructor() {} | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr index a423069ef1..e2c7f4ed6a 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr @@ -1,11 +1,11 @@ error: encountered conflicting ink! attribute argument - --> $DIR/constructor-payable.rs:9:28 + --> tests/ui/contract/fail/constructor-payable.rs:9:28 | 9 | #[ink(constructor, payable)] | ^^^^^^^ error: constructors are implicitly payable - --> $DIR/constructor-payable.rs:9:28 + --> tests/ui/contract/fail/constructor-payable.rs:9:28 | 9 | #[ink(constructor, payable)] | ^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr index 27847841dc..b10addb66d 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr @@ -1,5 +1,5 @@ error: ink! constructors must have no `self` receiver - --> $DIR/constructor-self-receiver-01.rs:10:28 + --> tests/ui/contract/fail/constructor-self-receiver-01.rs:10:28 | 10 | pub fn constructor(&self) -> Self { | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr index 30dc058141..f217562f53 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr @@ -1,5 +1,5 @@ error: ink! constructors must have no `self` receiver - --> $DIR/constructor-self-receiver-02.rs:10:28 + --> tests/ui/contract/fail/constructor-self-receiver-02.rs:10:28 | 10 | pub fn constructor(&mut self) -> Self { | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr index 644f4b384c..30cdf70f02 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr @@ -1,11 +1,11 @@ error[E0411]: cannot find type `Self` in this scope - --> $DIR/constructor-self-receiver-03.rs:10:35 + --> tests/ui/contract/fail/constructor-self-receiver-03.rs:10:35 | 10 | pub fn constructor(this: &Self) -> Self { | ^^^^ `Self` is only available in impls, traits, and type definitions error[E0106]: missing lifetime specifier - --> $DIR/constructor-self-receiver-03.rs:10:34 + --> tests/ui/contract/fail/constructor-self-receiver-03.rs:10:34 | 10 | pub fn constructor(this: &Self) -> Self { | ^ expected named lifetime parameter diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr index 31cb2f18d5..c5259d8f9b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr @@ -1,5 +1,5 @@ error: ink! constructors must have no `self` receiver - --> $DIR/constructor-self-receiver-04.rs:10:28 + --> tests/ui/contract/fail/constructor-self-receiver-04.rs:10:28 | 10 | pub fn constructor(self) -> Self { | ^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr b/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr index f46e07c71d..d340ce7205 100644 --- a/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr @@ -1,5 +1,5 @@ error: ink! constructors must not be unsafe - --> $DIR/constructor-unsafe.rs:10:13 + --> tests/ui/contract/fail/constructor-unsafe.rs:10:13 | 10 | pub unsafe fn constructor() -> Self { | ^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr b/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr index 1292e5f32b..42ea9e9f95 100644 --- a/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr @@ -1,5 +1,5 @@ error: encountered conflicting ink! attribute argument - --> $DIR/event-conflicting-storage.rs:9:11 + --> tests/ui/contract/fail/event-conflicting-storage.rs:9:11 | 9 | #[ink(storage)] | ^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr index 1900ad503d..a6ab00f062 100644 --- a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>` is not satisfied - --> $DIR/event-too-many-topics-anonymous.rs:27:5 + --> tests/ui/contract/fail/event-too-many-topics-anonymous.rs:27:5 | 27 | / pub struct Event { 28 | | #[ink(topic)] @@ -17,7 +17,7 @@ error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>` as RespectTopicLimit<12_usize>> and 87 others note: required by a bound in `EventRespectsTopicLimit` - --> $DIR/topics.rs:48:43 + --> $WORKSPACE/crates/lang/src/codegen/event/topics.rs | -48 | ::LenTopics: RespectTopicLimit, + | ::LenTopics: RespectTopicLimit, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr index 50f783b605..f047abb61b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>` is not satisfied - --> $DIR/event-too-many-topics.rs:27:5 + --> tests/ui/contract/fail/event-too-many-topics.rs:27:5 | 27 | / pub struct Event { 28 | | #[ink(topic)] @@ -17,7 +17,7 @@ error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>` as RespectTopicLimit<12_usize>> and 87 others note: required by a bound in `EventRespectsTopicLimit` - --> $DIR/topics.rs:48:43 + --> $WORKSPACE/crates/lang/src/codegen/event/topics.rs | -48 | ::LenTopics: RespectTopicLimit, + | ::LenTopics: RespectTopicLimit, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr index 49bb9207d6..50d787d613 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/impl-block-for-non-storage-01.rs:20:10 + --> tests/ui/contract/fail/impl-block-for-non-storage-01.rs:20:10 | 20 | impl NonContract { | ^^^^^^^^^^^ expected struct `Contract`, found struct `NonContract` @@ -8,7 +8,7 @@ error[E0308]: mismatched types found struct `IsSameType` error[E0599]: no function or associated item named `constructor_2` found for struct `Contract` in the current scope - --> $DIR/impl-block-for-non-storage-01.rs:22:16 + --> tests/ui/contract/fail/impl-block-for-non-storage-01.rs:22:16 | 6 | pub struct Contract {} | ------------------- function or associated item `constructor_2` not found for this @@ -20,7 +20,7 @@ error[E0599]: no function or associated item named `constructor_2` found for str | help: there is an associated function with a similar name: `constructor_1` error[E0599]: no function or associated item named `message_2` found for struct `Contract` in the current scope - --> $DIR/impl-block-for-non-storage-01.rs:27:16 + --> tests/ui/contract/fail/impl-block-for-non-storage-01.rs:27:16 | 6 | pub struct Contract {} | ------------------- function or associated item `message_2` not found for this diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr index 71c7b05ee9..3aa844764b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/impl-block-for-non-storage-02.rs:21:10 + --> tests/ui/contract/fail/impl-block-for-non-storage-02.rs:21:10 | 21 | impl NonContract {} | ^^^^^^^^^^^ expected struct `Contract`, found struct `NonContract` diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr index 62c3572774..d4e5efa7e4 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr @@ -1,5 +1,5 @@ error: encountered invalid Rust identifier for namespace argument - --> $DIR/impl-block-namespace-invalid-identifier.rs:8:23 + --> tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs:8:23 | 8 | #[ink(namespace = "::invalid_identifier")] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr index f8f1be3916..a6014a9e97 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr @@ -1,5 +1,5 @@ error: expected string type for `namespace` argument, e.g. #[ink(namespace = "hello")] - --> $DIR/impl-block-namespace-invalid-type.rs:8:11 + --> tests/ui/contract/fail/impl-block-namespace-invalid-type.rs:8:11 | 8 | #[ink(namespace = true)] | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr index 414c502fc7..b09ed8ec0c 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr @@ -1,5 +1,5 @@ error: encountered #[ink(namespace)] that is missing its string parameter. Did you mean #[ink(namespace = name: str)] ? - --> $DIR/impl-block-namespace-missing-argument.rs:8:11 + --> tests/ui/contract/fail/impl-block-namespace-missing-argument.rs:8:11 | 8 | #[ink(namespace)] | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr index c68e582000..55c4462a04 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `env` found for reference `&Contract` in the current scope - --> $DIR/impl-block-using-env-no-marker.rs:24:26 + --> tests/ui/contract/fail/impl-block-using-env-no-marker.rs:24:26 | 24 | let _ = self.env().caller(); | ^^^ method not found in `&Contract` diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr index 09f63cdf55..45d8ceab93 100644 --- a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr @@ -1,5 +1,5 @@ error[E0599]: no function or associated item named `env` found for struct `Contract` in the current scope - --> $DIR/impl-block-using-static-env-no-marker.rs:22:27 + --> tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs:22:27 | 6 | pub struct Contract {} | ------------------- function or associated item `env` not found for this diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr index 7629695388..c4e6b6f323 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr @@ -1,31 +1,31 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/message-input-non-codec.rs:18:31 + --> tests/ui/contract/fail/message-input-non-codec.rs:18:31 | 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $DIR/type_check.rs:41:8 + --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs | -41 | T: scale::Decode + 'static; + | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> $DIR/message-input-non-codec.rs:18:9 + --> tests/ui/contract/fail/message-input-non-codec.rs:18:9 | 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `parity_scale_codec::Decode::decode` - --> $DIR/codec.rs:284:15 + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs | -284 | fn decode(input: &mut I) -> Result; + | fn decode(input: &mut I) -> Result; | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/message-input-non-codec.rs:3:1 + --> tests/ui/contract/fail/message-input-non-codec.rs:3:1 | 3 | #[ink::contract] | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` @@ -37,7 +37,7 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied - --> $DIR/message-input-non-codec.rs:18:9 + --> tests/ui/contract/fail/message-input-non-codec.rs:18:9 | 18 | pub fn message(&self, _input: NonCodecType) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr b/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr index c12c1703c8..f74e49855d 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr @@ -1,5 +1,5 @@ error: ink! message arguments must have an identifier - --> $DIR/message-input-pattern.rs:15:31 + --> tests/ui/contract/fail/message-input-pattern.rs:15:31 | 15 | pub fn message(&self, (_a, _b): (i32, i32)) {} | ^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr index bec9e51efd..032c7c9bc5 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/message-returns-non-codec.rs:18:34 + --> tests/ui/contract/fail/message-returns-non-codec.rs:18:34 | 18 | pub fn message(&self) -> NonCodecType { | ^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `DispatchOutput` - --> $DIR/type_check.rs:69:8 + --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs | -69 | T: scale::Encode + 'static; + | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> $DIR/message-returns-non-codec.rs:18:9 + --> tests/ui/contract/fail/message-returns-non-codec.rs:18:9 | 18 | / pub fn message(&self) -> NonCodecType { 19 | | NonCodecType @@ -21,21 +21,32 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `execute_message` - --> $DIR/execution.rs:139:13 + --> $WORKSPACE/crates/lang/src/codegen/dispatch/execution.rs | -139 | Output: scale::Encode + 'static, + | Output: scale::Encode + 'static, | ^^^^^^^^^^^^^ required by this bound in `execute_message` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied - --> $DIR/message-returns-non-codec.rs:18:9 - | -6 | pub struct NonCodecType; - | ------------------------ doesn't satisfy `NonCodecType: parity_scale_codec::Decode` + --> tests/ui/contract/fail/message-returns-non-codec.rs:18:9 + | +6 | pub struct NonCodecType; + | ------------------------ doesn't satisfy `NonCodecType: parity_scale_codec::Decode` ... -18 | / pub fn message(&self) -> NonCodecType { -19 | | NonCodecType -20 | | } - | |_________^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NonCodecType: parity_scale_codec::Decode` +18 | / pub fn message(&self) -> NonCodecType { +19 | | NonCodecType +20 | | } + | |_________^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NonCodecType: parity_scale_codec::Decode` +note: the following trait must be implemented + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs + | + | / pub trait Decode: Sized { + | | // !INTERNAL USE ONLY! + | | // This const helps SCALE to optimize the encoding/decoding by doing fake specialization. + | | #[doc(hidden)] +... | + | | } + | | } + | |_^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr b/crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr index 3d3381238b..7dea02f224 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr @@ -1,5 +1,5 @@ error: ink! messages must not return `Self` - --> $DIR/message-returns-self.rs:15:39 + --> tests/ui/contract/fail/message-returns-self.rs:15:39 | 15 | pub fn returns_self(&self) -> Self {} | ^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr index 60c05f90c5..91585edc1b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr @@ -1,5 +1,5 @@ error: #[ink(selector = ..)] attributes with string inputs are deprecated. use an integer instead, e.g. #[ink(selector = 1)] or #[ink(selector = 0xC0DECAFE)]. - --> $DIR/message-selector-invalid-type-01.rs:14:24 + --> tests/ui/contract/fail/message-selector-invalid-type-01.rs:14:24 | 14 | #[ink(message, selector = "0xC0DECAFE")] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr index 260667e14a..f261b80a9b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr @@ -1,5 +1,5 @@ error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE] - --> $DIR/message-selector-invalid-type-02.rs:14:24 + --> tests/ui/contract/fail/message-selector-invalid-type-02.rs:14:24 | 14 | #[ink(message, selector = true)] | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr b/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr index 5214ea4b75..2e5d84a55c 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr @@ -1,5 +1,5 @@ error: encountered #[ink(selector)] that is missing its u32 parameter. Did you mean #[ink(selector = value: u32)] ? - --> $DIR/message-selector-missing-arg.rs:14:24 + --> tests/ui/contract/fail/message-selector-missing-arg.rs:14:24 | 14 | #[ink(message, selector)] | ^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr index 352752bb69..2f8df8130e 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr @@ -1,5 +1,5 @@ error: ink! messages must have `&self` or `&mut self` receiver - --> $DIR/message-self-receiver-invalid-01.rs:15:24 + --> tests/ui/contract/fail/message-self-receiver-invalid-01.rs:15:24 | 15 | pub fn message(this: &Self) {} | ^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr index 6643bf87a7..3caaa0e6a7 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr @@ -1,5 +1,5 @@ error: ink! messages must have `&self` or `&mut self` receiver - --> $DIR/message-self-receiver-invalid-02.rs:15:24 + --> tests/ui/contract/fail/message-self-receiver-invalid-02.rs:15:24 | 15 | pub fn message(this: &mut Self) {} | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr index 54b17afa2d..0c95e3170d 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr @@ -1,5 +1,5 @@ error: ink! messages must have `&self` or `&mut self` receiver - --> $DIR/message-self-receiver-invalid-03.rs:15:24 + --> tests/ui/contract/fail/message-self-receiver-invalid-03.rs:15:24 | 15 | pub fn message(self) {} | ^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr index 882afcf4cb..5a145a2765 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr @@ -1,5 +1,5 @@ error: ink! messages must have `&self` or `&mut self` receiver - --> $DIR/message-self-receiver-missing.rs:14:9 + --> tests/ui/contract/fail/message-self-receiver-missing.rs:14:9 | 14 | / #[ink(message)] 15 | | pub fn message() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr b/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr index dc04994ebc..0f27d2dc91 100644 --- a/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr @@ -1,5 +1,5 @@ error: unknown ink! attribute (path) - --> $DIR/message-unknown-property.rs:15:15 + --> tests/ui/contract/fail/message-unknown-property.rs:15:15 | 15 | #[ink(unknown_marker)] | ^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr b/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr index bd8a62c5cb..851947f71c 100644 --- a/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr @@ -1,5 +1,5 @@ error: missing ink! constructor - --> $DIR/module-missing-constructor.rs:4:1 + --> tests/ui/contract/fail/module-missing-constructor.rs:4:1 | 4 | / mod contact { 5 | | #[ink(storage)] diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr b/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr index 55307a51f6..b71b1d5bd4 100644 --- a/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr @@ -1,5 +1,5 @@ error: missing ink! message - --> $DIR/module-missing-message.rs:4:1 + --> tests/ui/contract/fail/module-missing-message.rs:4:1 | 4 | / mod contract { 5 | | #[ink(storage)] diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr b/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr index 0b1ba684b6..2559d3726b 100644 --- a/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr @@ -1,5 +1,5 @@ error: missing ink! storage struct - --> $DIR/module-missing-storage.rs:4:1 + --> tests/ui/contract/fail/module-missing-storage.rs:4:1 | 4 | / mod contract { 5 | | // #[ink(storage)] diff --git a/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr b/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr index 4876a882a0..98faa7ab85 100644 --- a/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr @@ -1,5 +1,5 @@ error: encountered multiple ink! storage structs, expected exactly one - --> $DIR/module-multiple-storages.rs:4:1 + --> tests/ui/contract/fail/module-multiple-storages.rs:4:1 | 4 | / mod contract { 5 | | #[ink(storage)] @@ -11,13 +11,13 @@ error: encountered multiple ink! storage structs, expected exactly one | |_^ error: ink! storage struct here - --> $DIR/module-multiple-storages.rs:6:5 + --> tests/ui/contract/fail/module-multiple-storages.rs:6:5 | 6 | pub struct Contract {} | ^^^^^^^^^^^^^^^^^^^^^^ error: ink! storage struct here - --> $DIR/module-multiple-storages.rs:19:5 + --> tests/ui/contract/fail/module-multiple-storages.rs:19:5 | 19 | pub struct Contract2 {} | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr b/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr index 2bd2d0b8b1..2a326233af 100644 --- a/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr @@ -1,83 +1,83 @@ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:4:5 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:4:5 | 4 | mod __ink_contract { | ^^^^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:6:16 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:6:16 | 6 | pub struct __ink_Contract {} | ^^^^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:8:11 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:8:11 | 8 | const __ink_CONST: () = (); | ^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:9:12 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:9:12 | 9 | static __ink_STATIC: () = (); | ^^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:10:10 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:10:10 | 10 | type __ink_Type = (); | ^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:12:10 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:12:10 | 12 | impl __ink_Contract { | ^^^^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:14:16 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:14:16 | 14 | pub fn __ink_constructor(__ink_input: __ink_Type) -> Self { | ^^^^^^^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:14:34 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:14:34 | 14 | pub fn __ink_constructor(__ink_input: __ink_Type) -> Self { | ^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:14:47 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:14:47 | 14 | pub fn __ink_constructor(__ink_input: __ink_Type) -> Self { | ^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:19:16 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:19:16 | 19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { | ^^^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:19:37 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:19:37 | 19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { | ^^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:19:50 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:19:50 | 19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { | ^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:19:65 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:19:65 | 19 | pub fn __ink_message(&self, __ink_input: __ink_Type) -> __ink_Type { | ^^^^^^^^^^ error: encountered invalid identifier starting with __ink_ - --> $DIR/module-use-forbidden-idents.rs:20:17 + --> tests/ui/contract/fail/module-use-forbidden-idents.rs:20:17 | 20 | let __ink_first = (); | ^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr b/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr index ac89d8f635..84ef72bc72 100644 --- a/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr @@ -1,5 +1,5 @@ error: encountered conflicting ink! attribute argument - --> $DIR/storage-conflicting-event.rs:6:11 + --> tests/ui/contract/fail/storage-conflicting-event.rs:6:11 | 6 | #[ink(event)] | ^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr b/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr index ceb8cea190..b24ba558ba 100644 --- a/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr @@ -1,5 +1,5 @@ error: unknown ink! attribute (path) - --> $DIR/storage-unknown-marker.rs:6:11 + --> tests/ui/contract/fail/storage-unknown-marker.rs:6:11 | 6 | #[ink(unknown_or_unsupported)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr index 7090f19090..bf03fd4337 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr @@ -1,5 +1,5 @@ error: namespace ink! property is not allowed on ink! trait implementation blocks - --> $DIR/trait-impl-namespace-invalid.rs:23:5 + --> tests/ui/contract/fail/trait-impl-namespace-invalid.rs:23:5 | 23 | / #[ink(namespace = "namespace")] 24 | | impl TraitDefinition for Contract { diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr index fa51818549..4c6a717217 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/trait-message-payable-mismatch.rs:25:9 + --> tests/ui/contract/fail/trait-message-payable-mismatch.rs:25:9 | 25 | fn message(&self) {} | ^^^^^^^^^^^^^^^^^^^^ expected `false`, found `true` diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr index 626ab04c9d..5e93d3f759 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/trait-message-selector-mismatch.rs:25:9 + --> tests/ui/contract/fail/trait-message-selector-mismatch.rs:25:9 | 25 | fn message(&self) {} | ^^^^^^^^^^^^^^^^^^^^ expected `1_u32`, found `2_u32` diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr index 2974adf324..8c55038281 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1083895717_u32>` for type `contract::Contract` - --> $DIR/trait-message-selector-overlap-1.rs:47:9 + --> tests/ui/contract/fail/trait-message-selector-overlap-1.rs:47:9 | 42 | fn message(&self) {} | ----------------- first implementation here diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr index cd76925773..ab83edd8e3 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<1518209067_u32>` for type `contract::Contract` - --> $DIR/trait-message-selector-overlap-2.rs:47:9 + --> tests/ui/contract/fail/trait-message-selector-overlap-2.rs:47:9 | 42 | fn message(&self) {} | ----------------- first implementation here diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr b/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr index 784d320b7b..1324671f7a 100644 --- a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr +++ b/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input. found Bool(LitBool { value: true }) - --> $DIR/invalid_parameter_type_01.rs:3:37 + --> tests/ui/selector_bytes/fail/invalid_parameter_type_01.rs:3:37 | 3 | const _: u32 = ink::selector_bytes!(true); | ^^^^ diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr b/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr index 770056f463..14976c8846 100644 --- a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr +++ b/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input. found Int(LitInt { token: 42 }) - --> $DIR/invalid_parameter_type_02.rs:3:37 + --> tests/ui/selector_bytes/fail/invalid_parameter_type_02.rs:3:37 | 3 | const _: u32 = ink::selector_bytes!(42); | ^^ diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.stderr b/crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.stderr index 9ef98ced0f..b9c47fed49 100644 --- a/crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.stderr +++ b/crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input: unexpected end of input, expected literal - --> $DIR/missing_parameter.rs:3:16 + --> tests/ui/selector_bytes/fail/missing_parameter.rs:3:16 | 3 | const _: u32 = ink::selector_bytes!(); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.stderr b/crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.stderr index 481785cd06..8e70cd06ac 100644 --- a/crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.stderr +++ b/crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input: expected literal - --> $DIR/non_literal_parameter.rs:4:37 + --> tests/ui/selector_bytes/fail/non_literal_parameter.rs:4:37 | 4 | const _: u32 = ink::selector_bytes!(INPUT); | ^^^^^ diff --git a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr b/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr index 01bb41caa0..6ff0319a58 100644 --- a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr +++ b/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input. found Bool(LitBool { value: true }) - --> $DIR/invalid_parameter_type_01.rs:3:34 + --> tests/ui/selector_id/fail/invalid_parameter_type_01.rs:3:34 | 3 | const _: u32 = ink::selector_id!(true); | ^^^^ diff --git a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr b/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr index b559036512..37f957377f 100644 --- a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr +++ b/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input. found Int(LitInt { token: 42 }) - --> $DIR/invalid_parameter_type_02.rs:3:34 + --> tests/ui/selector_id/fail/invalid_parameter_type_02.rs:3:34 | 3 | const _: u32 = ink::selector_id!(42); | ^^ diff --git a/crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.stderr b/crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.stderr index f26d1abbfa..27fc30eb56 100644 --- a/crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.stderr +++ b/crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input: unexpected end of input, expected literal - --> $DIR/missing_parameter.rs:3:16 + --> tests/ui/selector_id/fail/missing_parameter.rs:3:16 | 3 | const _: u32 = ink::selector_id!(); | ^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.stderr b/crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.stderr index 226fc0471e..ea9ade3062 100644 --- a/crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.stderr +++ b/crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.stderr @@ -1,5 +1,5 @@ error: expected string or byte string literal as input: expected literal - --> $DIR/non_literal_parameter.rs:4:34 + --> tests/ui/selector_id/fail/non_literal_parameter.rs:4:34 | 4 | const _: u32 = ink::selector_id!(INPUT); | ^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr index 4b43b6bc9e..408b47b84c 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr @@ -1,5 +1,5 @@ error: encountered invalid Rust identifier for the ink! namespace configuration parameter - --> $DIR/config_namespace_invalid_1.rs:3:37 + --> tests/ui/trait_def/fail/config_namespace_invalid_1.rs:3:37 | 3 | #[ink::trait_definition(namespace = "::invalid::rust::identifier")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr index d6bea37617..704e3fb61b 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr @@ -1,5 +1,5 @@ error: ink! config options require an argument separated by '=' - --> $DIR/config_namespace_invalid_2.rs:3:25 + --> tests/ui/trait_def/fail/config_namespace_invalid_2.rs:3:25 | 3 | #[ink::trait_definition(namespace)] | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr index df82146b0b..38ae37022b 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr @@ -1,5 +1,5 @@ error: encountered invalid Rust identifier for the ink! namespace configuration parameter - --> $DIR/config_namespace_invalid_3.rs:3:37 + --> tests/ui/trait_def/fail/config_namespace_invalid_3.rs:3:37 | 3 | #[ink::trait_definition(namespace = "")] | ^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr index 5ad2705959..ff715414d9 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr @@ -1,5 +1,5 @@ error: expected a string literal for `namespace` ink! trait definition configuration argument - --> $DIR/config_namespace_invalid_4.rs:3:25 + --> tests/ui/trait_def/fail/config_namespace_invalid_4.rs:3:25 | 3 | #[ink::trait_definition(namespace = true)] | ^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr index adb4402568..7ab4223454 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr @@ -1,5 +1,5 @@ error: associated constants in ink! trait definitions are not supported, yet - --> $DIR/definition_assoc_const.rs:5:5 + --> tests/ui/trait_def/fail/definition_assoc_const.rs:5:5 | 5 | const CONST: bool; | ^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr index 5719ca6e62..14bdfbd199 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr @@ -1,5 +1,5 @@ error: associated types in ink! trait definitions are not supported, yet - --> $DIR/definition_assoc_type.rs:5:5 + --> tests/ui/trait_def/fail/definition_assoc_type.rs:5:5 | 5 | type Type; | ^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr index 3cea1be911..3460253bf3 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr @@ -1,5 +1,5 @@ error: ink! trait definitions must not have constructors - --> $DIR/definition_constructor.rs:5:5 + --> tests/ui/trait_def/fail/definition_constructor.rs:5:5 | 5 | / #[ink(constructor)] 6 | | fn constructor() -> Self; diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr index b084b40280..4b9db3aacf 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr @@ -1,5 +1,5 @@ error: encountered invalid empty ink! trait definition - --> $DIR/definition_empty.rs:4:1 + --> tests/ui/trait_def/fail/definition_empty.rs:4:1 | 4 | pub trait TraitDefinition {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr index edd92f6b44..a0381027e1 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr @@ -1,5 +1,5 @@ error: ink! trait definitions must not be generic - --> $DIR/definition_generic.rs:4:27 + --> tests/ui/trait_def/fail/definition_generic.rs:4:27 | 4 | pub trait TraitDefinition { | ^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr index 4a66ed5714..b559983203 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr @@ -1,5 +1,5 @@ error: ink! trait definitions must have public visibility - --> $DIR/definition_non_pub.rs:3:1 + --> tests/ui/trait_def/fail/definition_non_pub.rs:3:1 | 3 | #[ink::trait_definition] | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr index e0cc2dc76f..d47c5818d4 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr @@ -1,5 +1,5 @@ error: missing #[ink(message)] or #[ink(constructor)] flags on ink! trait method - --> $DIR/definition_rust_method.rs:5:5 + --> tests/ui/trait_def/fail/definition_rust_method.rs:5:5 | 5 | fn rust_method(&self); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr index e13ce9e491..f66a8d803d 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr @@ -1,5 +1,5 @@ error: ink! trait definitions with supertraits are not supported, yet - --> $DIR/definition_super_trait_invalid_1.rs:6:28 + --> tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs:6:28 | 6 | pub trait TraitDefinition: SuperTraitDefinition { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr index 1561de9505..3350a2b89c 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr @@ -1,5 +1,5 @@ error: ink! trait definitions with supertraits are not supported, yet - --> $DIR/definition_super_trait_invalid_2.rs:10:28 + --> tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs:10:28 | 10 | pub trait TraitDefinition: SuperTraitDefinition { | ^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr b/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr index c558155d3f..063a7c2d23 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr @@ -1,5 +1,5 @@ error: ink! trait definitions cannot be unsafe - --> $DIR/definition_unsafe.rs:4:5 + --> tests/ui/trait_def/fail/definition_unsafe.rs:4:5 | 4 | pub unsafe trait TraitDefinition { | ^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr index 37e22a8ab9..4a3c6d02a5 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr @@ -1,5 +1,5 @@ error: ink! trait methods with non default ABI are not supported - --> $DIR/message_abi_invalid.rs:6:5 + --> tests/ui/trait_def/fail/message_abi_invalid.rs:6:5 | 6 | extern "C" fn message_ref(&self); | ^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr index 83761ecbab..b1e6354058 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr @@ -1,5 +1,5 @@ error: async ink! trait methods are not supported - --> $DIR/message_async_invalid.rs:6:5 + --> tests/ui/trait_def/fail/message_async_invalid.rs:6:5 | 6 | async fn message_ref(&self); | ^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr index b5af29423e..4cf9f2fa07 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr @@ -1,5 +1,5 @@ error: const ink! trait methods are not supported - --> $DIR/message_const_invalid.rs:6:5 + --> tests/ui/trait_def/fail/message_const_invalid.rs:6:5 | 6 | const fn message_ref(&self); | ^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr index 539f48c611..53b3112851 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr @@ -1,5 +1,5 @@ error: encountered conflicting ink! attribute argument - --> $DIR/message_constructor_conflict.rs:5:20 + --> tests/ui/trait_def/fail/message_constructor_conflict.rs:5:20 | 5 | #[ink(message, constructor)] | ^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr index ee7fc0005f..aba46f5059 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr @@ -1,5 +1,5 @@ error: ink! trait methods with default implementations are not supported - --> $DIR/message_default_impl.rs:6:23 + --> tests/ui/trait_def/fail/message_default_impl.rs:6:23 | 6 | fn message(&self) {} | ^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr index 5a5e1442dd..c2df8eda52 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr @@ -1,5 +1,5 @@ error: generic ink! trait methods are not supported - --> $DIR/message_generic_invalid.rs:6:20 + --> tests/ui/trait_def/fail/message_generic_invalid.rs:6:20 | 6 | fn message_ref(&self); | ^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr index e0b5b92f14..34a8d561e0 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeDecode` is not satisfied - --> $DIR/message_input_non_codec.rs:8:23 + --> tests/ui/trait_def/fail/message_input_non_codec.rs:8:23 | 8 | fn message(&self, input: NonCodec); | ^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodec` | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodec` note: required by a bound in `DispatchInput` - --> $DIR/type_check.rs:41:8 + --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs | -41 | T: scale::Decode + 'static; + | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied - --> $DIR/message_input_non_codec.rs:5:1 + --> tests/ui/trait_def/fail/message_input_non_codec.rs:5:1 | 5 | #[ink::trait_definition] | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` @@ -25,7 +25,7 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied = note: this error originates in the attribute macro `ink::trait_definition` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied - --> $DIR/message_input_non_codec.rs:7:5 + --> tests/ui/trait_def/fail/message_input_non_codec.rs:7:5 | 7 | / #[ink(message)] 8 | | fn message(&self, input: NonCodec); diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr index 678fd877ba..dedc753932 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr @@ -1,5 +1,5 @@ error[E0642]: patterns aren't allowed in functions without bodies - --> $DIR/message_input_pattern_invalid.rs:6:23 + --> tests/ui/trait_def/fail/message_input_pattern_invalid.rs:6:23 | 6 | fn message(&self, (a, b): (i32, i32)); | ^^^^^^ pattern not allowed in function without body diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr index b89f1a353d..498ba518fa 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr @@ -1,25 +1,36 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied - --> $DIR/message_output_non_codec.rs:8:26 + --> tests/ui/trait_def/fail/message_output_non_codec.rs:8:26 | 8 | fn message(&self) -> NonCodec; | ^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodec` | = note: required because of the requirements on the impl of `Encode` for `NonCodec` note: required by a bound in `DispatchOutput` - --> $DIR/type_check.rs:69:8 + --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs | -69 | T: scale::Encode + 'static; + | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>`, but its trait bounds were not satisfied - --> $DIR/message_output_non_codec.rs:7:5 - | -3 | pub struct NonCodec; - | -------------------- doesn't satisfy `NonCodec: parity_scale_codec::Decode` + --> tests/ui/trait_def/fail/message_output_non_codec.rs:7:5 + | +3 | pub struct NonCodec; + | -------------------- doesn't satisfy `NonCodec: parity_scale_codec::Decode` ... -7 | / #[ink(message)] -8 | | fn message(&self) -> NonCodec; - | |__________________________________^ method cannot be called on `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>` due to unsatisfied trait bounds - | - = note: the following trait bounds were not satisfied: - `NonCodec: parity_scale_codec::Decode` +7 | / #[ink(message)] +8 | | fn message(&self) -> NonCodec; + | |__________________________________^ method cannot be called on `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NonCodec: parity_scale_codec::Decode` +note: the following trait must be implemented + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs + | + | / pub trait Decode: Sized { + | | // !INTERNAL USE ONLY! + | | // This const helps SCALE to optimize the encoding/decoding by doing fake specialization. + | | #[doc(hidden)] +... | + | | } + | | } + | |_^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr index e207aa54bb..5b341d5a4e 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr @@ -1,5 +1,5 @@ error: unknown ink! attribute argument (name = value) - --> $DIR/message_payable_invalid_1.rs:5:20 + --> tests/ui/trait_def/fail/message_payable_invalid_1.rs:5:20 | 5 | #[ink(message, payable = false)] | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr index 16f8b5ebbe..f794664ce1 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr @@ -1,5 +1,5 @@ error: unknown ink! attribute argument (name = value) - --> $DIR/message_payable_invalid_2.rs:5:20 + --> tests/ui/trait_def/fail/message_payable_invalid_2.rs:5:20 | 5 | #[ink(message, payable = true)] | ^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr index fb10f7034f..c81f1bd2d4 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_receiver_invalid_1.rs:6:5 + --> tests/ui/trait_def/fail/message_receiver_invalid_1.rs:6:5 | 6 | fn message(); | ^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr index 7edfb1ce81..bbe8fef44a 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_receiver_invalid_2.rs:6:5 + --> tests/ui/trait_def/fail/message_receiver_invalid_2.rs:6:5 | 6 | fn message(this: Self); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr index 8e26f4c4ed..59e41cd4c4 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_receiver_invalid_3.rs:6:5 + --> tests/ui/trait_def/fail/message_receiver_invalid_3.rs:6:5 | 6 | fn message(this: &Self); | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr index 9ae0881e6a..3f89dbd8c7 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr @@ -1,5 +1,5 @@ error: missing or malformed `&self` or `&mut self` receiver for ink! message - --> $DIR/message_receiver_missing.rs:6:5 + --> tests/ui/trait_def/fail/message_receiver_missing.rs:6:5 | 6 | fn message(); | ^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr index 4aed23d8e8..33da5adc7d 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr @@ -1,5 +1,5 @@ error: expecteded 4-digit hexcode for `selector` argument, e.g. #[ink(selector = 0xC0FEBABE] - --> $DIR/message_selector_invalid_1.rs:5:20 + --> tests/ui/trait_def/fail/message_selector_invalid_1.rs:5:20 | 5 | #[ink(message, selector = true)] | ^^^^^^^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr index aef66faddf..1b47d602f9 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr @@ -1,5 +1,5 @@ error: encountered #[ink(selector)] that is missing its u32 parameter. Did you mean #[ink(selector = value: u32)] ? - --> $DIR/message_selector_invalid_2.rs:5:20 + --> tests/ui/trait_def/fail/message_selector_invalid_2.rs:5:20 | 5 | #[ink(message, selector)] | ^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr index 386c093424..26530c4858 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr @@ -1,11 +1,11 @@ error: encountered duplicate selector ([0, 0, 0, 1]) in the same ink! trait definition - --> $DIR/message_selector_overlap.rs:9:8 + --> tests/ui/trait_def/fail/message_selector_overlap.rs:9:8 | 9 | fn message_2(&self); | ^^^^^^^^^ error: first ink! trait constructor or message with same selector found here - --> $DIR/message_selector_overlap.rs:6:8 + --> tests/ui/trait_def/fail/message_selector_overlap.rs:6:8 | 6 | fn message_1(&self); | ^^^^^^^^^ diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr b/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr index 671a0ff9b7..4d7d1fe35a 100644 --- a/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr +++ b/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr @@ -1,5 +1,5 @@ error: unsafe ink! trait methods are not supported - --> $DIR/message_unsafe_invalid.rs:6:5 + --> tests/ui/trait_def/fail/message_unsafe_invalid.rs:6:5 | 6 | unsafe fn message_ref(&self); | ^^^^^^ From ea5c9958cd7304f7eba935a8ac1b8964c059438d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 09:48:49 +0200 Subject: [PATCH 466/493] add comment that explains why we have both result checks in execution --- crates/lang/src/codegen/dispatch/execution.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/lang/src/codegen/dispatch/execution.rs b/crates/lang/src/codegen/dispatch/execution.rs index 2631dcbe29..1ad6e6837c 100644 --- a/crates/lang/src/codegen/dispatch/execution.rs +++ b/crates/lang/src/codegen/dispatch/execution.rs @@ -155,6 +155,11 @@ where alloc::finalize(); } if TypeId::of::() != TypeId::of::<()>() { + // We include a check for `is_result_type!(Output)` despite the fact that this + // is indirectly covered by `is_result_err!(&result)` because the Rust compiler + // will have more opportunities to optimize the whole conditional away. This is + // due to the fact that `is_result_type!` relies on constant information whereas + // is_result_err!` requires `&self`. let revert_state = config.may_revert && is_result_type!(Output) && is_result_err!(&result); ink_env::return_value::( From a51112867b05b7656c80417d48a5ead0df20932e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 11:34:02 +0200 Subject: [PATCH 467/493] introduce DecodeDispatch trait This replaces the bare use of scale::Decode for ink! constructor and message decoders. The advantage is that it can return DispatchError instead of scale::Error. Also adds new UI test and docs with a usage example. --- crates/lang/codegen/src/generator/dispatch.rs | 54 +++++-- .../contract/pass/dispatch-decoder-works.rs | 132 ++++++++++++++++ crates/lang/src/reflect/dispatch.rs | 146 ++++++++++++++++-- crates/lang/src/reflect/mod.rs | 1 + 4 files changed, 302 insertions(+), 31 deletions(-) create mode 100644 crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 8dd19678c3..4a76c41cfb 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -489,7 +489,8 @@ impl Dispatch<'_> { quote_spanned!(constructor_span=> #constructor_selector => { ::core::result::Result::Ok(Self::#constructor_ident( - <#constructor_input as ::scale::Decode>::decode(input)? + <#constructor_input as ::scale::Decode>::decode(input) + .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidParameters)? )) } ) @@ -522,26 +523,38 @@ impl Dispatch<'_> { quote_spanned!(span=> const _: () = { #[allow(non_camel_case_types)] + // #[derive(::core::fmt::Debug, ::core::cmp::PartialEq)] pub enum __ink_ConstructorDecoder { #( #constructors_variants ),* } - impl ::scale::Decode for __ink_ConstructorDecoder { - fn decode(input: &mut I) -> ::core::result::Result + impl ::ink_lang::reflect::DecodeDispatch for __ink_ConstructorDecoder { + fn decode_dispatch(input: &mut I) + -> ::core::result::Result where I: ::scale::Input, { - match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { + match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input) + .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidSelector)? + { #( #constructor_match , )* _invalid => ::core::result::Result::Err( - <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( - "encountered unknown ink! constructor selector" - ) + ::ink_lang::reflect::DispatchError::UnknownSelector ) } } } + impl ::scale::Decode for __ink_ConstructorDecoder { + fn decode(input: &mut I) -> ::core::result::Result + where + I: ::scale::Input, + { + ::decode_dispatch(input) + .map_err(::core::convert::Into::into) + } + } + impl ::ink_lang::reflect::ExecuteDispatchable for __ink_ConstructorDecoder { fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::reflect::DispatchError> { match self { @@ -613,7 +626,8 @@ impl Dispatch<'_> { quote_spanned!(message_span=> #message_selector => { ::core::result::Result::Ok(Self::#message_ident( - <#message_input as ::scale::Decode>::decode(input)? + <#message_input as ::scale::Decode>::decode(input) + .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidParameters)? )) } ) @@ -680,26 +694,38 @@ impl Dispatch<'_> { quote_spanned!(span=> const _: () = { #[allow(non_camel_case_types)] + // #[derive(::core::fmt::Debug, ::core::cmp::PartialEq)] pub enum __ink_MessageDecoder { #( #message_variants ),* } - impl ::scale::Decode for __ink_MessageDecoder { - fn decode(input: &mut I) -> ::core::result::Result + impl ::ink_lang::reflect::DecodeDispatch for __ink_MessageDecoder { + fn decode_dispatch(input: &mut I) + -> ::core::result::Result where I: ::scale::Input, { - match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input)? { + match <[::core::primitive::u8; 4usize] as ::scale::Decode>::decode(input) + .map_err(|_| ::ink_lang::reflect::DispatchError::InvalidSelector)? + { #( #message_match , )* _invalid => ::core::result::Result::Err( - <::scale::Error as ::core::convert::From<&'static ::core::primitive::str>>::from( - "encountered unknown ink! message selector" - ) + ::ink_lang::reflect::DispatchError::UnknownSelector ) } } } + impl ::scale::Decode for __ink_MessageDecoder { + fn decode(input: &mut I) -> ::core::result::Result + where + I: ::scale::Input, + { + ::decode_dispatch(input) + .map_err(::core::convert::Into::into) + } + } + impl ::ink_lang::reflect::ExecuteDispatchable for __ink_MessageDecoder { #[allow(clippy::nonminimal_bool)] fn execute_dispatchable(self) -> ::core::result::Result<(), ::ink_lang::reflect::DispatchError> { diff --git a/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs b/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs new file mode 100644 index 0000000000..102e57879a --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs @@ -0,0 +1,132 @@ +use ink_lang as ink; +use ink_lang::{ + reflect::{ + ContractConstructorDecoder, + ContractMessageDecoder, + DecodeDispatch, + DispatchError, + }, + selector_bytes, +}; +use scale::Encode; + +#[ink::contract] +pub mod contract { + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor(_input_1: bool, _input_2: i32) -> Self { + Self {} + } + + #[ink(message)] + pub fn message(&self, _input_1: bool, _input_2: i32) {} + } +} + +use contract::Contract; + +fn main() { + constructor_decoder_works(); + message_decoder_works(); +} + +fn constructor_decoder_works() { + // Valid call to `constructor`: + { + let mut input_bytes = Vec::new(); + input_bytes.extend(selector_bytes!("constructor")); + input_bytes.extend(true.encode()); + input_bytes.extend(42i32.encode()); + assert!( + <::Type as DecodeDispatch>::decode_dispatch( + &mut &input_bytes[..]).is_ok() + ); + } + // Invalid call with invalid selector (or empty input). + { + let mut input_bytes = Vec::new(); + assert_eq!( + <::Type + as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) + .map(|_| ()) + .unwrap_err(), + DispatchError::InvalidSelector, + ); + } + // Invalid call to `message` with unknown selector. + { + let mut input_bytes = Vec::new(); + input_bytes.extend(selector_bytes!("unknown_selector")); + assert_eq!( + <::Type + as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) + .map(|_| ()) + .unwrap_err(), + DispatchError::UnknownSelector, + ); + } + // Invalid call to `message` with invalid (or missing) parameters. + { + let mut input_bytes = Vec::new(); + input_bytes.extend(selector_bytes!("constructor")); + assert_eq!( + <::Type + as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) + .map(|_| ()) + .unwrap_err(), + DispatchError::InvalidParameters, + ); + } +} + +fn message_decoder_works() { + // Valid call to `message`: + { + let mut input_bytes = Vec::new(); + input_bytes.extend(selector_bytes!("message")); + input_bytes.extend(true.encode()); + input_bytes.extend(42i32.encode()); + assert!( + <::Type as DecodeDispatch>::decode_dispatch( + &mut &input_bytes[..]).is_ok() + ); + } + // Invalid call with invalid selector (or empty input). + { + let mut input_bytes = Vec::new(); + assert_eq!( + <::Type + as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) + .map(|_| ()) + .unwrap_err(), + DispatchError::InvalidSelector, + ); + } + // Invalid call to `message` with unknown selector. + { + let mut input_bytes = Vec::new(); + input_bytes.extend(selector_bytes!("unknown_selector")); + assert_eq!( + <::Type + as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) + .map(|_| ()) + .unwrap_err(), + DispatchError::UnknownSelector, + ); + } + // Invalid call to `message` with invalid (or missing) parameters. + { + let mut input_bytes = Vec::new(); + input_bytes.extend(selector_bytes!("message")); + assert_eq!( + <::Type + as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) + .map(|_| ()) + .unwrap_err(), + DispatchError::InvalidParameters, + ); + } +} diff --git a/crates/lang/src/reflect/dispatch.rs b/crates/lang/src/reflect/dispatch.rs index bc7a811d0d..4a396f631f 100644 --- a/crates/lang/src/reflect/dispatch.rs +++ b/crates/lang/src/reflect/dispatch.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use derive_more::Display; +use core::fmt::Display; /// Reflects the number of dispatchable ink! messages and constructors respectively. /// @@ -502,7 +502,7 @@ pub trait ContractMessageDecoder { /// ``` pub trait ContractConstructorDecoder { /// The ink! smart contract constructor decoder type. - type Type: scale::Decode + ExecuteDispatchable; + type Type: DecodeDispatch + ExecuteDispatchable; } /// Starts the execution of the respective ink! message or constructor call. @@ -516,24 +516,136 @@ pub trait ExecuteDispatchable { } /// An error that can occur during dispatch of ink! dispatchables. -#[derive(Debug, Copy, Clone, Display)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum DispatchError { - #[display(fmt = "unknown selector")] + /// Failed to decode into a valid dispatch selector. + InvalidSelector, + /// The decoded selector is not known to the dispatch decoder. UnknownSelector, - #[display(fmt = "unknown constructor selector")] - UnknownInstantiateSelector, - #[display(fmt = "unknown message selector")] - UnknownCallSelector, - - #[display(fmt = "unable to decoded input parameter bytes")] + /// Failed to decode the parameters for the selected dispatchable. InvalidParameters, - #[display(fmt = "unable to decoded input parameter bytes for constructor")] - InvalidInstantiateParameters, - #[display(fmt = "unable to decoded input parameter bytes for message")] - InvalidCallParameters, - - #[display(fmt = "could not read input parameters")] + /// Failed to read execution input for the dispatchable. CouldNotReadInput, - #[display(fmt = "paid an unpayable message")] + /// Invalidly paid an unpayable dispatchable. PaidUnpayableMessage, } + +impl Display for DispatchError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl DispatchError { + /// Returns a string representation of the error. + #[inline] + fn as_str(&self) -> &'static str { + match self { + Self::InvalidSelector => "unable to decode selector", + Self::UnknownSelector => "encountered unknown selector", + Self::InvalidParameters => "unable to decode input", + Self::CouldNotReadInput => "could not read input", + Self::PaidUnpayableMessage => "paid an unpayable message", + } + } +} + +impl From for scale::Error { + #[inline] + fn from(error: DispatchError) -> Self { + Self::from(error.as_str()) + } +} + +/// Decodes an ink! dispatch input into a known selector and its expected parameters. +/// +/// # Note +/// +/// This trait is automatically implemented for ink! message and constructor decoders. +/// +/// # Errors +/// +/// Returns an error if any of the decode steps failed: +/// +/// - `InvalidSelector`: The first four bytes could not properly decoded into the selector. +/// - `UnknownSelector`: The decoded selector did not match any of the expected ones. +/// - `InvalidParameters`: Failed to decoded the parameters for the selected dispatchable. +/// +/// The other dispatch errors are handled by other structures usually. +/// +/// # Usage +/// +/// ``` +/// use ink_lang as ink; +/// # use ink_lang::reflect::{ContractMessageDecoder, DecodeDispatch, DispatchError}; +/// # use ink_lang::selector_bytes; +/// # use scale::Encode; +/// +/// #[ink::contract] +/// pub mod contract { +/// #[ink(storage)] +/// pub struct Contract {} +/// +/// impl Contract { +/// #[ink(constructor)] +/// pub fn constructor() -> Self { Self {} } +/// +/// #[ink(message)] +/// pub fn message(&self, input_1: bool, input_2: i32) {} +/// } +/// } +/// +/// use contract::Contract; +/// +/// fn main() { +/// // Valid call to `message`: +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("message")); +/// input_bytes.extend(true.encode()); +/// input_bytes.extend(42i32.encode()); +/// assert!( +/// <::Type as DecodeDispatch>::decode_dispatch( +/// &mut &input_bytes[..]).is_ok() +/// ); +/// } +/// // Invalid call with invalid selector (or empty input). +/// { +/// let mut input_bytes = Vec::new(); +/// assert_eq!( +/// <::Type +/// as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) +/// # .map(|_| ()) +/// .unwrap_err(), +/// DispatchError::InvalidSelector, +/// ); +/// } +/// // Invalid call to `message` with unknown selector. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("unknown_selector")); +/// assert_eq!( +/// <::Type +/// as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) +/// # .map(|_| ()) +/// .unwrap_err(), +/// DispatchError::UnknownSelector, +/// ); +/// } +/// // Invalid call to `message` with invalid (or missing) parameters. +/// { +/// let mut input_bytes = Vec::new(); +/// input_bytes.extend(selector_bytes!("message")); +/// assert_eq!( +/// <::Type +/// as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) +/// # .map(|_| ()) +/// .unwrap_err(), +/// DispatchError::InvalidParameters, +/// ); +/// } +/// } +/// ``` +pub trait DecodeDispatch: scale::Decode { + fn decode_dispatch(input: &mut I) -> Result; +} diff --git a/crates/lang/src/reflect/mod.rs b/crates/lang/src/reflect/mod.rs index 43c39bda1c..3d31dba021 100644 --- a/crates/lang/src/reflect/mod.rs +++ b/crates/lang/src/reflect/mod.rs @@ -40,6 +40,7 @@ pub use self::{ ContractDispatchableConstructors, ContractDispatchableMessages, ContractMessageDecoder, + DecodeDispatch, DispatchError, DispatchableConstructorInfo, DispatchableMessageInfo, From 53ab40b75249fa2ec2bd56b96a3d1880b7344d63 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 11:37:03 +0200 Subject: [PATCH 468/493] use selector_bytes! in UI test --- .../lang/macro/tests/ui/contract/pass/constructor-selector.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs b/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs index 64e446c303..2fdadebaad 100644 --- a/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs +++ b/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs @@ -1,5 +1,6 @@ use contract::Contract; use ink_lang as ink; +use ink_lang::selector_bytes; #[ink::contract] mod contract { @@ -38,7 +39,7 @@ fn main() { >>::IDS[0] }, >>::SELECTOR, - [0x5C, 0x5D, 0x42, 0x89], + selector_bytes!("constructor_0") ); assert_eq!( Date: Sat, 9 Oct 2021 11:46:28 +0200 Subject: [PATCH 469/493] slightly improve fail UI tests --- .../ui/contract/fail/trait-message-selector-overlap-1.rs | 8 ++++---- .../ui/contract/fail/trait-message-selector-overlap-2.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs index f402c766d1..b23b597325 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs @@ -1,4 +1,4 @@ -mod foo { +mod foo1 { use ink_lang as ink; #[ink::trait_definition] @@ -8,7 +8,7 @@ mod foo { } } -mod bar { +mod foo2 { use ink_lang as ink; #[ink::trait_definition] @@ -23,8 +23,8 @@ use ink_lang as ink; #[ink::contract] pub mod contract { use super::{ - bar::TraitDefinition as TraitDefinition2, - foo::TraitDefinition as TraitDefinition1, + foo1::TraitDefinition as TraitDefinition1, + foo2::TraitDefinition as TraitDefinition2, }; #[ink(storage)] diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs index 8bcb70f49d..4c4f5bc101 100644 --- a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs @@ -1,4 +1,4 @@ -mod foo { +mod foo1 { use ink_lang as ink; #[ink::trait_definition(namespace = "same")] @@ -8,7 +8,7 @@ mod foo { } } -mod bar { +mod foo2 { use ink_lang as ink; #[ink::trait_definition(namespace = "same")] @@ -23,8 +23,8 @@ use ink_lang as ink; #[ink::contract] pub mod contract { use super::{ - bar::TraitDefinition as TraitDefinition2, - foo::TraitDefinition as TraitDefinition1, + foo1::TraitDefinition as TraitDefinition1, + foo2::TraitDefinition as TraitDefinition2, }; #[ink(storage)] From 8f1c4ea9ddff06643a28b4d6bcf27af46152f8a3 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 11:46:37 +0200 Subject: [PATCH 470/493] fix warning in passing UI test --- .../macro/tests/ui/contract/pass/dispatch-decoder-works.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs b/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs index 102e57879a..db374f94c1 100644 --- a/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs +++ b/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs @@ -47,7 +47,7 @@ fn constructor_decoder_works() { } // Invalid call with invalid selector (or empty input). { - let mut input_bytes = Vec::new(); + let input_bytes = Vec::new(); assert_eq!( <::Type as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) @@ -96,7 +96,7 @@ fn message_decoder_works() { } // Invalid call with invalid selector (or empty input). { - let mut input_bytes = Vec::new(); + let input_bytes = Vec::new(); assert_eq!( <::Type as DecodeDispatch>::decode_dispatch(&mut &input_bytes[..]) From b522fefc5c517fe9fb15f2b43f655d0ceb78018d Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 11:46:53 +0200 Subject: [PATCH 471/493] add new UI test to guard against trait message selector overlaps --- .../fail/trait-message-selector-overlap-3.rs | 51 +++++++++++++++++++ .../trait-message-selector-overlap-3.stderr | 8 +++ 2 files changed, 59 insertions(+) create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.rs create mode 100644 crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.rs b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.rs new file mode 100644 index 0000000000..0594163daf --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.rs @@ -0,0 +1,51 @@ +mod foo1 { + use ink_lang as ink; + + #[ink::trait_definition] + pub trait TraitDefinition1 { + #[ink(message, selector = 42)] + fn message1(&self); + } +} + +mod foo2 { + use ink_lang as ink; + + #[ink::trait_definition] + pub trait TraitDefinition2 { + #[ink(message, selector = 42)] + fn message2(&self); + } +} + +use ink_lang as ink; + +#[ink::contract] +pub mod contract { + use super::{ + foo1::TraitDefinition1, + foo2::TraitDefinition2, + }; + + #[ink(storage)] + pub struct Contract {} + + impl Contract { + #[ink(constructor)] + pub fn constructor() -> Self { + Self {} + } + } + + impl TraitDefinition1 for Contract { + #[ink(message)] + fn message1(&self) {} + } + + impl TraitDefinition2 for Contract { + #[ink(message)] + fn message2(&self) {} + } +} + +fn main() {} diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr new file mode 100644 index 0000000000..3e99b03a02 --- /dev/null +++ b/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr @@ -0,0 +1,8 @@ +error[E0119]: conflicting implementations of trait `ink_lang::reflect::DispatchableMessageInfo<42_u32>` for type `contract::Contract` + --> tests/ui/contract/fail/trait-message-selector-overlap-3.rs:47:9 + | +42 | fn message1(&self) {} + | ------------------ first implementation here +... +47 | fn message2(&self) {} + | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `contract::Contract` From b9b2aaf366a82972d5919f0775e7f7369af575bd Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 11:57:53 +0200 Subject: [PATCH 472/493] move UI tests from ink_lang_macro to ink_lang crate directory --- crates/lang/Cargo.toml | 6 +++++- crates/lang/{macro => }/tests/compile_tests.rs | 0 .../tests/ui/blake2b/fail/invalid_parameter_type_01.rs | 0 .../tests/ui/blake2b/fail/invalid_parameter_type_01.stderr | 0 .../tests/ui/blake2b/fail/invalid_parameter_type_02.rs | 0 .../tests/ui/blake2b/fail/invalid_parameter_type_02.stderr | 0 .../{macro => }/tests/ui/blake2b/fail/missing_parameter.rs | 0 .../tests/ui/blake2b/fail/missing_parameter.stderr | 0 .../tests/ui/blake2b/fail/non_literal_parameter.rs | 0 .../tests/ui/blake2b/fail/non_literal_parameter.stderr | 0 .../{macro => }/tests/ui/blake2b/pass/bytestring_input.rs | 0 .../tests/ui/blake2b/pass/no_implicit_prelude.rs | 0 .../lang/{macro => }/tests/ui/blake2b/pass/string_input.rs | 0 .../{macro => }/tests/ui/chain_extension/E-01-simple.rs | 0 .../fail/config-compile-as-dependency-invalid-type-01.rs | 0 .../config-compile-as-dependency-invalid-type-01.stderr | 0 .../fail/config-compile-as-dependency-invalid-type-02.rs | 0 .../config-compile-as-dependency-invalid-type-02.stderr | 0 .../fail/config-compile-as-dependency-missing-arg.rs | 0 .../fail/config-compile-as-dependency-missing-arg.stderr | 0 .../config-dynamic-storage-allocator-invalid-type-01.rs | 0 .../config-dynamic-storage-allocator-invalid-type-01.stderr | 0 .../config-dynamic-storage-allocator-invalid-type-02.rs | 0 .../config-dynamic-storage-allocator-invalid-type-02.stderr | 0 .../fail/config-dynamic-storage-allocator-missing-arg.rs | 0 .../config-dynamic-storage-allocator-missing-arg.stderr | 0 .../{macro => }/tests/ui/contract/fail/constructor-abi.rs | 0 .../tests/ui/contract/fail/constructor-abi.stderr | 0 .../{macro => }/tests/ui/contract/fail/constructor-async.rs | 0 .../tests/ui/contract/fail/constructor-async.stderr | 0 .../{macro => }/tests/ui/contract/fail/constructor-const.rs | 0 .../tests/ui/contract/fail/constructor-const.stderr | 0 .../tests/ui/contract/fail/constructor-input-non-codec.rs | 0 .../ui/contract/fail/constructor-input-non-codec.stderr | 0 .../tests/ui/contract/fail/constructor-input-pattern.rs | 0 .../tests/ui/contract/fail/constructor-input-pattern.stderr | 0 .../tests/ui/contract/fail/constructor-missing-return.rs | 0 .../ui/contract/fail/constructor-missing-return.stderr | 0 .../tests/ui/contract/fail/constructor-payable.rs | 0 .../tests/ui/contract/fail/constructor-payable.stderr | 0 .../tests/ui/contract/fail/constructor-self-receiver-01.rs | 0 .../ui/contract/fail/constructor-self-receiver-01.stderr | 0 .../tests/ui/contract/fail/constructor-self-receiver-02.rs | 0 .../ui/contract/fail/constructor-self-receiver-02.stderr | 0 .../tests/ui/contract/fail/constructor-self-receiver-03.rs | 0 .../ui/contract/fail/constructor-self-receiver-03.stderr | 0 .../tests/ui/contract/fail/constructor-self-receiver-04.rs | 0 .../ui/contract/fail/constructor-self-receiver-04.stderr | 0 .../tests/ui/contract/fail/constructor-unsafe.rs | 0 .../tests/ui/contract/fail/constructor-unsafe.stderr | 0 .../tests/ui/contract/fail/event-conflicting-storage.rs | 0 .../tests/ui/contract/fail/event-conflicting-storage.stderr | 0 .../ui/contract/fail/event-too-many-topics-anonymous.rs | 0 .../ui/contract/fail/event-too-many-topics-anonymous.stderr | 0 .../tests/ui/contract/fail/event-too-many-topics.rs | 0 .../tests/ui/contract/fail/event-too-many-topics.stderr | 0 .../tests/ui/contract/fail/impl-block-for-non-storage-01.rs | 0 .../ui/contract/fail/impl-block-for-non-storage-01.stderr | 0 .../tests/ui/contract/fail/impl-block-for-non-storage-02.rs | 0 .../ui/contract/fail/impl-block-for-non-storage-02.stderr | 0 .../fail/impl-block-namespace-invalid-identifier.rs | 0 .../fail/impl-block-namespace-invalid-identifier.stderr | 0 .../ui/contract/fail/impl-block-namespace-invalid-type.rs | 0 .../contract/fail/impl-block-namespace-invalid-type.stderr | 0 .../contract/fail/impl-block-namespace-missing-argument.rs | 0 .../fail/impl-block-namespace-missing-argument.stderr | 0 .../ui/contract/fail/impl-block-using-env-no-marker.rs | 0 .../ui/contract/fail/impl-block-using-env-no-marker.stderr | 0 .../contract/fail/impl-block-using-static-env-no-marker.rs | 0 .../fail/impl-block-using-static-env-no-marker.stderr | 0 .../tests/ui/contract/fail/message-input-non-codec.rs | 0 .../tests/ui/contract/fail/message-input-non-codec.stderr | 0 .../tests/ui/contract/fail/message-input-pattern.rs | 0 .../tests/ui/contract/fail/message-input-pattern.stderr | 0 .../tests/ui/contract/fail/message-returns-non-codec.rs | 0 .../tests/ui/contract/fail/message-returns-non-codec.stderr | 0 .../tests/ui/contract/fail/message-returns-self.rs | 0 .../tests/ui/contract/fail/message-returns-self.stderr | 0 .../ui/contract/fail/message-selector-invalid-type-01.rs | 0 .../contract/fail/message-selector-invalid-type-01.stderr | 0 .../ui/contract/fail/message-selector-invalid-type-02.rs | 0 .../contract/fail/message-selector-invalid-type-02.stderr | 0 .../tests/ui/contract/fail/message-selector-missing-arg.rs | 0 .../ui/contract/fail/message-selector-missing-arg.stderr | 0 .../ui/contract/fail/message-self-receiver-invalid-01.rs | 0 .../contract/fail/message-self-receiver-invalid-01.stderr | 0 .../ui/contract/fail/message-self-receiver-invalid-02.rs | 0 .../contract/fail/message-self-receiver-invalid-02.stderr | 0 .../ui/contract/fail/message-self-receiver-invalid-03.rs | 0 .../contract/fail/message-self-receiver-invalid-03.stderr | 0 .../tests/ui/contract/fail/message-self-receiver-missing.rs | 0 .../ui/contract/fail/message-self-receiver-missing.stderr | 0 .../tests/ui/contract/fail/message-unknown-property.rs | 0 .../tests/ui/contract/fail/message-unknown-property.stderr | 0 .../tests/ui/contract/fail/module-missing-constructor.rs | 0 .../ui/contract/fail/module-missing-constructor.stderr | 0 .../tests/ui/contract/fail/module-missing-message.rs | 0 .../tests/ui/contract/fail/module-missing-message.stderr | 0 .../tests/ui/contract/fail/module-missing-storage.rs | 0 .../tests/ui/contract/fail/module-missing-storage.stderr | 0 .../tests/ui/contract/fail/module-multiple-storages.rs | 0 .../tests/ui/contract/fail/module-multiple-storages.stderr | 0 .../tests/ui/contract/fail/module-use-forbidden-idents.rs | 0 .../ui/contract/fail/module-use-forbidden-idents.stderr | 0 .../tests/ui/contract/fail/storage-conflicting-event.rs | 0 .../tests/ui/contract/fail/storage-conflicting-event.stderr | 0 .../tests/ui/contract/fail/storage-unknown-marker.rs | 0 .../tests/ui/contract/fail/storage-unknown-marker.stderr | 0 .../tests/ui/contract/fail/trait-impl-namespace-invalid.rs | 0 .../ui/contract/fail/trait-impl-namespace-invalid.stderr | 0 .../ui/contract/fail/trait-message-payable-mismatch.rs | 0 .../ui/contract/fail/trait-message-payable-mismatch.stderr | 0 .../ui/contract/fail/trait-message-selector-mismatch.rs | 0 .../ui/contract/fail/trait-message-selector-mismatch.stderr | 0 .../ui/contract/fail/trait-message-selector-overlap-1.rs | 0 .../contract/fail/trait-message-selector-overlap-1.stderr | 0 .../ui/contract/fail/trait-message-selector-overlap-2.rs | 0 .../contract/fail/trait-message-selector-overlap-2.stderr | 0 .../ui/contract/fail/trait-message-selector-overlap-3.rs | 0 .../contract/fail/trait-message-selector-overlap-3.stderr | 0 .../ui/contract/pass/config-compile-as-dependency-false.rs | 0 .../ui/contract/pass/config-compile-as-dependency-true.rs | 0 .../{macro => }/tests/ui/contract/pass/config-custom-env.rs | 0 .../contract/pass/config-dynamic-storage-allocator-false.rs | 0 .../contract/pass/config-dynamic-storage-allocator-true.rs | 0 .../tests/ui/contract/pass/constructor-many-inputs.rs | 0 .../tests/ui/contract/pass/constructor-selector.rs | 0 .../tests/ui/contract/pass/dispatch-decoder-works.rs | 0 .../lang/{macro => }/tests/ui/contract/pass/env-access.rs | 0 .../{macro => }/tests/ui/contract/pass/event-anonymous.rs | 0 .../tests/ui/contract/pass/event-config-more-topics.rs | 0 .../tests/ui/contract/pass/event-many-definitions.rs | 0 .../tests/ui/contract/pass/event-single-definition.rs | 0 .../lang/{macro => }/tests/ui/contract/pass/event-topics.rs | 0 .../tests/ui/contract/pass/example-erc20-works.rs | 0 .../tests/ui/contract/pass/example-erc721-works.rs | 0 .../tests/ui/contract/pass/example-flipper-works.rs | 0 .../tests/ui/contract/pass/example-incrementer-works.rs | 0 .../tests/ui/contract/pass/example-trait-flipper-works.rs | 0 .../ui/contract/pass/example-trait-incrementer-works.rs | 0 .../tests/ui/contract/pass/impl-alias-storage.rs | 0 .../tests/ui/contract/pass/impl-block-namespace.rs | 0 .../tests/ui/contract/pass/impl-block-using-env.rs | 0 .../tests/ui/contract/pass/impl-with-property.rs | 0 .../tests/ui/contract/pass/message-many-inputs.rs | 0 .../tests/ui/contract/pass/message-many-outputs.rs | 0 .../{macro => }/tests/ui/contract/pass/message-payable.rs | 0 .../{macro => }/tests/ui/contract/pass/message-selector.rs | 0 .../{macro => }/tests/ui/contract/pass/minimal-contract.rs | 0 .../{macro => }/tests/ui/contract/pass/module-env-types.rs | 0 .../tests/ui/contract/pass/module-non-ink-items.rs | 0 .../tests/ui/contract/pass/no-implicit-prelude.rs | 0 .../tests/ui/contract/pass/storage-many-fields.rs | 0 .../tests/ui/contract/pass/storage-packed-fields.rs | 0 .../tests/ui/contract/pass/storage-single-field.rs | 0 .../tests/ui/contract/pass/storage-with-derives.rs | 0 .../tests/ui/contract/pass/trait-message-payable-guard.rs | 0 .../tests/ui/contract/pass/trait-message-selector-guard.rs | 0 .../ui/selector_bytes/fail/invalid_parameter_type_01.rs | 0 .../ui/selector_bytes/fail/invalid_parameter_type_01.stderr | 0 .../ui/selector_bytes/fail/invalid_parameter_type_02.rs | 0 .../ui/selector_bytes/fail/invalid_parameter_type_02.stderr | 0 .../tests/ui/selector_bytes/fail/missing_parameter.rs | 0 .../tests/ui/selector_bytes/fail/missing_parameter.stderr | 0 .../tests/ui/selector_bytes/fail/non_literal_parameter.rs | 0 .../ui/selector_bytes/fail/non_literal_parameter.stderr | 0 .../tests/ui/selector_bytes/pass/bytestring_input.rs | 0 .../tests/ui/selector_bytes/pass/no_implicit_prelude.rs | 0 .../tests/ui/selector_bytes/pass/string_input.rs | 0 .../tests/ui/selector_id/fail/invalid_parameter_type_01.rs | 0 .../ui/selector_id/fail/invalid_parameter_type_01.stderr | 0 .../tests/ui/selector_id/fail/invalid_parameter_type_02.rs | 0 .../ui/selector_id/fail/invalid_parameter_type_02.stderr | 0 .../tests/ui/selector_id/fail/missing_parameter.rs | 0 .../tests/ui/selector_id/fail/missing_parameter.stderr | 0 .../tests/ui/selector_id/fail/non_literal_parameter.rs | 0 .../tests/ui/selector_id/fail/non_literal_parameter.stderr | 0 .../tests/ui/selector_id/pass/bytestring_input.rs | 0 .../tests/ui/selector_id/pass/no_implicit_prelude.rs | 0 .../{macro => }/tests/ui/selector_id/pass/string_input.rs | 0 .../tests/ui/trait_def/fail/config_namespace_invalid_1.rs | 0 .../ui/trait_def/fail/config_namespace_invalid_1.stderr | 0 .../tests/ui/trait_def/fail/config_namespace_invalid_2.rs | 0 .../ui/trait_def/fail/config_namespace_invalid_2.stderr | 0 .../tests/ui/trait_def/fail/config_namespace_invalid_3.rs | 0 .../ui/trait_def/fail/config_namespace_invalid_3.stderr | 0 .../tests/ui/trait_def/fail/config_namespace_invalid_4.rs | 0 .../ui/trait_def/fail/config_namespace_invalid_4.stderr | 0 .../tests/ui/trait_def/fail/definition_assoc_const.rs | 0 .../tests/ui/trait_def/fail/definition_assoc_const.stderr | 0 .../tests/ui/trait_def/fail/definition_assoc_type.rs | 0 .../tests/ui/trait_def/fail/definition_assoc_type.stderr | 0 .../tests/ui/trait_def/fail/definition_constructor.rs | 0 .../tests/ui/trait_def/fail/definition_constructor.stderr | 0 .../{macro => }/tests/ui/trait_def/fail/definition_empty.rs | 0 .../tests/ui/trait_def/fail/definition_empty.stderr | 0 .../tests/ui/trait_def/fail/definition_generic.rs | 0 .../tests/ui/trait_def/fail/definition_generic.stderr | 0 .../tests/ui/trait_def/fail/definition_non_pub.rs | 0 .../tests/ui/trait_def/fail/definition_non_pub.stderr | 0 .../tests/ui/trait_def/fail/definition_rust_method.rs | 0 .../tests/ui/trait_def/fail/definition_rust_method.stderr | 0 .../ui/trait_def/fail/definition_super_trait_invalid_1.rs | 0 .../trait_def/fail/definition_super_trait_invalid_1.stderr | 0 .../ui/trait_def/fail/definition_super_trait_invalid_2.rs | 0 .../trait_def/fail/definition_super_trait_invalid_2.stderr | 0 .../tests/ui/trait_def/fail/definition_unsafe.rs | 0 .../tests/ui/trait_def/fail/definition_unsafe.stderr | 0 .../tests/ui/trait_def/fail/message_abi_invalid.rs | 0 .../tests/ui/trait_def/fail/message_abi_invalid.stderr | 0 .../tests/ui/trait_def/fail/message_async_invalid.rs | 0 .../tests/ui/trait_def/fail/message_async_invalid.stderr | 0 .../tests/ui/trait_def/fail/message_const_invalid.rs | 0 .../tests/ui/trait_def/fail/message_const_invalid.stderr | 0 .../tests/ui/trait_def/fail/message_constructor_conflict.rs | 0 .../ui/trait_def/fail/message_constructor_conflict.stderr | 0 .../tests/ui/trait_def/fail/message_default_impl.rs | 0 .../tests/ui/trait_def/fail/message_default_impl.stderr | 0 .../tests/ui/trait_def/fail/message_generic_invalid.rs | 0 .../tests/ui/trait_def/fail/message_generic_invalid.stderr | 0 .../tests/ui/trait_def/fail/message_input_non_codec.rs | 0 .../tests/ui/trait_def/fail/message_input_non_codec.stderr | 0 .../ui/trait_def/fail/message_input_pattern_invalid.rs | 0 .../ui/trait_def/fail/message_input_pattern_invalid.stderr | 0 .../tests/ui/trait_def/fail/message_output_non_codec.rs | 0 .../tests/ui/trait_def/fail/message_output_non_codec.stderr | 0 .../tests/ui/trait_def/fail/message_payable_invalid_1.rs | 0 .../ui/trait_def/fail/message_payable_invalid_1.stderr | 0 .../tests/ui/trait_def/fail/message_payable_invalid_2.rs | 0 .../ui/trait_def/fail/message_payable_invalid_2.stderr | 0 .../tests/ui/trait_def/fail/message_receiver_invalid_1.rs | 0 .../ui/trait_def/fail/message_receiver_invalid_1.stderr | 0 .../tests/ui/trait_def/fail/message_receiver_invalid_2.rs | 0 .../ui/trait_def/fail/message_receiver_invalid_2.stderr | 0 .../tests/ui/trait_def/fail/message_receiver_invalid_3.rs | 0 .../ui/trait_def/fail/message_receiver_invalid_3.stderr | 0 .../tests/ui/trait_def/fail/message_receiver_missing.rs | 0 .../tests/ui/trait_def/fail/message_receiver_missing.stderr | 0 .../tests/ui/trait_def/fail/message_selector_invalid_1.rs | 0 .../ui/trait_def/fail/message_selector_invalid_1.stderr | 0 .../tests/ui/trait_def/fail/message_selector_invalid_2.rs | 0 .../ui/trait_def/fail/message_selector_invalid_2.stderr | 0 .../tests/ui/trait_def/fail/message_selector_overlap.rs | 0 .../tests/ui/trait_def/fail/message_selector_overlap.stderr | 0 .../tests/ui/trait_def/fail/message_unsafe_invalid.rs | 0 .../tests/ui/trait_def/fail/message_unsafe_invalid.stderr | 0 .../tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs | 0 .../lang/{macro => }/tests/ui/trait_def/pass/many_inputs.rs | 0 .../{macro => }/tests/ui/trait_def/pass/many_outputs.rs | 0 .../tests/ui/trait_def/pass/no-implicit-prelude.rs | 0 .../{macro => }/tests/ui/trait_def/pass/payable_message.rs | 0 .../tests/ui/trait_def/pass/simple_definition.rs | 0 .../{macro => }/tests/ui/trait_def/pass/using-env-types.rs | 0 .../{macro => }/tests/ui/trait_def/pass/valid_selectors.rs | 0 .../tests/ui/trait_def/pass/valid_selectors_namespace.rs | 0 .../{macro => }/tests/ui/trait_def/pass/with_namespace.rs | 0 crates/lang/{macro => }/tests/unique_topics.rs | 0 257 files changed, 5 insertions(+), 1 deletion(-) rename crates/lang/{macro => }/tests/compile_tests.rs (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/invalid_parameter_type_01.rs (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/invalid_parameter_type_02.rs (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/missing_parameter.rs (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/missing_parameter.stderr (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/non_literal_parameter.rs (100%) rename crates/lang/{macro => }/tests/ui/blake2b/fail/non_literal_parameter.stderr (100%) rename crates/lang/{macro => }/tests/ui/blake2b/pass/bytestring_input.rs (100%) rename crates/lang/{macro => }/tests/ui/blake2b/pass/no_implicit_prelude.rs (100%) rename crates/lang/{macro => }/tests/ui/blake2b/pass/string_input.rs (100%) rename crates/lang/{macro => }/tests/ui/chain_extension/E-01-simple.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-abi.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-abi.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-async.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-async.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-const.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-const.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-input-non-codec.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-input-non-codec.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-input-pattern.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-input-pattern.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-missing-return.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-missing-return.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-payable.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-payable.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-01.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-01.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-02.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-02.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-03.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-03.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-04.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-self-receiver-04.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-unsafe.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/constructor-unsafe.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/event-conflicting-storage.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/event-conflicting-storage.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/event-too-many-topics-anonymous.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/event-too-many-topics.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/event-too-many-topics.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-for-non-storage-01.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-for-non-storage-02.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-using-env-no-marker.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-input-non-codec.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-input-non-codec.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-input-pattern.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-input-pattern.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-returns-non-codec.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-returns-non-codec.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-returns-self.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-returns-self.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-selector-invalid-type-01.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-selector-invalid-type-01.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-selector-invalid-type-02.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-selector-invalid-type-02.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-selector-missing-arg.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-selector-missing-arg.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-invalid-01.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-invalid-02.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-invalid-03.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-missing.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-self-receiver-missing.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-unknown-property.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/message-unknown-property.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-missing-constructor.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-missing-constructor.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-missing-message.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-missing-message.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-missing-storage.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-missing-storage.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-multiple-storages.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-multiple-storages.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-use-forbidden-idents.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/module-use-forbidden-idents.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/storage-conflicting-event.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/storage-conflicting-event.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/storage-unknown-marker.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/storage-unknown-marker.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-impl-namespace-invalid.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-payable-mismatch.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-payable-mismatch.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-mismatch.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-mismatch.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-overlap-1.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-overlap-2.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-overlap-3.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/config-compile-as-dependency-false.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/config-compile-as-dependency-true.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/config-custom-env.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/constructor-many-inputs.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/constructor-selector.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/dispatch-decoder-works.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/env-access.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/event-anonymous.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/event-config-more-topics.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/event-many-definitions.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/event-single-definition.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/event-topics.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/example-erc20-works.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/example-erc721-works.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/example-flipper-works.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/example-incrementer-works.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/example-trait-flipper-works.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/example-trait-incrementer-works.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/impl-alias-storage.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/impl-block-namespace.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/impl-block-using-env.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/impl-with-property.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/message-many-inputs.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/message-many-outputs.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/message-payable.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/message-selector.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/minimal-contract.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/module-env-types.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/module-non-ink-items.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/no-implicit-prelude.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/storage-many-fields.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/storage-packed-fields.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/storage-single-field.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/storage-with-derives.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/trait-message-payable-guard.rs (100%) rename crates/lang/{macro => }/tests/ui/contract/pass/trait-message-selector-guard.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/invalid_parameter_type_01.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/invalid_parameter_type_02.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/missing_parameter.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/missing_parameter.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/non_literal_parameter.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/fail/non_literal_parameter.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/pass/bytestring_input.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/pass/no_implicit_prelude.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_bytes/pass/string_input.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/invalid_parameter_type_01.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/invalid_parameter_type_02.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/missing_parameter.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/missing_parameter.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/non_literal_parameter.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_id/fail/non_literal_parameter.stderr (100%) rename crates/lang/{macro => }/tests/ui/selector_id/pass/bytestring_input.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_id/pass/no_implicit_prelude.rs (100%) rename crates/lang/{macro => }/tests/ui/selector_id/pass/string_input.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_1.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_2.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_3.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_4.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_assoc_const.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_assoc_const.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_assoc_type.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_assoc_type.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_constructor.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_constructor.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_empty.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_empty.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_generic.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_generic.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_non_pub.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_non_pub.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_rust_method.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_rust_method.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_unsafe.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/definition_unsafe.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_abi_invalid.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_abi_invalid.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_async_invalid.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_async_invalid.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_const_invalid.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_const_invalid.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_constructor_conflict.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_constructor_conflict.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_default_impl.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_default_impl.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_generic_invalid.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_generic_invalid.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_input_non_codec.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_input_non_codec.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_input_pattern_invalid.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_output_non_codec.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_output_non_codec.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_payable_invalid_1.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_payable_invalid_1.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_payable_invalid_2.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_payable_invalid_2.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_invalid_1.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_invalid_2.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_invalid_3.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_missing.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_receiver_missing.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_selector_invalid_1.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_selector_invalid_1.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_selector_invalid_2.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_selector_invalid_2.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_selector_overlap.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_selector_overlap.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_unsafe_invalid.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/fail/message_unsafe_invalid.stderr (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/many_inputs.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/many_outputs.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/no-implicit-prelude.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/payable_message.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/simple_definition.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/using-env-types.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/valid_selectors.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/valid_selectors_namespace.rs (100%) rename crates/lang/{macro => }/tests/ui/trait_def/pass/with_namespace.rs (100%) rename crates/lang/{macro => }/tests/unique_topics.rs (100%) diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index dd22ef7b80..364d6161fb 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -26,7 +26,11 @@ scale = { package = "parity-scale-codec", version = "2", default-features = fals derive_more = { version = "0.99", default-features = false, features = ["from"] } [dev-dependencies] -# required for the doctest of `env_access::EnvAccess::instantiate_contract` +ink_lang_ir = { version = "3.0.0-rc5", path = "ir" } +ink_metadata = { version = "3.0.0-rc5", path = "../metadata" } + +trybuild = { version = "1.0.49", features = ["diff"] } +# Required for the doctest of `env_access::EnvAccess::instantiate_contract` scale-info = { version = "0.6", default-features = false, features = ["derive"] } [features] diff --git a/crates/lang/macro/tests/compile_tests.rs b/crates/lang/tests/compile_tests.rs similarity index 100% rename from crates/lang/macro/tests/compile_tests.rs rename to crates/lang/tests/compile_tests.rs diff --git a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.rs b/crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_01.rs similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.rs rename to crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_01.rs diff --git a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr b/crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr rename to crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_01.stderr diff --git a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.rs b/crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_02.rs similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.rs rename to crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_02.rs diff --git a/crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr b/crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr rename to crates/lang/tests/ui/blake2b/fail/invalid_parameter_type_02.stderr diff --git a/crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.rs b/crates/lang/tests/ui/blake2b/fail/missing_parameter.rs similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.rs rename to crates/lang/tests/ui/blake2b/fail/missing_parameter.rs diff --git a/crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.stderr b/crates/lang/tests/ui/blake2b/fail/missing_parameter.stderr similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/missing_parameter.stderr rename to crates/lang/tests/ui/blake2b/fail/missing_parameter.stderr diff --git a/crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.rs b/crates/lang/tests/ui/blake2b/fail/non_literal_parameter.rs similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.rs rename to crates/lang/tests/ui/blake2b/fail/non_literal_parameter.rs diff --git a/crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.stderr b/crates/lang/tests/ui/blake2b/fail/non_literal_parameter.stderr similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/fail/non_literal_parameter.stderr rename to crates/lang/tests/ui/blake2b/fail/non_literal_parameter.stderr diff --git a/crates/lang/macro/tests/ui/blake2b/pass/bytestring_input.rs b/crates/lang/tests/ui/blake2b/pass/bytestring_input.rs similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/pass/bytestring_input.rs rename to crates/lang/tests/ui/blake2b/pass/bytestring_input.rs diff --git a/crates/lang/macro/tests/ui/blake2b/pass/no_implicit_prelude.rs b/crates/lang/tests/ui/blake2b/pass/no_implicit_prelude.rs similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/pass/no_implicit_prelude.rs rename to crates/lang/tests/ui/blake2b/pass/no_implicit_prelude.rs diff --git a/crates/lang/macro/tests/ui/blake2b/pass/string_input.rs b/crates/lang/tests/ui/blake2b/pass/string_input.rs similarity index 100% rename from crates/lang/macro/tests/ui/blake2b/pass/string_input.rs rename to crates/lang/tests/ui/blake2b/pass/string_input.rs diff --git a/crates/lang/macro/tests/ui/chain_extension/E-01-simple.rs b/crates/lang/tests/ui/chain_extension/E-01-simple.rs similarity index 100% rename from crates/lang/macro/tests/ui/chain_extension/E-01-simple.rs rename to crates/lang/tests/ui/chain_extension/E-01-simple.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs b/crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs rename to crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr b/crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr rename to crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-01.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs b/crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs rename to crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr b/crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr rename to crates/lang/tests/ui/contract/fail/config-compile-as-dependency-invalid-type-02.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs b/crates/lang/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs rename to crates/lang/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr b/crates/lang/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr rename to crates/lang/tests/ui/contract/fail/config-compile-as-dependency-missing-arg.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs b/crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs rename to crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr b/crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr rename to crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-01.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs b/crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs rename to crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr b/crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr rename to crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-invalid-type-02.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs b/crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs rename to crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr b/crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr rename to crates/lang/tests/ui/contract/fail/config-dynamic-storage-allocator-missing-arg.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.rs b/crates/lang/tests/ui/contract/fail/constructor-abi.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-abi.rs rename to crates/lang/tests/ui/contract/fail/constructor-abi.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr b/crates/lang/tests/ui/contract/fail/constructor-abi.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-abi.stderr rename to crates/lang/tests/ui/contract/fail/constructor-abi.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-async.rs b/crates/lang/tests/ui/contract/fail/constructor-async.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-async.rs rename to crates/lang/tests/ui/contract/fail/constructor-async.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr b/crates/lang/tests/ui/contract/fail/constructor-async.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-async.stderr rename to crates/lang/tests/ui/contract/fail/constructor-async.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-const.rs b/crates/lang/tests/ui/contract/fail/constructor-const.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-const.rs rename to crates/lang/tests/ui/contract/fail/constructor-const.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr b/crates/lang/tests/ui/contract/fail/constructor-const.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-const.stderr rename to crates/lang/tests/ui/contract/fail/constructor-const.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.rs b/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.rs rename to crates/lang/tests/ui/contract/fail/constructor-input-non-codec.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-input-non-codec.stderr rename to crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.rs b/crates/lang/tests/ui/contract/fail/constructor-input-pattern.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.rs rename to crates/lang/tests/ui/contract/fail/constructor-input-pattern.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr b/crates/lang/tests/ui/contract/fail/constructor-input-pattern.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-input-pattern.stderr rename to crates/lang/tests/ui/contract/fail/constructor-input-pattern.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.rs b/crates/lang/tests/ui/contract/fail/constructor-missing-return.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.rs rename to crates/lang/tests/ui/contract/fail/constructor-missing-return.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr b/crates/lang/tests/ui/contract/fail/constructor-missing-return.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-missing-return.stderr rename to crates/lang/tests/ui/contract/fail/constructor-missing-return.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-payable.rs b/crates/lang/tests/ui/contract/fail/constructor-payable.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-payable.rs rename to crates/lang/tests/ui/contract/fail/constructor-payable.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr b/crates/lang/tests/ui/contract/fail/constructor-payable.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-payable.stderr rename to crates/lang/tests/ui/contract/fail/constructor-payable.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.rs b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-01.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.rs rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-01.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-01.stderr rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-01.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.rs b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-02.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.rs rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-02.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-02.stderr rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-02.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.rs b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-03.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.rs rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-03.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-03.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-03.stderr rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-03.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.rs b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-04.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.rs rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-04.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr b/crates/lang/tests/ui/contract/fail/constructor-self-receiver-04.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-self-receiver-04.stderr rename to crates/lang/tests/ui/contract/fail/constructor-self-receiver-04.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.rs b/crates/lang/tests/ui/contract/fail/constructor-unsafe.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.rs rename to crates/lang/tests/ui/contract/fail/constructor-unsafe.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr b/crates/lang/tests/ui/contract/fail/constructor-unsafe.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/constructor-unsafe.stderr rename to crates/lang/tests/ui/contract/fail/constructor-unsafe.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.rs b/crates/lang/tests/ui/contract/fail/event-conflicting-storage.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.rs rename to crates/lang/tests/ui/contract/fail/event-conflicting-storage.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr b/crates/lang/tests/ui/contract/fail/event-conflicting-storage.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/event-conflicting-storage.stderr rename to crates/lang/tests/ui/contract/fail/event-conflicting-storage.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.rs b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.rs rename to crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr rename to crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.rs b/crates/lang/tests/ui/contract/fail/event-too-many-topics.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.rs rename to crates/lang/tests/ui/contract/fail/event-too-many-topics.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/event-too-many-topics.stderr rename to crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs b/crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-01.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.rs rename to crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-01.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr b/crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr rename to crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-01.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.rs b/crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-02.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.rs rename to crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-02.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr b/crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr rename to crates/lang/tests/ui/contract/fail/impl-block-for-non-storage-02.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs b/crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs rename to crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr b/crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr rename to crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-identifier.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs b/crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs rename to crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-type.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr b/crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr rename to crates/lang/tests/ui/contract/fail/impl-block-namespace-invalid-type.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs b/crates/lang/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs rename to crates/lang/tests/ui/contract/fail/impl-block-namespace-missing-argument.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr b/crates/lang/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr rename to crates/lang/tests/ui/contract/fail/impl-block-namespace-missing-argument.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.rs b/crates/lang/tests/ui/contract/fail/impl-block-using-env-no-marker.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.rs rename to crates/lang/tests/ui/contract/fail/impl-block-using-env-no-marker.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr b/crates/lang/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr rename to crates/lang/tests/ui/contract/fail/impl-block-using-env-no-marker.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs b/crates/lang/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs rename to crates/lang/tests/ui/contract/fail/impl-block-using-static-env-no-marker.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr b/crates/lang/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr rename to crates/lang/tests/ui/contract/fail/impl-block-using-static-env-no-marker.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.rs b/crates/lang/tests/ui/contract/fail/message-input-non-codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.rs rename to crates/lang/tests/ui/contract/fail/message-input-non-codec.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-input-non-codec.stderr rename to crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.rs b/crates/lang/tests/ui/contract/fail/message-input-pattern.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-input-pattern.rs rename to crates/lang/tests/ui/contract/fail/message-input-pattern.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr b/crates/lang/tests/ui/contract/fail/message-input-pattern.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-input-pattern.stderr rename to crates/lang/tests/ui/contract/fail/message-input-pattern.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.rs b/crates/lang/tests/ui/contract/fail/message-returns-non-codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.rs rename to crates/lang/tests/ui/contract/fail/message-returns-non-codec.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/lang/tests/ui/contract/fail/message-returns-non-codec.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-returns-non-codec.stderr rename to crates/lang/tests/ui/contract/fail/message-returns-non-codec.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-self.rs b/crates/lang/tests/ui/contract/fail/message-returns-self.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-returns-self.rs rename to crates/lang/tests/ui/contract/fail/message-returns-self.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr b/crates/lang/tests/ui/contract/fail/message-returns-self.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-returns-self.stderr rename to crates/lang/tests/ui/contract/fail/message-returns-self.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.rs b/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-01.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.rs rename to crates/lang/tests/ui/contract/fail/message-selector-invalid-type-01.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr b/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-01.stderr rename to crates/lang/tests/ui/contract/fail/message-selector-invalid-type-01.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.rs b/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.rs rename to crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr b/crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-selector-invalid-type-02.stderr rename to crates/lang/tests/ui/contract/fail/message-selector-invalid-type-02.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.rs b/crates/lang/tests/ui/contract/fail/message-selector-missing-arg.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.rs rename to crates/lang/tests/ui/contract/fail/message-selector-missing-arg.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr b/crates/lang/tests/ui/contract/fail/message-selector-missing-arg.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-selector-missing-arg.stderr rename to crates/lang/tests/ui/contract/fail/message-selector-missing-arg.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.rs b/crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-01.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.rs rename to crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-01.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr b/crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr rename to crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-01.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.rs b/crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-02.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.rs rename to crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-02.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr b/crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr rename to crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-02.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.rs b/crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-03.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.rs rename to crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-03.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr b/crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr rename to crates/lang/tests/ui/contract/fail/message-self-receiver-invalid-03.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.rs b/crates/lang/tests/ui/contract/fail/message-self-receiver-missing.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.rs rename to crates/lang/tests/ui/contract/fail/message-self-receiver-missing.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr b/crates/lang/tests/ui/contract/fail/message-self-receiver-missing.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-self-receiver-missing.stderr rename to crates/lang/tests/ui/contract/fail/message-self-receiver-missing.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.rs b/crates/lang/tests/ui/contract/fail/message-unknown-property.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-unknown-property.rs rename to crates/lang/tests/ui/contract/fail/message-unknown-property.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr b/crates/lang/tests/ui/contract/fail/message-unknown-property.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/message-unknown-property.stderr rename to crates/lang/tests/ui/contract/fail/message-unknown-property.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.rs b/crates/lang/tests/ui/contract/fail/module-missing-constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.rs rename to crates/lang/tests/ui/contract/fail/module-missing-constructor.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr b/crates/lang/tests/ui/contract/fail/module-missing-constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-missing-constructor.stderr rename to crates/lang/tests/ui/contract/fail/module-missing-constructor.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-message.rs b/crates/lang/tests/ui/contract/fail/module-missing-message.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-missing-message.rs rename to crates/lang/tests/ui/contract/fail/module-missing-message.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr b/crates/lang/tests/ui/contract/fail/module-missing-message.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-missing-message.stderr rename to crates/lang/tests/ui/contract/fail/module-missing-message.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.rs b/crates/lang/tests/ui/contract/fail/module-missing-storage.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-missing-storage.rs rename to crates/lang/tests/ui/contract/fail/module-missing-storage.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr b/crates/lang/tests/ui/contract/fail/module-missing-storage.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-missing-storage.stderr rename to crates/lang/tests/ui/contract/fail/module-missing-storage.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.rs b/crates/lang/tests/ui/contract/fail/module-multiple-storages.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.rs rename to crates/lang/tests/ui/contract/fail/module-multiple-storages.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr b/crates/lang/tests/ui/contract/fail/module-multiple-storages.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-multiple-storages.stderr rename to crates/lang/tests/ui/contract/fail/module-multiple-storages.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.rs b/crates/lang/tests/ui/contract/fail/module-use-forbidden-idents.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.rs rename to crates/lang/tests/ui/contract/fail/module-use-forbidden-idents.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr b/crates/lang/tests/ui/contract/fail/module-use-forbidden-idents.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/module-use-forbidden-idents.stderr rename to crates/lang/tests/ui/contract/fail/module-use-forbidden-idents.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.rs b/crates/lang/tests/ui/contract/fail/storage-conflicting-event.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.rs rename to crates/lang/tests/ui/contract/fail/storage-conflicting-event.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr b/crates/lang/tests/ui/contract/fail/storage-conflicting-event.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/storage-conflicting-event.stderr rename to crates/lang/tests/ui/contract/fail/storage-conflicting-event.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.rs b/crates/lang/tests/ui/contract/fail/storage-unknown-marker.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.rs rename to crates/lang/tests/ui/contract/fail/storage-unknown-marker.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr b/crates/lang/tests/ui/contract/fail/storage-unknown-marker.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/storage-unknown-marker.stderr rename to crates/lang/tests/ui/contract/fail/storage-unknown-marker.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.rs b/crates/lang/tests/ui/contract/fail/trait-impl-namespace-invalid.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.rs rename to crates/lang/tests/ui/contract/fail/trait-impl-namespace-invalid.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr b/crates/lang/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr rename to crates/lang/tests/ui/contract/fail/trait-impl-namespace-invalid.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.rs b/crates/lang/tests/ui/contract/fail/trait-message-payable-mismatch.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.rs rename to crates/lang/tests/ui/contract/fail/trait-message-payable-mismatch.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr b/crates/lang/tests/ui/contract/fail/trait-message-payable-mismatch.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-payable-mismatch.stderr rename to crates/lang/tests/ui/contract/fail/trait-message-payable-mismatch.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.rs b/crates/lang/tests/ui/contract/fail/trait-message-selector-mismatch.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.rs rename to crates/lang/tests/ui/contract/fail/trait-message-selector-mismatch.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr b/crates/lang/tests/ui/contract/fail/trait-message-selector-mismatch.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-mismatch.stderr rename to crates/lang/tests/ui/contract/fail/trait-message-selector-mismatch.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs b/crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-1.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.rs rename to crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-1.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr b/crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr rename to crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-1.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs b/crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-2.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.rs rename to crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-2.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr b/crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr rename to crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-2.stderr diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.rs b/crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-3.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.rs rename to crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-3.rs diff --git a/crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr b/crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr similarity index 100% rename from crates/lang/macro/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr rename to crates/lang/tests/ui/contract/fail/trait-message-selector-overlap-3.stderr diff --git a/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-false.rs b/crates/lang/tests/ui/contract/pass/config-compile-as-dependency-false.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-false.rs rename to crates/lang/tests/ui/contract/pass/config-compile-as-dependency-false.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-true.rs b/crates/lang/tests/ui/contract/pass/config-compile-as-dependency-true.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/config-compile-as-dependency-true.rs rename to crates/lang/tests/ui/contract/pass/config-compile-as-dependency-true.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/config-custom-env.rs b/crates/lang/tests/ui/contract/pass/config-custom-env.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/config-custom-env.rs rename to crates/lang/tests/ui/contract/pass/config-custom-env.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs b/crates/lang/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs rename to crates/lang/tests/ui/contract/pass/config-dynamic-storage-allocator-false.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs b/crates/lang/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs rename to crates/lang/tests/ui/contract/pass/config-dynamic-storage-allocator-true.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/constructor-many-inputs.rs b/crates/lang/tests/ui/contract/pass/constructor-many-inputs.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/constructor-many-inputs.rs rename to crates/lang/tests/ui/contract/pass/constructor-many-inputs.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs b/crates/lang/tests/ui/contract/pass/constructor-selector.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/constructor-selector.rs rename to crates/lang/tests/ui/contract/pass/constructor-selector.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs b/crates/lang/tests/ui/contract/pass/dispatch-decoder-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/dispatch-decoder-works.rs rename to crates/lang/tests/ui/contract/pass/dispatch-decoder-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/env-access.rs b/crates/lang/tests/ui/contract/pass/env-access.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/env-access.rs rename to crates/lang/tests/ui/contract/pass/env-access.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/event-anonymous.rs b/crates/lang/tests/ui/contract/pass/event-anonymous.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/event-anonymous.rs rename to crates/lang/tests/ui/contract/pass/event-anonymous.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/event-config-more-topics.rs b/crates/lang/tests/ui/contract/pass/event-config-more-topics.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/event-config-more-topics.rs rename to crates/lang/tests/ui/contract/pass/event-config-more-topics.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/event-many-definitions.rs b/crates/lang/tests/ui/contract/pass/event-many-definitions.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/event-many-definitions.rs rename to crates/lang/tests/ui/contract/pass/event-many-definitions.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/event-single-definition.rs b/crates/lang/tests/ui/contract/pass/event-single-definition.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/event-single-definition.rs rename to crates/lang/tests/ui/contract/pass/event-single-definition.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/event-topics.rs b/crates/lang/tests/ui/contract/pass/event-topics.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/event-topics.rs rename to crates/lang/tests/ui/contract/pass/event-topics.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs b/crates/lang/tests/ui/contract/pass/example-erc20-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/example-erc20-works.rs rename to crates/lang/tests/ui/contract/pass/example-erc20-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/example-erc721-works.rs b/crates/lang/tests/ui/contract/pass/example-erc721-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/example-erc721-works.rs rename to crates/lang/tests/ui/contract/pass/example-erc721-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/example-flipper-works.rs b/crates/lang/tests/ui/contract/pass/example-flipper-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/example-flipper-works.rs rename to crates/lang/tests/ui/contract/pass/example-flipper-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs b/crates/lang/tests/ui/contract/pass/example-incrementer-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/example-incrementer-works.rs rename to crates/lang/tests/ui/contract/pass/example-incrementer-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/example-trait-flipper-works.rs b/crates/lang/tests/ui/contract/pass/example-trait-flipper-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/example-trait-flipper-works.rs rename to crates/lang/tests/ui/contract/pass/example-trait-flipper-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs b/crates/lang/tests/ui/contract/pass/example-trait-incrementer-works.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/example-trait-incrementer-works.rs rename to crates/lang/tests/ui/contract/pass/example-trait-incrementer-works.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-alias-storage.rs b/crates/lang/tests/ui/contract/pass/impl-alias-storage.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/impl-alias-storage.rs rename to crates/lang/tests/ui/contract/pass/impl-alias-storage.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-block-namespace.rs b/crates/lang/tests/ui/contract/pass/impl-block-namespace.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/impl-block-namespace.rs rename to crates/lang/tests/ui/contract/pass/impl-block-namespace.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-block-using-env.rs b/crates/lang/tests/ui/contract/pass/impl-block-using-env.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/impl-block-using-env.rs rename to crates/lang/tests/ui/contract/pass/impl-block-using-env.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/impl-with-property.rs b/crates/lang/tests/ui/contract/pass/impl-with-property.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/impl-with-property.rs rename to crates/lang/tests/ui/contract/pass/impl-with-property.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/message-many-inputs.rs b/crates/lang/tests/ui/contract/pass/message-many-inputs.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/message-many-inputs.rs rename to crates/lang/tests/ui/contract/pass/message-many-inputs.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/message-many-outputs.rs b/crates/lang/tests/ui/contract/pass/message-many-outputs.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/message-many-outputs.rs rename to crates/lang/tests/ui/contract/pass/message-many-outputs.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/message-payable.rs b/crates/lang/tests/ui/contract/pass/message-payable.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/message-payable.rs rename to crates/lang/tests/ui/contract/pass/message-payable.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/message-selector.rs b/crates/lang/tests/ui/contract/pass/message-selector.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/message-selector.rs rename to crates/lang/tests/ui/contract/pass/message-selector.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs b/crates/lang/tests/ui/contract/pass/minimal-contract.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/minimal-contract.rs rename to crates/lang/tests/ui/contract/pass/minimal-contract.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/module-env-types.rs b/crates/lang/tests/ui/contract/pass/module-env-types.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/module-env-types.rs rename to crates/lang/tests/ui/contract/pass/module-env-types.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/module-non-ink-items.rs b/crates/lang/tests/ui/contract/pass/module-non-ink-items.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/module-non-ink-items.rs rename to crates/lang/tests/ui/contract/pass/module-non-ink-items.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs b/crates/lang/tests/ui/contract/pass/no-implicit-prelude.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/no-implicit-prelude.rs rename to crates/lang/tests/ui/contract/pass/no-implicit-prelude.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-many-fields.rs b/crates/lang/tests/ui/contract/pass/storage-many-fields.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/storage-many-fields.rs rename to crates/lang/tests/ui/contract/pass/storage-many-fields.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-packed-fields.rs b/crates/lang/tests/ui/contract/pass/storage-packed-fields.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/storage-packed-fields.rs rename to crates/lang/tests/ui/contract/pass/storage-packed-fields.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-single-field.rs b/crates/lang/tests/ui/contract/pass/storage-single-field.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/storage-single-field.rs rename to crates/lang/tests/ui/contract/pass/storage-single-field.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/storage-with-derives.rs b/crates/lang/tests/ui/contract/pass/storage-with-derives.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/storage-with-derives.rs rename to crates/lang/tests/ui/contract/pass/storage-with-derives.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/trait-message-payable-guard.rs b/crates/lang/tests/ui/contract/pass/trait-message-payable-guard.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/trait-message-payable-guard.rs rename to crates/lang/tests/ui/contract/pass/trait-message-payable-guard.rs diff --git a/crates/lang/macro/tests/ui/contract/pass/trait-message-selector-guard.rs b/crates/lang/tests/ui/contract/pass/trait-message-selector-guard.rs similarity index 100% rename from crates/lang/macro/tests/ui/contract/pass/trait-message-selector-guard.rs rename to crates/lang/tests/ui/contract/pass/trait-message-selector-guard.rs diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.rs b/crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_01.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.rs rename to crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_01.rs diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr b/crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr rename to crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_01.stderr diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.rs b/crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_02.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.rs rename to crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_02.rs diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr b/crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr rename to crates/lang/tests/ui/selector_bytes/fail/invalid_parameter_type_02.stderr diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.rs b/crates/lang/tests/ui/selector_bytes/fail/missing_parameter.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.rs rename to crates/lang/tests/ui/selector_bytes/fail/missing_parameter.rs diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.stderr b/crates/lang/tests/ui/selector_bytes/fail/missing_parameter.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/missing_parameter.stderr rename to crates/lang/tests/ui/selector_bytes/fail/missing_parameter.stderr diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.rs b/crates/lang/tests/ui/selector_bytes/fail/non_literal_parameter.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.rs rename to crates/lang/tests/ui/selector_bytes/fail/non_literal_parameter.rs diff --git a/crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.stderr b/crates/lang/tests/ui/selector_bytes/fail/non_literal_parameter.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/fail/non_literal_parameter.stderr rename to crates/lang/tests/ui/selector_bytes/fail/non_literal_parameter.stderr diff --git a/crates/lang/macro/tests/ui/selector_bytes/pass/bytestring_input.rs b/crates/lang/tests/ui/selector_bytes/pass/bytestring_input.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/pass/bytestring_input.rs rename to crates/lang/tests/ui/selector_bytes/pass/bytestring_input.rs diff --git a/crates/lang/macro/tests/ui/selector_bytes/pass/no_implicit_prelude.rs b/crates/lang/tests/ui/selector_bytes/pass/no_implicit_prelude.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/pass/no_implicit_prelude.rs rename to crates/lang/tests/ui/selector_bytes/pass/no_implicit_prelude.rs diff --git a/crates/lang/macro/tests/ui/selector_bytes/pass/string_input.rs b/crates/lang/tests/ui/selector_bytes/pass/string_input.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_bytes/pass/string_input.rs rename to crates/lang/tests/ui/selector_bytes/pass/string_input.rs diff --git a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.rs b/crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_01.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.rs rename to crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_01.rs diff --git a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr b/crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr rename to crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_01.stderr diff --git a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.rs b/crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_02.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.rs rename to crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_02.rs diff --git a/crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr b/crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr rename to crates/lang/tests/ui/selector_id/fail/invalid_parameter_type_02.stderr diff --git a/crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.rs b/crates/lang/tests/ui/selector_id/fail/missing_parameter.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.rs rename to crates/lang/tests/ui/selector_id/fail/missing_parameter.rs diff --git a/crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.stderr b/crates/lang/tests/ui/selector_id/fail/missing_parameter.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/missing_parameter.stderr rename to crates/lang/tests/ui/selector_id/fail/missing_parameter.stderr diff --git a/crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.rs b/crates/lang/tests/ui/selector_id/fail/non_literal_parameter.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.rs rename to crates/lang/tests/ui/selector_id/fail/non_literal_parameter.rs diff --git a/crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.stderr b/crates/lang/tests/ui/selector_id/fail/non_literal_parameter.stderr similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/fail/non_literal_parameter.stderr rename to crates/lang/tests/ui/selector_id/fail/non_literal_parameter.stderr diff --git a/crates/lang/macro/tests/ui/selector_id/pass/bytestring_input.rs b/crates/lang/tests/ui/selector_id/pass/bytestring_input.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/pass/bytestring_input.rs rename to crates/lang/tests/ui/selector_id/pass/bytestring_input.rs diff --git a/crates/lang/macro/tests/ui/selector_id/pass/no_implicit_prelude.rs b/crates/lang/tests/ui/selector_id/pass/no_implicit_prelude.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/pass/no_implicit_prelude.rs rename to crates/lang/tests/ui/selector_id/pass/no_implicit_prelude.rs diff --git a/crates/lang/macro/tests/ui/selector_id/pass/string_input.rs b/crates/lang/tests/ui/selector_id/pass/string_input.rs similarity index 100% rename from crates/lang/macro/tests/ui/selector_id/pass/string_input.rs rename to crates/lang/tests/ui/selector_id/pass/string_input.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.rs rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_1.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.rs rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_2.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_3.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.rs rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_3.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_3.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_4.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.rs rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_4.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr b/crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr rename to crates/lang/tests/ui/trait_def/fail/config_namespace_invalid_4.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs b/crates/lang/tests/ui/trait_def/fail/definition_assoc_const.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.rs rename to crates/lang/tests/ui/trait_def/fail/definition_assoc_const.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr b/crates/lang/tests/ui/trait_def/fail/definition_assoc_const.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_const.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_assoc_const.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs b/crates/lang/tests/ui/trait_def/fail/definition_assoc_type.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.rs rename to crates/lang/tests/ui/trait_def/fail/definition_assoc_type.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr b/crates/lang/tests/ui/trait_def/fail/definition_assoc_type.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_assoc_type.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_assoc_type.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs b/crates/lang/tests/ui/trait_def/fail/definition_constructor.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.rs rename to crates/lang/tests/ui/trait_def/fail/definition_constructor.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr b/crates/lang/tests/ui/trait_def/fail/definition_constructor.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_constructor.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_constructor.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs b/crates/lang/tests/ui/trait_def/fail/definition_empty.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_empty.rs rename to crates/lang/tests/ui/trait_def/fail/definition_empty.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr b/crates/lang/tests/ui/trait_def/fail/definition_empty.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_empty.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_empty.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.rs b/crates/lang/tests/ui/trait_def/fail/definition_generic.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_generic.rs rename to crates/lang/tests/ui/trait_def/fail/definition_generic.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr b/crates/lang/tests/ui/trait_def/fail/definition_generic.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_generic.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_generic.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.rs b/crates/lang/tests/ui/trait_def/fail/definition_non_pub.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.rs rename to crates/lang/tests/ui/trait_def/fail/definition_non_pub.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr b/crates/lang/tests/ui/trait_def/fail/definition_non_pub.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_non_pub.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_non_pub.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.rs b/crates/lang/tests/ui/trait_def/fail/definition_rust_method.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.rs rename to crates/lang/tests/ui/trait_def/fail/definition_rust_method.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr b/crates/lang/tests/ui/trait_def/fail/definition_rust_method.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_rust_method.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_rust_method.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs b/crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs rename to crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr b/crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_1.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs b/crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs rename to crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr b/crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_super_trait_invalid_2.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.rs b/crates/lang/tests/ui/trait_def/fail/definition_unsafe.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.rs rename to crates/lang/tests/ui/trait_def/fail/definition_unsafe.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr b/crates/lang/tests/ui/trait_def/fail/definition_unsafe.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/definition_unsafe.stderr rename to crates/lang/tests/ui/trait_def/fail/definition_unsafe.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs b/crates/lang/tests/ui/trait_def/fail/message_abi_invalid.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.rs rename to crates/lang/tests/ui/trait_def/fail/message_abi_invalid.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr b/crates/lang/tests/ui/trait_def/fail/message_abi_invalid.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_abi_invalid.stderr rename to crates/lang/tests/ui/trait_def/fail/message_abi_invalid.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.rs b/crates/lang/tests/ui/trait_def/fail/message_async_invalid.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.rs rename to crates/lang/tests/ui/trait_def/fail/message_async_invalid.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr b/crates/lang/tests/ui/trait_def/fail/message_async_invalid.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_async_invalid.stderr rename to crates/lang/tests/ui/trait_def/fail/message_async_invalid.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.rs b/crates/lang/tests/ui/trait_def/fail/message_const_invalid.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.rs rename to crates/lang/tests/ui/trait_def/fail/message_const_invalid.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr b/crates/lang/tests/ui/trait_def/fail/message_const_invalid.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_const_invalid.stderr rename to crates/lang/tests/ui/trait_def/fail/message_const_invalid.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.rs b/crates/lang/tests/ui/trait_def/fail/message_constructor_conflict.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.rs rename to crates/lang/tests/ui/trait_def/fail/message_constructor_conflict.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr b/crates/lang/tests/ui/trait_def/fail/message_constructor_conflict.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_constructor_conflict.stderr rename to crates/lang/tests/ui/trait_def/fail/message_constructor_conflict.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.rs b/crates/lang/tests/ui/trait_def/fail/message_default_impl.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.rs rename to crates/lang/tests/ui/trait_def/fail/message_default_impl.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr b/crates/lang/tests/ui/trait_def/fail/message_default_impl.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_default_impl.stderr rename to crates/lang/tests/ui/trait_def/fail/message_default_impl.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.rs b/crates/lang/tests/ui/trait_def/fail/message_generic_invalid.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.rs rename to crates/lang/tests/ui/trait_def/fail/message_generic_invalid.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr b/crates/lang/tests/ui/trait_def/fail/message_generic_invalid.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_generic_invalid.stderr rename to crates/lang/tests/ui/trait_def/fail/message_generic_invalid.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.rs b/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.rs rename to crates/lang/tests/ui/trait_def/fail/message_input_non_codec.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_input_non_codec.stderr rename to crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.rs b/crates/lang/tests/ui/trait_def/fail/message_input_pattern_invalid.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.rs rename to crates/lang/tests/ui/trait_def/fail/message_input_pattern_invalid.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr b/crates/lang/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr rename to crates/lang/tests/ui/trait_def/fail/message_input_pattern_invalid.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.rs b/crates/lang/tests/ui/trait_def/fail/message_output_non_codec.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.rs rename to crates/lang/tests/ui/trait_def/fail/message_output_non_codec.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/lang/tests/ui/trait_def/fail/message_output_non_codec.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_output_non_codec.stderr rename to crates/lang/tests/ui/trait_def/fail/message_output_non_codec.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs b/crates/lang/tests/ui/trait_def/fail/message_payable_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.rs rename to crates/lang/tests/ui/trait_def/fail/message_payable_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr b/crates/lang/tests/ui/trait_def/fail/message_payable_invalid_1.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_1.stderr rename to crates/lang/tests/ui/trait_def/fail/message_payable_invalid_1.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs b/crates/lang/tests/ui/trait_def/fail/message_payable_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.rs rename to crates/lang/tests/ui/trait_def/fail/message_payable_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr b/crates/lang/tests/ui/trait_def/fail/message_payable_invalid_2.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_payable_invalid_2.stderr rename to crates/lang/tests/ui/trait_def/fail/message_payable_invalid_2.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.rs b/crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.rs rename to crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr b/crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr rename to crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_1.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.rs b/crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.rs rename to crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr b/crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr rename to crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_2.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.rs b/crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_3.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.rs rename to crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_3.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr b/crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr rename to crates/lang/tests/ui/trait_def/fail/message_receiver_invalid_3.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.rs b/crates/lang/tests/ui/trait_def/fail/message_receiver_missing.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.rs rename to crates/lang/tests/ui/trait_def/fail/message_receiver_missing.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr b/crates/lang/tests/ui/trait_def/fail/message_receiver_missing.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_receiver_missing.stderr rename to crates/lang/tests/ui/trait_def/fail/message_receiver_missing.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs b/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.rs rename to crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr b/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_1.stderr rename to crates/lang/tests/ui/trait_def/fail/message_selector_invalid_1.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs b/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_2.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.rs rename to crates/lang/tests/ui/trait_def/fail/message_selector_invalid_2.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr b/crates/lang/tests/ui/trait_def/fail/message_selector_invalid_2.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_selector_invalid_2.stderr rename to crates/lang/tests/ui/trait_def/fail/message_selector_invalid_2.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs b/crates/lang/tests/ui/trait_def/fail/message_selector_overlap.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.rs rename to crates/lang/tests/ui/trait_def/fail/message_selector_overlap.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr b/crates/lang/tests/ui/trait_def/fail/message_selector_overlap.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_selector_overlap.stderr rename to crates/lang/tests/ui/trait_def/fail/message_selector_overlap.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.rs b/crates/lang/tests/ui/trait_def/fail/message_unsafe_invalid.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.rs rename to crates/lang/tests/ui/trait_def/fail/message_unsafe_invalid.rs diff --git a/crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr b/crates/lang/tests/ui/trait_def/fail/message_unsafe_invalid.stderr similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/fail/message_unsafe_invalid.stderr rename to crates/lang/tests/ui/trait_def/fail/message_unsafe_invalid.stderr diff --git a/crates/lang/macro/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs b/crates/lang/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs rename to crates/lang/tests/ui/trait_def/pass/avoid_overlap_with_namespace.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/many_inputs.rs b/crates/lang/tests/ui/trait_def/pass/many_inputs.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/many_inputs.rs rename to crates/lang/tests/ui/trait_def/pass/many_inputs.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/many_outputs.rs b/crates/lang/tests/ui/trait_def/pass/many_outputs.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/many_outputs.rs rename to crates/lang/tests/ui/trait_def/pass/many_outputs.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/no-implicit-prelude.rs b/crates/lang/tests/ui/trait_def/pass/no-implicit-prelude.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/no-implicit-prelude.rs rename to crates/lang/tests/ui/trait_def/pass/no-implicit-prelude.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs b/crates/lang/tests/ui/trait_def/pass/payable_message.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/payable_message.rs rename to crates/lang/tests/ui/trait_def/pass/payable_message.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs b/crates/lang/tests/ui/trait_def/pass/simple_definition.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/simple_definition.rs rename to crates/lang/tests/ui/trait_def/pass/simple_definition.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/using-env-types.rs b/crates/lang/tests/ui/trait_def/pass/using-env-types.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/using-env-types.rs rename to crates/lang/tests/ui/trait_def/pass/using-env-types.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors.rs b/crates/lang/tests/ui/trait_def/pass/valid_selectors.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/valid_selectors.rs rename to crates/lang/tests/ui/trait_def/pass/valid_selectors.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/valid_selectors_namespace.rs b/crates/lang/tests/ui/trait_def/pass/valid_selectors_namespace.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/valid_selectors_namespace.rs rename to crates/lang/tests/ui/trait_def/pass/valid_selectors_namespace.rs diff --git a/crates/lang/macro/tests/ui/trait_def/pass/with_namespace.rs b/crates/lang/tests/ui/trait_def/pass/with_namespace.rs similarity index 100% rename from crates/lang/macro/tests/ui/trait_def/pass/with_namespace.rs rename to crates/lang/tests/ui/trait_def/pass/with_namespace.rs diff --git a/crates/lang/macro/tests/unique_topics.rs b/crates/lang/tests/unique_topics.rs similarity index 100% rename from crates/lang/macro/tests/unique_topics.rs rename to crates/lang/tests/unique_topics.rs From 551da209a220223b77fb3cf75f71b35b138fbd3f Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 12:08:55 +0200 Subject: [PATCH 473/493] adjust UI tests after moving --- .../ui/contract/fail/constructor-input-non-codec.stderr | 4 ++-- .../contract/fail/event-too-many-topics-anonymous.stderr | 4 ++-- .../tests/ui/contract/fail/event-too-many-topics.stderr | 4 ++-- .../tests/ui/contract/fail/message-input-non-codec.stderr | 4 ++-- .../ui/contract/fail/message-returns-non-codec.stderr | 8 ++++---- .../ui/trait_def/fail/message_input_non_codec.stderr | 4 ++-- .../ui/trait_def/fail/message_output_non_codec.stderr | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr index 4e16403b25..c1709b1ce3 100644 --- a/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr +++ b/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs + --> src/codegen/dispatch/type_check.rs:41:8 | - | T: scale::Decode + 'static; +41 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied diff --git a/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr index a6ab00f062..026ef1c4dd 100644 --- a/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr +++ b/crates/lang/tests/ui/contract/fail/event-too-many-topics-anonymous.stderr @@ -17,7 +17,7 @@ error[E0277]: the trait bound `EventTopics<4_usize>: RespectTopicLimit<2_usize>` as RespectTopicLimit<12_usize>> and 87 others note: required by a bound in `EventRespectsTopicLimit` - --> $WORKSPACE/crates/lang/src/codegen/event/topics.rs + --> src/codegen/event/topics.rs:48:43 | - | ::LenTopics: RespectTopicLimit, +48 | ::LenTopics: RespectTopicLimit, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr b/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr index f047abb61b..4ae2bbb32c 100644 --- a/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr +++ b/crates/lang/tests/ui/contract/fail/event-too-many-topics.stderr @@ -17,7 +17,7 @@ error[E0277]: the trait bound `EventTopics<3_usize>: RespectTopicLimit<2_usize>` as RespectTopicLimit<12_usize>> and 87 others note: required by a bound in `EventRespectsTopicLimit` - --> $WORKSPACE/crates/lang/src/codegen/event/topics.rs + --> src/codegen/event/topics.rs:48:43 | - | ::LenTopics: RespectTopicLimit, +48 | ::LenTopics: RespectTopicLimit, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EventRespectsTopicLimit` diff --git a/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr index c4e6b6f323..78445e6995 100644 --- a/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr +++ b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` note: required by a bound in `DispatchInput` - --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs + --> src/codegen/dispatch/type_check.rs:41:8 | - | T: scale::Decode + 'static; +41 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied diff --git a/crates/lang/tests/ui/contract/fail/message-returns-non-codec.stderr b/crates/lang/tests/ui/contract/fail/message-returns-non-codec.stderr index 032c7c9bc5..2dbf27249a 100644 --- a/crates/lang/tests/ui/contract/fail/message-returns-non-codec.stderr +++ b/crates/lang/tests/ui/contract/fail/message-returns-non-codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `DispatchOutput` - --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs + --> src/codegen/dispatch/type_check.rs:69:8 | - | T: scale::Encode + 'static; +69 | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied @@ -21,9 +21,9 @@ error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodecType` note: required by a bound in `execute_message` - --> $WORKSPACE/crates/lang/src/codegen/dispatch/execution.rs + --> src/codegen/dispatch/execution.rs:139:13 | - | Output: scale::Encode + 'static, +139 | Output: scale::Encode + 'static, | ^^^^^^^^^^^^^ required by this bound in `execute_message` error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set>>, Set>>`, but its trait bounds were not satisfied diff --git a/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr b/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr index 34a8d561e0..9cf33c6922 100644 --- a/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr +++ b/crates/lang/tests/ui/trait_def/fail/message_input_non_codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeDecode` is not satisfied | = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodec` note: required by a bound in `DispatchInput` - --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs + --> src/codegen/dispatch/type_check.rs:41:8 | - | T: scale::Decode + 'static; +41 | T: scale::Decode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied diff --git a/crates/lang/tests/ui/trait_def/fail/message_output_non_codec.stderr b/crates/lang/tests/ui/trait_def/fail/message_output_non_codec.stderr index 498ba518fa..ffdb0343f2 100644 --- a/crates/lang/tests/ui/trait_def/fail/message_output_non_codec.stderr +++ b/crates/lang/tests/ui/trait_def/fail/message_output_non_codec.stderr @@ -6,9 +6,9 @@ error[E0277]: the trait bound `NonCodec: WrapperTypeEncode` is not satisfied | = note: required because of the requirements on the impl of `Encode` for `NonCodec` note: required by a bound in `DispatchOutput` - --> $WORKSPACE/crates/lang/src/codegen/dispatch/type_check.rs + --> src/codegen/dispatch/type_check.rs:69:8 | - | T: scale::Encode + 'static; +69 | T: scale::Encode + 'static; | ^^^^^^^^^^^^^ required by this bound in `DispatchOutput` error[E0599]: the method `fire` exists for struct `CallBuilder::AccountId>, Unset, Unset<::Balance>, Set>>, Set>>`, but its trait bounds were not satisfied From 14c11fb3468c65a66e506e3b90104755f899022e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 12:09:17 +0200 Subject: [PATCH 474/493] remove unused dev-dependencies from ink_lang_macro after moving UI tests --- crates/lang/macro/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index b00bdb77ad..2b90cbeafe 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -28,9 +28,6 @@ ink_metadata = { version = "3.0.0-rc5", path = "../../metadata/" } ink_env = { version = "3.0.0-rc5", path = "../../env/" } ink_storage = { version = "3.0.0-rc5", path = "../../storage/" } ink_lang = { version = "3.0.0-rc5", path = ".." } -ink_prelude = { version = "3.0.0-rc5", path = "../../prelude/" } - -trybuild = { version = "1.0.49", features = ["diff"] } scale-info = { version = "0.6", default-features = false, features = ["derive"] } [lib] From 1ca57ae35dddc7195c84ab7bd154cea3d536d1ef Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 12:22:52 +0200 Subject: [PATCH 475/493] fix compilation error with Wasm target --- crates/lang/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index 364d6161fb..251add7a4d 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -27,7 +27,7 @@ derive_more = { version = "0.99", default-features = false, features = ["from"] [dev-dependencies] ink_lang_ir = { version = "3.0.0-rc5", path = "ir" } -ink_metadata = { version = "3.0.0-rc5", path = "../metadata" } +ink_metadata = { version = "3.0.0-rc5", default-features = false, path = "../metadata" } trybuild = { version = "1.0.49", features = ["diff"] } # Required for the doctest of `env_access::EnvAccess::instantiate_contract` From 4a92351b06406305815c4800fc49bdca046142d5 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 12:49:56 +0200 Subject: [PATCH 476/493] fix CI with formatting checks for UI tests --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 322cf708d3..0c25bb0030 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -289,8 +289,8 @@ fmt: script: - cargo fmt --verbose --all -- --check # For the UI tests we need to disable the license check - - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/macro/tests/ui/contract/{pass,fail}/*.rs - - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/macro/tests/ui/trait_def/{pass,fail}/*.rs + - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/tests/ui/contract/{pass,fail}/*.rs + - cargo fmt --verbose --all -- --check --config=license_template_path="" crates/lang/tests/ui/trait_def/{pass,fail}/*.rs #### stage: examples From ebd2be387b45ed91adbbe0b85fc526ef3c16fb84 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 12:50:44 +0200 Subject: [PATCH 477/493] add unpayable to hunspell dictionary --- .config/cargo_spellcheck.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/cargo_spellcheck.dic b/.config/cargo_spellcheck.dic index d08d2fd453..11f19a0cc7 100644 --- a/.config/cargo_spellcheck.dic +++ b/.config/cargo_spellcheck.dic @@ -96,3 +96,4 @@ implementer/S deduplicated wildcard/S payability +unpayable From f92ab20987d917a4aea1550130c594ac6a417b5b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 13:07:26 +0200 Subject: [PATCH 478/493] fix hunspell spelling issues --- crates/lang/ir/src/ir/trait_def/config.rs | 2 +- crates/lang/ir/src/ir/trait_def/item/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/ir/src/ir/trait_def/config.rs b/crates/lang/ir/src/ir/trait_def/config.rs index 8f564a0e90..5cd790e8ba 100644 --- a/crates/lang/ir/src/ir/trait_def/config.rs +++ b/crates/lang/ir/src/ir/trait_def/config.rs @@ -102,7 +102,7 @@ impl TryFrom for TraitDefinitionConfig { } impl TraitDefinitionConfig { - /// Returns the namespace config argument if any as string. + /// Returns the namespace configuration argument if any as string. pub fn namespace(&self) -> Option<&syn::LitStr> { self.namespace.as_ref() } diff --git a/crates/lang/ir/src/ir/trait_def/item/mod.rs b/crates/lang/ir/src/ir/trait_def/item/mod.rs index fe347ec640..69cb677a38 100644 --- a/crates/lang/ir/src/ir/trait_def/item/mod.rs +++ b/crates/lang/ir/src/ir/trait_def/item/mod.rs @@ -60,7 +60,7 @@ impl TryFrom for InkItemTrait { } impl InkItemTrait { - /// Creates a new ink! item trait from the given config and trait definition. + /// Creates a new ink! item trait from the given configuration and trait definition. pub fn new( config: &TraitDefinitionConfig, item_trait: syn::ItemTrait, From 36123df2f45c3f1ac7959ef0a72cdd8fbd526627 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Sat, 9 Oct 2021 14:01:20 +0200 Subject: [PATCH 479/493] move ink-experimental-engine to ink_lang crate Used by unique topics test. --- crates/lang/Cargo.toml | 7 +++++++ crates/lang/macro/Cargo.toml | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/lang/Cargo.toml b/crates/lang/Cargo.toml index 251add7a4d..b64e9fcfb1 100644 --- a/crates/lang/Cargo.toml +++ b/crates/lang/Cargo.toml @@ -46,3 +46,10 @@ std = [ "scale/std", ] show-codegen-docs = [] + +# Due to https://github.com/rust-lang/cargo/issues/6915 features that affect a dev-dependency +# currently can't be enabled by a parent crate, hence `["ink_env/ink-experimental-engine"]` does +# not work. +# After we switch to the new off-chain environment with https://github.com/paritytech/ink/issues/565 +# we can remove the feature altogether. +ink-experimental-engine = [] diff --git a/crates/lang/macro/Cargo.toml b/crates/lang/macro/Cargo.toml index 2b90cbeafe..a47de31db4 100644 --- a/crates/lang/macro/Cargo.toml +++ b/crates/lang/macro/Cargo.toml @@ -41,10 +41,3 @@ std = [ "ink_lang_ir/std", "ink_primitives/std", ] - -# Due to https://github.com/rust-lang/cargo/issues/6915 features that affect a dev-dependency -# currently can't be enabled by a parent crate, hence `["ink_env/ink-experimental-engine"]` does -# not work. -# After we switch to the new off-chain environment with https://github.com/paritytech/ink/issues/565 -# we can remove the feature altogether. -ink-experimental-engine = [] From 321aefe416e7ae2edc9514573e36302f7af7c22b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 11:55:28 +0200 Subject: [PATCH 480/493] update UI tests for new nightly compiler --- .../fail/constructor-input-non-codec.stderr | 41 --------------- .../fail/message-input-non-codec.stderr | 51 ------------------- 2 files changed, 92 deletions(-) delete mode 100644 crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr delete mode 100644 crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr diff --git a/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr deleted file mode 100644 index c1709b1ce3..0000000000 --- a/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr +++ /dev/null @@ -1,41 +0,0 @@ -error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> tests/ui/contract/fail/constructor-input-non-codec.rs:13:28 - | -13 | pub fn constructor(_input: NonCodecType) -> Self { - | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` - | - = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` -note: required by a bound in `DispatchInput` - --> src/codegen/dispatch/type_check.rs:41:8 - | -41 | T: scale::Decode + 'static; - | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` - -error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> tests/ui/contract/fail/constructor-input-non-codec.rs:13:9 - | -13 | / pub fn constructor(_input: NonCodecType) -> Self { -14 | | Self {} -15 | | } - | |_________^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` - | - = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` -note: required by a bound in `parity_scale_codec::Decode::decode` - --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs - | - | fn decode(input: &mut I) -> Result; - | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` - -error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> tests/ui/contract/fail/constructor-input-non-codec.rs:3:1 - | -3 | #[ink::contract] - | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` -... -13 | / pub fn constructor(_input: NonCodecType) -> Self { -14 | | Self {} -15 | | } - | |_________- required by a bound introduced by this call - | - = note: required because of the requirements on the impl of `Encode` for `NonCodecType` - = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr deleted file mode 100644 index 78445e6995..0000000000 --- a/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr +++ /dev/null @@ -1,51 +0,0 @@ -error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> tests/ui/contract/fail/message-input-non-codec.rs:18:31 - | -18 | pub fn message(&self, _input: NonCodecType) {} - | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` - | - = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` -note: required by a bound in `DispatchInput` - --> src/codegen/dispatch/type_check.rs:41:8 - | -41 | T: scale::Decode + 'static; - | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` - -error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied - --> tests/ui/contract/fail/message-input-non-codec.rs:18:9 - | -18 | pub fn message(&self, _input: NonCodecType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` - | - = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` -note: required by a bound in `parity_scale_codec::Decode::decode` - --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs - | - | fn decode(input: &mut I) -> Result; - | ^^^^^ required by this bound in `parity_scale_codec::Decode::decode` - -error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied - --> tests/ui/contract/fail/message-input-non-codec.rs:3:1 - | -3 | #[ink::contract] - | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` -... -18 | pub fn message(&self, _input: NonCodecType) {} - | ---------------------------------------------- required by a bound introduced by this call - | - = note: required because of the requirements on the impl of `Encode` for `NonCodecType` - = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied - --> tests/ui/contract/fail/message-input-non-codec.rs:18:9 - | -18 | pub fn message(&self, _input: NonCodecType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds - | - ::: $WORKSPACE/crates/env/src/call/execution_input.rs - | - | pub struct ArgumentList { - | ----------------------------------- doesn't satisfy `_: Encode` - | - = note: the following trait bounds were not satisfied: - `ArgumentList, ArgumentList>: Encode` From 3caa44bb0e297821b6f981eacada7e5e1de3a6bf Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 12:12:38 +0200 Subject: [PATCH 481/493] add missing fixed UI tests --- .../fail/constructor-input-non-codec.stderr | 41 +++++++++++++++ .../fail/message-input-non-codec.stderr | 51 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr create mode 100644 crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr diff --git a/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr new file mode 100644 index 0000000000..c5e6bacd40 --- /dev/null +++ b/crates/lang/tests/ui/contract/fail/constructor-input-non-codec.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> tests/ui/contract/fail/constructor-input-non-codec.rs:13:28 + | +13 | pub fn constructor(_input: NonCodecType) -> Self { + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `DispatchInput` + --> src/codegen/dispatch/type_check.rs:41:8 + | +41 | T: scale::Decode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> tests/ui/contract/fail/constructor-input-non-codec.rs:13:9 + | +13 | / pub fn constructor(_input: NonCodecType) -> Self { +14 | | Self {} +15 | | } + | |_________^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `parity_scale_codec::Decode::decode` + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs + | + | fn decode(input: &mut I) -> Result; + | ^ required by this bound in `parity_scale_codec::Decode::decode` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied + --> tests/ui/contract/fail/constructor-input-non-codec.rs:3:1 + | +3 | #[ink::contract] + | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` +... +13 | / pub fn constructor(_input: NonCodecType) -> Self { +14 | | Self {} +15 | | } + | |_________- required by a bound introduced by this call + | + = note: required because of the requirements on the impl of `Encode` for `NonCodecType` + = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr new file mode 100644 index 0000000000..9b470de454 --- /dev/null +++ b/crates/lang/tests/ui/contract/fail/message-input-non-codec.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> tests/ui/contract/fail/message-input-non-codec.rs:18:31 + | +18 | pub fn message(&self, _input: NonCodecType) {} + | ^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `DispatchInput` + --> src/codegen/dispatch/type_check.rs:41:8 + | +41 | T: scale::Decode + 'static; + | ^^^^^^^^^^^^^ required by this bound in `DispatchInput` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeDecode` is not satisfied + --> tests/ui/contract/fail/message-input-non-codec.rs:18:9 + | +18 | pub fn message(&self, _input: NonCodecType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `WrapperTypeDecode` is not implemented for `NonCodecType` + | + = note: required because of the requirements on the impl of `parity_scale_codec::Decode` for `NonCodecType` +note: required by a bound in `parity_scale_codec::Decode::decode` + --> $CARGO/parity-scale-codec-2.3.1/src/codec.rs + | + | fn decode(input: &mut I) -> Result; + | ^ required by this bound in `parity_scale_codec::Decode::decode` + +error[E0277]: the trait bound `NonCodecType: WrapperTypeEncode` is not satisfied + --> tests/ui/contract/fail/message-input-non-codec.rs:3:1 + | +3 | #[ink::contract] + | ^^^^^^^^^^^^^^^^ the trait `WrapperTypeEncode` is not implemented for `NonCodecType` +... +18 | pub fn message(&self, _input: NonCodecType) {} + | ---------------------------------------------- required by a bound introduced by this call + | + = note: required because of the requirements on the impl of `Encode` for `NonCodecType` + = note: this error originates in the attribute macro `ink::contract` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0599]: the method `fire` exists for struct `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>`, but its trait bounds were not satisfied + --> tests/ui/contract/fail/message-input-non-codec.rs:18:9 + | +18 | pub fn message(&self, _input: NonCodecType) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `ink_env::call::CallBuilder, Unset, Unset, Set, ArgumentList>>>, Set<()>>` due to unsatisfied trait bounds + | + ::: $WORKSPACE/crates/env/src/call/execution_input.rs + | + | pub struct ArgumentList { + | ----------------------------------- doesn't satisfy `_: Encode` + | + = note: the following trait bounds were not satisfied: + `ArgumentList, ArgumentList>: Encode` From f081583945fcbad01742b184cc50b40f38877aa6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 12:12:51 +0200 Subject: [PATCH 482/493] fix spelling issue in UI test --- .../lang/tests/ui/contract/fail/module-missing-constructor.rs | 2 +- .../tests/ui/contract/fail/module-missing-constructor.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/lang/tests/ui/contract/fail/module-missing-constructor.rs b/crates/lang/tests/ui/contract/fail/module-missing-constructor.rs index 5d7148422f..e259a4d142 100644 --- a/crates/lang/tests/ui/contract/fail/module-missing-constructor.rs +++ b/crates/lang/tests/ui/contract/fail/module-missing-constructor.rs @@ -1,7 +1,7 @@ use ink_lang as ink; #[ink::contract] -mod contact { +mod contract { #[ink(storage)] pub struct Contract {} diff --git a/crates/lang/tests/ui/contract/fail/module-missing-constructor.stderr b/crates/lang/tests/ui/contract/fail/module-missing-constructor.stderr index 851947f71c..fa0735e4b7 100644 --- a/crates/lang/tests/ui/contract/fail/module-missing-constructor.stderr +++ b/crates/lang/tests/ui/contract/fail/module-missing-constructor.stderr @@ -1,7 +1,7 @@ error: missing ink! constructor --> tests/ui/contract/fail/module-missing-constructor.rs:4:1 | -4 | / mod contact { +4 | / mod contract { 5 | | #[ink(storage)] 6 | | pub struct Contract {} 7 | | From d97da21453a4d6d97f08ccae71450a44544ef555 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 12:49:06 +0200 Subject: [PATCH 483/493] add docs explaining usage of AccumulatorRef et.al. in delegator example --- examples/delegator/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/delegator/lib.rs b/examples/delegator/lib.rs index 08ae5116a1..52fd773be7 100644 --- a/examples/delegator/lib.rs +++ b/examples/delegator/lib.rs @@ -44,11 +44,16 @@ mod delegator { /// Delegates calls to an `adder` or `subber` contract to mutate /// a value in an `accumulator` contract. /// + /// # Note + /// /// In order to deploy the `delegator` smart contract we first /// have to manually put the code of the `accumulator`, `adder` /// and `subber` smart contracts, receive their code hashes from /// the signalled events and put their code hash into our /// `delegator` smart contract. + /// + /// The `AccumulatorRef`, `AdderRef` and `SubberRef` are smart contract + /// reference types that have been automatically generated by ink!. #[ink(storage)] pub struct Delegator { /// Says which of `adder` or `subber` is currently in use. From 5c08ccf3fe7ee612b0d43cd78c0dcf33652379c6 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 12:51:41 +0200 Subject: [PATCH 484/493] extend is_result unit tests --- crates/lang/src/result_info.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/lang/src/result_info.rs b/crates/lang/src/result_info.rs index 94b3d90447..12632d6aa3 100644 --- a/crates/lang/src/result_info.rs +++ b/crates/lang/src/result_info.rs @@ -89,6 +89,10 @@ mod tests { assert!(is_result_type!(Result, ()>)); assert!(is_result_type!(Result<(), Result<(), ()>>)); assert!(is_result_type!(Result, Result<(), ()>>)); + + // Check that type aliases work, too. + type MyResult = Result<(), ()>; + assert!(is_result_type!(MyResult)); } #[test] @@ -105,5 +109,11 @@ mod tests { assert!(is_result_err!(Err::<(), i32>(5))); assert!(is_result_err!(Err::(false))); assert!(is_result_err!(Err::>(Ok(42)))); + + { + // Check that we do not simply check against `Result` as identifier. + type Result = Option<()>; + assert!(!is_result_type!(Result)); + } } } From 3d29b8640104f597e2e3bc89fc4733f27f7380fa Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 12:52:47 +0200 Subject: [PATCH 485/493] re-add pretty assertions --- crates/metadata/src/tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/metadata/src/tests.rs b/crates/metadata/src/tests.rs index bd5489c8fe..aefa57d6fc 100644 --- a/crates/metadata/src/tests.rs +++ b/crates/metadata/src/tests.rs @@ -13,6 +13,7 @@ // limitations under the License. use super::*; +use pretty_assertions::assert_eq; use scale_info::{ IntoPortable, Registry, From 629c24e4d6845056e760699fe4c16aa09ceffa9a Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 12:53:03 +0200 Subject: [PATCH 486/493] normalize used version in ink-metadata crate --- crates/metadata/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/metadata/Cargo.toml b/crates/metadata/Cargo.toml index 94fa545378..3fda3597d7 100644 --- a/crates/metadata/Cargo.toml +++ b/crates/metadata/Cargo.toml @@ -24,8 +24,8 @@ derive_more = { version = "0.99", default-features = false, features = ["from"] scale-info = { version = "1.0", default-features = false, features = ["derive", "serde", "decode"] } [dev-dependencies] -pretty_assertions = "1.0.0" -serde_json = "1.0" +pretty_assertions = "1" +serde_json = "1" [features] default = [ From 7db14d98645d98ffea3db7113503672b99e9abdc Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 12:56:48 +0200 Subject: [PATCH 487/493] add skeleton for ink! 3.0-rc7 in RELEASES --- RELEASES.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 2aadd1230b..ca9f989234 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,13 @@ +# Version 3.0-rc7 (UNRELEASED) + +This is the 7th release candidate for ink! 3.0. + +## Added + +## Changed + +## Fixed + # Version 3.0-rc6 This is the 6th release candidate for ink! 3.0. From f72bfaf2547827b8a1458ad7a9c9e0c851baad8e Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 13:11:25 +0200 Subject: [PATCH 488/493] add release information about this PR to RELEASES.md --- RELEASES.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index ca9f989234..5e6e7da222 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4,10 +4,44 @@ This is the 7th release candidate for ink! 3.0. ## Added +- The ink! codegen now heavily relies on static type information based on traits defined in `ink_lang`. + - Some of those traits and their carried information can be used for static reflection of ink! + smart contracts. Those types and traits reside in the new `ink_lang::reflect` module and is + publicly usable by ink! smart contract authors. + ## Changed +- ink! Contract via `#[ink::contract]`: + - ink! smart contracts now always generated two contract types. Given `MyContract`: + + - `MyContract` will still be the storage struct. + However, it can now additionally be used as static dependency in other smart contracts. + Static dependencies can be envisioned as being directly embedded into a smart contract. + - `MyContractRef` is pretty much the same of what we had gotten with the old `ink-as-dependency`. + It is a typed thin-wrapper around an `AccountId` that is mirroring the ink! smart contract's API + and implemented traits. +- ink! Trait Definitions via `#[ink::trait_definition]`: + - ink! trait definitions no longer can define trait constructors. + - ink! trait implementations now inherit `selector` and `payable` properties for trait messages. + - Now explicitly setting `selector` or `payable` property for an implemented ink! trait method + will only act as a guard that the set property is in fact the same as defined by the ink! + trait definition. +- Improve quite a few ink! specific compile errors: + - For example when using ink! messages and constructors that have inputs or outputs that cannot + be encoded or decoded using the SCALE codec. +- Simplified selector computation for ink! trait methods. + - Now selectors are encoded as `blake2b({namespace}::{trait_identifier}::{message_identifier})[0..4]`. + If no `namespace` is set for the ink! trait definition then the formula is + `blake2b({trait_identifier}::{message_identifier})[0..4]`. + Where `trait_identifier` and `message_identifier` both refer to the identifiers of the ink! trait + definition and ink! trait message respectively. + ## Fixed +- Contracts that are compiled as root (the default) now properly revert the transaction if a message + returned `Result::Err`. + - This does not apply to ink! smart contracts that are used as dependencies. Therefore it is still possible to match against a result return type for a called dependency. + # Version 3.0-rc6 This is the 6th release candidate for ink! 3.0. From f1b0bd6ca5139639d6da4483db3eafc7d6f9ad64 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Tue, 19 Oct 2021 13:26:30 +0200 Subject: [PATCH 489/493] use ink! 3.0-rc6 in multisig example contract --- examples/multisig/Cargo.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/multisig/Cargo.toml b/examples/multisig/Cargo.toml index 05d37e1db9..f324ce3782 100755 --- a/examples/multisig/Cargo.toml +++ b/examples/multisig/Cargo.toml @@ -5,15 +5,15 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -ink_primitives = { version = "3.0.0-rc5", path = "../../crates/primitives", default-features = false } -ink_metadata = { version = "3.0.0-rc5", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } -ink_env = { version = "3.0.0-rc5", path = "../../crates/env", default-features = false } -ink_storage = { version = "3.0.0-rc5", path = "../../crates/storage", default-features = false } -ink_lang = { version = "3.0.0-rc5", path = "../../crates/lang", default-features = false } -ink_prelude = { version = "3.0.0-rc5", path = "../../crates/prelude", default-features = false } +ink_primitives = { version = "3.0.0-rc6", path = "../../crates/primitives", default-features = false } +ink_metadata = { version = "3.0.0-rc6", path = "../../crates/metadata", default-features = false, features = ["derive"], optional = true } +ink_env = { version = "3.0.0-rc6", path = "../../crates/env", default-features = false } +ink_storage = { version = "3.0.0-rc6", path = "../../crates/storage", default-features = false } +ink_lang = { version = "3.0.0-rc6", path = "../../crates/lang", default-features = false } +ink_prelude = { version = "3.0.0-rc6", path = "../../crates/prelude", default-features = false } scale = { package = "parity-scale-codec", version = "2", default-features = false, features = ["derive"] } -scale-info = { version = "1.0", default-features = false, features = ["derive"], optional = true } +scale-info = { version = "1", default-features = false, features = ["derive"], optional = true } [lib] name = "multisig" From e6bd613c35945e9afbd6c001728b7bad5c14019c Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 20 Oct 2021 23:49:42 +0200 Subject: [PATCH 490/493] fix docs --- crates/lang/ir/src/ir/selector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/lang/ir/src/ir/selector.rs b/crates/lang/ir/src/ir/selector.rs index 8bdcded304..59dc661574 100644 --- a/crates/lang/ir/src/ir/selector.rs +++ b/crates/lang/ir/src/ir/selector.rs @@ -51,7 +51,7 @@ impl<'a> TraitPrefix<'a> { } } - /// Returns a shared slice over the bytes of the namespace. + /// Returns a vector over the bytes of the namespace. pub fn namespace_bytes(&self) -> Vec { self.namespace .map(|namespace| namespace.value().into_bytes()) From d2a44dda5751e1fc446a6ba504b6d1038a2e943b Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 20 Oct 2021 23:50:20 +0200 Subject: [PATCH 491/493] remove commented out code --- crates/lang/codegen/src/generator/dispatch.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/lang/codegen/src/generator/dispatch.rs b/crates/lang/codegen/src/generator/dispatch.rs index 4a76c41cfb..6b01510bab 100644 --- a/crates/lang/codegen/src/generator/dispatch.rs +++ b/crates/lang/codegen/src/generator/dispatch.rs @@ -523,7 +523,6 @@ impl Dispatch<'_> { quote_spanned!(span=> const _: () = { #[allow(non_camel_case_types)] - // #[derive(::core::fmt::Debug, ::core::cmp::PartialEq)] pub enum __ink_ConstructorDecoder { #( #constructors_variants ),* } From 74cd0b27fa3b981d4ecc5211fa3b94079ec19709 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Wed, 20 Oct 2021 23:53:47 +0200 Subject: [PATCH 492/493] use unzip to partition input_bindings and input_types (thanks andrew!) --- .../src/generator/as_dependency/call_builder.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs index 9666b942c7..94cc3f9c9f 100644 --- a/crates/lang/codegen/src/generator/as_dependency/call_builder.rs +++ b/crates/lang/codegen/src/generator/as_dependency/call_builder.rs @@ -266,16 +266,11 @@ impl CallBuilder<'_> { let message_ident = message.ident(); let output_ident = generator::output_ident(message_ident); let trait_info = generator::generate_reference_to_trait_info(span, trait_path); - let input_bindings = message + let (input_bindings, input_types): (Vec<_>, Vec<_>) = message .callable() .inputs() - .map(|input| &input.pat) - .collect::>(); - let input_types = message - .callable() - .inputs() - .map(|input| &input.ty) - .collect::>(); + .map(|input| (&input.pat, &input.ty)) + .unzip(); let mut_token = message .receiver() .is_ref_mut() From a903971cae52098ec3c7b6fd12a4c604c3358585 Mon Sep 17 00:00:00 2001 From: Robin Freyler Date: Thu, 21 Oct 2021 00:00:24 +0200 Subject: [PATCH 493/493] improve #[ink(extension)] missing parameter error message --- crates/lang/ir/src/ir/attrs.rs | 4 ++-- crates/lang/ir/src/ir/chain_extension.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/lang/ir/src/ir/attrs.rs b/crates/lang/ir/src/ir/attrs.rs index a0b7c377d1..99ba725f94 100644 --- a/crates/lang/ir/src/ir/attrs.rs +++ b/crates/lang/ir/src/ir/attrs.rs @@ -918,7 +918,7 @@ impl TryFrom for AttributeFrag { )), "extension" => Err(format_err!( meta, - "encountered #[ink(extension)] that is missing its N parameter. \ + "encountered #[ink(extension)] that is missing its `id` parameter. \ Did you mean #[ink(extension = id: u32)] ?" )), "handle_status" => Err(format_err!( @@ -1260,7 +1260,7 @@ mod tests { #[ink(extension)] }, Err( - "encountered #[ink(extension)] that is missing its N parameter. \ + "encountered #[ink(extension)] that is missing its `id` parameter. \ Did you mean #[ink(extension = id: u32)] ?", ), ); diff --git a/crates/lang/ir/src/ir/chain_extension.rs b/crates/lang/ir/src/ir/chain_extension.rs index 8936fec3fb..e589f54747 100644 --- a/crates/lang/ir/src/ir/chain_extension.rs +++ b/crates/lang/ir/src/ir/chain_extension.rs @@ -783,7 +783,8 @@ mod tests { } ); assert_ink_chain_extension_eq_err!( - error: "encountered #[ink(extension)] that is missing its N parameter. Did you mean #[ink(extension = id: u32)] ?", + error: "encountered #[ink(extension)] that is missing its `id` parameter. \ + Did you mean #[ink(extension = id: u32)] ?", pub trait MyChainExtension { #[ink(extension)] fn has_self_receiver();