Function std::intrinsics::const_eval_select

const: unstable · source · []
pub unsafe fn const_eval_select<ARG, F, G, RET>(
    arg: ARG,
    _called_in_const: F,
    called_at_rt: G
) -> RET where
    F: FnOnce<ARG, Output = RET>,
    G: FnOnce<ARG, Output = RET>, 
🔬This is a nightly-only experimental API. (const_eval_select)
Expand description

Selects which function to call depending on the context.

If this function is evaluated at compile-time, then a call to this intrinsic will be replaced with a call to called_in_const. It gets replaced with a call to called_at_rt otherwise.

Type Requirements

The two functions must be both function items. They cannot be function pointers or closures.

arg will be the arguments that will be passed to either one of the two functions, therefore, both functions must accept the same type of arguments. Both functions must return RET.

Safety

The two functions must behave observably equivalent. Safe code in other crates may assume that calling a const fn at compile-time and at run-time produces the same result. A function that produces a different result when evaluated at run-time, or has any other observable side-effects, is unsound.

Here is an example of how this could cause a problem:

#![feature(const_eval_select)]
#![feature(core_intrinsics)]
use std::hint::unreachable_unchecked;
use std::intrinsics::const_eval_select;

// Crate A
pub const fn inconsistent() -> i32 {
    fn runtime() -> i32 { 1 }
    const fn compiletime() -> i32 { 2 }

    unsafe {
        // and `runtime`.
        const_eval_select((), compiletime, runtime)
    }
}

// Crate B
const X: i32 = inconsistent();
let x = inconsistent();
if x != X { unsafe { unreachable_unchecked(); }}
Run

This code causes Undefined Behavior when being run, since the unreachable_unchecked is actually being reached. The bug is in crate A, which violates the principle that a const fn must behave the same at compile-time and at run-time. The unsafe code in crate B is fine.