Skip to content

Commit 1eb203d

Browse files
committed
Make const_eval_select a rustc_intrinsic
1 parent b6679c0 commit 1eb203d

File tree

1 file changed

+74
-56
lines changed

1 file changed

+74
-56
lines changed

core/src/intrinsics.rs

+74-56
Original file line numberDiff line numberDiff line change
@@ -2508,62 +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-
/// This function is safe to call, but note the stability concerns below.
2518-
///
2519-
/// # Type Requirements
2520-
///
2521-
/// The two functions must be both function items. They cannot be function
2522-
/// pointers or closures. The first function must be a `const fn`.
2523-
///
2524-
/// `arg` will be the tupled arguments that will be passed to either one of
2525-
/// the two functions, therefore, both functions must accept the same type of
2526-
/// arguments. Both functions must return RET.
2527-
///
2528-
/// # Stability concerns
2529-
///
2530-
/// Rust has not yet decided that `const fn` are allowed to tell whether
2531-
/// they run at compile-time or at runtime. Therefore, when using this
2532-
/// intrinsic anywhere that can be reached from stable, it is crucial that
2533-
/// the end-to-end behavior of the stable `const fn` is the same for both
2534-
/// modes of execution. (Here, Undefined Behavior is considered "the same"
2535-
/// as any other behavior, so if the function exhibits UB at runtime then
2536-
/// it may do whatever it wants at compile-time.)
2537-
///
2538-
/// Here is an example of how this could cause a problem:
2539-
/// ```no_run
2540-
/// #![feature(const_eval_select)]
2541-
/// #![feature(core_intrinsics)]
2542-
/// # #![allow(internal_features)]
2543-
/// # #![cfg_attr(bootstrap, allow(unused))]
2544-
/// use std::intrinsics::const_eval_select;
2545-
///
2546-
/// // Standard library
2547-
/// # #[cfg(not(bootstrap))]
2548-
/// pub const fn inconsistent() -> i32 {
2549-
/// fn runtime() -> i32 { 1 }
2550-
/// const fn compiletime() -> i32 { 2 }
2551-
///
2552-
// // ⚠ This code violates the required equivalence of `compiletime`
2553-
/// // and `runtime`.
2554-
/// const_eval_select((), compiletime, runtime)
2555-
/// }
2556-
/// # #[cfg(bootstrap)]
2557-
/// # pub const fn inconsistent() -> i32 { 0 }
2558-
///
2559-
/// // User Crate
2560-
/// const X: i32 = inconsistent();
2561-
/// let x = inconsistent();
2562-
/// assert_eq!(x, X);
2563-
/// ```
2564-
///
2565-
/// Currently such an assertion would always succeed; until Rust decides
2566-
/// otherwise, that principle should not be violated.
2511+
#[cfg(bootstrap)]
25672512
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
25682513
#[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
25692514
pub fn const_eval_select<ARG: Tuple, F, G, RET>(
@@ -2576,6 +2521,79 @@ extern "rust-intrinsic" {
25762521
F: FnOnce<ARG, Output = RET>;
25772522
}
25782523

2524+
/// Selects which function to call depending on the context.
2525+
///
2526+
/// If this function is evaluated at compile-time, then a call to this
2527+
/// intrinsic will be replaced with a call to `called_in_const`. It gets
2528+
/// replaced with a call to `called_at_rt` otherwise.
2529+
///
2530+
/// This function is safe to call, but note the stability concerns below.
2531+
///
2532+
/// # Type Requirements
2533+
///
2534+
/// The two functions must be both function items. They cannot be function
2535+
/// pointers or closures. The first function must be a `const fn`.
2536+
///
2537+
/// `arg` will be the tupled arguments that will be passed to either one of
2538+
/// the two functions, therefore, both functions must accept the same type of
2539+
/// arguments. Both functions must return RET.
2540+
///
2541+
/// # Stability concerns
2542+
///
2543+
/// Rust has not yet decided that `const fn` are allowed to tell whether
2544+
/// they run at compile-time or at runtime. Therefore, when using this
2545+
/// intrinsic anywhere that can be reached from stable, it is crucial that
2546+
/// the end-to-end behavior of the stable `const fn` is the same for both
2547+
/// modes of execution. (Here, Undefined Behavior is considered "the same"
2548+
/// as any other behavior, so if the function exhibits UB at runtime then
2549+
/// it may do whatever it wants at compile-time.)
2550+
///
2551+
/// Here is an example of how this could cause a problem:
2552+
/// ```no_run
2553+
/// #![feature(const_eval_select)]
2554+
/// #![feature(core_intrinsics)]
2555+
/// # #![allow(internal_features)]
2556+
/// # #![cfg_attr(bootstrap, allow(unused))]
2557+
/// use std::intrinsics::const_eval_select;
2558+
///
2559+
/// // Standard library
2560+
/// # #[cfg(not(bootstrap))]
2561+
/// pub const fn inconsistent() -> i32 {
2562+
/// fn runtime() -> i32 { 1 }
2563+
/// const fn compiletime() -> i32 { 2 }
2564+
///
2565+
// // ⚠ This code violates the required equivalence of `compiletime`
2566+
/// // and `runtime`.
2567+
/// const_eval_select((), compiletime, runtime)
2568+
/// }
2569+
/// # #[cfg(bootstrap)]
2570+
/// # pub const fn inconsistent() -> i32 { 0 }
2571+
///
2572+
/// // User Crate
2573+
/// const X: i32 = inconsistent();
2574+
/// let x = inconsistent();
2575+
/// assert_eq!(x, X);
2576+
/// ```
2577+
///
2578+
/// Currently such an assertion would always succeed; until Rust decides
2579+
/// otherwise, that principle should not be violated.
2580+
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
2581+
#[unstable(feature = "core_intrinsics", issue = "none")]
2582+
#[cfg(not(bootstrap))]
2583+
#[rustc_intrinsic]
2584+
#[rustc_intrinsic_must_be_overridden]
2585+
pub const fn const_eval_select<ARG: Tuple, F, G, RET>(
2586+
_arg: ARG,
2587+
_called_in_const: F,
2588+
_called_at_rt: G,
2589+
) -> RET
2590+
where
2591+
G: FnOnce<ARG, Output = RET>,
2592+
F: FnOnce<ARG, Output = RET>,
2593+
{
2594+
unreachable!()
2595+
}
2596+
25792597
/// Returns whether the argument's value is statically known at
25802598
/// compile-time.
25812599
///

0 commit comments

Comments
 (0)