Skip to content
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

[Unreleased]

### Added
- Add `#[ink::contract_ref]` attribute - [#2648](https://github.com/use-ink/ink/pull/2648)

### Fixed
- `name` override fixes for message id computation and trait definitions - [#2649](https://github.com/use-ink/ink/pull/2649)

Expand Down
35 changes: 25 additions & 10 deletions crates/ink/codegen/src/generator/trait_def/call_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use super::TraitDefinition;
use crate::{
generator,
traits::GenerateCode,
};
use derive_more::From;
use ink_primitives::abi::Abi;
use proc_macro2::{
Span,
TokenStream as TokenStream2,
Expand All @@ -27,6 +23,12 @@ use quote::{
quote_spanned,
};

use super::TraitDefinition;
use crate::{
generator,
traits::GenerateCode,
};

impl TraitDefinition<'_> {
/// Generates code for the global trait call builder for an ink! trait.
///
Expand All @@ -37,8 +39,8 @@ impl TraitDefinition<'_> {
/// 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()
pub fn generate_call_builder(&self, abi: Option<Abi>) -> TokenStream2 {
CallBuilder::from((*self, abi)).generate_code()
}

/// The identifier of the ink! trait call builder.
Expand All @@ -51,6 +53,7 @@ impl TraitDefinition<'_> {
#[derive(From)]
struct CallBuilder<'a> {
trait_def: TraitDefinition<'a>,
abi: Option<Abi>,
}

impl GenerateCode for CallBuilder<'_> {
Expand Down Expand Up @@ -168,7 +171,9 @@ impl CallBuilder<'_> {
fn generate_auxiliary_trait_impls(&self) -> TokenStream2 {
let span = self.span();
let call_builder_ident = self.ident();
let sol_codec = if cfg!(any(ink_abi = "sol", ink_abi = "all")) {
let sol_codec = if matches!(self.abi, Some(Abi::Sol))
|| cfg!(any(ink_abi = "sol", ink_abi = "all"))
{
// These manual implementations are a bit more efficient than the derived
// equivalents.
quote_spanned!(span=>
Expand Down Expand Up @@ -356,7 +361,7 @@ impl CallBuilder<'_> {
let trait_ident = self.trait_def.trait_def.item().ident();
let trait_info_ident = self.trait_def.trait_info_ident();
let builder_ident = self.ident();
generate_abi_impls!(@tokens |abi: TokenStream2| {
let generator = |abi: TokenStream2| {
let message_impls = self.generate_ink_trait_impl_messages(abi.clone());
quote_spanned!(span=>
impl<E> #trait_ident for #builder_ident<E, #abi>
Expand All @@ -369,7 +374,17 @@ impl CallBuilder<'_> {
#message_impls
}
)
})
};
match self.abi {
None => generate_abi_impls!(@tokens generator),
Some(abi) => {
let abi_ty = match abi {
Abi::Ink => quote!(::ink::abi::Ink),
Abi::Sol => quote!(::ink::abi::Sol),
};
generator(abi_ty)
}
}
}

/// Generate the code for all ink! trait messages implemented by the trait call
Expand Down
47 changes: 31 additions & 16 deletions crates/ink/codegen/src/generator/trait_def/call_forwarder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use super::TraitDefinition;
use crate::{
generator,
traits::GenerateCode,
};
use derive_more::From;
use ink_primitives::abi::Abi;
use proc_macro2::{
Span,
TokenStream as TokenStream2,
Expand All @@ -27,6 +23,12 @@ use quote::{
quote_spanned,
};

use super::TraitDefinition;
use crate::{
generator,
traits::GenerateCode,
};

impl TraitDefinition<'_> {
/// Generates code for the global trait call forwarder for an ink! trait.
///
Expand All @@ -38,8 +40,8 @@ impl TraitDefinition<'_> {
/// - 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()
pub fn generate_call_forwarder(&self, abi: Option<Abi>) -> TokenStream2 {
CallForwarder::from((*self, abi)).generate_code()
}

/// The identifier of the ink! trait call forwarder.
Expand All @@ -52,6 +54,7 @@ impl TraitDefinition<'_> {
#[derive(From)]
struct CallForwarder<'a> {
trait_def: TraitDefinition<'a>,
abi: Option<Abi>,
}

impl GenerateCode for CallForwarder<'_> {
Expand Down Expand Up @@ -366,17 +369,29 @@ impl CallForwarder<'_> {
let trait_info_ident = self.trait_def.trait_info_ident();
let forwarder_ident = self.ident();
let message_impls = self.generate_ink_trait_impl_messages();
generate_abi_impls!(@tokens |abi| quote_spanned!(span=>
impl<E> #trait_ident for #forwarder_ident<E, #abi>
where
E: ::ink::env::Environment,
{
#[allow(non_camel_case_types)]
type __ink_TraitInfo = #trait_info_ident<E>;
let generator = |abi| {
quote_spanned!(span=>
impl<E> #trait_ident for #forwarder_ident<E, #abi>
where
E: ::ink::env::Environment,
{
#[allow(non_camel_case_types)]
type __ink_TraitInfo = #trait_info_ident<E>;

#message_impls
#message_impls
}
)
};
match self.abi {
None => generate_abi_impls!(@tokens generator),
Some(abi) => {
let abi_ty = match abi {
Abi::Ink => quote!(::ink::abi::Ink),
Abi::Sol => quote!(::ink::abi::Sol),
};
generator(abi_ty)
}
))
}
}

/// Generate the code for all ink! trait messages implemented by the trait call
Expand Down
17 changes: 12 additions & 5 deletions crates/ink/codegen/src/generator/trait_def/message_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ impl TraitDefinition<'_> {
/// 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_message_builder(&self) -> TokenStream2 {
MessageBuilder::from(*self).generate_code()
pub fn generate_message_builder(&self, abi: Option<Abi>) -> TokenStream2 {
MessageBuilder::from((*self, abi)).generate_code()
}

/// The identifier of the ink! trait message builder.
Expand All @@ -54,6 +54,7 @@ impl TraitDefinition<'_> {
#[derive(From)]
struct MessageBuilder<'a> {
trait_def: TraitDefinition<'a>,
abi: Option<Abi>,
}

impl GenerateCode for MessageBuilder<'_> {
Expand Down Expand Up @@ -109,7 +110,9 @@ impl MessageBuilder<'_> {
fn generate_auxiliary_trait_impls(&self) -> TokenStream2 {
let span = self.span();
let message_builder_ident = self.trait_def.message_builder_ident();
let sol_codec = if cfg!(any(ink_abi = "sol", ink_abi = "all")) {
let sol_codec = if matches!(self.abi, Some(Abi::Sol))
|| cfg!(any(ink_abi = "sol", ink_abi = "all"))
{
// These manual implementations are a bit more efficient than the derived
// equivalents.
quote_spanned!(span=>
Expand Down Expand Up @@ -173,7 +176,7 @@ impl MessageBuilder<'_> {
let trait_ident = self.trait_def.trait_def.item().ident();
let trait_info_ident = self.trait_def.trait_info_ident();
let message_builder_ident = self.trait_def.message_builder_ident();
generate_abi_impls!(@type |abi| {
let generator = |abi| {
let abi_ty = match abi {
Abi::Ink => quote!(::ink::abi::Ink),
Abi::Sol => quote!(::ink::abi::Sol),
Expand All @@ -190,7 +193,11 @@ impl MessageBuilder<'_> {
#message_impls
}
)
})
};
match self.abi {
None => generate_abi_impls!(@type generator),
Some(abi) => generator(abi),
}
}

/// Generate the code for all ink! trait messages implemented by the trait call
Expand Down
23 changes: 18 additions & 5 deletions crates/ink/codegen/src/generator/trait_def/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ mod definition;
mod message_builder;
mod trait_registry;

use crate::GenerateCode;
use derive_more::From;
use ink_primitives::abi::Abi;
use proc_macro2::{
Span,
TokenStream as TokenStream2,
Expand All @@ -29,10 +29,23 @@ use quote::{
quote_spanned,
};

use crate::GenerateCode;

/// Generator to create the ink! storage struct and important trait implementations.
#[derive(From, Copy, Clone)]
pub struct TraitDefinition<'a> {
trait_def: &'a ir::InkTraitDefinition,
abi: Option<Abi>,
}

impl<'a> From<&'a ir::InkTraitDefinition> for TraitDefinition<'a> {
#[inline]
fn from(value: &'a ir::InkTraitDefinition) -> Self {
TraitDefinition {
trait_def: value,
abi: None,
}
}
}

impl TraitDefinition<'_> {
Expand All @@ -55,10 +68,10 @@ impl GenerateCode for TraitDefinition<'_> {
fn generate_code(&self) -> TokenStream2 {
let span = self.trait_def.item().span();
let trait_definition = self.generate_trait_definition();
let trait_registry = self.generate_trait_registry_impl();
let trait_message_builder = self.generate_message_builder();
let trait_call_builder = self.generate_call_builder();
let trait_call_forwarder = self.generate_call_forwarder();
let trait_registry = self.generate_trait_registry_impl(self.abi);
let trait_message_builder = self.generate_message_builder(self.abi);
let trait_call_builder = self.generate_call_builder(self.abi);
let trait_call_forwarder = self.generate_call_forwarder(self.abi);
quote_spanned!(span =>
#trait_definition
const _: () = {
Expand Down
31 changes: 16 additions & 15 deletions crates/ink/codegen/src/generator/trait_def/trait_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ impl TraitDefinition<'_> {
/// This also generates the code for the global trait info object which
/// implements some `ink` 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()
pub fn generate_trait_registry_impl(&self, abi: Option<Abi>) -> TokenStream2 {
TraitRegistry::from((*self, abi)).generate_code()
}

/// Returns the identifier for the ink! trait definition info object.
Expand All @@ -63,6 +63,7 @@ impl TraitDefinition<'_> {
#[derive(From)]
struct TraitRegistry<'a> {
trait_def: TraitDefinition<'a>,
abi: Option<Abi>,
}

impl GenerateCode for TraitRegistry<'_> {
Expand Down Expand Up @@ -193,9 +194,11 @@ impl TraitRegistry<'_> {
selector,
message.mutates(),
);
let inout_guards = generate_abi_impls!(@type |abi| {
Self::generate_inout_guards_for_message(message, abi)
});
let generator = |abi| Self::generate_inout_guards_for_message(message, abi);
let inout_guards = match self.abi {
None => generate_abi_impls!(@type generator),
Some(abi) => generator(abi),
};
let impl_body = match option_env!("INK_COVERAGE_REPORTING") {
Some("true") => {
quote! {
Expand Down Expand Up @@ -343,15 +346,12 @@ impl TraitRegistry<'_> {
let span = message.span();
let trait_info_ident = self.trait_def.trait_info_ident();
let is_payable = message.ink_attrs().is_payable();
generate_abi_impls!(@type |abi| {
let generator = |abi| {
let (local_id, selector_bytes) = match abi {
Abi::Ink => {
let local_id = message.local_id();
let selector_bytes = selector.hex_lits();
(
quote!(#local_id),
quote!([ #( #selector_bytes ),* ])
)
(quote!(#local_id), quote!([ #( #selector_bytes ),* ]))
}
Abi::Sol => {
let name = message.normalized_name();
Expand All @@ -364,10 +364,7 @@ impl TraitRegistry<'_> {
::core::primitive::u32::from_be_bytes(#selector_bytes)
}
);
(
selector_id,
selector_bytes
)
(selector_id, selector_bytes)
}
};
quote_spanned!(span=>
Expand All @@ -376,6 +373,10 @@ impl TraitRegistry<'_> {
const SELECTOR: [::core::primitive::u8; 4usize] = #selector_bytes;
}
)
})
};
match self.abi {
None => generate_abi_impls!(@type generator),
Some(abi) => generator(abi),
}
}
}
9 changes: 8 additions & 1 deletion crates/ink/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
html_favicon_url = "https://use.ink/crate-docs/favicon.png"
)]

pub use ink_primitives::reflect;
pub use ink_primitives::{
abi::Abi,
reflect,
};
mod enforced_error;
mod generator;
mod traits;
Expand Down Expand Up @@ -73,6 +76,10 @@ impl<'a> CodeGenerator for &'a ir::InkTraitDefinition {
type Generator = generator::TraitDefinition<'a>;
}

impl<'a> CodeGenerator for (&'a ir::InkTraitDefinition, Option<Abi>) {
type Generator = generator::TraitDefinition<'a>;
}

impl<'a> CodeGenerator for &'a ir::InkTest {
type Generator = generator::InkTest<'a>;
}
Expand Down
Loading
Loading