@@ -2515,6 +2515,8 @@ extern "rust-intrinsic" {
25152515/// intrinsic will be replaced with a call to `called_in_const`. It gets 
25162516/// replaced with a call to `called_at_rt` otherwise. 
25172517/// 
2518+ /// This function is safe to call, but note the stability concerns below. 
2519+ /// 
25182520/// # Type Requirements 
25192521/// 
25202522/// The two functions must be both function items. They cannot be function 
@@ -2524,45 +2526,47 @@ extern "rust-intrinsic" {
25242526/// the two functions, therefore, both functions must accept the same type of 
25252527/// arguments. Both functions must return RET. 
25262528/// 
2527- /// # Safety  
2529+ /// # Stability concerns  
25282530/// 
2529- /// The two functions must behave observably equivalent. Safe code in other 
2530- /// crates may assume that calling a `const fn` at compile-time and at run-time 
2531- /// produces the same result. A function that produces a different result when 
2532- /// evaluated at run-time, or has any other observable side-effects, is 
2533- /// *unsound*. 
2531+ /// Rust has not yet decided that `const fn` are allowed to tell whether 
2532+ /// they run at compile-time or at runtime. Therefore, when using this 
2533+ /// intrinsic anywhere that can be reached from stable, it is crucial that 
2534+ /// the end-to-end behavior of the stable `const fn` is the same for both 
2535+ /// modes of execution. (Here, Undefined Behavior is considerd "the same" 
2536+ /// as any other behavior, so if the function exhibits UB at runtime then 
2537+ /// it may do whatever it wants at compile-time.) 
25342538/// 
25352539/// Here is an example of how this could cause a problem: 
25362540/// ```no_run 
25372541/// #![feature(const_eval_select)] 
25382542/// #![feature(core_intrinsics)] 
25392543/// # #![allow(internal_features)] 
2540- /// use std::hint::unreachable_unchecked;  
2544+ /// # #![cfg_attr(bootstrap, allow(unused))]  
25412545/// use std::intrinsics::const_eval_select; 
25422546/// 
2543- /// // Crate A 
2547+ /// // Standard library 
2548+ /// # #[cfg(not(bootstrap))] 
25442549/// pub const fn inconsistent() -> i32 { 
25452550///     fn runtime() -> i32 { 1 } 
25462551///     const fn compiletime() -> i32 { 2 } 
25472552/// 
2548- ///     unsafe { 
2549- //          // ⚠ This code violates the required equivalence of `compiletime` 
2550-     ///         // and `runtime`. 
2551- ///         const_eval_select((), compiletime, runtime) 
2552- ///     } 
2553+ //      // ⚠ This code violates the required equivalence of `compiletime` 
2554+     ///     // and `runtime`. 
2555+ ///     const_eval_select((), compiletime, runtime) 
25532556/// } 
2557+ /// # #[cfg(bootstrap)] 
2558+ /// # pub const fn inconsistent() -> i32 { 0 } 
25542559/// 
2555- /// // Crate B  
2560+ /// // User Crate  
25562561/// const X: i32 = inconsistent(); 
25572562/// let x = inconsistent(); 
2558- /// if x != X { unsafe { unreachable_unchecked(); }}  
2563+ /// assert_eq!(x, X);  
25592564/// ``` 
25602565/// 
2561- /// This code causes Undefined Behavior when being run, since the 
2562- /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, 
2563- /// which violates the principle that a `const fn` must behave the same at 
2564- /// compile-time and at run-time. The unsafe code in crate B is fine. 
2566+ /// Currently such an assertion would always succeed; until Rust decides 
2567+ /// otherwise, that principle should not be violated. 
25652568#[ rustc_const_unstable( feature = "const_eval_select" ,  issue = "none" ) ]  
2569+     #[ cfg_attr( not( bootstrap) ,  rustc_safe_intrinsic) ]  
25662570    pub  fn  const_eval_select < ARG :  Tuple ,  F ,  G ,  RET > ( 
25672571        arg :  ARG , 
25682572        called_in_const :  F , 
0 commit comments