Unverified Commit 5d7d855c authored by Hero Bird's avatar Hero Bird Committed by GitHub
Browse files

Implement trait support - Part 2/3 - New ink! codegen (#470)

* [lang/codegen] initial impl of the new ink! codegen

This new codegen is based on the (also) new ink! IR.

* [lang/macro] apply rustfmt to imports

* [lang/codegen] apply rustfmt

* [lang/ir] add ItemMod::{attrs, vis} getters

* [lang/codegen] make use of ir::ItemMod::{attrs, vis} in codegen

* [lang/codegen] restructure ink_lang_codegen library

* [lang/codegen] appliy clippy suggestion

* [lang/ir] add Event::attrs() and ToTokens impl for EventField

* [lang/codegen] apply rustfmt

* [lang/codegen] implement Event code generator

* [lang/codegen] make use of the new Events code generator

* [lang/ir] make ir::Callable always Copy and Clone

* [lang/ir] rename CallableWithSelector::item -> callable

* [lang/ir] add Callable::kind() trait method

* [lang/codegen] add dispatch enum code generation

* [lang/codegen] enable dispatch code generator

* [lang/codegen] add generation for constructor dispatch enum

* [lang/codegen] implement contract entry points

* [lang/codegen] implement code generation for DispatchUsingMode impl

* [lang/codegen] add trait impl namespaces Msg<S> and Constr<S>

* [lang/ir] add ir::Message::inputs_span() getter

* [lang/codegen] add codegen for dispatch trait impls for ink! messages

* [lang/codegen] plug-in dispatch trait impls code gen

* [lang/ir] add Callable::inputs_span trait method

* [lang/codegen] implement dispatch trait impl codegen for ink! constructors

Also this implementation avoids a lot of code duplication with the similar code generation for dispatch trait impl of ink! messages.

* [lang/codegen] make generate_input_bindings doc tests pass

* [lang/ir] apply rustfmt

* [lang/codegen] fix message and constructor namespaces

* [lang/ir] add {Message, Constructor}::attrs getter

* [lang/codegen] implement codegen for ink! ItemImpls

* [lang/codegen] remove some unneeded imports for ItemImpl codegen

* [lang/codegen] automatically import ink_lang's Env, EmitEvent and StaticEnv traits

* [lang/codegen] do not generate for ink-as-dependency

* [lang/codegen] initial impl for cross-calling codegen

Not complete, yet. Also we stubled upon the fact that due to the
additional Rust trait support we have to completely change how we
generate code for cross-calling. Research!

* [core] rename utils.rs -> selector.rs

* [core] add common mod for common abstractions for call and create

* [core] improve ExecutionInput: add useful trait impls

* [core] refactor call builder

* [core] adjust rest of ink_core to changed imports

* [core] implement new CreateBuilder

* [core] remove old InstantiateBuilder

* [core] remove no longer needed traits

* [core] add eval,invoke,eval_params,invoke_params to CallBuilder

This makes both CallBuilder and CreateBuilder more similar to each other.

* [core] apply rustfmt

* [core] adjust environment to new CreateBuilder

* [core] apply rustfmt

* [core] move eval and invoke to CallParams

* [core] adjust on-chain impl for CallBuilder

* [core] add explanation for the cfg

* [core] move instantiate to CreateParams

* [core] make CreateParams getters crate private

* [core] rename Call -> CallParams

* [core] improve doc comment

* [lang] adjust lang for new call and create builders

* [core] expose builder construction through build_call and build_create

* [core] remove Default impl for empty ExecutionInput

* [core] add usage examples to build_call

* [core] improve usage doc example of build_call

* [core] improve doc tests for build_call

* [core] add doc test example to build_create

* [core] fix compilation after merge

* [metadata] make constuctor and message name an array and add is_payable

Only messages need is_payable field since constructors must always be payable.

* [lang/codegen] add metadata code generation

* [lang/ir] implement lint to ensure there are no __ink_ prefixed identifiers

Identifiers starting with __ink_ may only be used by the ink! codegen.
So far this has been only implemented on TokenTree or TokenStream level and not on parsed syn abstractions leading to arcane errors. E.g. it was possible to catch errors if an __ink_ substring appeared in a string literal before.

* [metadata] make serialized Layout fields camelCase

* [lang/ir, lang/macro] apply rustfmt

* [lang/ir] initial implementation of #[ink::trait_definition] proc. macro

* [lang/ir] re-export InkTrait

* [lang/macro] create new proc. macro for ink! trait definitions

* [lang/ir] improve error messages of #[ink::trat_definition] a bit

* [lang/ir] add many more unit tests

* [lang/ir] apply rustfmt

* [lang/ir] fixed spelling bug

* [lang/ir] fix handling or errorneous Self receiver in ink! constructors

* [lang/ir] add bunch of new unit tests for #[ink::trait_definition] proc. macro

* [lang/ir] add some more unit tests

* [lang/ir] implement checks for invalid ink! attributes

* [lang/ir] add unit tests for invalid ink! attributes

* [lang/ir] use syn's builtin receiver getter

* [lang/ir] add iterators for ink! trait definition

* [lang/ir] add getters for generic info of ink! trait definition

* [lang/ir] fix a unit test testing too much

* [lang/ir] deny ink! trait definitions with supertraits

We might add support for supertraits in future versions.

* [lang/ir] add verify_hash functions

* [lang/ir] simplify ink! trait verification hash

There now is only a single hash instead of a hash per constructor and message.

* [lang/ir] add InkTrait::attrs() getter

* [lang/ir] add re-exports for most InkTrait types

* [lang/codegen] initial implementation of #[ink::trait_definition] codegen

Does not yet include the verification hash generation.

* [lang/codegen] refine codegen for ink! trait definitions

* [lang, lang/codegen] use correct trait for ink! trait definition checking

* [lang/codegen] rework crate exposed API

* [lang/ir] fix return value of ir::InkTrait::new

* [lang/macro] update codegen driver for ink! trait definition

* [core, lang/codegen, lang/ir, metadata] apply clippy suggestions

* [lang/codegen, lang/ir, lang/macro, lang] apply rustfmt

* [lang/macro] add ink_lang_codegen dependency

Needed for #[ink::trait_definition] proc. macro.

* [core/derive] use _ as const name instead of generated one

* [lang/codegen] prefix {Constructo,Message}DispatchEnum ident with __ink_

* [lang/codegen] use payable instead of is_payable

* [lang/codegen] hide some generated types

* [lang/ir] improve error span of bad storage struct visibility

* [core] add CallBuilder::returns to signal return type

Also this adds CallBuilder::fire as a quick way to fire off the call.
The CallBuilder::invoke_params and CallBuilder::eval_params are no longer needed and thus removed.

* [lang/ir] implement ToTokens for ir::Receiver

* [lang/codegen] apply #[doc(hidden)] to generated call forwarders

* [lang/codegen] slightly clean-up code

* [lang/codegen] use new call infrastructure for call forwarders

* [lang/codegen] add codegen for short-hand cross-contract message calls

* [lang/codegen] add #[inline] to generated short-hand message calls

* [lang/codegen] improve short-hand call error message

* [lang/codegen] do not generate conflicting impls

* [lang/codegen] generate non-ink! specific user defined items

* [lang/ir] remove some commented out code

* [core, lang/ir] apply rustfmt

* [core] add CreateBuilder::instantiate

* [lang/codegen] fix generate_arg_list

* [lang/codegen] add cross-calling codegen for non-trait constructor impls

* [lang/codegen] add an associated type per trait constructor in ink! trait definition

* [lang/codegen] remove former Output associated type in ink! trait definition

* [lang] re-export trait_definiction proc. macro from ink_lang crate

* [lang/ir] expose InkTrait::compute_verify_hash

* [lang/ir] add ir::ItemImpl::trait_ident

* [lang/codegen] fix some bugs with trait_definition codegen

* [lang/codegen] add codegen for cross-calling ink! trait implementations

* [lang/codegen] surpress warning in generated code

* [lang/codegen] fix bug in generated trait constructors

* [lang/codegen] add codegen for trait implementation blocks

* [lang/ir] allow access to parent impl block from within a CallableWithSelector

* [lang/codegen] make dispatch trait impls more explicit for trait impls

* [lang/codegen] fix and fully implement cross-calling (trait) impl blocks

Works now for both trait impl blocks as well as inherent impl blocks.
Only missing piece now is the codegen for the call forwarders and their impl blocks.

* [lang/ir] add ir::ItemImpl::attrs getter

* [lang/codegen] add codegen for impl block attributes for cross-calling

* [lang/codegen] correctly re-generate attributes for impl blocks

* [lang/codegen] generate forwarder inherent impl blocks

* [lang, lang/codegen] adjust ink::trait_definition proc. macro codegen

Now it also generates an associated return type per message.
Those have to respect the ink_lang::ImpliesReturn trait.

* [lang/codegen] add cross-calling call forwarder codegen for trait impl blocks

* [lang] add NeverReturns utility codegen type

* [lang/codegen] implement codegen for cross-calling trait impl blocks

* [*] apply rustfmt

* [lang/codegen] apply some clippy suggestions

* [lang/codegen] always use std feature for itertools dependency

Otherwise codegen won't work for Wasm32 compilations.

* [lang/ir] fix error span for bad event visibility modifier

* [lang/ir, lang/codegen] fix event fields codegen

* [lang/codegen] fix incorrectly generated EmitEvent trait impl

* [lang/codegen] fix bugs with ink-as-dependency and event usage

* [lang, lang/codegen] add ContractEnv trait

Used to query EnvTypes trait impl using the ink! storage struct.

* [lang, lang/codegen] implement payable messages and dynamic storage alloc

Now it is possible to control whether to use the dynamic storage allocator provided by ink! in ink! itself.
Also this PR implements codegen for non-payable messages.

* [lang/macro, lang/codegen] apply rustfmt

* [lang/ir] error upon payable constructor

ink! constructors are payable by default.

* [core] remove EnvTypes::Call associated type

No longer needed since we just removed the ability to directly call the runtime.

* [core] add MAX_EVENT_TOPICS to EnvTypes trait

* [lang, lang/codegen] optimize message payment checks codegen

* [lang/ir, lang/codegen] dynamic storage allocator: rename + change default

New default is set to "false" so only contracts that actually use this feature need to specify it.
Also renamed to dynamic_storage_allocator to better carry intention.

* [lang, lang/codegen] add codegen to guard against too many event topics

* [lang/codegen] pull topic guards codegen out of topics impl codegen const

* [lang/codegen] split event topic guards into their own method

* [lang] apply rustftm

* [lang/ir] remove unnecessary lifetime

* [lang] make use of deny_payment internally

* [lang/macro] ignore UI compile tests for now

These will be re-enabled for the follow-up PR.

* [metadata] rename is_payable -> payable (also for metadata format)

* [lang/ir] resolve duplicate code for non-pub visibility checking

Was duplicated for events and storage structs.

* [lang/ir] apply rustfmt

* [lang/codegen] removed commented-out code and update license header

* [lang/codegen] update crate description

* [core] move CreateParams impl blocks closer to struct definition

* [lang/macro] use US english

* [core] fix incorrect doc comment
parent 552d38bb
Pipeline #108763 failed with stages
in 5 minutes and 7 seconds
...@@ -7,6 +7,7 @@ members = [ ...@@ -7,6 +7,7 @@ members = [
"lang", "lang",
"lang/macro", "lang/macro",
"lang/ir", "lang/ir",
"lang/codegen",
"prelude", "prelude",
"primitives", "primitives",
] ]
......
...@@ -17,9 +17,9 @@ use quote::quote; ...@@ -17,9 +17,9 @@ use quote::quote;
/// Derives `ink_core`'s `PackedLayout` trait for the given `struct` or `enum`. /// Derives `ink_core`'s `PackedLayout` trait for the given `struct` or `enum`.
pub fn packed_layout_derive(mut s: synstructure::Structure) -> TokenStream2 { pub fn packed_layout_derive(mut s: synstructure::Structure) -> TokenStream2 {
s.bind_with(|_| synstructure::BindStyle::Move); s.bind_with(|_| synstructure::BindStyle::Move)
s.add_bounds(synstructure::AddBounds::Generics); .add_bounds(synstructure::AddBounds::Generics)
.underscore_const(true);
let pull_body = s.each(|binding| { let pull_body = s.each(|binding| {
quote! { ::ink_core::storage2::traits::PackedLayout::pull_packed(#binding, __key); } quote! { ::ink_core::storage2::traits::PackedLayout::pull_packed(#binding, __key); }
}); });
...@@ -29,7 +29,6 @@ pub fn packed_layout_derive(mut s: synstructure::Structure) -> TokenStream2 { ...@@ -29,7 +29,6 @@ pub fn packed_layout_derive(mut s: synstructure::Structure) -> TokenStream2 {
let clear_body = s.each(|binding| { let clear_body = s.each(|binding| {
quote! { ::ink_core::storage2::traits::PackedLayout::clear_packed(#binding, __key); } quote! { ::ink_core::storage2::traits::PackedLayout::clear_packed(#binding, __key); }
}); });
s.gen_impl(quote! { s.gen_impl(quote! {
gen impl ::ink_core::storage2::traits::PackedLayout for @Self { gen impl ::ink_core::storage2::traits::PackedLayout for @Self {
fn pull_packed(&mut self, __key: &::ink_primitives::Key) { fn pull_packed(&mut self, __key: &::ink_primitives::Key) {
......
...@@ -197,8 +197,9 @@ fn spread_layout_enum_derive(s: &synstructure::Structure) -> TokenStream2 { ...@@ -197,8 +197,9 @@ fn spread_layout_enum_derive(s: &synstructure::Structure) -> TokenStream2 {
/// Derives `ink_core`'s `SpreadLayout` trait for the given `struct` or `enum`. /// Derives `ink_core`'s `SpreadLayout` trait for the given `struct` or `enum`.
pub fn spread_layout_derive(mut s: synstructure::Structure) -> TokenStream2 { pub fn spread_layout_derive(mut s: synstructure::Structure) -> TokenStream2 {
s.bind_with(|_| synstructure::BindStyle::Move); s.bind_with(|_| synstructure::BindStyle::Move)
s.add_bounds(synstructure::AddBounds::Generics); .add_bounds(synstructure::AddBounds::Generics)
.underscore_const(true);
match s.ast().data { match s.ast().data {
syn::Data::Struct(_) => spread_layout_struct_derive(&s), syn::Data::Struct(_) => spread_layout_struct_derive(&s),
syn::Data::Enum(_) => spread_layout_enum_derive(&s), syn::Data::Enum(_) => spread_layout_enum_derive(&s),
......
...@@ -104,8 +104,9 @@ fn storage_layout_enum(s: &synstructure::Structure) -> TokenStream2 { ...@@ -104,8 +104,9 @@ fn storage_layout_enum(s: &synstructure::Structure) -> TokenStream2 {
} }
pub fn storage_layout_derive(mut s: synstructure::Structure) -> TokenStream2 { pub fn storage_layout_derive(mut s: synstructure::Structure) -> TokenStream2 {
s.bind_with(|_| synstructure::BindStyle::Move); s.bind_with(|_| synstructure::BindStyle::Move)
s.add_bounds(synstructure::AddBounds::Generics); .add_bounds(synstructure::AddBounds::Generics)
.underscore_const(true);
match s.ast().data { match s.ast().data {
syn::Data::Struct(_) => storage_layout_struct(&s), syn::Data::Struct(_) => storage_layout_struct(&s),
syn::Data::Enum(_) => storage_layout_enum(&s), syn::Data::Enum(_) => storage_layout_enum(&s),
......
...@@ -21,8 +21,7 @@ fn unit_struct_works() { ...@@ -21,8 +21,7 @@ fn unit_struct_works() {
struct UnitStruct; struct UnitStruct;
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_PackedLayout_FOR_UnitStruct: () = {
impl ::ink_core::storage2::traits::PackedLayout for UnitStruct { impl ::ink_core::storage2::traits::PackedLayout for UnitStruct {
fn pull_packed(&mut self, __key: &::ink_primitives::Key) { fn pull_packed(&mut self, __key: &::ink_primitives::Key) {
match self { match self {
...@@ -59,8 +58,7 @@ fn struct_works() { ...@@ -59,8 +58,7 @@ fn struct_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_PackedLayout_FOR_NamedFields: () = {
impl ::ink_core::storage2::traits::PackedLayout for NamedFields { impl ::ink_core::storage2::traits::PackedLayout for NamedFields {
fn pull_packed(&mut self, __key: &::ink_primitives::Key) { fn pull_packed(&mut self, __key: &::ink_primitives::Key) {
match self { match self {
...@@ -137,8 +135,7 @@ fn enum_works() { ...@@ -137,8 +135,7 @@ fn enum_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_PackedLayout_FOR_MixedEnum: () = {
impl ::ink_core::storage2::traits::PackedLayout for MixedEnum { impl ::ink_core::storage2::traits::PackedLayout for MixedEnum {
fn pull_packed(&mut self, __key: &::ink_primitives::Key) { fn pull_packed(&mut self, __key: &::ink_primitives::Key) {
match self { match self {
...@@ -229,8 +226,7 @@ fn generic_struct_works() { ...@@ -229,8 +226,7 @@ fn generic_struct_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_PackedLayout_FOR_GenericStruct: () = {
impl<T1, T2> ::ink_core::storage2::traits::PackedLayout for GenericStruct<T1, T2> impl<T1, T2> ::ink_core::storage2::traits::PackedLayout for GenericStruct<T1, T2>
where where
T1: ::ink_core::storage2::traits::PackedLayout, T1: ::ink_core::storage2::traits::PackedLayout,
...@@ -298,8 +294,7 @@ fn generic_enum_works() { ...@@ -298,8 +294,7 @@ fn generic_enum_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_PackedLayout_FOR_GenericEnum: () = {
impl<T1, T2> ::ink_core::storage2::traits::PackedLayout for GenericEnum<T1, T2> impl<T1, T2> ::ink_core::storage2::traits::PackedLayout for GenericEnum<T1, T2>
where where
T1: ::ink_core::storage2::traits::PackedLayout, T1: ::ink_core::storage2::traits::PackedLayout,
......
...@@ -21,8 +21,7 @@ fn unit_struct_works() { ...@@ -21,8 +21,7 @@ fn unit_struct_works() {
struct UnitStruct; struct UnitStruct;
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_SpreadLayout_FOR_UnitStruct: () = {
impl ::ink_core::storage2::traits::SpreadLayout for UnitStruct { impl ::ink_core::storage2::traits::SpreadLayout for UnitStruct {
#[allow(unused_comparisons)] #[allow(unused_comparisons)]
const FOOTPRINT: u64 = [0u64, 0u64][(0u64 < 0u64) as usize]; const FOOTPRINT: u64 = [0u64, 0u64][(0u64 < 0u64) as usize];
...@@ -61,8 +60,7 @@ fn struct_works() { ...@@ -61,8 +60,7 @@ fn struct_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_SpreadLayout_FOR_NamedFields: () = {
impl ::ink_core::storage2::traits::SpreadLayout for NamedFields { impl ::ink_core::storage2::traits::SpreadLayout for NamedFields {
#[allow(unused_comparisons)] #[allow(unused_comparisons)]
const FOOTPRINT: u64 = [ const FOOTPRINT: u64 = [
...@@ -172,8 +170,7 @@ fn enum_works() { ...@@ -172,8 +170,7 @@ fn enum_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_SpreadLayout_FOR_MixedEnum: () = {
impl ::ink_core::storage2::traits::SpreadLayout for MixedEnum { impl ::ink_core::storage2::traits::SpreadLayout for MixedEnum {
#[allow(unused_comparisons)] #[allow(unused_comparisons)]
const FOOTPRINT : u64 = 1 + [ const FOOTPRINT : u64 = 1 + [
...@@ -447,8 +444,7 @@ fn generic_struct_works() { ...@@ -447,8 +444,7 @@ fn generic_struct_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_SpreadLayout_FOR_GenericStruct: () = {
impl<T1, T2> ::ink_core::storage2::traits::SpreadLayout for GenericStruct<T1, T2> impl<T1, T2> ::ink_core::storage2::traits::SpreadLayout for GenericStruct<T1, T2>
where where
T1: ::ink_core::storage2::traits::SpreadLayout, T1: ::ink_core::storage2::traits::SpreadLayout,
...@@ -544,8 +540,7 @@ fn generic_enum_works() { ...@@ -544,8 +540,7 @@ fn generic_enum_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_SpreadLayout_FOR_GenericEnum: () = {
impl<T1, T2> ::ink_core::storage2::traits::SpreadLayout for GenericEnum<T1, T2> impl<T1, T2> ::ink_core::storage2::traits::SpreadLayout for GenericEnum<T1, T2>
where where
T1: ::ink_core::storage2::traits::SpreadLayout, T1: ::ink_core::storage2::traits::SpreadLayout,
......
...@@ -21,8 +21,7 @@ fn unit_struct_works() { ...@@ -21,8 +21,7 @@ fn unit_struct_works() {
struct UnitStruct; struct UnitStruct;
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_StorageLayout_FOR_UnitStruct: () = {
impl ::ink_core::storage2::traits::StorageLayout for UnitStruct { impl ::ink_core::storage2::traits::StorageLayout for UnitStruct {
fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout { fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout {
::ink_metadata::layout2::Layout::Struct( ::ink_metadata::layout2::Layout::Struct(
...@@ -42,8 +41,7 @@ fn tuple_struct_works() { ...@@ -42,8 +41,7 @@ fn tuple_struct_works() {
struct TupleStruct(bool, u32, i64); struct TupleStruct(bool, u32, i64);
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_StorageLayout_FOR_TupleStruct: () = {
impl ::ink_core::storage2::traits::StorageLayout for TupleStruct { impl ::ink_core::storage2::traits::StorageLayout for TupleStruct {
fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout { fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout {
::ink_metadata::layout2::Layout::Struct( ::ink_metadata::layout2::Layout::Struct(
...@@ -80,8 +78,7 @@ fn named_fields_struct_works() { ...@@ -80,8 +78,7 @@ fn named_fields_struct_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_StorageLayout_FOR_NamedFieldsStruct: () = {
impl ::ink_core::storage2::traits::StorageLayout for NamedFieldsStruct { impl ::ink_core::storage2::traits::StorageLayout for NamedFieldsStruct {
fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout { fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout {
::ink_metadata::layout2::Layout::Struct( ::ink_metadata::layout2::Layout::Struct(
...@@ -114,8 +111,7 @@ fn clike_enum_works() { ...@@ -114,8 +111,7 @@ fn clike_enum_works() {
enum ClikeEnum { A, B, C } enum ClikeEnum { A, B, C }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_StorageLayout_FOR_ClikeEnum: () = {
impl ::ink_core::storage2::traits::StorageLayout for ClikeEnum { impl ::ink_core::storage2::traits::StorageLayout for ClikeEnum {
fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout { fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout {
let dispatch_key = __key_ptr.advance_by(1); let dispatch_key = __key_ptr.advance_by(1);
...@@ -172,8 +168,7 @@ fn mixed_enum_works() { ...@@ -172,8 +168,7 @@ fn mixed_enum_works() {
} }
} }
expands to { expands to {
#[allow(non_upper_case_globals)] const _: () = {
const _DERIVE_ink_core_storage2_traits_StorageLayout_FOR_MixedEnum: () = {
impl ::ink_core::storage2::traits::StorageLayout for MixedEnum { impl ::ink_core::storage2::traits::StorageLayout for MixedEnum {
fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout { fn layout(__key_ptr: &mut ::ink_core::storage2::traits::KeyPtr) -> ::ink_metadata::layout2::Layout {
let dispatch_key = __key_ptr.advance_by(1); let dispatch_key = __key_ptr.advance_by(1);
......
...@@ -21,9 +21,9 @@ use crate::env::{ ...@@ -21,9 +21,9 @@ use crate::env::{
TypedEnv, TypedEnv,
}, },
call::{ call::{
utils::ReturnType,
CallParams, CallParams,
InstantiateParams, CreateParams,
ReturnType,
}, },
engine::{ engine::{
EnvInstance, EnvInstance,
...@@ -313,7 +313,7 @@ where ...@@ -313,7 +313,7 @@ where
/// - If given insufficient endowment. /// - If given insufficient endowment.
/// - If the returned account ID failed to decode properly. /// - If the returned account ID failed to decode properly.
pub fn instantiate_contract<T, Args, C>( pub fn instantiate_contract<T, Args, C>(
params: &InstantiateParams<T, Args, C>, params: &CreateParams<T, Args, C>,
) -> Result<T::AccountId> ) -> Result<T::AccountId>
where where
T: EnvTypes, T: EnvTypes,
......
...@@ -14,9 +14,9 @@ ...@@ -14,9 +14,9 @@
use crate::env::{ use crate::env::{
call::{ call::{
utils::ReturnType,
CallParams, CallParams,
InstantiateParams, CreateParams,
ReturnType,
}, },
EnvTypes, EnvTypes,
Result, Result,
...@@ -278,7 +278,7 @@ pub trait TypedEnv: Env { ...@@ -278,7 +278,7 @@ pub trait TypedEnv: Env {
/// For more details visit: [`ink_core::env::instantiate_contract`] /// For more details visit: [`ink_core::env::instantiate_contract`]
fn instantiate_contract<T, Args, C>( fn instantiate_contract<T, Args, C>(
&mut self, &mut self,
params: &InstantiateParams<T, Args, C>, params: &CreateParams<T, Args, C>,
) -> Result<T::AccountId> ) -> Result<T::AccountId>
where where
T: EnvTypes, T: EnvTypes,
......
// Copyright 2019-2020 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;
use crate::env::{
call::{
state,
ArgsList,
Argument,
ArgumentList,
EmptyArgumentList,
ExecutionInput,
Selector,
},
EnvTypes,
Result,
};
/// Represents a return type.
///
/// Used as a marker type to differentiate at compile-time between invoke and evaluate.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ReturnType<T>(PhantomData<fn() -> T>);
/// The final parameters to the cross-contract call.
pub struct CallParams<E, Args, R>
where
E: EnvTypes,
{
/// The account ID of the to-be-called smart contract.
callee: E::AccountId,
/// The maximum gas costs allowed for the call.
gas_limit: u64,
/// The transferred value for the call.
transferred_value: E::Balance,
/// The expected return type.
return_type: PhantomData<ReturnType<R>>,
/// The already encoded call data respecting the ABI.
call_data: ExecutionInput<Args>,
}
/// Builds up a call.
pub struct CallBuilder<E, Args, R, Seal>
where
E: EnvTypes,
{
/// The current parameters that have been built up so far.
params: CallParams<E, Args, R>,
/// Seal state.
seal: PhantomData<Seal>,
}
impl<E, Args, R> CallParams<E, Args, R>
where
E: EnvTypes,
{
/// The code hash of the contract.
#[inline]
pub fn callee(&self) -> &E::AccountId {
&self.callee
}
/// The gas limit for the contract instantiation.
#[inline]
pub fn gas_limit(&self) -> u64 {
self.gas_limit
}
/// The transferred value for the called contract.
#[inline]
pub fn transferred_value(&self) -> &E::Balance {
&self.transferred_value
}
/// The raw encoded input data.
#[inline]
pub fn input_data(&self) -> &ExecutionInput<Args> {
&self.call_data
}
}
impl<E, R> CallParams<E, EmptyArgumentList, R>
where
E: EnvTypes,
E::Balance: Default,
{
/// Creates the default set of parameters for the cross-contract call.
#[inline]
fn new(callee: E::AccountId, selector: Selector) -> Self {
Self {
callee,
gas_limit: 0,
transferred_value: E::Balance::default(),
return_type: PhantomData,
call_data: ExecutionInput::new(selector),
}
}
/// Returns a builder for a cross-contract call that might return data.
#[inline]
pub fn eval(
callee: E::AccountId,
selector: Selector,
) -> CallBuilder<E, EmptyArgumentList, ReturnType<R>, state::Unsealed> {
CallBuilder {
params: CallParams::new(callee, selector),
seal: Default::default(),
}
}
/// Returns a builder for a cross-contract call that cannot return data.
///
/// Prefer this over [`CallParams::eval`] if possible since it is the more efficient operation.
#[inline]
pub fn invoke(
callee: E::AccountId,
selector: Selector,
) -> CallBuilder<E, EmptyArgumentList, (), state::Unsealed> {
CallBuilder {
params: CallParams::new(callee, selector),
seal: Default::default(),
}
}
}
impl<E, Args, R, Seal> CallBuilder<E, Args, R, Seal>
where
E: EnvTypes,
{
/// Sets the maximumly allowed gas costs for the call.
#[inline]
pub fn gas_limit(mut self, gas_limit: u64) -> Self {
self.params.gas_limit = gas_limit;
self
}
/// Sets the value transferred upon the execution of the call.
#[inline]
pub fn transferred_value(mut self, value: E::Balance) -> Self {
self.params.transferred_value = value;
self
}
}
impl<E, R> CallBuilder<E, EmptyArgumentList, R, state::Unsealed>
where
E: EnvTypes,
{
/// Pushes an argument to the inputs of the call.
#[inline]
pub fn push_arg<A>(
self,
arg: A,
) -> CallBuilder<E, ArgumentList<Argument<A>, EmptyArgumentList>, R, state::Unsealed>
where
A: scale::Encode,
{
CallBuilder {
params: CallParams {
call_data: self.params.call_data.push_arg(arg),
callee: self.params.callee,
gas_limit: self.params.gas_limit,
transferred_value: self.params.transferred_value,
return_type: self.params.return_type,
},
seal: Default::default(),
}
}
}
impl<'a, E, ArgsHead, ArgsRest, R>
CallBuilder<E, ArgsList<ArgsHead, ArgsRest>, R, state::Unsealed>
where
E: EnvTypes,
{
/// Pushes an argument to the inputs of the call.
#[inline]
pub fn push_arg<A>(
self,
arg: A,
) -> CallBuilder<E, ArgsList<A, ArgsList<ArgsHead, ArgsRest>>, R, state::Unsealed>
where
A: scale::Encode,
{
CallBuilder {
params: CallParams {
call_data: self.params.call_data.push_arg(arg),
callee: self.params.callee,
gas_limit: self.params.gas_limit,
transferred_value: self.params.transferred_value,
return_type: self.params.return_type,
},
seal: Default::default(),
}
}
}
impl<E, Args, R> CallBuilder<E, Args, R, state::Unsealed>
where
E: EnvTypes,
{
/// Seals the call builder to prevent further arguments.
#[inline]
pub fn seal(self) -> CallBuilder<E, Args, R, state::Sealed> {
CallBuilder {
params: self.params,
seal: Default::default(),
}
}
}
impl<E, Args, R, Seal> CallBuilder<E, Args, ReturnType<R>, Seal>
where
E: EnvTypes,
Args: scale::Encode,
R: scale::Decode,
{
/// Fires the call to the remote smart contract.
/// Returns the returned data back to the caller.
#[inline]
pub fn fire(self) -> Result<R>