-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Enable contracts for const functions #138374
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
Conversation
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.
In what case is the unreachable error being generated? Can you turn it into a minimal example? I'm not totally sure what's going on with the code generation.
I am still trying to understand why the new logic triggers the new warning, when the old one didn't.
So, if you look at the following example from one of the tests: #![feature(contracts)]
pub struct Baz { baz: i32 }
#[core::contracts::requires(x.baz > 0)]
#[core::contracts::ensures(|ret| *ret > 100)]
pub fn nest(x: Baz) -> i32
{
loop {
return x.baz + 50;
}
} with the existing changes, you will get a warning:
which in a way it makes sense, since we do add a call to check the post-condition after the loop statement. What I don't get is why it wasn't being triggered before, and whether I can mark the new code as If I compile with fn nest(x: Baz) -> i32 {
#[lang = "contract_check_requires"](|| x.baz > 0);
let __ensures_checker = #[lang = "contract_build_check_ensures"](|ret| *ret > 100);
#[lang = "contract_check_ensures"]({
loop { return #[lang = "contract_check_ensures"](x.baz + 50, __ensures_checker); }
}, __ensures_checker)
} before the changes, we had: fn nest(x: Baz) -> i32 {
#[lang = "contract_check_requires"](|| x.baz > 0);
let __ensures_checker = #[lang = "contract_build_check_ensures"](|ret| *ret > 100);
__ensures_checker({ loop { return __ensures_checker(x.baz + 50); } })
} |
2ff3baa
to
4dd0bca
Compare
This comment has been minimized.
This comment has been minimized.
@compiler-errors any thoughts? |
No, I didn't look at it yet |
In the example,
My understanding is that fn nest(x: Baz) -> i32 {
#[lang = "contract_check_requires"](|| x.baz > 0);
let __ensures_checker = #[lang = "contract_build_check_ensures"](|ret| *ret > 100);
#[lang = "contract_check_ensures"]({
loop { return #[lang = "contract_check_ensures"](x.baz + 50, __ensures_checker); }
}, #[allow(unreachable_code)] __ensures_checker)
} |
The call is added as part of lowering the AST today. We can reconsider it though. |
☔ The latest upstream changes (presumably #138996) made this pull request unmergeable. Please resolve the merge conflicts. |
Use `const_eval_select!()` macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions. This commit also removes one level of indirection for ensures clauses, however, it currently has a spurious warning message when the bottom of the function is unreachable.
4dd0bca
to
4f62bc2
Compare
Invert the order that we pass the arguments to the `contract_check_ensures` function to avoid the warning when the tail of the function is unreachable. Note that the call itself is also unreachable, but we have already handled that case by ignoring unreachable call for contract calls.
4f62bc2
to
3feac59
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.
Just a nit
LGTM from a const-eval perspective. I can't say anything about the |
Just confirming that all the contracts proposed in #136578 pass with the latest set of changes in this PR. |
@compiler-errors, any chance you can take a look at this PR? |
Co-authored-by: Ralf Jung <[email protected]>
@bors r=compiler-errors,oli-obk,RalfJung |
…ct, r=compiler-errors,oli-obk,RalfJung Enable contracts for const functions Use `const_eval_select!()` macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions. This commit also removes one level of indirection for ensures clauses since we no longer build a closure around the ensures predicate. Resolves rust-lang#136925 **Call-out:** This is still a draft PR since CI is broken due to a new warning message for unreachable code when the bottom of the function is indeed unreachable. It's not clear to me why the warning wasn't triggered before. r? `@compiler-errors`
Rollup of 12 pull requests Successful merges: - rust-lang#138374 (Enable contracts for const functions) - rust-lang#138380 (ci: add runners for vanilla LLVM 20) - rust-lang#138393 (Allow const patterns of matches to contain pattern types) - rust-lang#139393 (rustdoc-json: Output target feature information) - rust-lang#139517 (std: sys: process: uefi: Use NULL stdin by default) - rust-lang#139554 (std: add Output::exit_ok) - rust-lang#139745 (Avoid unused clones in `Cloned<I>` and `Copied<I>`) - rust-lang#139757 (opt-dist: use executable-extension for host llvm-profdata) - rust-lang#139778 (Add test for issue 34834) - rust-lang#139783 (Use `compiletest-ignore-dir` for bootstrap self-tests) - rust-lang#139789 (do not unnecessarily leak auto traits in item bounds) - rust-lang#139791 (drop global where-bounds before merging candidates) r? `@ghost` `@rustbot` modify labels: rollup
…ct, r=compiler-errors,oli-obk,RalfJung Enable contracts for const functions Use `const_eval_select!()` macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions. This commit also removes one level of indirection for ensures clauses since we no longer build a closure around the ensures predicate. Resolves rust-lang#136925 **Call-out:** This is still a draft PR since CI is broken due to a new warning message for unreachable code when the bottom of the function is indeed unreachable. It's not clear to me why the warning wasn't triggered before. r? ``@compiler-errors``
Rollup of 17 pull requests Successful merges: - rust-lang#138374 (Enable contracts for const functions) - rust-lang#138380 (ci: add runners for vanilla LLVM 20) - rust-lang#138393 (Allow const patterns of matches to contain pattern types) - rust-lang#139517 (std: sys: process: uefi: Use NULL stdin by default) - rust-lang#139554 (std: add Output::exit_ok) - rust-lang#139660 (compiletest: Add an experimental new executor to replace libtest) - rust-lang#139669 (Overhaul `AssocItem`) - rust-lang#139671 (Proc macro span API redesign: Replace proc_macro::SourceFile by Span::{file, local_file}) - rust-lang#139750 (std/thread: Use default stack size from menuconfig for NuttX) - rust-lang#139772 (Remove `hir::Map`) - rust-lang#139785 (Let CStrings be either 1 or 2 byte aligned.) - rust-lang#139789 (do not unnecessarily leak auto traits in item bounds) - rust-lang#139791 (drop global where-bounds before merging candidates) - rust-lang#139798 (normalize: prefer `ParamEnv` over `AliasBound` candidates) - rust-lang#139822 (Fix: Map EOPNOTSUPP to ErrorKind::Unsupported on Unix) - rust-lang#139833 (Fix some HIR pretty-printing problems) - rust-lang#139836 (Basic tests of MPMC receiver cloning) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#138374 - celinval:issue-136925-const-contract, r=compiler-errors,oli-obk,RalfJung Enable contracts for const functions Use `const_eval_select!()` macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions. This commit also removes one level of indirection for ensures clauses since we no longer build a closure around the ensures predicate. Resolves rust-lang#136925 **Call-out:** This is still a draft PR since CI is broken due to a new warning message for unreachable code when the bottom of the function is indeed unreachable. It's not clear to me why the warning wasn't triggered before. r? ```@compiler-errors```
…ct, r=compiler-errors,oli-obk,RalfJung Enable contracts for const functions Use `const_eval_select!()` macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions. This commit also removes one level of indirection for ensures clauses since we no longer build a closure around the ensures predicate. Resolves rust-lang#136925 **Call-out:** This is still a draft PR since CI is broken due to a new warning message for unreachable code when the bottom of the function is indeed unreachable. It's not clear to me why the warning wasn't triggered before. r? ```@compiler-errors```
Rollup of 17 pull requests Successful merges: - rust-lang#138374 (Enable contracts for const functions) - rust-lang#138380 (ci: add runners for vanilla LLVM 20) - rust-lang#138393 (Allow const patterns of matches to contain pattern types) - rust-lang#139517 (std: sys: process: uefi: Use NULL stdin by default) - rust-lang#139554 (std: add Output::exit_ok) - rust-lang#139660 (compiletest: Add an experimental new executor to replace libtest) - rust-lang#139669 (Overhaul `AssocItem`) - rust-lang#139671 (Proc macro span API redesign: Replace proc_macro::SourceFile by Span::{file, local_file}) - rust-lang#139750 (std/thread: Use default stack size from menuconfig for NuttX) - rust-lang#139772 (Remove `hir::Map`) - rust-lang#139785 (Let CStrings be either 1 or 2 byte aligned.) - rust-lang#139789 (do not unnecessarily leak auto traits in item bounds) - rust-lang#139791 (drop global where-bounds before merging candidates) - rust-lang#139798 (normalize: prefer `ParamEnv` over `AliasBound` candidates) - rust-lang#139822 (Fix: Map EOPNOTSUPP to ErrorKind::Unsupported on Unix) - rust-lang#139833 (Fix some HIR pretty-printing problems) - rust-lang#139836 (Basic tests of MPMC receiver cloning) r? `@ghost` `@rustbot` modify labels: rollup
Use
const_eval_select!()
macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions.This commit also removes one level of indirection for ensures clauses since we no longer build a closure around the ensures predicate.
Resolves #136925
Call-out: This is still a draft PR since CI is broken due to a new warning message for unreachable code when the bottom of the function is indeed unreachable. It's not clear to me why the warning wasn't triggered before.
r? @compiler-errors