-
Notifications
You must be signed in to change notification settings - Fork 449
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
Refactor implementation of call builders for traits #983
Conversation
I think the problem is that in the case of the local crate we know all implementation of the trait, so we know that |
I implemented idea from the comment. To show that it works=) It is not a final change, I need validation from @Robbepop and @cmichi. If they agree, I will implement it fully. Also maybe you want to use this approach in several places. I tested |
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.
Hey @xgreenx!
I'm gonna try and get up to speed to this so we can move forward with it. So from what I understand the problem is that right now ink!
does not support contracts which implement multiple external traits. However, it does support contracts with:
- Multiple internal traits (so defined by the contract itself)
- A single external trait
From the compiler error it looks like this has to do with the structure of the codegen
around the CallBuilder
.
I still need to dig into the code, but can you describe (at a high level) how the solution you propose here with the extra trait implementation fixes this problem?
Also, can you either merge or rebase master
?
At the moment the code generates the implementation of traits for The idea of the suggested fix is to define a generic implementation for So in two words, I suggest implementing traits for
I can do that, but if you are okay with the idea of the change, I can implement it fully(clean up the code, update tests). I did a draft implementation to show that it fixes the problem and still creates a right |
I need to understand the original code before I can assess if your solution should go beyond a draft, so hang tight for now |
Okay, so I'm still trying to wrap my head around the root of the problem, maybe you can help me understand. So again, the compiler complains about "conflicting implementations of trait From the expanded example contract you provided, here are the two places where we try and implement Since the compiler is complaining, this implies that: let T1 = <::ink_lang::reflect::TraitDefinitionRegistry<Environment> as Increment>::__ink_TraitInfo;
let T2 = <::ink_lang::reflect::TraitDefinitionRegistry<Environment> as Reset>::__ink_TraitInfo;
T1 == T2 Otherwise the trait implementations would be different. The definitions for This leaves us with two different structs, Since these are different types, the trait implementations should be different. What am I missing here? |
Everything is right. The code generates the implementation for the impl ::ink_lang::codegen::TraitCallForwarderFor<#trait_info> for #cb_ident
When two traits are defined in the crate of the contract then |
Okay, so I was pretty stumped here and luckily @ascjones came to the rescue identifying this as rust-lang/rust#51445. So the first fix that comes to mind for me is to have the macro extract the concrete type behind |
Could you elaborate more on it? Because I didn't get it=) |
So instead of the macro generating |
The problem is that It is why it was initially moved to Your idea requires the user to import an additional generated type or explicitly write a path to the trait(in that case we can use the same prefix for the type like |
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.
Okay, so I get how you're trying to solve this. I'm not a huge fan of the blanket impl, but I get why you're doing it. If possible, I'd look for ways to tighten the scope of the implementation up a bit.
Another thing I noticed, there's no more implementation of TraitCallForwarderFor
for CallBuilder
. I wonder if that's going to have any unintended consequences.
Anyways, I'm okay moving forward with this approach, so feel free to merge master and clean it up once you get a chance
a39b980
to
d5cecc4
Compare
🦑 📈 ink! Example Contracts ‒ Changes Report 📉 🦑These are the results when building the
Link to the run | Last update: Wed Feb 16 23:42:16 CET 2022 |
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.
Couple of questions, but I think it looks alright
/// We insert markers for these errors in the generated contract code. | ||
/// This is necessary since we can't check these errors at compile time | ||
/// of the contract. | ||
/// `cargo-contract` checks the contract code for these error markers | ||
/// when building a contract and fails if it finds markers. |
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.
We'll need a follow up in cargo-contract
to remove these checks
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.
It is used in the implementation of the to+account_id
for TraitDefinitionRegistry
. So I moved that comment there=)
Codecov Report
@@ Coverage Diff @@
## master #983 +/- ##
==========================================
- Coverage 78.72% 75.53% -3.20%
==========================================
Files 253 252 -1
Lines 9409 9257 -152
==========================================
- Hits 7407 6992 -415
- Misses 2002 2265 +263
Continue to review full report at Codecov.
|
d5cecc4
to
bf251aa
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.
Still trying to clarify things around the __ink_enforce_error
thing
Oh, also a couple of thoughs.
|
|
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.
Some small doc fixes, but I think this is good to go 😄
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.
Looks good, thanks!
Gonna see if we can get another quick look (@ascjones 😃?) before merging
Yes I am looking at this today! |
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.
The main issue I have is that this is quite a significant refactoring to solve this particular issue. To this end I explored a few alternatives to see whether it is possible to fix it with a much smaller change. The one I came up with is #1136. Please have a look and let me know what you think of that. There may be some issues with it that I have not considered.
@xgreenx how CI team can help in this review? |
@TriplEight The CI team was requested automatically for review, since you added yourself as code owners a while ago. I think there were some temporary changes to the GitLab config to comment some stages out, but now no longer. I'm removing the request for you to review. |
@xgreenx #1141 is merged now, which fixes the conflicting impls issue which I understand was the main motivator for this change. However you did say that there were other motivations for this refactor which aren't mentioned here:
So up to you how you want to proceed - I suggest to close this and open a fresh PR when the blanket implementation is actually required for the future change, and we can review it in the context of that and removing code redundancy. |
@xgreenx Thanks a lot for finding the bug in the first place, providing a solution and partaking in all the discussions on how to fix it! Even though we ended up closing your PR with the first approach to fix the bug, we wouldn't have gotten to the final solution without you and the discussions we had with you on possible solutions. We want to give you a tip for all of that. Thank you! Could you edit your description of this PR and add either one of those?
or
|
/tip medium |
1 similar comment
/tip medium |
A medium tip was successfully submitted for xgreenx (1nNaTpU9GHFvF7ZrSMu2CudQjXftR8Aqx58oMDgcuoH8dKe on polkadot). |
Before that pull request
#[ink_lang::contract]
generated the implementation of call builders for the contract. That generated code usedink_lang::codegen::TraitCallForwarderFor<TraitInfoType>
to implement traits defined via#[ink_lang::trait_definition]
. But if traits are foreign(defined in the another crate) it caused a compilation error that two implementation ofink_lang::codegen::TraitCallForwarderFor<TraitInfoType1>
andink_lang::codegen::TraitCallForwarderFor<TraitInfoType2>
are conflicting.The reason the types were conflicting (despite being different) is because of rust-lang/rust#51445.
The idea of the change is to generate the blanket implementation of the traits for call builders during the definition of the traits(In the same crate where the trait is defined). It will prevent the compilation error because
__ink_TraitInfo
is not foreign.Closes #982.