-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Contract variable declarations #144444
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
Open
dawidl022
wants to merge
1
commit into
rust-lang:master
Choose a base branch
from
dawidl022:contracts/variable-scoping-rebased
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Contract variable declarations #144444
dawidl022
wants to merge
1
commit into
rust-lang:master
from
dawidl022:contracts/variable-scoping-rebased
+325
−61
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68621b6
to
4a765bc
Compare
This comment has been minimized.
This comment has been minimized.
4a765bc
to
ab96f97
Compare
This comment has been minimized.
This comment has been minimized.
ab96f97
to
e41951a
Compare
This comment has been minimized.
This comment has been minimized.
matthiaskrgr
added a commit
to matthiaskrgr/rust
that referenced
this pull request
Oct 16, 2025
…ng, r=oli-obk Guard HIR lowered contracts with `contract_checks` 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 rust-lang#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 both `requires` and `ensures`, but not in the function body (PR rust-lang#144444). As those declarations may also have side-effects, it's good to guard them with `contract_checks` - the new lowering approach allows for this to be done easily. Contracts tracking issue: rust-lang#128044 **Known limiatations**: - It is still possible to early return from the *function* from within a contract, e.g. ```rust #[ensures({if x > 0 { return 0 }; |_| true})] fn foo(x: u32) -> i32 { 42 } ``` When `foo` is called with an argument greater than 0, instead of `42`, `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 rust-lang#136578, and has not been addressed in this PR, i.e. the `mir-opt` and `codegen` tests that fail in rust-lang#136578 still fail with these new HIR lowering changes.~ Contracts should now be optimised out when disabled, however some regressions tests still need to be added to be sure that is indeed the case.
rust-timer
added a commit
that referenced
this pull request
Oct 16, 2025
Rollup merge of #144438 - dawidl022:contracts/guarded-lowering, r=oli-obk Guard HIR lowered contracts with `contract_checks` 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 both `requires` and `ensures`, but not in the function body (PR #144444). As those declarations may also have side-effects, it's good to guard them with `contract_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. ```rust #[ensures({if x > 0 { return 0 }; |_| true})] fn foo(x: u32) -> i32 { 42 } ``` When `foo` is called with an argument greater than 0, instead of `42`, `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 #136578, and has not been addressed in this PR, i.e. the `mir-opt` and `codegen` tests that fail in #136578 still fail with these new HIR lowering changes.~ Contracts should now be optimised out when disabled, however some regressions tests still need to be added to be sure that is indeed the case.
e41951a
to
838dda6
Compare
838dda6
to
a291a4d
Compare
This comment has been minimized.
This comment has been minimized.
Contract variables can be declared in the `requires` clause and can be referenced both in `requires` and `ensures`, subject to usual borrow checking rules. This allows any setup common to both the `requires` and `ensures` clauses to only be done once.
a291a4d
to
aeae085
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
S-waiting-on-review
Status: Awaiting review from the assignee but also interested parties.
T-compiler
Relevant to the compiler team, which will review and decide on the PR/issue.
T-libs
Relevant to the library team, which will review and decide on the PR/issue.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This change adds contract variables that can be declared in the
requires
clause and can be referenced both inrequires
andensures
, subject to usual borrow checking rules. This allows any setup common to both therequires
andensures
clauses to only be done once.In particular, one future use case would be for Fulminate-like ownership assertions in contracts, that are essentially side-effects, and executing them twice would alter the semantics of the contract.
As of this change,
requires
can now be an arbitrary sequence of statements, with the final expression being of typebool
. They are executed in sequence as expected, before checking if the finalbool
expression holds.This PR depends on #144438 (which has now been merged).
Contracts tracking issue: #128044
Other changes introduced:
{}
when using multiple statements. The change is backwards compatible, in that wrapping the content in{}
still works as before. The macros also now treatrequires
andensures
uniformally, meaning therequires
closure is built inside the parser, as opposed to in the macro.Known limiatations:
Contracts with variable declarations are subject to the regular borrow checking rules, and the way contracts are currently lowered limits the usefulness of contract variable declarations. Consider the below example:
We have used the new variable declarations feature to remember the initial value pointed to by
x
, however, movingx
into theensures
does not pass the borrow checker, meaning the above function contract is illegal. Ideally, something like the above should be expressable in contracts.