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.
This commit is contained in:
Celina G. Val
2025-01-17 14:49:10 -08:00
parent 804cce47d9
commit 2bb1464cb6
7 changed files with 57 additions and 72 deletions

View File

@@ -1,38 +1,21 @@
//! Unstable module containing the unstable contracts lang items and attribute macros.
#![cfg(not(bootstrap))]
#[cfg(not(bootstrap))]
pub use crate::macros::builtin::contracts_ensures as ensures;
#[cfg(not(bootstrap))]
pub use crate::macros::builtin::contracts_requires as requires;
/// Emitted by rustc as a desugaring of `#[requires(PRED)] fn foo(x: X) { ... }`
/// into: `fn foo(x: X) { check_requires(|| PRED) ... }`
#[cfg(not(bootstrap))]
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
#[lang = "contract_check_requires"]
#[track_caller]
pub fn check_requires<C: FnOnce() -> bool>(c: C) {
if core::intrinsics::contract_checks() {
assert!(core::intrinsics::contract_check_requires(c), "failed requires check");
}
}
pub use crate::macros::builtin::{contracts_ensures as ensures, contracts_requires as requires};
/// Emitted by rustc as a desugaring of `#[ensures(PRED)] fn foo() -> R { ... [return R;] ... }`
/// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }`
/// (including the implicit return of the tail expression, if any).
#[cfg(not(bootstrap))]
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
#[lang = "contract_build_check_ensures"]
#[track_caller]
pub fn build_check_ensures<Ret, C>(c: C) -> impl (FnOnce(Ret) -> Ret) + Copy
pub fn build_check_ensures<Ret, C>(cond: C) -> impl (Fn(Ret) -> Ret) + Copy
where
C: for<'a> FnOnce(&'a Ret) -> bool + Copy + 'static,
C: for<'a> Fn(&'a Ret) -> bool + Copy + 'static,
{
#[track_caller]
move |ret| {
if core::intrinsics::contract_checks() {
assert!(core::intrinsics::contract_check_ensures(&ret, c), "failed ensures check");
}
crate::intrinsics::contract_check_ensures(&ret, cond);
ret
}
}