Skip to content

Commit ce44501

Browse files
committed
Add const_eval_select intrinsic
1 parent d3aa27b commit ce44501

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

core/src/intrinsics.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,3 +2221,72 @@ 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+
#[lang = "const_eval_select"]
2262+
#[rustc_do_not_const_check]
2263+
pub const unsafe fn const_eval_select<ARG, F, G, RET>(
2264+
arg: ARG,
2265+
_called_in_const: F,
2266+
called_at_rt: G,
2267+
) -> RET
2268+
where
2269+
F: ~const FnOnce(ARG) -> RET,
2270+
G: FnOnce(ARG) -> RET + ~const Drop,
2271+
{
2272+
called_at_rt(arg)
2273+
}
2274+
2275+
#[cfg(not(bootstrap))]
2276+
#[unstable(
2277+
feature = "const_eval_select",
2278+
issue = "none",
2279+
reason = "const_eval_select will never be stable"
2280+
)]
2281+
#[lang = "const_eval_select_ct"]
2282+
pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>(
2283+
arg: ARG,
2284+
called_in_const: F,
2285+
_called_at_rt: G,
2286+
) -> RET
2287+
where
2288+
F: ~const FnOnce(ARG) -> RET,
2289+
G: FnOnce(ARG) -> RET + ~const Drop,
2290+
{
2291+
called_in_const(arg)
2292+
}

0 commit comments

Comments
 (0)