-
Notifications
You must be signed in to change notification settings - Fork 429
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 trait support - Part 1/3 - New ink! IR #451
Conversation
e67b4c3
to
eae7db9
Compare
Codecov Report
@@ Coverage Diff @@
## master #451 +/- ##
==========================================
- Coverage 86.83% 84.80% -2.03%
==========================================
Files 135 125 -10
Lines 5877 5343 -534
==========================================
- Hits 5103 4531 -572
- Misses 774 812 +38
Continue to review full report at Codecov.
|
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.
WIP 7/30 files
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.
WIP 12/30
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.
30/30. Left some comments - looking good
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.
LGTM
This is in order to sync naming with the syn crate.
Co-authored-by: Andrew Jones <[email protected]>
Co-authored-by: Andrew Jones <[email protected]>
Co-authored-by: Andrew Jones <[email protected]>
Co-authored-by: Andrew Jones <[email protected]>
afc5436
to
5e4b6ae
Compare
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.
LGTM!
Implements & closes #441.
tl;dr
The PR packs all of the new definitions into a new ink! crate, called
ink_lang_ir
.This new crate provides abstractions to parse, analyze and inspect ink! smart contract code on an IR level.
Other utilities, such as the planned new ink! codegen can then depend on
ink_lang_ir
and use its API to do their jobs.A rough outline of the API surface is shown in the screenshot below:
ToDo List
Event
Storage
Message
Constructor
salt
tonamespace
.(&Field, bool)
where if thebool
istrue
the&Field
is a topic field.TryFrom<syn::Module> for ir2::Module
.#[ink(storage)]
structs.#[ink(constructor)]
.#[ink(message)]
.Constructor
andMessage
checks from withinir2::ItemImpl
.Message
of inherentItemImpl
has public visibility.Message
of traitItemImpl
has inherited visibility. (Maybe not needed.)In order to sanely implement traits we have to change the ink!'s IR to no longer be message & constructor focused but implementation block centric. That way we can also generate code that is more similar to the original user input. Also this allows to have more fine grained control over the output of ink! as a user.
By rewriting the ink! IR we are trying to find a design and implementation that suits other issues in the issue tracker, e.g. being able to apply multiple ink! markers to entities, e.g.:
Main Challenge & Problem
The main challenge behind ink!'s trait support is to somehow enforce on a syntactical level (we are still just a macro) that either none (normal trait implementation) or all methods lead to some properly specified ink! trait implementation.
E.g. when looking at a trait with default members or with super traits it is easy that we could implement a trait like this:
While the above example is safe and ink! would be able to provide proper accessors to it so that users cannot misuse it or do cross-calls that end in nowhere the following example is more involved for ink! (or even impossible to safeguard).
In this example, since ink! only ever has access to the syntactical portions of all items the ink! macro cannot know the internal structure of the
SuperTrait
or even theBaseTrait
and only sees the requiredBaseTrait::foo
method for which it creates the correct code. However, forBaseTrait::bar
it will generate incorrect code that callsSuperTrait::super_foo
without it being a proper cross-contract call on the chain. This is a huge problem and I currently do not see any solution to this. Since we cannot spot this we cannot even generate a warning in its place. The only potential solution is to require traits to be defined in the same ink! module where they have been implemented which kind of destroys the gains of having them in the first place.We still think that the above mentioned problem can be fixed if we don't implement non-ink! marked traits for the cross-calling wrappers of a contract. We believe that this way we can again guarantee that all trait implementations will result in a proper cross-contract call.