@@ -2508,59 +2508,7 @@ extern "rust-intrinsic" {
2508
2508
#[ rustc_nounwind]
2509
2509
pub fn vtable_align ( ptr : * const ( ) ) -> usize ;
2510
2510
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) ]
2564
2512
#[ rustc_const_unstable( feature = "const_eval_select" , issue = "none" ) ]
2565
2513
pub fn const_eval_select < ARG : Tuple , F , G , RET > (
2566
2514
arg : ARG ,
@@ -2572,6 +2520,76 @@ extern "rust-intrinsic" {
2572
2520
F : FnOnce < ARG , Output = RET > ;
2573
2521
}
2574
2522
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
+
2575
2593
/// Returns whether the argument's value is statically known at
2576
2594
/// compile-time.
2577
2595
///
0 commit comments