Skip to content

Commit b7bb312

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 bdae382 commit b7bb312

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
@@ -4062,18 +4062,32 @@ pub const fn contract_checks() -> bool {
40624062
false
40634063
}
40644064

4065+
/// Check if the pre-condition `cond` has been met.
4066+
///
4067+
/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
4068+
/// returns false.
40654069
#[cfg(not(bootstrap))]
40664070
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
4071+
#[lang = "contract_check_requires"]
40674072
#[rustc_intrinsic]
4068-
pub fn contract_check_requires<C: FnOnce() -> bool>(c: C) -> bool {
4069-
c()
4073+
pub fn contract_check_requires<C: Fn() -> bool>(cond: C) {
4074+
if contract_checks() && !cond() {
4075+
// Emit no unwind panic in case this was a safety requirement.
4076+
crate::panicking::panic_nounwind("failed requires check");
4077+
}
40704078
}
40714079

4080+
/// Check if the post-condition `cond` has been met.
4081+
///
4082+
/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
4083+
/// returns false.
40724084
#[cfg(not(bootstrap))]
40734085
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
40744086
#[rustc_intrinsic]
4075-
pub fn contract_check_ensures<'a, Ret, C: FnOnce(&'a Ret) -> bool>(ret: &'a Ret, c: C) -> bool {
4076-
c(ret)
4087+
pub fn contract_check_ensures<'a, Ret, C: Fn(&'a Ret) -> bool>(ret: &'a Ret, cond: C) {
4088+
if contract_checks() && !cond(ret) {
4089+
crate::panicking::panic_nounwind("failed ensures check");
4090+
}
40774091
}
40784092

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

0 commit comments

Comments
 (0)