Skip to content

Commit ff980f2

Browse files
committed
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.
1 parent aae37fe commit ff980f2

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

core/src/intrinsics/mod.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,9 +2637,10 @@ pub const unsafe fn const_make_global(ptr: *mut u8) -> *const u8 {
26372637
/// of not prematurely committing at compile-time to whether contract
26382638
/// checking is turned on, so that we can specify contracts in libstd
26392639
/// and let an end user opt into turning them on.
2640-
#[rustc_const_unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
26412640
#[unstable(feature = "contracts_internals", issue = "128044" /* compiler-team#759 */)]
2641+
#[rustc_const_unstable(feature = "contracts", issue = "128044")]
26422642
#[inline(always)]
2643+
#[lang = "contract_checks"]
26432644
#[rustc_intrinsic]
26442645
pub const fn contract_checks() -> bool {
26452646
// FIXME: should this be `false` or `cfg!(contract_checks)`?
@@ -2668,7 +2669,7 @@ pub const fn contract_check_requires<C: Fn() -> bool + Copy>(cond: C) {
26682669
if const {
26692670
// Do nothing
26702671
} else {
2671-
if contract_checks() && !cond() {
2672+
if !cond() {
26722673
// Emit no unwind panic in case this was a safety requirement.
26732674
crate::panicking::panic_nounwind("failed requires check");
26742675
}
@@ -2681,6 +2682,8 @@ pub const fn contract_check_requires<C: Fn() -> bool + Copy>(cond: C) {
26812682
/// By default, if `contract_checks` is enabled, this will panic with no unwind if the condition
26822683
/// returns false.
26832684
///
2685+
/// If `cond` is `None`, then no postcondition checking is performed.
2686+
///
26842687
/// Note that this function is a no-op during constant evaluation.
26852688
#[unstable(feature = "contracts_internals", issue = "128044")]
26862689
// Similar to `contract_check_requires`, we need to use the user-facing
@@ -2689,16 +2692,24 @@ pub const fn contract_check_requires<C: Fn() -> bool + Copy>(cond: C) {
26892692
#[rustc_const_unstable(feature = "contracts", issue = "128044")]
26902693
#[lang = "contract_check_ensures"]
26912694
#[rustc_intrinsic]
2692-
pub const fn contract_check_ensures<C: Fn(&Ret) -> bool + Copy, Ret>(cond: C, ret: Ret) -> Ret {
2695+
pub const fn contract_check_ensures<C: Fn(&Ret) -> bool + Copy, Ret>(
2696+
cond: Option<C>,
2697+
ret: Ret,
2698+
) -> Ret {
26932699
const_eval_select!(
2694-
@capture[C: Fn(&Ret) -> bool + Copy, Ret] { cond: C, ret: Ret } -> Ret :
2700+
@capture[C: Fn(&Ret) -> bool + Copy, Ret] { cond: Option<C>, ret: Ret } -> Ret :
26952701
if const {
26962702
// Do nothing
26972703
ret
26982704
} else {
2699-
if contract_checks() && !cond(&ret) {
2700-
// Emit no unwind panic in case this was a safety requirement.
2701-
crate::panicking::panic_nounwind("failed ensures check");
2705+
match cond {
2706+
crate::option::Option::Some(cond) => {
2707+
if !cond(&ret) {
2708+
// Emit no unwind panic in case this was a safety requirement.
2709+
crate::panicking::panic_nounwind("failed ensures check");
2710+
}
2711+
},
2712+
crate::option::Option::None => {},
27022713
}
27032714
ret
27042715
}

0 commit comments

Comments
 (0)