@@ -2508,59 +2508,7 @@ extern "rust-intrinsic" {
25082508 #[ rustc_nounwind]
25092509 pub fn vtable_align ( ptr : * const ( ) ) -> usize ;
25102510
2511- /// Selects which function to call depending on the context.
2512- ///
2513- /// If this function is evaluated at compile-time, then a call to this
2514- /// intrinsic will be replaced with a call to `called_in_const`. It gets
2515- /// replaced with a call to `called_at_rt` otherwise.
2516- ///
2517- /// # Type Requirements
2518- ///
2519- /// The two functions must be both function items. They cannot be function
2520- /// pointers or closures. The first function must be a `const fn`.
2521- ///
2522- /// `arg` will be the tupled arguments that will be passed to either one of
2523- /// the two functions, therefore, both functions must accept the same type of
2524- /// arguments. Both functions must return RET.
2525- ///
2526- /// # Safety
2527- ///
2528- /// The two functions must behave observably equivalent. Safe code in other
2529- /// crates may assume that calling a `const fn` at compile-time and at run-time
2530- /// produces the same result. A function that produces a different result when
2531- /// evaluated at run-time, or has any other observable side-effects, is
2532- /// *unsound*.
2533- ///
2534- /// Here is an example of how this could cause a problem:
2535- /// ```no_run
2536- /// #![feature(const_eval_select)]
2537- /// #![feature(core_intrinsics)]
2538- /// # #![allow(internal_features)]
2539- /// use std::hint::unreachable_unchecked;
2540- /// use std::intrinsics::const_eval_select;
2541- ///
2542- /// // Crate A
2543- /// pub const fn inconsistent() -> i32 {
2544- /// fn runtime() -> i32 { 1 }
2545- /// const fn compiletime() -> i32 { 2 }
2546- ///
2547- /// unsafe {
2548- // // ⚠ This code violates the required equivalence of `compiletime`
2549- /// // and `runtime`.
2550- /// const_eval_select((), compiletime, runtime)
2551- /// }
2552- /// }
2553- ///
2554- /// // Crate B
2555- /// const X: i32 = inconsistent();
2556- /// let x = inconsistent();
2557- /// if x != X { unsafe { unreachable_unchecked(); }}
2558- /// ```
2559- ///
2560- /// This code causes Undefined Behavior when being run, since the
2561- /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
2562- /// which violates the principle that a `const fn` must behave the same at
2563- /// compile-time and at run-time. The unsafe code in crate B is fine.
2511+ #[ cfg( bootstrap) ]
25642512 #[ rustc_const_unstable( feature = "const_eval_select" , issue = "none" ) ]
25652513 pub fn const_eval_select < ARG : Tuple , F , G , RET > (
25662514 arg : ARG ,
@@ -2572,6 +2520,76 @@ extern "rust-intrinsic" {
25722520 F : FnOnce < ARG , Output = RET > ;
25732521}
25742522
2523+ /// Selects which function to call depending on the context.
2524+ ///
2525+ /// If this function is evaluated at compile-time, then a call to this
2526+ /// intrinsic will be replaced with a call to `called_in_const`. It gets
2527+ /// replaced with a call to `called_at_rt` otherwise.
2528+ ///
2529+ /// # Type Requirements
2530+ ///
2531+ /// The two functions must be both function items. They cannot be function
2532+ /// pointers or closures. The first function must be a `const fn`.
2533+ ///
2534+ /// `arg` will be the tupled arguments that will be passed to either one of
2535+ /// the two functions, therefore, both functions must accept the same type of
2536+ /// arguments. Both functions must return RET.
2537+ ///
2538+ /// # Safety
2539+ ///
2540+ /// The two functions must behave observably equivalent. Safe code in other
2541+ /// crates may assume that calling a `const fn` at compile-time and at run-time
2542+ /// produces the same result. A function that produces a different result when
2543+ /// evaluated at run-time, or has any other observable side-effects, is
2544+ /// *unsound*.
2545+ ///
2546+ /// Here is an example of how this could cause a problem:
2547+ /// ```no_run
2548+ /// #![feature(const_eval_select)]
2549+ /// #![feature(core_intrinsics)]
2550+ /// # #![allow(internal_features)]
2551+ /// use std::hint::unreachable_unchecked;
2552+ /// use std::intrinsics::const_eval_select;
2553+ ///
2554+ /// // Crate A
2555+ /// pub const fn inconsistent() -> i32 {
2556+ /// fn runtime() -> i32 { 1 }
2557+ /// const fn compiletime() -> i32 { 2 }
2558+ ///
2559+ /// unsafe {
2560+ // // ⚠ This code violates the required equivalence of `compiletime`
2561+ /// // and `runtime`.
2562+ /// const_eval_select((), compiletime, runtime)
2563+ /// }
2564+ /// }
2565+ ///
2566+ /// // Crate B
2567+ /// const X: i32 = inconsistent();
2568+ /// let x = inconsistent();
2569+ /// if x != X { unsafe { unreachable_unchecked(); }}
2570+ /// ```
2571+ ///
2572+ /// This code causes Undefined Behavior when being run, since the
2573+ /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
2574+ /// which violates the principle that a `const fn` must behave the same at
2575+ /// compile-time and at run-time. The unsafe code in crate B is fine.
2576+ #[ rustc_const_unstable( feature = "const_eval_select" , issue = "none" ) ]
2577+ #[ unstable( feature = "core_intrinsics" , issue = "none" ) ]
2578+ #[ cfg( not( bootstrap) ) ]
2579+ #[ rustc_intrinsic]
2580+ #[ rustc_intrinsic_must_be_overridden]
2581+ pub const unsafe fn const_eval_select < ARG : Tuple , F , G , RET > (
2582+ _arg : ARG ,
2583+ _called_in_const : F ,
2584+ _called_at_rt : G ,
2585+ ) -> RET
2586+ where
2587+ G : FnOnce < ARG , Output = RET > ,
2588+ F : FnOnce < ARG , Output = RET > ,
2589+ {
2590+ unreachable ! ( )
2591+ }
2592+
25752593/// Returns whether the argument's value is statically known at
25762594/// compile-time.
25772595///
0 commit comments