Skip to content

Commit 75cb4c1

Browse files
celinvalgitbot
authored and
gitbot
committed
Improve contracts intrisics and remove wrapper function
1. Document the new intrinsics. 2. Make the intrinsics actually check the contract if enabled, and remove `contract::check_requires` function. 3. Use panic with no unwind in case contract is using to check for safety, we probably don't want to unwind. Following the same reasoning as UB checks.
1 parent 188ffee commit 75cb4c1

File tree

2 files changed

+23
-26
lines changed

2 files changed

+23
-26
lines changed

core/src/contracts.rs

+5-22
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,21 @@
11
//! Unstable module containing the unstable contracts lang items and attribute macros.
2+
#![cfg(not(bootstrap))]
23

3-
#[cfg(not(bootstrap))]
4-
pub use crate::macros::builtin::contracts_ensures as ensures;
5-
#[cfg(not(bootstrap))]
6-
pub use crate::macros::builtin::contracts_requires as requires;
7-
8-
/// Emitted by rustc as a desugaring of `#[requires(PRED)] fn foo(x: X) { ... }`
9-
/// into: `fn foo(x: X) { check_requires(|| PRED) ... }`
10-
#[cfg(not(bootstrap))]
11-
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
12-
#[lang = "contract_check_requires"]
13-
#[track_caller]
14-
pub fn check_requires<C: FnOnce() -> bool>(c: C) {
15-
if core::intrinsics::contract_checks() {
16-
assert!(core::intrinsics::contract_check_requires(c), "failed requires check");
17-
}
18-
}
4+
pub use crate::macros::builtin::{contracts_ensures as ensures, contracts_requires as requires};
195

206
/// Emitted by rustc as a desugaring of `#[ensures(PRED)] fn foo() -> R { ... [return R;] ... }`
217
/// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }`
228
/// (including the implicit return of the tail expression, if any).
23-
#[cfg(not(bootstrap))]
249
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
2510
#[lang = "contract_build_check_ensures"]
2611
#[track_caller]
27-
pub fn build_check_ensures<Ret, C>(c: C) -> impl (FnOnce(Ret) -> Ret) + Copy
12+
pub fn build_check_ensures<Ret, C>(cond: C) -> impl (Fn(Ret) -> Ret) + Copy
2813
where
29-
C: for<'a> FnOnce(&'a Ret) -> bool + Copy + 'static,
14+
C: for<'a> Fn(&'a Ret) -> bool + Copy + 'static,
3015
{
3116
#[track_caller]
3217
move |ret| {
33-
if core::intrinsics::contract_checks() {
34-
assert!(core::intrinsics::contract_check_ensures(&ret, c), "failed ensures check");
35-
}
18+
crate::intrinsics::contract_check_ensures(&ret, cond);
3619
ret
3720
}
3821
}

core/src/intrinsics/mod.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -4082,18 +4082,32 @@ pub const fn contract_checks() -> bool {
40824082
false
40834083
}
40844084

4085+
/// Check if the pre-condition `cond` has been met.
4086+
///
4087+
/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
4088+
/// returns false.
40854089
#[cfg(not(bootstrap))]
40864090
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
4091+
#[lang = "contract_check_requires"]
40874092
#[rustc_intrinsic]
4088-
pub fn contract_check_requires<C: FnOnce() -> bool>(c: C) -> bool {
4089-
c()
4093+
pub fn contract_check_requires<C: Fn() -> bool>(cond: C) {
4094+
if contract_checks() && !cond() {
4095+
// Emit no unwind panic in case this was a safety requirement.
4096+
crate::panicking::panic_nounwind("failed requires check");
4097+
}
40904098
}
40914099

4100+
/// Check if the post-condition `cond` has been met.
4101+
///
4102+
/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
4103+
/// returns false.
40924104
#[cfg(not(bootstrap))]
40934105
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
40944106
#[rustc_intrinsic]
4095-
pub fn contract_check_ensures<'a, Ret, C: FnOnce(&'a Ret) -> bool>(ret: &'a Ret, c: C) -> bool {
4096-
c(ret)
4107+
pub fn contract_check_ensures<'a, Ret, C: Fn(&'a Ret) -> bool>(ret: &'a Ret, cond: C) {
4108+
if contract_checks() && !cond(ret) {
4109+
crate::panicking::panic_nounwind("failed ensures check");
4110+
}
40974111
}
40984112

40994113
/// The intrinsic will return the size stored in that vtable.

0 commit comments

Comments
 (0)