-
Notifications
You must be signed in to change notification settings - Fork 13.6k
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
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.
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 |
#[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 |
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 in
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.