@@ -2570,15 +2570,14 @@ extern "rust-intrinsic" {
2570
2570
#[ cfg( not( bootstrap) ) ]
2571
2571
pub fn is_val_statically_known < T : Copy > ( arg : T ) -> bool ;
2572
2572
2573
- #[ rustc_const_stable ( feature = "delayed_debug_assertions" , since = "0.0.0 " ) ]
2573
+ #[ rustc_const_unstable ( feature = "delayed_debug_assertions" , issue = "none " ) ]
2574
2574
#[ rustc_safe_intrinsic]
2575
- #[ rustc_nounwind]
2576
2575
#[ cfg( not( bootstrap) ) ]
2577
2576
pub ( crate ) fn debug_assertions ( ) -> bool ;
2578
2577
}
2579
2578
2580
2579
#[ cfg( bootstrap) ]
2581
- #[ rustc_const_stable ( feature = "delayed_debug_assertions" , since = "0.0.0 " ) ]
2580
+ #[ rustc_const_unstable ( feature = "delayed_debug_assertions" , issue = "none " ) ]
2582
2581
pub ( crate ) const fn debug_assertions ( ) -> bool {
2583
2582
cfg ! ( debug_assertions)
2584
2583
}
@@ -2599,9 +2598,27 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2599
2598
/// Check that the preconditions of an unsafe function are followed, if debug_assertions are on,
2600
2599
/// and only at runtime.
2601
2600
///
2602
- /// This macro should be called as `assert_unsafe_precondition!((name: Type) => Expression)`
2603
- /// where the names specified will be moved into the macro as captured variables, and defines an item
2604
- /// to call `const_eval_select` on.
2601
+ /// This macro should be called as
2602
+ /// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)`
2603
+ /// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all
2604
+ /// those arguments are passed to a function via [`const_eval_select`].
2605
+ ///
2606
+ /// These checks are behind a condition which is evaluated at codegen time, not expansion time like
2607
+ /// [`debug_assert`]. This means that a standard library built with optimizations and debug
2608
+ /// assertions disabled will have these checks optimized out of its monomorphizations, but if a
2609
+ /// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of
2610
+ /// this macro, that monomorphization will contain the check.
2611
+ ///
2612
+ /// Since these checks cannot be optimized out in MIR, some care must be taken in both call and
2613
+ /// implementation to mitigate their compile-time overhead. The runtime function that we
2614
+ /// [`const_eval_select`] to is monomorphic, `#[inline(never)]`, and `#[rustc_nounwind]`. That
2615
+ /// combination of properties ensures that the code for the checks is only compiled once, and has a
2616
+ /// minimal impact on the caller's code size.
2617
+ ///
2618
+ /// Caller should also introducing any other `let` bindings or any code outside this macro in order
2619
+ /// to call it. Since the precompiled standard library is built with full debuginfo and these
2620
+ /// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough
2621
+ /// debuginfo to have a measurable compile-time impact on debug builds.
2605
2622
///
2606
2623
/// # Safety
2607
2624
///
@@ -2619,21 +2636,20 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2619
2636
macro_rules! assert_unsafe_precondition {
2620
2637
( $message: expr, ( $( $arg: expr => $name: ident: $ty: ty) ,* $( , ) ?) => $e: expr $( , ) ?) => {
2621
2638
{
2622
- #[ inline( never) ]
2623
- #[ rustc_nounwind]
2624
- fn precondition_check( $( $name: $ty) ,* ) {
2625
- if !$e {
2626
- :: core:: panicking:: panic_nounwind(
2627
- concat!( "unsafe precondition(s) violated: " , $message)
2628
- ) ;
2639
+ #[ inline( never) ]
2640
+ #[ rustc_nounwind]
2641
+ fn precondition_check( $( $name: $ty) ,* ) {
2642
+ if !$e {
2643
+ :: core:: panicking:: panic_nounwind(
2644
+ concat!( "unsafe precondition(s) violated: " , $message)
2645
+ ) ;
2646
+ }
2629
2647
}
2630
- }
2631
- #[ inline]
2632
- const fn comptime( $( _: $ty) ,* ) { }
2648
+ const fn comptime( $( _: $ty) ,* ) { }
2633
2649
2634
- if :: core:: intrinsics:: debug_assertions( ) {
2635
- :: core:: intrinsics:: const_eval_select( ( $( $arg, ) * ) , comptime, precondition_check) ;
2636
- }
2650
+ if :: core:: intrinsics:: debug_assertions( ) {
2651
+ :: core:: intrinsics:: const_eval_select( ( $( $arg, ) * ) , comptime, precondition_check) ;
2652
+ }
2637
2653
}
2638
2654
} ;
2639
2655
}
0 commit comments