Skip to content

Commit 15a4ed6

Browse files
committed
adjust const_eval_select documentation
1 parent e6d2de9 commit 15a4ed6

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

library/core/src/intrinsics.rs

+31-10
Original file line numberDiff line numberDiff line change
@@ -2271,19 +2271,40 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
22712271
///
22722272
/// # Safety
22732273
///
2274-
/// This intrinsic allows breaking [referential transparency] in `const fn`
2275-
/// and is therefore `unsafe`.
2274+
/// The two functions must behave observably equivalent. Safe code in other
2275+
/// crates may assume that calling a `const fn` at compile-time and at run-time
2276+
/// produces the same result. A function that produces a different result when
2277+
/// evaluated at run-time, or has any other observable side-effects, is
2278+
/// *unsound*.
2279+
///
2280+
/// Here is an example of how this could cause a problem:
2281+
/// ```no_run
2282+
/// #![feature(const_eval_select)]
2283+
/// use std::hint::unreachable_unchecked;
2284+
/// use std::intrinsics::const_eval_select;
2285+
///
2286+
/// // Crate A
2287+
/// pub const fn inconsistent() -> i32 {
2288+
/// fn runtime() -> i32 { 1 }
2289+
/// const fn compiletime() -> i32 { 2 }
22762290
///
2277-
/// Code that uses this intrinsic must be extremely careful to ensure that
2278-
/// `const fn`s remain referentially-transparent independently of when they
2279-
/// are evaluated.
2291+
/// unsafe {
2292+
// // ⚠ This code violates the required equivalence of `compiletime`
2293+
/// // and `runtime`.
2294+
/// const_eval_select((), compiletime, runtime)
2295+
/// }
2296+
/// }
22802297
///
2281-
/// The Rust compiler assumes that it is sound to replace a call to a `const
2282-
/// fn` with the result produced by evaluating it at compile-time. If
2283-
/// evaluating the function at run-time were to produce a different result,
2284-
/// or have any other observable side-effects, the behavior is undefined.
2298+
/// // Crate B
2299+
/// const X: i32 = inconsistent();
2300+
/// let x = inconsistent();
2301+
/// if x != X { unsafe { unreachable_unchecked(); }}
2302+
/// ```
22852303
///
2286-
/// [referential transparency]: https://en.wikipedia.org/wiki/Referential_transparency
2304+
/// This code causes Undefined Behavior when being run, since the
2305+
/// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
2306+
/// which violates the principle that a `const fn` must behave the same at
2307+
/// compile-time and at run-time. The unsafe code in crate B is fine.
22872308
#[unstable(
22882309
feature = "const_eval_select",
22892310
issue = "none",

0 commit comments

Comments
 (0)