Skip to content

Commit 55b3682

Browse files
committed
Auto merge of rust-lang#89247 - fee1-dead:const-eval-select, r=oli-obk
Add `const_eval_select` intrinsic Adds an intrinsic that calls a given function when evaluated at compiler time, but generates a call to another function when called at runtime. See rust-lang/const-eval#7 for previous discussion. r? `@oli-obk.`
2 parents 48594ed + fd4be63 commit 55b3682

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

core/src/intrinsics.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,3 +2221,74 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
22212221
// SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
22222222
unsafe { write_bytes(dst, val, count) }
22232223
}
2224+
2225+
/// Selects which function to call depending on the context.
2226+
///
2227+
/// If this function is evaluated at compile-time, then a call to this
2228+
/// intrinsic will be replaced with a call to `called_in_const`. It gets
2229+
/// replaced with a call to `called_at_rt` otherwise.
2230+
///
2231+
/// # Type Requirements
2232+
///
2233+
/// The two functions must be both function items. They cannot be function
2234+
/// pointers or closures.
2235+
///
2236+
/// `arg` will be the arguments that will be passed to either one of the
2237+
/// two functions, therefore, both functions must accept the same type of
2238+
/// arguments. Both functions must return RET.
2239+
///
2240+
/// # Safety
2241+
///
2242+
/// This intrinsic allows breaking [referential transparency] in `const fn`
2243+
/// and is therefore `unsafe`.
2244+
///
2245+
/// Code that uses this intrinsic must be extremely careful to ensure that
2246+
/// `const fn`s remain referentially-transparent independently of when they
2247+
/// are evaluated.
2248+
///
2249+
/// The Rust compiler assumes that it is sound to replace a call to a `const
2250+
/// fn` with the result produced by evaluating it at compile-time. If
2251+
/// evaluating the function at run-time were to produce a different result,
2252+
/// or have any other observable side-effects, the behavior is undefined.
2253+
///
2254+
/// [referential transparency]: https://en.wikipedia.org/wiki/Referential_transparency
2255+
#[cfg(not(bootstrap))]
2256+
#[unstable(
2257+
feature = "const_eval_select",
2258+
issue = "none",
2259+
reason = "const_eval_select will never be stable"
2260+
)]
2261+
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
2262+
#[lang = "const_eval_select"]
2263+
#[rustc_do_not_const_check]
2264+
pub const unsafe fn const_eval_select<ARG, F, G, RET>(
2265+
arg: ARG,
2266+
_called_in_const: F,
2267+
called_at_rt: G,
2268+
) -> RET
2269+
where
2270+
F: ~const FnOnce<ARG, Output = RET>,
2271+
G: FnOnce<ARG, Output = RET> + ~const Drop,
2272+
{
2273+
called_at_rt.call_once(arg)
2274+
}
2275+
2276+
#[cfg(not(bootstrap))]
2277+
#[unstable(
2278+
feature = "const_eval_select",
2279+
issue = "none",
2280+
reason = "const_eval_select will never be stable"
2281+
)]
2282+
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
2283+
#[lang = "const_eval_select_ct"]
2284+
pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>(
2285+
arg: ARG,
2286+
called_in_const: F,
2287+
_called_at_rt: G,
2288+
) -> RET
2289+
where
2290+
F: ~const FnOnce<ARG, Output = RET>,
2291+
G: FnOnce<ARG, Output = RET> + ~const Drop,
2292+
{
2293+
called_in_const.call_once(arg)
2294+
}

0 commit comments

Comments
 (0)