-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Guard HIR lowered contracts with contract_checks
#144438
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
base: master
Are you sure you want to change the base?
Conversation
What if we remove the The main downside is that there will be no way to enable the |
I think this would indeed fix the issue. I wanted to try it out, but wasn't sure how to access compiler flags (e.g. |
You should be able to access them through |
library/core/src/intrinsics/mod.rs
Outdated
#[lang = "contract_checks"] | ||
#[rustc_intrinsic] |
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.
Making the same thing both a lang item and an intrinsic doesn't make a lot of sense. Why do you propose to do this?
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.
Making the same thing both a lang item and an intrinsic doesn't make a lot of sense.
Could you please elaborate why this doesn't make sense, or point me to sources where I can read up on this? I don't really understand the relationship between the two.
Why do you propose to do this?
I added the lang item annotation so that I can generate HIR code referring to contract_checks
, and did not think there was anything wrong with that, given that both contract_check_requires
and contract_check_ensures
are already marked both as lang items and intrinsics.
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.
Hm, I didn't realize we already have things hat are both.
The reason I said that it doesn't make sense is that intrinsics are one way to make a function magic, and lang items are another. Having a function be magic in 2 different ways is... a bit too much magic?^^
Lang items are strictly more powerful than intrinsics, so I would have expected this to be just a lang item then, and not also an intrinsic. But if this works fine then I guess we can keep it for now. It can always be changed later.
I'm happy to implement it that way, and if there is consensus, close this this PR in favour of that solution. I imagine that even with Maybe the "typechecking when disabled issue" is not a priority right now, given that we're still figuring out what exactly the contract language should be (i.e. what extra rules contracts have to obey w.r.t. regular rust code). If that's the case, I'm happy to proceed with whatever makes most sense for now. Right now, when naively guarding the call to |
Goal: fully optimise out contracts when disabled, whilst preserving type checkingAs suggested by @RalfJung, I am starting a high-level discussion on what the HIR lowering should look like "sketching out the lowering "on paper" until it has a shape that has good chances of being optimizeable.", detailing the designed I've tried out and what didn't work in each. Hopefully, we can together come up with a lowering strategy that meets the above goal. Note: the above goal was not the original purpose of this PR, but given the discussions here, it seems it is desirable. The original purpose of the PR was to ensure no part of the contract was executed when disabled, and to prepare for #144444. New lowering approach proposed in this PRWe split the lowering of contracts into 4 distinct cases, providing the lowered pseudocode for each:
Limitations of the lowering approachSince Potential solutionsEvaluate
|
Is something setting However, I also don't understand what you think that would achieve. You already generate hard-coded
Regarding the inference issue - the type of
This one seems most promising to me. Everything the MIR opts need is right there in the body without knowing anything about what the intrinsics do, and passing |
This comment has been minimized.
This comment has been minimized.
Refactor contract HIR lowering to ensure no contract code is executed when contract-checks are disabled. The call to contract_checks is moved to inside the lowered fn body, and contract closures are built conditionally, ensuring no side-effects present in contracts occur when those are disabled.
3f1f989
to
8c14d58
Compare
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
I went for:
and the contracts in #136578 now pass the What would be a good way of rigorously testing whether contracts are indeed fully optimised out with this change, as opposed to relying on the observation that one optimisation test that was failing before now succeeds? |
This comment has been minimized.
This comment has been minimized.
This allows the optimiser to properly eliminate contract code when runtime contract checks are disabled. It comes at the cost of having to recompile upstream crates (e.g. std) to enable contracts in them. However, this trade off is acceptable if it means disabled runtime contract checks do not affect the runtime performance of the functions they annotate. With the proper elimination of contract code, which this change introduces, the runtime performance of annotated functions should be the same as the original unannotated function.
8c14d58
to
1d15fc3
Compare
The contract_checks compiler flag is now used to determine if runtime contract checks should be enabled, as opposed to the compiler intrinsic as previously.
The compiler complained about uncecessary parenthesis on contract clauses, which were insterted by the contract macros. This commit changes the macro to use braces as the delimiter instead, fixing the issue.
1d15fc3
to
f0e0592
Compare
@celinval what clean up needs to be done for this? I removed the intrinsic from |
Hey @dawidl022, yes, we should remove the symbol and type check. And thank you! |
Refactor contract HIR lowering to ensure no contract code is executed when contract-checks are disabled.
The call to
contract_checks
is moved to inside the lowered fn body, and contract closures are built conditionally, ensuring no side-effects present in contracts occur when those are disabled. This partially addresses #139548, i.e. the bad behavior no longer happens with contract checks disabled (-Zcontract-checks=no
).The change is made in preparation for adding contract variable declarations - variables declared before the
requires
assertion, and accessible from bothrequires
andensures
, but not in the function body (PR #144444). As those declarations may also have side-effects, it's good to guard them withcontract_checks
- the new lowering approach allows for this to be done easily.Contracts tracking issue: #128044
Known limiatations:
It is still possible to early return from the function from within a contract, e.g.
When
foo
is called with an argument greater than 0, instead of42
,0
will be returned.As this is not a regression, it is not addressed in this PR. However, it may be worth revisiting later down the line, as users may expect a form of early return from contract specifications, and so returning from the entire function could cause confusion.
Contracts are still not optimised out when disabled. Currently, even when contracts are disabled, the code generated causes existing optimisations to fail, meaning even disabled contracts could impact runtime performance. This issue is blocking Add contracts for all functions inContracts should now be optimised out when disabled, however some regressions tests still need to be added to be sure that is indeed the case.Alignment
#136578, and has not been addressed in this PR, i.e. themir-opt
andcodegen
tests that fail in Add contracts for all functions inAlignment
#136578 still fail with these new HIR lowering changes.