diff options
| author | Ralf Jung <post@ralfj.de> | 2021-11-28 13:48:53 -0500 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2021-11-28 13:54:56 -0500 |
| commit | 15a4ed693722b4bb6d2fa43272a58ab94acfec1a (patch) | |
| tree | 8d246430b577f0417436d2e40a4d4ff8fde0965f | |
| parent | e6d2de9483a27f846f003fc745713339a9122473 (diff) | |
| download | rust-15a4ed693722b4bb6d2fa43272a58ab94acfec1a.tar.gz rust-15a4ed693722b4bb6d2fa43272a58ab94acfec1a.zip | |
adjust const_eval_select documentation
| -rw-r--r-- | library/core/src/intrinsics.rs | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 23b28766d70..3814c4237f1 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2271,19 +2271,40 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { /// /// # Safety /// -/// This intrinsic allows breaking [referential transparency] in `const fn` -/// and is therefore `unsafe`. +/// 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: +/// ```no_run +/// #![feature(const_eval_select)] +/// 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 } /// -/// Code that uses this intrinsic must be extremely careful to ensure that -/// `const fn`s remain referentially-transparent independently of when they -/// are evaluated. +/// unsafe { +// // ⚠ This code violates the required equivalence of `compiletime` +/// // and `runtime`. +/// const_eval_select((), compiletime, runtime) +/// } +/// } /// -/// The Rust compiler assumes that it is sound to replace a call to a `const -/// fn` with the result produced by evaluating it at compile-time. If -/// evaluating the function at run-time were to produce a different result, -/// or have any other observable side-effects, the behavior is undefined. +/// // Crate B +/// const X: i32 = inconsistent(); +/// let x = inconsistent(); +/// if x != X { unsafe { unreachable_unchecked(); }} +/// ``` /// -/// [referential transparency]: https://en.wikipedia.org/wiki/Referential_transparency +/// 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. #[unstable( feature = "const_eval_select", issue = "none", |
