-
Notifications
You must be signed in to change notification settings - Fork 432
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement new trait definition codegen 🚀 #665
Conversation
Does the scope of this PR include the "As Storage Entity" functionality from #631? |
Is this a very much needed feature? Actually I would like to try to keep the scope of the initial MVP small. |
That's alright, I was sincerely asking if it's part of it or not, not requesting it to be included. |
The part should open up possibility to add this feature at a later point in time. However, there are still some open questions as to how the storage-related parts should syntactically look like. There are some ways, non of them obviously the best. |
Do you have ETA for this cool change?(= |
The latest commit no longer produces compile errors in the new codegen. So the new codegen basically works now. However, plenty of stuff still needs to be implemented. This whole thing is much more than just the new trait system as it will feature quite a bit other stuff, too. Will write about this more soon. The following smart contract works with the latest commit: 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() }
}
/// 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.inc_by(1)
}
#[ink(message)]
fn get(&self) -> u64 {
self.value
}
}
impl Reset for Incrementer {
#[ink(message)]
fn reset(&mut self) {
self.value = 0;
}
}
} |
Could you describe a little bit how static dependency will work, please? |
Best described by this delegator example: The gist examples already compile on this branch. |
Codecov Report
@@ Coverage Diff @@
## master #665 +/- ##
==========================================
- Coverage 82.75% 79.14% -3.62%
==========================================
Files 191 243 +52
Lines 8239 9128 +889
==========================================
+ Hits 6818 7224 +406
- Misses 1421 1904 +483
Continue to review full report at Codecov.
|
…n-calls # Conflicts: # crates/lang/Cargo.toml # crates/lang/codegen/src/generator/metadata.rs # crates/lang/macro/Cargo.toml # crates/lang/src/env_access.rs # crates/storage/derive/Cargo.toml
Done. However, I just saw that some of the things that have been implemented as side-PRs have not been included properly into the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
394 / 406
Implements #631.
Implementation TODOs:
TraitUniqueId
and its associated unique ID calculation.TraitCallForwarderFor
and others.Balance
orAccounId
by themselves.#[ink::contract]
#[ink::trait_definition]
(follow-up Add more UI tests for ink! chain extensions #951)#[ink::chain_extension]
ink_lang
definitions into publicreflect
and private/hiddencodegen
modules.reflect
module and definitions can be used by ink! smart contract authors to reflect upon their own smart contract code to a certain extend.codegen
module is hidden from users and only serves as purpose to provide definitions that can be used by the ink! codegen to enforce some Rust compiler type system based checks on the ink! smart contract code.scale::Decode + 'static
.scale::Encode + 'static
.Result::Err(_)
.ink_lang::TraitImplementer<const ID: u32>
trait implementations and super traits.payable
for them.payable
.<Contract>Ref
and its API.Overall ink! design:
Remove(Moved to a follow-up PR)ink-as-dependency
crate feature for ink! smart contracts.Add(Moved to a follow-up PR)ink-as-root
crate feature for ink! smart contracts.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 oldink-as-dependency
. It is a typed thin-wrapper around anAccountId
that is mirroring the ink! smart contract's API and implemented traits.ink! IR module:
payable:bool
modifier for ink! trait messages.namespace:str
modifier for ink! trait definitions.ink! trait definitions:
#[ink::trait_definition(..)]
#[ink(constructor)]
definitions in ink! trait definitions.This allows us to later introduce abstractions such as dynamic trait calling. (Not implemented in this PR.)
#[ink::trait_definition(namespace: str)]
.#[ink(selector: u32)]
modifier.ink! trait implementation blocks:
impl MyTrait for MyContract { ... }
#[ink(namespace: str)]
modifier on ink! trait implementation blocks.namespace
modifier would destroy trait calling invariants.#[ink(selector: u32)]
modifier.selector
in trait impl blocks would destroy trait calling invariants.selector
property on ink! trait messages in order to guard against the ink! trait definition silently changing theselector
property from the respective ink! message. This cannot be used to alter theselector
of an ink! message in an ink! implementation block. If used the selector must match the selector given via the ink! trait definition of the ink! trait message.#[ink(payable: bool)]
modifier.payable
property on ink! trait messages in order to guard against the ink! trait definition silently removing thepayable
property from the respective ink! message. Applyingpayable
on ink! trait message in implementation blocks won't alter the payability of the ink! message.Tests for the implementation:
Miscellaneous changes:
ink_storage
traits.#[ink::contract(..)]
macro.#[ink::trait_definition(..)]
macro.Drawback of the Implementation
Follow-Ups:
#[ink(payable: bool)]
modifier.#[ink(payable = flag:bool)]
instead of just#[ink(payable)]
.value: bool
ink! attributes work the same to unify user experience.ink-as-dependency
optional crate feature of ink! smart contracts withink-as-root
crate feature.ink-as-root
crate feature just states the opposite.However, it should be totally fine and maybe even useful to have ink! trait definitions as supertraits of other ink! trait definitions.
Oursourced Work
ink! modifiers:
#[ink(..)]
#[ink(selector: u32)]
to enableu32
parseable inputs#[ink(selector = 1)]
#[ink(selector = 0x01)]
#[ink(selector = "0x00000001)]
#[ink(selector: str)]
.#[ink(selector = "0xC0DECAFE")]
is no longer accepted.Use
#[ink(selector = 0xC0DECAFE)]
instead.New utility proc. macros
blake2x256
,selector_id!
andselector_bytes!
function-like proc. macros.[u8; 32]
(blake2x256
)[u8; 4]
(selector_bytes
)u32
(selector_id
)Minor simplifications and code dupe reductions in codegen #938
Improve macro hygiene in message and constructor selector namespace types #936
Misc cleanups in ink! codegen #935
Move ink_lang_macro UI tests into macro-specific folders #934
Refactor and modernize dispatch codegen #933
Add trait-incrementer example smart contract #932
Check namespace argument is identifier #931
Unrestrict parity-scale-codec crate version #930
Expand selectors as hex-encoded literals in metadata #927
Improve SpreadLayout and StorageLayout derive macro hygiene #926