diff options
| author | bors <bors@rust-lang.org> | 2021-12-10 21:59:07 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-12-10 21:59:07 +0000 |
| commit | f0448f44bcda55fd9eb71da82495ef648eedb4e4 (patch) | |
| tree | d7157697f5cdcd6bf59adb15521427a212f0dbce /library/core/src | |
| parent | 0b42deaccc2cbe17a68067aa5fdb76104369e1fd (diff) | |
| parent | 1fca934898354160b46c17c58b67707a2dcb8988 (diff) | |
| download | rust-f0448f44bcda55fd9eb71da82495ef648eedb4e4.tar.gz rust-f0448f44bcda55fd9eb71da82495ef648eedb4e4.zip | |
Auto merge of #91760 - matthiaskrgr:rollup-zcemh6j, r=matthiaskrgr
Rollup of 10 pull requests Successful merges: - #90407 (Document all public items in `rustc_incremental`) - #90897 (Fix incorrect stability attributes) - #91105 (Fix method name reference in stream documentation) - #91325 (adjust const_eval_select documentation) - #91470 (code-cov: generate dead functions with private/default linkage) - #91482 (Update documentation to use `from()` to initialize `HashMap`s and `BTreeMap`s) - #91524 (Fix Vec::extend_from_slice docs) - #91575 (Fix ICE on format string of macro with secondary-label) - #91625 (Remove redundant [..]s) - #91646 (Fix documentation for `core::ready::Ready`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/future/ready.rs | 2 | ||||
| -rw-r--r-- | library/core/src/intrinsics.rs | 49 | ||||
| -rw-r--r-- | library/core/src/num/saturating.rs | 2 | ||||
| -rw-r--r-- | library/core/src/num/uint_macros.rs | 2 | ||||
| -rw-r--r-- | library/core/src/slice/raw.rs | 4 | ||||
| -rw-r--r-- | library/core/src/stream/mod.rs | 6 |
6 files changed, 43 insertions, 22 deletions
diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index cc905d288f9..48f20f90a32 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -2,7 +2,7 @@ use crate::future::Future; use crate::pin::Pin; use crate::task::{Context, Poll}; -/// Creates a future that is immediately ready with a value. +/// A future that is immediately ready with a value. /// /// This `struct` is created by [`ready()`]. See its /// documentation for more. diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index edbc250eb0d..8c6a7a56966 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2070,8 +2070,8 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us #[cfg(debug_assertions)] const fn compiletime_check<T>(_src: *const T, _dst: *mut T, _count: usize) {} #[cfg(debug_assertions)] - // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to - // not do them during compile time + // SAFETY: As per our safety precondition, we may assume that the `abort` above is never reached. + // Therefore, compiletime_check and runtime_check are observably equivalent. unsafe { const_eval_select((src, dst, count), compiletime_check, runtime_check); } @@ -2161,8 +2161,8 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { #[cfg(debug_assertions)] const fn compiletime_check<T>(_src: *const T, _dst: *mut T) {} #[cfg(debug_assertions)] - // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to - // not do them during compile time + // SAFETY: As per our safety precondition, we may assume that the `abort` above is never reached. + // Therefore, compiletime_check and runtime_check are observably equivalent. unsafe { const_eval_select((src, dst), compiletime_check, runtime_check); } @@ -2273,19 +2273,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*. /// -/// Code that uses this intrinsic must be extremely careful to ensure that -/// `const fn`s remain referentially-transparent independently of when they -/// are evaluated. +/// 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; /// -/// 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 A +/// pub const fn inconsistent() -> i32 { +/// fn runtime() -> i32 { 1 } +/// const fn compiletime() -> i32 { 2 } /// -/// [referential transparency]: https://en.wikipedia.org/wiki/Referential_transparency +/// unsafe { +// // ⚠ This code violates the required equivalence of `compiletime` +/// // and `runtime`. +/// const_eval_select((), compiletime, runtime) +/// } +/// } +/// +/// // Crate B +/// const X: i32 = inconsistent(); +/// let x = inconsistent(); +/// if x != X { unsafe { unreachable_unchecked(); }} +/// ``` +/// +/// 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", diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index ba81f3f9fd6..d9b14c82e96 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -628,7 +628,7 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] - #[rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0")] + #[rustc_const_unstable(feature = "saturating_int_impl", issue = "87920")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn reverse_bits(self) -> Self { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a15eabf7966..054b814b7e0 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2223,7 +2223,7 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[rustc_const_unstable(feature = "wrapping_next_power_of_two", issue = "32463")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn wrapping_next_power_of_two(self) -> Self { diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index d98db3f57c0..e7972838184 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -149,8 +149,8 @@ const fn debug_check_data_len<T>(data: *const T, len: usize) { // it is not required for safety (the safety must be guatanteed by // the `from_raw_parts[_mut]` caller). // - // Since the checks are not required, we ignore them in CTFE as they can't - // be done there (alignment does not make much sense there). + // As per our safety precondition, we may assume that assertion above never fails. + // Therefore, noop and rt_check are observably equivalent. unsafe { crate::intrinsics::const_eval_select((data,), noop, rt_check); } diff --git a/library/core/src/stream/mod.rs b/library/core/src/stream/mod.rs index 58dc8e1e5e6..b59a46d5f3a 100644 --- a/library/core/src/stream/mod.rs +++ b/library/core/src/stream/mod.rs @@ -114,9 +114,9 @@ //! # Laziness //! //! Streams are *lazy*. This means that just creating a stream doesn't _do_ a -//! whole lot. Nothing really happens until you call `next`. This is sometimes a -//! source of confusion when creating a stream solely for its side effects. The -//! compiler will warn us about this kind of behavior: +//! whole lot. Nothing really happens until you call `poll_next`. This is +//! sometimes a source of confusion when creating a stream solely for its side +//! effects. The compiler will warn us about this kind of behavior: //! //! ```text //! warning: unused result that must be used: streams do nothing unless polled |
