Skip to content

Commit 8cff771

Browse files
Add #[ink::contract_ref] attribute (#2648)
* codegen: Allow ABI override for generated trait definition abstractions * macro: `interface` attribute macro * tests: Add precompile integration test * chore: Remove unnecessary dependency * Update changelog * formatting Co-authored-by: Michael Müller <mich@elmueller.net> * formatting Co-authored-by: Michael Müller <mich@elmueller.net> * formatting Co-authored-by: Michael Müller <mich@elmueller.net> * macro: Rename `ink::contract_ref!` to `ink::contract_ref_from_path!` * macro: Rename `#[ink::interface]` to `#[ink::contract_ref]` * Update changelog --------- Co-authored-by: Michael Müller <mich@elmueller.net>
1 parent ac188f1 commit 8cff771

File tree

17 files changed

+705
-88
lines changed

17 files changed

+705
-88
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
[Unreleased]
88

9+
### Added
10+
- Add `#[ink::contract_ref]` attribute - [#2648](https://github.com/use-ink/ink/pull/2648)
11+
912
### Fixed
1013
- `name` override fixes for message id computation and trait definitions - [#2649](https://github.com/use-ink/ink/pull/2649)
1114

crates/ink/codegen/src/generator/trait_def/call_builder.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use super::TraitDefinition;
16-
use crate::{
17-
generator,
18-
traits::GenerateCode,
19-
};
2015
use derive_more::From;
16+
use ink_primitives::abi::Abi;
2117
use proc_macro2::{
2218
Span,
2319
TokenStream as TokenStream2,
@@ -27,6 +23,12 @@ use quote::{
2723
quote_spanned,
2824
};
2925

26+
use super::TraitDefinition;
27+
use crate::{
28+
generator,
29+
traits::GenerateCode,
30+
};
31+
3032
impl TraitDefinition<'_> {
3133
/// Generates code for the global trait call builder for an ink! trait.
3234
///
@@ -37,8 +39,8 @@ impl TraitDefinition<'_> {
3739
/// gas limit, endowment etc.
3840
/// - The call builder is used directly by the generated call forwarder. There exists
3941
/// one global call forwarder and call builder pair for every ink! trait definition.
40-
pub fn generate_call_builder(&self) -> TokenStream2 {
41-
CallBuilder::from(*self).generate_code()
42+
pub fn generate_call_builder(&self, abi: Option<Abi>) -> TokenStream2 {
43+
CallBuilder::from((*self, abi)).generate_code()
4244
}
4345

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

5659
impl GenerateCode for CallBuilder<'_> {
@@ -168,7 +171,9 @@ impl CallBuilder<'_> {
168171
fn generate_auxiliary_trait_impls(&self) -> TokenStream2 {
169172
let span = self.span();
170173
let call_builder_ident = self.ident();
171-
let sol_codec = if cfg!(any(ink_abi = "sol", ink_abi = "all")) {
174+
let sol_codec = if matches!(self.abi, Some(Abi::Sol))
175+
|| cfg!(any(ink_abi = "sol", ink_abi = "all"))
176+
{
172177
// These manual implementations are a bit more efficient than the derived
173178
// equivalents.
174179
quote_spanned!(span=>
@@ -356,7 +361,7 @@ impl CallBuilder<'_> {
356361
let trait_ident = self.trait_def.trait_def.item().ident();
357362
let trait_info_ident = self.trait_def.trait_info_ident();
358363
let builder_ident = self.ident();
359-
generate_abi_impls!(@tokens |abi: TokenStream2| {
364+
let generator = |abi: TokenStream2| {
360365
let message_impls = self.generate_ink_trait_impl_messages(abi.clone());
361366
quote_spanned!(span=>
362367
impl<E> #trait_ident for #builder_ident<E, #abi>
@@ -369,7 +374,17 @@ impl CallBuilder<'_> {
369374
#message_impls
370375
}
371376
)
372-
})
377+
};
378+
match self.abi {
379+
None => generate_abi_impls!(@tokens generator),
380+
Some(abi) => {
381+
let abi_ty = match abi {
382+
Abi::Ink => quote!(::ink::abi::Ink),
383+
Abi::Sol => quote!(::ink::abi::Sol),
384+
};
385+
generator(abi_ty)
386+
}
387+
}
373388
}
374389

375390
/// Generate the code for all ink! trait messages implemented by the trait call

crates/ink/codegen/src/generator/trait_def/call_forwarder.rs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use super::TraitDefinition;
16-
use crate::{
17-
generator,
18-
traits::GenerateCode,
19-
};
2015
use derive_more::From;
16+
use ink_primitives::abi::Abi;
2117
use proc_macro2::{
2218
Span,
2319
TokenStream as TokenStream2,
@@ -27,6 +23,12 @@ use quote::{
2723
quote_spanned,
2824
};
2925

26+
use super::TraitDefinition;
27+
use crate::{
28+
generator,
29+
traits::GenerateCode,
30+
};
31+
3032
impl TraitDefinition<'_> {
3133
/// Generates code for the global trait call forwarder for an ink! trait.
3234
///
@@ -38,8 +40,8 @@ impl TraitDefinition<'_> {
3840
/// - The call forwarder is associated to the call builder for the same ink! trait
3941
/// definition and handles all ink! trait calls into another contract instance
4042
/// on-chain. For constructing custom calls it forwards to the call builder.
41-
pub fn generate_call_forwarder(&self) -> TokenStream2 {
42-
CallForwarder::from(*self).generate_code()
43+
pub fn generate_call_forwarder(&self, abi: Option<Abi>) -> TokenStream2 {
44+
CallForwarder::from((*self, abi)).generate_code()
4345
}
4446

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

5760
impl GenerateCode for CallForwarder<'_> {
@@ -366,17 +369,29 @@ impl CallForwarder<'_> {
366369
let trait_info_ident = self.trait_def.trait_info_ident();
367370
let forwarder_ident = self.ident();
368371
let message_impls = self.generate_ink_trait_impl_messages();
369-
generate_abi_impls!(@tokens |abi| quote_spanned!(span=>
370-
impl<E> #trait_ident for #forwarder_ident<E, #abi>
371-
where
372-
E: ::ink::env::Environment,
373-
{
374-
#[allow(non_camel_case_types)]
375-
type __ink_TraitInfo = #trait_info_ident<E>;
372+
let generator = |abi| {
373+
quote_spanned!(span=>
374+
impl<E> #trait_ident for #forwarder_ident<E, #abi>
375+
where
376+
E: ::ink::env::Environment,
377+
{
378+
#[allow(non_camel_case_types)]
379+
type __ink_TraitInfo = #trait_info_ident<E>;
376380

377-
#message_impls
381+
#message_impls
382+
}
383+
)
384+
};
385+
match self.abi {
386+
None => generate_abi_impls!(@tokens generator),
387+
Some(abi) => {
388+
let abi_ty = match abi {
389+
Abi::Ink => quote!(::ink::abi::Ink),
390+
Abi::Sol => quote!(::ink::abi::Sol),
391+
};
392+
generator(abi_ty)
378393
}
379-
))
394+
}
380395
}
381396

382397
/// Generate the code for all ink! trait messages implemented by the trait call

crates/ink/codegen/src/generator/trait_def/message_builder.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ impl TraitDefinition<'_> {
4040
/// gas limit, endowment etc.
4141
/// - The call builder is used directly by the generated call forwarder. There exists
4242
/// one global call forwarder and call builder pair for every ink! trait definition.
43-
pub fn generate_message_builder(&self) -> TokenStream2 {
44-
MessageBuilder::from(*self).generate_code()
43+
pub fn generate_message_builder(&self, abi: Option<Abi>) -> TokenStream2 {
44+
MessageBuilder::from((*self, abi)).generate_code()
4545
}
4646

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

5960
impl GenerateCode for MessageBuilder<'_> {
@@ -109,7 +110,9 @@ impl MessageBuilder<'_> {
109110
fn generate_auxiliary_trait_impls(&self) -> TokenStream2 {
110111
let span = self.span();
111112
let message_builder_ident = self.trait_def.message_builder_ident();
112-
let sol_codec = if cfg!(any(ink_abi = "sol", ink_abi = "all")) {
113+
let sol_codec = if matches!(self.abi, Some(Abi::Sol))
114+
|| cfg!(any(ink_abi = "sol", ink_abi = "all"))
115+
{
113116
// These manual implementations are a bit more efficient than the derived
114117
// equivalents.
115118
quote_spanned!(span=>
@@ -173,7 +176,7 @@ impl MessageBuilder<'_> {
173176
let trait_ident = self.trait_def.trait_def.item().ident();
174177
let trait_info_ident = self.trait_def.trait_info_ident();
175178
let message_builder_ident = self.trait_def.message_builder_ident();
176-
generate_abi_impls!(@type |abi| {
179+
let generator = |abi| {
177180
let abi_ty = match abi {
178181
Abi::Ink => quote!(::ink::abi::Ink),
179182
Abi::Sol => quote!(::ink::abi::Sol),
@@ -190,7 +193,11 @@ impl MessageBuilder<'_> {
190193
#message_impls
191194
}
192195
)
193-
})
196+
};
197+
match self.abi {
198+
None => generate_abi_impls!(@type generator),
199+
Some(abi) => generator(abi),
200+
}
194201
}
195202

196203
/// Generate the code for all ink! trait messages implemented by the trait call

crates/ink/codegen/src/generator/trait_def/mod.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ mod definition;
1818
mod message_builder;
1919
mod trait_registry;
2020

21-
use crate::GenerateCode;
2221
use derive_more::From;
22+
use ink_primitives::abi::Abi;
2323
use proc_macro2::{
2424
Span,
2525
TokenStream as TokenStream2,
@@ -29,10 +29,23 @@ use quote::{
2929
quote_spanned,
3030
};
3131

32+
use crate::GenerateCode;
33+
3234
/// Generator to create the ink! storage struct and important trait implementations.
3335
#[derive(From, Copy, Clone)]
3436
pub struct TraitDefinition<'a> {
3537
trait_def: &'a ir::InkTraitDefinition,
38+
abi: Option<Abi>,
39+
}
40+
41+
impl<'a> From<&'a ir::InkTraitDefinition> for TraitDefinition<'a> {
42+
#[inline]
43+
fn from(value: &'a ir::InkTraitDefinition) -> Self {
44+
TraitDefinition {
45+
trait_def: value,
46+
abi: None,
47+
}
48+
}
3649
}
3750

3851
impl TraitDefinition<'_> {
@@ -55,10 +68,10 @@ impl GenerateCode for TraitDefinition<'_> {
5568
fn generate_code(&self) -> TokenStream2 {
5669
let span = self.trait_def.item().span();
5770
let trait_definition = self.generate_trait_definition();
58-
let trait_registry = self.generate_trait_registry_impl();
59-
let trait_message_builder = self.generate_message_builder();
60-
let trait_call_builder = self.generate_call_builder();
61-
let trait_call_forwarder = self.generate_call_forwarder();
71+
let trait_registry = self.generate_trait_registry_impl(self.abi);
72+
let trait_message_builder = self.generate_message_builder(self.abi);
73+
let trait_call_builder = self.generate_call_builder(self.abi);
74+
let trait_call_forwarder = self.generate_call_forwarder(self.abi);
6275
quote_spanned!(span =>
6376
#trait_definition
6477
const _: () = {

crates/ink/codegen/src/generator/trait_def/trait_registry.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ impl TraitDefinition<'_> {
4949
/// This also generates the code for the global trait info object which
5050
/// implements some `ink` traits to provide common information about
5151
/// the ink! trait definition such as its unique identifier.
52-
pub fn generate_trait_registry_impl(&self) -> TokenStream2 {
53-
TraitRegistry::from(*self).generate_code()
52+
pub fn generate_trait_registry_impl(&self, abi: Option<Abi>) -> TokenStream2 {
53+
TraitRegistry::from((*self, abi)).generate_code()
5454
}
5555

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

6869
impl GenerateCode for TraitRegistry<'_> {
@@ -193,9 +194,11 @@ impl TraitRegistry<'_> {
193194
selector,
194195
message.mutates(),
195196
);
196-
let inout_guards = generate_abi_impls!(@type |abi| {
197-
Self::generate_inout_guards_for_message(message, abi)
198-
});
197+
let generator = |abi| Self::generate_inout_guards_for_message(message, abi);
198+
let inout_guards = match self.abi {
199+
None => generate_abi_impls!(@type generator),
200+
Some(abi) => generator(abi),
201+
};
199202
let impl_body = match option_env!("INK_COVERAGE_REPORTING") {
200203
Some("true") => {
201204
quote! {
@@ -343,15 +346,12 @@ impl TraitRegistry<'_> {
343346
let span = message.span();
344347
let trait_info_ident = self.trait_def.trait_info_ident();
345348
let is_payable = message.ink_attrs().is_payable();
346-
generate_abi_impls!(@type |abi| {
349+
let generator = |abi| {
347350
let (local_id, selector_bytes) = match abi {
348351
Abi::Ink => {
349352
let local_id = message.local_id();
350353
let selector_bytes = selector.hex_lits();
351-
(
352-
quote!(#local_id),
353-
quote!([ #( #selector_bytes ),* ])
354-
)
354+
(quote!(#local_id), quote!([ #( #selector_bytes ),* ]))
355355
}
356356
Abi::Sol => {
357357
let name = message.normalized_name();
@@ -364,10 +364,7 @@ impl TraitRegistry<'_> {
364364
::core::primitive::u32::from_be_bytes(#selector_bytes)
365365
}
366366
);
367-
(
368-
selector_id,
369-
selector_bytes
370-
)
367+
(selector_id, selector_bytes)
371368
}
372369
};
373370
quote_spanned!(span=>
@@ -376,6 +373,10 @@ impl TraitRegistry<'_> {
376373
const SELECTOR: [::core::primitive::u8; 4usize] = #selector_bytes;
377374
}
378375
)
379-
})
376+
};
377+
match self.abi {
378+
None => generate_abi_impls!(@type generator),
379+
Some(abi) => generator(abi),
380+
}
380381
}
381382
}

crates/ink/codegen/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@
3535
html_favicon_url = "https://use.ink/crate-docs/favicon.png"
3636
)]
3737

38-
pub use ink_primitives::reflect;
38+
pub use ink_primitives::{
39+
abi::Abi,
40+
reflect,
41+
};
3942
mod enforced_error;
4043
mod generator;
4144
mod traits;
@@ -73,6 +76,10 @@ impl<'a> CodeGenerator for &'a ir::InkTraitDefinition {
7376
type Generator = generator::TraitDefinition<'a>;
7477
}
7578

79+
impl<'a> CodeGenerator for (&'a ir::InkTraitDefinition, Option<Abi>) {
80+
type Generator = generator::TraitDefinition<'a>;
81+
}
82+
7683
impl<'a> CodeGenerator for &'a ir::InkTest {
7784
type Generator = generator::InkTest<'a>;
7885
}

0 commit comments

Comments
 (0)