@@ -2271,19 +2271,40 @@ pub unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
2271
2271
///
2272
2272
/// # Safety
2273
2273
///
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 }
2276
2290
///
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
+ /// }
2280
2297
///
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
+ /// ```
2285
2303
///
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.
2287
2308
#[ unstable(
2288
2309
feature = "const_eval_select" ,
2289
2310
issue = "none" ,
0 commit comments