summaryrefslogtreecommitdiffstats
path: root/library/core/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /library/core/src
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/src')
-rw-r--r--library/core/src/alloc/layout.rs2
-rw-r--r--library/core/src/arch.rs1
-rw-r--r--library/core/src/array/iter.rs28
-rw-r--r--library/core/src/cell.rs14
-rw-r--r--library/core/src/cell/once.rs46
-rw-r--r--library/core/src/char/decode.rs4
-rw-r--r--library/core/src/char/methods.rs9
-rw-r--r--library/core/src/cmp.rs76
-rw-r--r--library/core/src/convert/mod.rs59
-rw-r--r--library/core/src/default.rs1
-rw-r--r--library/core/src/error.rs8
-rw-r--r--library/core/src/ffi/c_str.rs2
-rw-r--r--library/core/src/ffi/mod.rs2
-rw-r--r--library/core/src/fmt/builders.rs145
-rw-r--r--library/core/src/fmt/mod.rs10
-rw-r--r--library/core/src/fmt/rt.rs4
-rw-r--r--library/core/src/future/mod.rs2
-rw-r--r--library/core/src/hint.rs2
-rw-r--r--library/core/src/intrinsics.rs11
-rw-r--r--library/core/src/intrinsics/mir.rs10
-rw-r--r--library/core/src/io/borrowed_buf.rs301
-rw-r--r--library/core/src/io/mod.rs6
-rw-r--r--library/core/src/iter/adapters/peekable.rs1
-rw-r--r--library/core/src/iter/adapters/zip.rs90
-rw-r--r--library/core/src/iter/mod.rs6
-rw-r--r--library/core/src/iter/sources.rs8
-rw-r--r--library/core/src/iter/sources/empty.rs1
-rw-r--r--library/core/src/iter/sources/from_coroutine.rs59
-rw-r--r--library/core/src/iter/sources/from_generator.rs58
-rw-r--r--library/core/src/iter/sources/once.rs1
-rw-r--r--library/core/src/iter/sources/once_with.rs2
-rw-r--r--library/core/src/iter/sources/successors.rs2
-rw-r--r--library/core/src/iter/traits/collect.rs1
-rw-r--r--library/core/src/iter/traits/iterator.rs11
-rw-r--r--library/core/src/lib.rs19
-rw-r--r--library/core/src/macros/mod.rs37
-rw-r--r--library/core/src/marker.rs60
-rw-r--r--library/core/src/mem/manually_drop.rs12
-rw-r--r--library/core/src/mem/maybe_uninit.rs24
-rw-r--r--library/core/src/mem/mod.rs97
-rw-r--r--library/core/src/net/ip_addr.rs154
-rw-r--r--library/core/src/net/socket_addr.rs51
-rw-r--r--library/core/src/num/f32.rs44
-rw-r--r--library/core/src/num/f64.rs42
-rw-r--r--library/core/src/num/int_macros.rs43
-rw-r--r--library/core/src/num/mod.rs11
-rw-r--r--library/core/src/num/saturating.rs4
-rw-r--r--library/core/src/num/uint_macros.rs18
-rw-r--r--library/core/src/ops/coroutine.rs139
-rw-r--r--library/core/src/ops/deref.rs163
-rw-r--r--library/core/src/ops/function.rs24
-rw-r--r--library/core/src/ops/generator.rs135
-rw-r--r--library/core/src/ops/index.rs2
-rw-r--r--library/core/src/ops/mod.rs10
-rw-r--r--library/core/src/ops/range.rs8
-rw-r--r--library/core/src/ops/try_trait.rs45
-rw-r--r--library/core/src/option.rs47
-rw-r--r--library/core/src/panic.rs45
-rw-r--r--library/core/src/panic/unwind_safe.rs1
-rw-r--r--library/core/src/panicking.rs13
-rw-r--r--library/core/src/pin.rs28
-rw-r--r--library/core/src/primitive_docs.rs67
-rw-r--r--library/core/src/ptr/const_ptr.rs39
-rw-r--r--library/core/src/ptr/mod.rs78
-rw-r--r--library/core/src/ptr/mut_ptr.rs37
-rw-r--r--library/core/src/ptr/non_null.rs5
-rw-r--r--library/core/src/result.rs1
-rw-r--r--library/core/src/slice/index.rs5
-rw-r--r--library/core/src/slice/iter.rs1
-rw-r--r--library/core/src/slice/mod.rs70
-rw-r--r--library/core/src/slice/raw.rs2
-rw-r--r--library/core/src/slice/sort.rs13
-rw-r--r--library/core/src/str/iter.rs2
-rw-r--r--library/core/src/str/mod.rs12
-rw-r--r--library/core/src/str/pattern.rs4
-rw-r--r--library/core/src/str/traits.rs1
-rw-r--r--library/core/src/sync/atomic.rs167
-rw-r--r--library/core/src/sync/exclusive.rs10
-rw-r--r--library/core/src/task/wake.rs15
-rw-r--r--library/core/src/time.rs9
80 files changed, 2092 insertions, 705 deletions
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 597303037..65946e09f 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -130,6 +130,8 @@ impl Layout {
}
/// The minimum byte alignment for a memory block of this layout.
+ ///
+ /// The returned alignment is guaranteed to be a power of two.
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
#[must_use = "this returns the minimum alignment, \
diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs
index fc2a5b89c..8817ec077 100644
--- a/library/core/src/arch.rs
+++ b/library/core/src/arch.rs
@@ -1,5 +1,6 @@
#![doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")]
+#[allow(unused_imports)]
#[stable(feature = "simd_arch", since = "1.27.0")]
pub use crate::core_arch::arch::*;
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 587877dff..321357a15 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -4,7 +4,7 @@ use crate::num::NonZeroUsize;
use crate::{
fmt,
intrinsics::transmute_unchecked,
- iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
+ iter::{self, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce},
mem::MaybeUninit,
ops::{IndexRange, Range},
ptr,
@@ -13,6 +13,7 @@ use crate::{
/// A by-value [array] iterator.
#[stable(feature = "array_value_iter", since = "1.51.0")]
#[rustc_insignificant_dtor]
+#[rustc_diagnostic_item = "ArrayIntoIter"]
pub struct IntoIter<T, const N: usize> {
/// This is the array we are iterating over.
///
@@ -293,6 +294,12 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
NonZeroUsize::new(remaining).map_or(Ok(()), Err)
}
+
+ #[inline]
+ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
+ // SAFETY: The caller must provide an idx that is in bound of the remainder.
+ unsafe { self.data.as_ptr().add(self.alive.start()).add(idx).cast::<T>().read() }
+ }
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
@@ -374,6 +381,25 @@ impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
+#[doc(hidden)]
+#[unstable(issue = "none", feature = "std_internals")]
+#[rustc_unsafe_specialization_marker]
+pub trait NonDrop {}
+
+// T: Copy as approximation for !Drop since get_unchecked does not advance self.alive
+// and thus we can't implement drop-handling
+#[unstable(issue = "none", feature = "std_internals")]
+impl<T: Copy> NonDrop for T {}
+
+#[doc(hidden)]
+#[unstable(issue = "none", feature = "std_internals")]
+unsafe impl<T, const N: usize> TrustedRandomAccessNoCoerce for IntoIter<T, N>
+where
+ T: NonDrop,
+{
+ const MAY_HAVE_SIDE_EFFECT: bool = false;
+}
+
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
fn clone(&self) -> Self {
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 3b4d99221..0978b3c92 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -556,7 +556,7 @@ impl<T: ?Sized> Cell<T> {
#[inline]
#[stable(feature = "cell_as_ptr", since = "1.12.0")]
#[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut T {
self.value.get()
}
@@ -755,7 +755,7 @@ impl Display for BorrowMutError {
}
// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
-#[inline(never)]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[cold]
fn panic_already_borrowed(err: BorrowMutError) -> ! {
@@ -763,7 +763,7 @@ fn panic_already_borrowed(err: BorrowMutError) -> ! {
}
// This ensures the panicking code is outlined from `borrow` for `RefCell`.
-#[inline(never)]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
#[cold]
fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
@@ -1112,7 +1112,7 @@ impl<T: ?Sized> RefCell<T> {
/// ```
#[inline]
#[stable(feature = "cell_as_ptr", since = "1.12.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub fn as_ptr(&self) -> *mut T {
self.value.get()
}
@@ -1423,6 +1423,7 @@ impl Clone for BorrowRef<'_> {
/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
#[must_not_suspend = "holding a Ref across suspend points can cause BorrowErrors"]
+#[rustc_diagnostic_item = "RefCellRef"]
pub struct Ref<'b, T: ?Sized + 'b> {
// NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a
// `Ref` argument doesn't hold immutability for its whole scope, only until it drops.
@@ -1804,6 +1805,7 @@ impl<'b> BorrowRefMut<'b> {
/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
#[must_not_suspend = "holding a RefMut across suspend points can cause BorrowErrors"]
+#[rustc_diagnostic_item = "RefCellRefMut"]
pub struct RefMut<'b, T: ?Sized + 'b> {
// NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a
// `RefMut` argument doesn't hold exclusivity for its whole scope, only until it drops.
@@ -2107,7 +2109,7 @@ impl<T: ?Sized> UnsafeCell<T> {
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn get(&self) -> *mut T {
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
// #[repr(transparent)]. This exploits std's special status, there is
@@ -2251,7 +2253,7 @@ impl<T: ?Sized> SyncUnsafeCell<T> {
/// when casting to `&mut T`, and ensure that there are no mutations
/// or mutable aliases going on when casting to `&T`
#[inline]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn get(&self) -> *mut T {
self.value.get()
}
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
index 2e8534f65..3877a0c48 100644
--- a/library/core/src/cell/once.rs
+++ b/library/core/src/cell/once.rs
@@ -87,10 +87,40 @@ impl<T> OnceCell<T> {
#[inline]
#[stable(feature = "once_cell", since = "1.70.0")]
pub fn set(&self, value: T) -> Result<(), T> {
- // SAFETY: Safe because we cannot have overlapping mutable borrows
- let slot = unsafe { &*self.inner.get() };
- if slot.is_some() {
- return Err(value);
+ match self.try_insert(value) {
+ Ok(_) => Ok(()),
+ Err((_, value)) => Err(value),
+ }
+ }
+
+ /// Sets the contents of the cell to `value` if the cell was empty, then
+ /// returns a reference to it.
+ ///
+ /// # Errors
+ ///
+ /// This method returns `Ok(&value)` if the cell was empty and
+ /// `Err(&current_value, value)` if it was full.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(once_cell_try_insert)]
+ ///
+ /// use std::cell::OnceCell;
+ ///
+ /// let cell = OnceCell::new();
+ /// assert!(cell.get().is_none());
+ ///
+ /// assert_eq!(cell.try_insert(92), Ok(&92));
+ /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
+ ///
+ /// assert!(cell.get().is_some());
+ /// ```
+ #[inline]
+ #[unstable(feature = "once_cell_try_insert", issue = "116693")]
+ pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
+ if let Some(old) = self.get() {
+ return Err((old, value));
}
// SAFETY: This is the only place where we set the slot, no races
@@ -98,8 +128,7 @@ impl<T> OnceCell<T> {
// checked that slot is currently `None`, so this write
// maintains the `inner`'s invariant.
let slot = unsafe { &mut *self.inner.get() };
- *slot = Some(value);
- Ok(())
+ Ok(slot.insert(value))
}
/// Gets the contents of the cell, initializing it with `f`
@@ -183,10 +212,9 @@ impl<T> OnceCell<T> {
let val = outlined_call(f)?;
// Note that *some* forms of reentrant initialization might lead to
// UB (see `reentrant_init` test). I believe that just removing this
- // `assert`, while keeping `set/get` would be sound, but it seems
+ // `panic`, while keeping `try_insert` would be sound, but it seems
// better to panic, rather than to silently use an old value.
- assert!(self.set(val).is_ok(), "reentrant init");
- Ok(self.get().unwrap())
+ if let Ok(val) = self.try_insert(val) { Ok(val) } else { panic!("reentrant init") }
}
/// Consumes the cell, returning the wrapped value.
diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs
index dbfe251f2..23319fbe5 100644
--- a/library/core/src/char/decode.rs
+++ b/library/core/src/char/decode.rs
@@ -2,6 +2,7 @@
use crate::error::Error;
use crate::fmt;
+use crate::iter::FusedIterator;
/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
///
@@ -105,6 +106,9 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
}
}
+#[stable(feature = "decode_utf16_fused_iterator", since = "1.75.0")]
+impl<I: Iterator<Item = u16> + FusedIterator> FusedIterator for DecodeUtf16<I> {}
+
impl DecodeUtf16Error {
/// Returns the unpaired surrogate which caused this error.
#[must_use]
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 4ac956e7b..7ce33bdd4 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1450,7 +1450,7 @@ impl char {
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_alphanumeric(&self) -> bool {
- matches!(*self, '0'..='9' | 'A'..='Z' | 'a'..='z')
+ matches!(*self, '0'..='9') | matches!(*self, 'A'..='Z') | matches!(*self, 'a'..='z')
}
/// Checks if the value is an ASCII decimal digit:
@@ -1553,7 +1553,7 @@ impl char {
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_hexdigit(&self) -> bool {
- matches!(*self, '0'..='9' | 'A'..='F' | 'a'..='f')
+ matches!(*self, '0'..='9') | matches!(*self, 'A'..='F') | matches!(*self, 'a'..='f')
}
/// Checks if the value is an ASCII punctuation character:
@@ -1591,7 +1591,10 @@ impl char {
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_punctuation(&self) -> bool {
- matches!(*self, '!'..='/' | ':'..='@' | '['..='`' | '{'..='~')
+ matches!(*self, '!'..='/')
+ | matches!(*self, ':'..='@')
+ | matches!(*self, '['..='`')
+ | matches!(*self, '{'..='~')
}
/// Checks if the value is an ASCII graphic character:
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 360806167..fadf2fcc9 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -3,14 +3,17 @@
//! This module contains various tools for comparing and ordering values. In
//! summary:
//!
-//! * [`Eq`] and [`PartialEq`] are traits that allow you to define total and
-//! partial equality between values, respectively. Implementing them overloads
-//! the `==` and `!=` operators.
+//! * [`PartialEq<Rhs>`] overloads the `==` and `!=` operators. In cases where
+//! `Rhs` (the right hand side's type) is `Self`, this trait corresponds to a
+//! partial equivalence relation.
+//! * [`Eq`] indicates that the overloaded `==` operator corresponds to an
+//! equivalence relation.
//! * [`Ord`] and [`PartialOrd`] are traits that allow you to define total and
//! partial orderings between values, respectively. Implementing them overloads
//! the `<`, `<=`, `>`, and `>=` operators.
//! * [`Ordering`] is an enum returned by the main functions of [`Ord`] and
-//! [`PartialOrd`], and describes an ordering.
+//! [`PartialOrd`], and describes an ordering of two values (less, equal, or
+//! greater).
//! * [`Reverse`] is a struct that allows you to easily reverse an ordering.
//! * [`max`] and [`min`] are functions that build off of [`Ord`] and allow you
//! to find the maximum or minimum of two values.
@@ -27,16 +30,21 @@ pub(crate) use bytewise::BytewiseEq;
use self::Ordering::*;
-/// Trait for equality comparisons.
+/// Trait for comparisons using the equality operator.
+///
+/// Implementing this trait for types provides the `==` and `!=` operators for
+/// those types.
///
/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
/// We use the easier-to-read infix notation in the remainder of this documentation.
///
-/// This trait allows for partial equality, for types that do not have a full
-/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
-/// so floating point types implement `PartialEq` but not [`trait@Eq`].
-/// Formally speaking, when `Rhs == Self`, this trait corresponds to a [partial equivalence
-/// relation](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
+/// This trait allows for comparisons using the equality operator, for types
+/// that do not have a full equivalence relation. For example, in floating point
+/// numbers `NaN != NaN`, so floating point types implement `PartialEq` but not
+/// [`trait@Eq`]. Formally speaking, when `Rhs == Self`, this trait corresponds
+/// to a [partial equivalence relation].
+///
+/// [partial equivalence relation]: https://en.wikipedia.org/wiki/Partial_equivalence_relation
///
/// Implementations must ensure that `eq` and `ne` are consistent with each other:
///
@@ -242,15 +250,15 @@ pub macro PartialEq($item:item) {
/* compiler built-in */
}
-/// Trait for equality comparisons which are [equivalence relations](
+/// Trait for comparisons corresponding to [equivalence relations](
/// https://en.wikipedia.org/wiki/Equivalence_relation).
///
-/// This means, that in addition to `a == b` and `a != b` being strict inverses, the equality must
-/// be (for all `a`, `b` and `c`):
+/// This means, that in addition to `a == b` and `a != b` being strict inverses,
+/// the relation must be (for all `a`, `b` and `c`):
///
/// - reflexive: `a == a`;
-/// - symmetric: `a == b` implies `b == a`; and
-/// - transitive: `a == b` and `b == c` implies `a == c`.
+/// - symmetric: `a == b` implies `b == a` (required by `PartialEq` as well); and
+/// - transitive: `a == b` and `b == c` implies `a == c` (required by `PartialEq` as well).
///
/// This property cannot be checked by the compiler, and therefore `Eq` implies
/// [`PartialEq`], and has no extra methods.
@@ -260,6 +268,10 @@ pub macro PartialEq($item:item) {
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
/// methods.
///
+/// Implement `Eq` in addition to `PartialEq` if it's guaranteed that
+/// `PartialEq::eq(a, a)` always returns `true` (reflexivity), in addition to
+/// the symmetric and transitive properties already required by `PartialEq`.
+///
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has
@@ -299,8 +311,7 @@ pub trait Eq: PartialEq<Self> {
//
// This should never be implemented by hand.
#[doc(hidden)]
- #[cfg_attr(bootstrap, no_coverage)] // rust-lang/rust#84605
- #[cfg_attr(not(bootstrap), coverage(off))] //
+ #[coverage(off)]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn assert_receiver_is_total_eq(&self) {}
@@ -310,8 +321,7 @@ pub trait Eq: PartialEq<Self> {
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
-#[cfg_attr(bootstrap, allow_internal_unstable(no_coverage))]
-#[cfg_attr(not(bootstrap), allow_internal_unstable(coverage_attribute))]
+#[allow_internal_unstable(coverage_attribute)]
pub macro Eq($item:item) {
/* compiler built-in */
}
@@ -676,12 +686,19 @@ impl<T: Clone> Clone for Reverse<T> {
///
/// ## Corollaries
///
-/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
-/// This means that for all `a`, `b` and `c`:
+/// From the above and the requirements of `PartialOrd`, it follows that for
+/// all `a`, `b` and `c`:
///
/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
+/// Mathematically speaking, the `<` operator defines a strict [weak order]. In
+/// cases where `==` conforms to mathematical equality, it also defines a
+/// strict [total order].
+///
+/// [weak order]: https://en.wikipedia.org/wiki/Weak_ordering
+/// [total order]: https://en.wikipedia.org/wiki/Total_order
+///
/// ## Derivable
///
/// This trait can be used with `#[derive]`.
@@ -723,7 +740,7 @@ impl<T: Clone> Clone for Reverse<T> {
/// - Two sequences are compared element by element.
/// - The first mismatching element defines which sequence is lexicographically less or greater than the other.
/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than the other.
-/// - If two sequence have equivalent elements and are of the same length, then the sequences are lexicographically equal.
+/// - If two sequences have equivalent elements and are of the same length, then the sequences are lexicographically equal.
/// - An empty sequence is lexicographically less than any non-empty sequence.
/// - Two empty sequences are lexicographically equal.
///
@@ -790,6 +807,7 @@ pub trait Ord: Eq + PartialOrd<Self> {
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_diagnostic_item = "ord_cmp_method"]
fn cmp(&self, other: &Self) -> Ordering;
/// Compares and returns the maximum of two values.
@@ -920,6 +938,20 @@ pub macro Ord($item:item) {
/// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
///
+/// ## Strict and non-strict partial orders
+///
+/// The `<` and `>` operators behave according to a *strict* partial order.
+/// However, `<=` and `>=` do **not** behave according to a *non-strict*
+/// partial order.
+/// That is because mathematically, a non-strict partial order would require
+/// reflexivity, i.e. `a <= a` would need to be true for every `a`. This isn't
+/// always the case for types that implement `PartialOrd`, for example:
+///
+/// ```
+/// let a = f64::sqrt(-1.0);
+/// assert_eq!(a <= a, false);
+/// ```
+///
/// ## Derivable
///
/// This trait can be used with `#[derive]`.
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index ff5a4c913..8c01b0973 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -100,6 +100,7 @@ pub use num::FloatToInt;
#[stable(feature = "convert_id", since = "1.33.0")]
#[rustc_const_stable(feature = "const_identity", since = "1.33.0")]
#[inline(always)]
+#[rustc_diagnostic_item = "convert_identity"]
pub const fn identity<T>(x: T) -> T {
x
}
@@ -137,7 +138,7 @@ pub const fn identity<T>(x: T) -> T {
///
/// [dereferenceable types]: core::ops::Deref
/// [pointed-to value]: core::ops::Deref::Target
-/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion
+/// ['`Deref` coercion']: core::ops::Deref#deref-coercion
///
/// ```
/// let x = Box::new(5i32);
@@ -243,7 +244,7 @@ pub trait AsRef<T: ?Sized> {
///
/// [mutably dereferenceable types]: core::ops::DerefMut
/// [pointed-to value]: core::ops::Deref::Target
-/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion
+/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion
///
/// ```
/// let mut x = Box::new(5i32);
@@ -478,6 +479,46 @@ pub trait Into<T>: Sized {
/// - `From<T> for U` implies [`Into`]`<U> for T`
/// - `From` is reflexive, which means that `From<T> for T` is implemented
///
+/// # When to implement `From`
+///
+/// While there's no technical restrictions on which conversions can be done using
+/// a `From` implementation, the general expectation is that the conversions
+/// should typically be restricted as follows:
+///
+/// * The conversion is *infallible*: if the conversion can fail, use [`TryFrom`]
+/// instead; don't provide a `From` impl that panics.
+///
+/// * The conversion is *lossless*: semantically, it should not lose or discard
+/// information. For example, `i32: From<u16>` exists, where the original
+/// value can be recovered using `u16: TryFrom<i32>`. And `String: From<&str>`
+/// exists, where you can get something equivalent to the original value via
+/// `Deref`. But `From` cannot be used to convert from `u32` to `u16`, since
+/// that cannot succeed in a lossless way. (There's some wiggle room here for
+/// information not considered semantically relevant. For example,
+/// `Box<[T]>: From<Vec<T>>` exists even though it might not preserve capacity,
+/// like how two vectors can be equal despite differing capacities.)
+///
+/// * The conversion is *value-preserving*: the conceptual kind and meaning of
+/// the resulting value is the same, even though the Rust type and technical
+/// representation might be different. For example `-1_i8 as u8` is *lossless*,
+/// since `as` casting back can recover the original value, but that conversion
+/// is *not* available via `From` because `-1` and `255` are different conceptual
+/// values (despite being identical bit patterns technically). But
+/// `f32: From<i16>` *is* available because `1_i16` and `1.0_f32` are conceptually
+/// the same real number (despite having very different bit patterns technically).
+/// `String: From<char>` is available because they're both *text*, but
+/// `String: From<u32>` is *not* available, since `1` (a number) and `"1"`
+/// (text) are too different. (Converting values to text is instead covered
+/// by the [`Display`](crate::fmt::Display) trait.)
+///
+/// * The conversion is *obvious*: it's the only reasonable conversion between
+/// the two types. Otherwise it's better to have it be a named method or
+/// constructor, like how [`str::as_bytes`] is a method and how integers have
+/// methods like [`u32::from_ne_bytes`], [`u32::from_le_bytes`], and
+/// [`u32::from_be_bytes`], none of which are `From` implementations. Whereas
+/// there's only one reasonable way to wrap an [`Ipv6Addr`](crate::net::Ipv6Addr)
+/// into an [`IpAddr`](crate::net::IpAddr), thus `IpAddr: From<Ipv6Addr>` exists.
+///
/// # Examples
///
/// [`String`] implements `From<&str>`:
@@ -532,7 +573,7 @@ pub trait Into<T>: Sized {
#[rustc_diagnostic_item = "From"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(on(
- all(_Self = "&str", any(T = "alloc::string::String", T = "std::string::String")),
+ all(_Self = "&str", T = "alloc::string::String"),
note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
))]
pub trait From<T>: Sized {
@@ -577,12 +618,11 @@ pub trait TryInto<T>: Sized {
/// For example, there is no way to convert an [`i64`] into an [`i32`]
/// using the [`From`] trait, because an [`i64`] may contain a value
/// that an [`i32`] cannot represent and so the conversion would lose data.
-/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
-/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
-/// [`i32::MAX`], or by some other method. The [`From`] trait is intended
-/// for perfect conversions, so the `TryFrom` trait informs the
-/// programmer when a type conversion could go bad and lets them
-/// decide how to handle it.
+/// This might be handled by truncating the [`i64`] to an [`i32`] or by
+/// simply returning [`i32::MAX`], or by some other method. The [`From`]
+/// trait is intended for perfect conversions, so the `TryFrom` trait
+/// informs the programmer when a type conversion could go bad and lets
+/// them decide how to handle it.
///
/// # Generic Implementations
///
@@ -642,6 +682,7 @@ pub trait TryFrom<T>: Sized {
/// Performs the conversion.
#[stable(feature = "try_from", since = "1.34.0")]
+ #[rustc_diagnostic_item = "try_from_fn"]
fn try_from(value: T) -> Result<Self, Self::Error>;
}
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 5242e97eb..16618b387 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -130,6 +130,7 @@ pub trait Default: Sized {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_diagnostic_item = "default_fn"]
fn default() -> Self;
}
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 1170221c1..f1a7ad935 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -439,10 +439,10 @@ where
/// * A Producer initializes the value of one of its fields of a specific type. (or is otherwise
/// prepared to generate a value requested). eg, `backtrace::Backtrace` or
/// `std::backtrace::Backtrace`
-/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace). In the case
-/// of a `dyn Error` trait object (the Producer), there are methods called `request_ref` and
-/// `request_value` are available to simplify obtaining an ``Option<T>`` for a given type. * The
-/// Producer, when requested, populates the given Request object which is given as a mutable
+/// * A Consumer requests an object of a specific type (say `std::backtrace::Backtrace`). In the
+/// case of a `dyn Error` trait object (the Producer), there are functions called `request_ref` and
+/// `request_value` to simplify obtaining an `Option<T>` for a given type.
+/// * The Producer, when requested, populates the given Request object which is given as a mutable
/// reference.
/// * The Consumer extracts a value or reference to the requested type from the `Request` object
/// wrapped in an `Option<T>`; in the case of `dyn Error` the aforementioned `request_ref` and `
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 93a6716d7..e7ec1fb73 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -487,7 +487,7 @@ impl CStr {
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *const c_char {
self.inner.as_ptr()
}
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index b2c9a0800..6908c824f 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -6,7 +6,7 @@
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.
-#![stable(feature = "", since = "1.30.0")]
+#![stable(feature = "core_ffi", since = "1.30.0")]
#![allow(non_camel_case_types)]
use crate::fmt;
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 922724804..4ccb58586 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -84,6 +84,7 @@ impl fmt::Write for PadAdapter<'_, '_> {
#[must_use = "must eventually call `finish()` on Debug builders"]
#[allow(missing_debug_implementations)]
#[stable(feature = "debug_builders", since = "1.2.0")]
+#[rustc_diagnostic_item = "DebugStruct"]
pub struct DebugStruct<'a, 'b: 'a> {
fmt: &'a mut fmt::Formatter<'b>,
result: fmt::Result,
@@ -129,6 +130,18 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self {
+ self.field_with(name, |f| value.fmt(f))
+ }
+
+ /// Adds a new field to the generated struct output.
+ ///
+ /// This method is equivalent to [`DebugStruct::field`], but formats the
+ /// value using a provided closure rather than by calling [`Debug::fmt`].
+ #[unstable(feature = "debug_closure_helpers", issue = "117729")]
+ pub fn field_with<F>(&mut self, name: &str, value_fmt: F) -> &mut Self
+ where
+ F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+ {
self.result = self.result.and_then(|_| {
if self.is_pretty() {
if !self.has_fields {
@@ -139,14 +152,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
writer.write_str(name)?;
writer.write_str(": ")?;
- value.fmt(&mut writer)?;
+ value_fmt(&mut writer)?;
writer.write_str(",\n")
} else {
let prefix = if self.has_fields { ", " } else { " { " };
self.fmt.write_str(prefix)?;
self.fmt.write_str(name)?;
self.fmt.write_str(": ")?;
- value.fmt(self.fmt)
+ value_fmt(self.fmt)
}
});
@@ -314,6 +327,18 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self {
+ self.field_with(|f| value.fmt(f))
+ }
+
+ /// Adds a new field to the generated tuple struct output.
+ ///
+ /// This method is equivalent to [`DebugTuple::field`], but formats the
+ /// value using a provided closure rather than by calling [`Debug::fmt`].
+ #[unstable(feature = "debug_closure_helpers", issue = "117729")]
+ pub fn field_with<F>(&mut self, value_fmt: F) -> &mut Self
+ where
+ F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+ {
self.result = self.result.and_then(|_| {
if self.is_pretty() {
if self.fields == 0 {
@@ -322,12 +347,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
let mut slot = None;
let mut state = Default::default();
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
- value.fmt(&mut writer)?;
+ value_fmt(&mut writer)?;
writer.write_str(",\n")
} else {
let prefix = if self.fields == 0 { "(" } else { ", " };
self.fmt.write_str(prefix)?;
- value.fmt(self.fmt)
+ value_fmt(self.fmt)
}
});
@@ -384,7 +409,10 @@ struct DebugInner<'a, 'b: 'a> {
}
impl<'a, 'b: 'a> DebugInner<'a, 'b> {
- fn entry(&mut self, entry: &dyn fmt::Debug) {
+ fn entry_with<F>(&mut self, entry_fmt: F)
+ where
+ F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+ {
self.result = self.result.and_then(|_| {
if self.is_pretty() {
if !self.has_fields {
@@ -393,13 +421,13 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
let mut slot = None;
let mut state = Default::default();
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state);
- entry.fmt(&mut writer)?;
+ entry_fmt(&mut writer)?;
writer.write_str(",\n")
} else {
if self.has_fields {
self.fmt.write_str(", ")?
}
- entry.fmt(self.fmt)
+ entry_fmt(self.fmt)
}
});
@@ -474,7 +502,20 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
- self.inner.entry(entry);
+ self.inner.entry_with(|f| entry.fmt(f));
+ self
+ }
+
+ /// Adds a new entry to the set output.
+ ///
+ /// This method is equivalent to [`DebugSet::entry`], but formats the
+ /// entry using a provided closure rather than by calling [`Debug::fmt`].
+ #[unstable(feature = "debug_closure_helpers", issue = "117729")]
+ pub fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
+ where
+ F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+ {
+ self.inner.entry_with(entry_fmt);
self
}
@@ -604,7 +645,20 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
/// ```
#[stable(feature = "debug_builders", since = "1.2.0")]
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
- self.inner.entry(entry);
+ self.inner.entry_with(|f| entry.fmt(f));
+ self
+ }
+
+ /// Adds a new entry to the list output.
+ ///
+ /// This method is equivalent to [`DebugList::entry`], but formats the
+ /// entry using a provided closure rather than by calling [`Debug::fmt`].
+ #[unstable(feature = "debug_closure_helpers", issue = "117729")]
+ pub fn entry_with<F>(&mut self, entry_fmt: F) -> &mut Self
+ where
+ F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+ {
+ self.inner.entry_with(entry_fmt);
self
}
@@ -774,6 +828,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
/// ```
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self {
+ self.key_with(|f| key.fmt(f))
+ }
+
+ /// Adds the key part of a new entry to the map output.
+ ///
+ /// This method is equivalent to [`DebugMap::key`], but formats the
+ /// key using a provided closure rather than by calling [`Debug::fmt`].
+ #[unstable(feature = "debug_closure_helpers", issue = "117729")]
+ pub fn key_with<F>(&mut self, key_fmt: F) -> &mut Self
+ where
+ F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+ {
self.result = self.result.and_then(|_| {
assert!(
!self.has_key,
@@ -788,13 +854,13 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
let mut slot = None;
self.state = Default::default();
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
- key.fmt(&mut writer)?;
+ key_fmt(&mut writer)?;
writer.write_str(": ")?;
} else {
if self.has_fields {
self.fmt.write_str(", ")?
}
- key.fmt(self.fmt)?;
+ key_fmt(self.fmt)?;
self.fmt.write_str(": ")?;
}
@@ -838,16 +904,28 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
/// ```
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self {
+ self.value_with(|f| value.fmt(f))
+ }
+
+ /// Adds the value part of a new entry to the map output.
+ ///
+ /// This method is equivalent to [`DebugMap::value`], but formats the
+ /// value using a provided closure rather than by calling [`Debug::fmt`].
+ #[unstable(feature = "debug_closure_helpers", issue = "117729")]
+ pub fn value_with<F>(&mut self, value_fmt: F) -> &mut Self
+ where
+ F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+ {
self.result = self.result.and_then(|_| {
assert!(self.has_key, "attempted to format a map value before its key");
if self.is_pretty() {
let mut slot = None;
let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state);
- value.fmt(&mut writer)?;
+ value_fmt(&mut writer)?;
writer.write_str(",\n")?;
} else {
- value.fmt(self.fmt)?;
+ value_fmt(self.fmt)?;
}
self.has_key = false;
@@ -935,3 +1013,44 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
self.fmt.alternate()
}
}
+
+/// Implements [`fmt::Debug`] and [`fmt::Display`] using a function.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(debug_closure_helpers)]
+/// use std::fmt;
+///
+/// let value = 'a';
+/// assert_eq!(format!("{}", value), "a");
+/// assert_eq!(format!("{:?}", value), "'a'");
+///
+/// let wrapped = fmt::FormatterFn(|f| write!(f, "{:?}", &value));
+/// assert_eq!(format!("{}", wrapped), "'a'");
+/// assert_eq!(format!("{:?}", wrapped), "'a'");
+/// ```
+#[unstable(feature = "debug_closure_helpers", issue = "117729")]
+pub struct FormatterFn<F>(pub F)
+where
+ F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result;
+
+#[unstable(feature = "debug_closure_helpers", issue = "117729")]
+impl<F> fmt::Debug for FormatterFn<F>
+where
+ F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ (self.0)(f)
+ }
+}
+
+#[unstable(feature = "debug_closure_helpers", issue = "117729")]
+impl<F> fmt::Display for FormatterFn<F>
+where
+ F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ (self.0)(f)
+ }
+}
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index fc91d1afc..e1b7b46a1 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -39,6 +39,9 @@ pub enum Alignment {
#[stable(feature = "debug_builders", since = "1.2.0")]
pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
+#[unstable(feature = "debug_closure_helpers", issue = "117729")]
+pub use self::builders::FormatterFn;
+
/// The type returned by formatter methods.
///
/// # Examples
@@ -239,6 +242,7 @@ impl<W: Write + ?Sized> Write for &mut W {
/// documentation of the methods defined on `Formatter` below.
#[allow(missing_debug_implementations)]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Formatter"]
pub struct Formatter<'a> {
flags: u32,
fill: char,
@@ -791,8 +795,10 @@ pub trait Octal {
/// assert_eq!(format!("l as binary is: {l:b}"), "l as binary is: 1101011");
///
/// assert_eq!(
-/// format!("l as binary is: {l:#032b}"),
-/// "l as binary is: 0b000000000000000000000001101011"
+/// // Note that the `0b` prefix added by `#` is included in the total width, so we
+/// // need to add two to correctly display all 32 bits.
+/// format!("l as binary is: {l:#034b}"),
+/// "l as binary is: 0b00000000000000000000000001101011"
/// );
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index d37888c27..5bf221b42 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -133,6 +133,10 @@ impl<'a> Argument<'a> {
Self::new(x, USIZE_MARKER)
}
+ // FIXME: Transmuting formatter in new and indirectly branching to/calling
+ // it here is an explicit CFI violation.
+ #[allow(inline_no_sanitize)]
+ #[no_sanitize(cfi, kcfi)]
#[inline(always)]
pub(super) fn fmt(&self, f: &mut Formatter<'_>) -> Result {
(self.formatter)(self.value, f)
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index 089493d37..0f77a2d83 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -38,7 +38,7 @@ pub use poll_fn::{poll_fn, PollFn};
/// This type is needed because:
///
-/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
+/// a) Coroutines cannot implement `for<'a, 'b> Coroutine<&'a mut Context<'b>>`, so we need to pass
/// a raw pointer (see <https://github.com/rust-lang/rust/issues/68923>).
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
/// non-Send/Sync as well, and we don't want that.
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 4bf3da073..ff177c70d 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -277,7 +277,7 @@ pub fn spin_loop() {
/// - Treats the call to `contains` and its result as volatile: the body of `benchmark` cannot
/// optimize this away
///
-/// This makes our benchmark much more realistic to how the function would be used in situ, where
+/// This makes our benchmark much more realistic to how the function would actually be used, where
/// arguments are usually not known at compile time and the result is used in some way.
#[inline]
#[stable(feature = "bench_black_box", since = "1.66.0")]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 4c76662ac..c5aef67b5 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1072,7 +1072,7 @@ extern "rust-intrinsic" {
/// zero-initialization: This will statically either panic, or do nothing.
///
/// This intrinsic does not have a stable counterpart.
- #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+ #[rustc_const_stable(feature = "const_assert_type2", since = "1.75.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn assert_zero_valid<T>();
@@ -1080,7 +1080,7 @@ extern "rust-intrinsic" {
/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing.
///
/// This intrinsic does not have a stable counterpart.
- #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+ #[rustc_const_stable(feature = "const_assert_type2", since = "1.75.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn assert_mem_uninitialized_valid<T>();
@@ -1509,12 +1509,14 @@ extern "rust-intrinsic" {
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
+ #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_load"]
pub fn unaligned_volatile_load<T>(src: *const T) -> T;
/// Performs a volatile store to the `dst` pointer.
/// The pointer is not required to be aligned.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_nounwind]
+ #[rustc_diagnostic_item = "intrinsics_unaligned_volatile_store"]
pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
/// Returns the square root of an `f32`
@@ -2277,7 +2279,7 @@ extern "rust-intrinsic" {
/// any safety invariants.
///
/// The stabilized version of this intrinsic is [`core::mem::discriminant`].
- #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
+ #[rustc_const_stable(feature = "const_discriminant", since = "1.75.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
@@ -2666,6 +2668,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
extern "rust-intrinsic" {
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
@@ -2761,6 +2764,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_copy"]
pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
extern "rust-intrinsic" {
#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
@@ -2834,6 +2838,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_write_bytes"]
pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
extern "rust-intrinsic" {
#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index cab195dad..b26a17ec3 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -12,8 +12,7 @@
//!
//! Typical usage will look like this:
//!
-#![cfg_attr(bootstrap, doc = "```rust,ignore")]
-#![cfg_attr(not(bootstrap), doc = "```rust")]
+//! ```rust
//! #![feature(core_intrinsics, custom_mir)]
//! #![allow(internal_features)]
//!
@@ -63,8 +62,7 @@
//!
//! # Examples
//!
-#![cfg_attr(bootstrap, doc = "```rust,ignore")]
-#![cfg_attr(not(bootstrap), doc = "```rust")]
+//! ```rust
//! #![feature(core_intrinsics, custom_mir)]
//! #![allow(internal_features)]
//!
@@ -106,7 +104,6 @@
//! }
//!
//! #[custom_mir(dialect = "runtime", phase = "optimized")]
-#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set
//! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
//! mir!(
//! let _unused;
@@ -319,8 +316,7 @@ define!(
///
/// # Examples
///
- #[cfg_attr(bootstrap, doc = "```rust,ignore")]
- #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// ```rust
/// #![allow(internal_features)]
/// #![feature(custom_mir, core_intrinsics)]
///
diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs
new file mode 100644
index 000000000..fe25cac28
--- /dev/null
+++ b/library/core/src/io/borrowed_buf.rs
@@ -0,0 +1,301 @@
+#![unstable(feature = "core_io_borrowed_buf", issue = "117693")]
+
+use crate::fmt::{self, Debug, Formatter};
+use crate::mem::{self, MaybeUninit};
+use crate::{cmp, ptr};
+
+/// A borrowed byte buffer which is incrementally filled and initialized.
+///
+/// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the
+/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet
+/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a
+/// subset of the initialized region.
+///
+/// In summary, the contents of the buffer can be visualized as:
+/// ```not_rust
+/// [ capacity ]
+/// [ filled | unfilled ]
+/// [ initialized | uninitialized ]
+/// ```
+///
+/// A `BorrowedBuf` is created around some existing data (or capacity for data) via a unique reference
+/// (`&mut`). The `BorrowedBuf` can be configured (e.g., using `clear` or `set_init`), but cannot be
+/// directly written. To write into the buffer, use `unfilled` to create a `BorrowedCursor`. The cursor
+/// has write-only access to the unfilled portion of the buffer (you can think of it as a
+/// write-only iterator).
+///
+/// The lifetime `'data` is a bound on the lifetime of the underlying data.
+pub struct BorrowedBuf<'data> {
+ /// The buffer's underlying data.
+ buf: &'data mut [MaybeUninit<u8>],
+ /// The length of `self.buf` which is known to be filled.
+ filled: usize,
+ /// The length of `self.buf` which is known to be initialized.
+ init: usize,
+}
+
+impl Debug for BorrowedBuf<'_> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.debug_struct("BorrowedBuf")
+ .field("init", &self.init)
+ .field("filled", &self.filled)
+ .field("capacity", &self.capacity())
+ .finish()
+ }
+}
+
+/// Create a new `BorrowedBuf` from a fully initialized slice.
+impl<'data> From<&'data mut [u8]> for BorrowedBuf<'data> {
+ #[inline]
+ fn from(slice: &'data mut [u8]) -> BorrowedBuf<'data> {
+ let len = slice.len();
+
+ BorrowedBuf {
+ // SAFETY: initialized data never becoming uninitialized is an invariant of BorrowedBuf
+ buf: unsafe { (slice as *mut [u8]).as_uninit_slice_mut().unwrap() },
+ filled: 0,
+ init: len,
+ }
+ }
+}
+
+/// Create a new `BorrowedBuf` from an uninitialized buffer.
+///
+/// Use `set_init` if part of the buffer is known to be already initialized.
+impl<'data> From<&'data mut [MaybeUninit<u8>]> for BorrowedBuf<'data> {
+ #[inline]
+ fn from(buf: &'data mut [MaybeUninit<u8>]) -> BorrowedBuf<'data> {
+ BorrowedBuf { buf, filled: 0, init: 0 }
+ }
+}
+
+impl<'data> BorrowedBuf<'data> {
+ /// Returns the total capacity of the buffer.
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ self.buf.len()
+ }
+
+ /// Returns the length of the filled part of the buffer.
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.filled
+ }
+
+ /// Returns the length of the initialized part of the buffer.
+ #[inline]
+ pub fn init_len(&self) -> usize {
+ self.init
+ }
+
+ /// Returns a shared reference to the filled portion of the buffer.
+ #[inline]
+ pub fn filled(&self) -> &[u8] {
+ // SAFETY: We only slice the filled part of the buffer, which is always valid
+ unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) }
+ }
+
+ /// Returns a mutable reference to the filled portion of the buffer.
+ #[inline]
+ pub fn filled_mut(&mut self) -> &mut [u8] {
+ // SAFETY: We only slice the filled part of the buffer, which is always valid
+ unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) }
+ }
+
+ /// Returns a cursor over the unfilled part of the buffer.
+ #[inline]
+ pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> {
+ BorrowedCursor {
+ start: self.filled,
+ // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its
+ // lifetime covariantly is safe.
+ buf: unsafe {
+ mem::transmute::<&'this mut BorrowedBuf<'data>, &'this mut BorrowedBuf<'this>>(self)
+ },
+ }
+ }
+
+ /// Clears the buffer, resetting the filled region to empty.
+ ///
+ /// The number of initialized bytes is not changed, and the contents of the buffer are not modified.
+ #[inline]
+ pub fn clear(&mut self) -> &mut Self {
+ self.filled = 0;
+ self
+ }
+
+ /// Asserts that the first `n` bytes of the buffer are initialized.
+ ///
+ /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer
+ /// bytes than are already known to be initialized.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized.
+ #[inline]
+ pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
+ self.init = cmp::max(self.init, n);
+ self
+ }
+}
+
+/// A writeable view of the unfilled portion of a [`BorrowedBuf`](BorrowedBuf).
+///
+/// Provides access to the initialized and uninitialized parts of the underlying `BorrowedBuf`.
+/// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or
+/// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the
+/// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform
+/// the cursor how many bytes have been written.
+///
+/// Once data is written to the cursor, it becomes part of the filled portion of the underlying
+/// `BorrowedBuf` and can no longer be accessed or re-written by the cursor. I.e., the cursor tracks
+/// the unfilled part of the underlying `BorrowedBuf`.
+///
+/// The lifetime `'a` is a bound on the lifetime of the underlying buffer (which means it is a bound
+/// on the data in that buffer by transitivity).
+#[derive(Debug)]
+pub struct BorrowedCursor<'a> {
+ /// The underlying buffer.
+ // Safety invariant: we treat the type of buf as covariant in the lifetime of `BorrowedBuf` when
+ // we create a `BorrowedCursor`. This is only safe if we never replace `buf` by assigning into
+ // it, so don't do that!
+ buf: &'a mut BorrowedBuf<'a>,
+ /// The length of the filled portion of the underlying buffer at the time of the cursor's
+ /// creation.
+ start: usize,
+}
+
+impl<'a> BorrowedCursor<'a> {
+ /// Reborrow this cursor by cloning it with a smaller lifetime.
+ ///
+ /// Since a cursor maintains unique access to its underlying buffer, the borrowed cursor is
+ /// not accessible while the new cursor exists.
+ #[inline]
+ pub fn reborrow<'this>(&'this mut self) -> BorrowedCursor<'this> {
+ BorrowedCursor {
+ // SAFETY: we never assign into `BorrowedCursor::buf`, so treating its
+ // lifetime covariantly is safe.
+ buf: unsafe {
+ mem::transmute::<&'this mut BorrowedBuf<'a>, &'this mut BorrowedBuf<'this>>(
+ self.buf,
+ )
+ },
+ start: self.start,
+ }
+ }
+
+ /// Returns the available space in the cursor.
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ self.buf.capacity() - self.buf.filled
+ }
+
+ /// Returns the number of bytes written to this cursor since it was created from a `BorrowedBuf`.
+ ///
+ /// Note that if this cursor is a reborrowed clone of another, then the count returned is the
+ /// count written via either cursor, not the count since the cursor was reborrowed.
+ #[inline]
+ pub fn written(&self) -> usize {
+ self.buf.filled - self.start
+ }
+
+ /// Returns a shared reference to the initialized portion of the cursor.
+ #[inline]
+ pub fn init_ref(&self) -> &[u8] {
+ // SAFETY: We only slice the initialized part of the buffer, which is always valid
+ unsafe { MaybeUninit::slice_assume_init_ref(&self.buf.buf[self.buf.filled..self.buf.init]) }
+ }
+
+ /// Returns a mutable reference to the initialized portion of the cursor.
+ #[inline]
+ pub fn init_mut(&mut self) -> &mut [u8] {
+ // SAFETY: We only slice the initialized part of the buffer, which is always valid
+ unsafe {
+ MaybeUninit::slice_assume_init_mut(&mut self.buf.buf[self.buf.filled..self.buf.init])
+ }
+ }
+
+ /// Returns a mutable reference to the uninitialized part of the cursor.
+ ///
+ /// It is safe to uninitialize any of these bytes.
+ #[inline]
+ pub fn uninit_mut(&mut self) -> &mut [MaybeUninit<u8>] {
+ &mut self.buf.buf[self.buf.init..]
+ }
+
+ /// Returns a mutable reference to the whole cursor.
+ ///
+ /// # Safety
+ ///
+ /// The caller must not uninitialize any bytes in the initialized portion of the cursor.
+ #[inline]
+ pub unsafe fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] {
+ &mut self.buf.buf[self.buf.filled..]
+ }
+
+ /// Advance the cursor by asserting that `n` bytes have been filled.
+ ///
+ /// After advancing, the `n` bytes are no longer accessible via the cursor and can only be
+ /// accessed via the underlying buffer. I.e., the buffer's filled portion grows by `n` elements
+ /// and its unfilled portion (and the capacity of this cursor) shrinks by `n` elements.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that the first `n` bytes of the cursor have been properly
+ /// initialised.
+ #[inline]
+ pub unsafe fn advance(&mut self, n: usize) -> &mut Self {
+ self.buf.filled += n;
+ self.buf.init = cmp::max(self.buf.init, self.buf.filled);
+ self
+ }
+
+ /// Initializes all bytes in the cursor.
+ #[inline]
+ pub fn ensure_init(&mut self) -> &mut Self {
+ let uninit = self.uninit_mut();
+ // SAFETY: 0 is a valid value for MaybeUninit<u8> and the length matches the allocation
+ // since it is comes from a slice reference.
+ unsafe {
+ ptr::write_bytes(uninit.as_mut_ptr(), 0, uninit.len());
+ }
+ self.buf.init = self.buf.capacity();
+
+ self
+ }
+
+ /// Asserts that the first `n` unfilled bytes of the cursor are initialized.
+ ///
+ /// `BorrowedBuf` assumes that bytes are never de-initialized, so this method does nothing when
+ /// called with fewer bytes than are already known to be initialized.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that the first `n` bytes of the buffer have already been initialized.
+ #[inline]
+ pub unsafe fn set_init(&mut self, n: usize) -> &mut Self {
+ self.buf.init = cmp::max(self.buf.init, self.buf.filled + n);
+ self
+ }
+
+ /// Appends data to the cursor, advancing position within its buffer.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `self.capacity()` is less than `buf.len()`.
+ #[inline]
+ pub fn append(&mut self, buf: &[u8]) {
+ assert!(self.capacity() >= buf.len());
+
+ // SAFETY: we do not de-initialize any of the elements of the slice
+ unsafe {
+ MaybeUninit::write_slice(&mut self.as_mut()[..buf.len()], buf);
+ }
+
+ // SAFETY: We just added the entire contents of buf to the filled section.
+ unsafe {
+ self.set_init(buf.len());
+ }
+ self.buf.filled += buf.len();
+ }
+}
diff --git a/library/core/src/io/mod.rs b/library/core/src/io/mod.rs
new file mode 100644
index 000000000..2f20180cd
--- /dev/null
+++ b/library/core/src/io/mod.rs
@@ -0,0 +1,6 @@
+//! Traits, helpers, and type definitions for core I/O functionality.
+
+mod borrowed_buf;
+
+#[unstable(feature = "core_io_borrowed_buf", issue = "117693")]
+pub use self::borrowed_buf::{BorrowedBuf, BorrowedCursor};
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
index 20aca323b..65ba42920 100644
--- a/library/core/src/iter/adapters/peekable.rs
+++ b/library/core/src/iter/adapters/peekable.rs
@@ -12,6 +12,7 @@ use crate::ops::{ControlFlow, Try};
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "IterPeekable"]
pub struct Peekable<I: Iterator> {
iter: I,
/// Remember a peeked value, even if it was None.
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index b6b0c90cb..77ccf5085 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -95,6 +95,14 @@ where
}
#[inline]
+ fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ ZipImpl::fold(self, init, f)
+ }
+
+ #[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
@@ -129,6 +137,9 @@ trait ZipImpl<A, B> {
where
A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator;
+ fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc;
// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
where
@@ -228,6 +239,14 @@ where
{
unreachable!("Always specialized");
}
+
+ #[inline]
+ default fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ SpecFold::spec_fold(self, init, f)
+ }
}
#[doc(hidden)]
@@ -251,6 +270,24 @@ where
// `Iterator::__iterator_get_unchecked`.
unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
}
+
+ #[inline]
+ fn fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ let mut accum = init;
+ let len = ZipImpl::size_hint(&self).0;
+ for i in 0..len {
+ // SAFETY: since Self: TrustedRandomAccessNoCoerce we can trust the size-hint to
+ // calculate the length and then use that to do unchecked iteration.
+ // fold consumes the iterator so we don't need to fixup any state.
+ unsafe {
+ accum = f(accum, self.get_unchecked(i));
+ }
+ }
+ accum
+ }
}
#[doc(hidden)]
@@ -590,3 +627,56 @@ unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccess f
unsafe { self.__iterator_get_unchecked(index) }
}
}
+
+trait SpecFold: Iterator {
+ fn spec_fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B;
+}
+
+impl<A: Iterator, B: Iterator> SpecFold for Zip<A, B> {
+ // Adapted from default impl from the Iterator trait
+ #[inline]
+ default fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ let mut accum = init;
+ while let Some(x) = ZipImpl::next(&mut self) {
+ accum = f(accum, x);
+ }
+ accum
+ }
+}
+
+impl<A: TrustedLen, B: TrustedLen> SpecFold for Zip<A, B> {
+ #[inline]
+ fn spec_fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
+ where
+ F: FnMut(Acc, Self::Item) -> Acc,
+ {
+ let mut accum = init;
+ loop {
+ let (upper, more) = if let Some(upper) = ZipImpl::size_hint(&self).1 {
+ (upper, false)
+ } else {
+ // Per TrustedLen contract a None upper bound means more than usize::MAX items
+ (usize::MAX, true)
+ };
+
+ for _ in 0..upper {
+ let pair =
+ // SAFETY: TrustedLen guarantees that at least `upper` many items are available
+ // therefore we know they can't be None
+ unsafe { (self.a.next().unwrap_unchecked(), self.b.next().unwrap_unchecked()) };
+ accum = f(accum, pair);
+ }
+
+ if !more {
+ break;
+ }
+ }
+ accum
+ }
+}
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index ca977d1ef..937a149ac 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -391,11 +391,11 @@ pub use self::traits::Iterator;
pub use self::range::Step;
#[unstable(
- feature = "iter_from_generator",
+ feature = "iter_from_coroutine",
issue = "43122",
- reason = "generators are unstable"
+ reason = "coroutines are unstable"
)]
-pub use self::sources::from_generator;
+pub use self::sources::from_coroutine;
#[stable(feature = "iter_empty", since = "1.2.0")]
pub use self::sources::{empty, Empty};
#[stable(feature = "iter_from_fn", since = "1.34.0")]
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 3ec426a3a..56c1f8607 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -1,6 +1,6 @@
mod empty;
+mod from_coroutine;
mod from_fn;
-mod from_generator;
mod once;
mod once_with;
mod repeat;
@@ -27,11 +27,11 @@ pub use self::repeat_with::{repeat_with, RepeatWith};
pub use self::from_fn::{from_fn, FromFn};
#[unstable(
- feature = "iter_from_generator",
+ feature = "iter_from_coroutine",
issue = "43122",
- reason = "generators are unstable"
+ reason = "coroutines are unstable"
)]
-pub use self::from_generator::from_generator;
+pub use self::from_coroutine::from_coroutine;
#[stable(feature = "iter_successors", since = "1.34.0")]
pub use self::successors::{successors, Successors};
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 243df015f..438e046a4 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -27,6 +27,7 @@ pub const fn empty<T>() -> Empty<T> {
/// This `struct` is created by the [`empty()`] function. See its documentation for more.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iter_empty", since = "1.2.0")]
+#[rustc_diagnostic_item = "IterEmpty"]
pub struct Empty<T>(marker::PhantomData<fn() -> T>);
#[stable(feature = "core_impl_debug", since = "1.9.0")]
diff --git a/library/core/src/iter/sources/from_coroutine.rs b/library/core/src/iter/sources/from_coroutine.rs
new file mode 100644
index 000000000..16fbca9b6
--- /dev/null
+++ b/library/core/src/iter/sources/from_coroutine.rs
@@ -0,0 +1,59 @@
+use crate::fmt;
+use crate::ops::{Coroutine, CoroutineState};
+use crate::pin::Pin;
+
+/// Creates a new iterator where each iteration calls the provided coroutine.
+///
+/// Similar to [`iter::from_fn`].
+///
+/// [`iter::from_fn`]: crate::iter::from_fn
+///
+/// # Examples
+///
+/// ```
+/// #![cfg_attr(bootstrap, feature(generators))]
+/// #![cfg_attr(not(bootstrap), feature(coroutines))]
+/// #![feature(iter_from_coroutine)]
+///
+/// let it = std::iter::from_coroutine(|| {
+/// yield 1;
+/// yield 2;
+/// yield 3;
+/// });
+/// let v: Vec<_> = it.collect();
+/// assert_eq!(v, [1, 2, 3]);
+/// ```
+#[inline]
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+pub fn from_coroutine<G: Coroutine<Return = ()> + Unpin>(coroutine: G) -> FromCoroutine<G> {
+ FromCoroutine(coroutine)
+}
+
+/// An iterator over the values yielded by an underlying coroutine.
+///
+/// This `struct` is created by the [`iter::from_coroutine()`] function. See its documentation for
+/// more.
+///
+/// [`iter::from_coroutine()`]: from_coroutine
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+#[derive(Clone)]
+pub struct FromCoroutine<G>(G);
+
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+impl<G: Coroutine<Return = ()> + Unpin> Iterator for FromCoroutine<G> {
+ type Item = G::Yield;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ match Pin::new(&mut self.0).resume(()) {
+ CoroutineState::Yielded(n) => Some(n),
+ CoroutineState::Complete(()) => None,
+ }
+ }
+}
+
+#[unstable(feature = "iter_from_coroutine", issue = "43122", reason = "coroutines are unstable")]
+impl<G> fmt::Debug for FromCoroutine<G> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("FromCoroutine").finish()
+ }
+}
diff --git a/library/core/src/iter/sources/from_generator.rs b/library/core/src/iter/sources/from_generator.rs
deleted file mode 100644
index 4cbe731b2..000000000
--- a/library/core/src/iter/sources/from_generator.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use crate::fmt;
-use crate::ops::{Generator, GeneratorState};
-use crate::pin::Pin;
-
-/// Creates a new iterator where each iteration calls the provided generator.
-///
-/// Similar to [`iter::from_fn`].
-///
-/// [`iter::from_fn`]: crate::iter::from_fn
-///
-/// # Examples
-///
-/// ```
-/// #![feature(generators)]
-/// #![feature(iter_from_generator)]
-///
-/// let it = std::iter::from_generator(|| {
-/// yield 1;
-/// yield 2;
-/// yield 3;
-/// });
-/// let v: Vec<_> = it.collect();
-/// assert_eq!(v, [1, 2, 3]);
-/// ```
-#[inline]
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-pub fn from_generator<G: Generator<Return = ()> + Unpin>(generator: G) -> FromGenerator<G> {
- FromGenerator(generator)
-}
-
-/// An iterator over the values yielded by an underlying generator.
-///
-/// This `struct` is created by the [`iter::from_generator()`] function. See its documentation for
-/// more.
-///
-/// [`iter::from_generator()`]: from_generator
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-#[derive(Clone)]
-pub struct FromGenerator<G>(G);
-
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-impl<G: Generator<Return = ()> + Unpin> Iterator for FromGenerator<G> {
- type Item = G::Yield;
-
- fn next(&mut self) -> Option<Self::Item> {
- match Pin::new(&mut self.0).resume(()) {
- GeneratorState::Yielded(n) => Some(n),
- GeneratorState::Complete(()) => None,
- }
- }
-}
-
-#[unstable(feature = "iter_from_generator", issue = "43122", reason = "generators are unstable")]
-impl<G> fmt::Debug for FromGenerator<G> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("FromGenerator").finish()
- }
-}
diff --git a/library/core/src/iter/sources/once.rs b/library/core/src/iter/sources/once.rs
index 6e9ed0d3c..21be4377d 100644
--- a/library/core/src/iter/sources/once.rs
+++ b/library/core/src/iter/sources/once.rs
@@ -61,6 +61,7 @@ pub fn once<T>(value: T) -> Once<T> {
/// This `struct` is created by the [`once()`] function. See its documentation for more.
#[derive(Clone, Debug)]
#[stable(feature = "iter_once", since = "1.2.0")]
+#[rustc_diagnostic_item = "IterOnce"]
pub struct Once<T> {
inner: crate::option::IntoIter<T>,
}
diff --git a/library/core/src/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs
index 9309a06c8..8b31ab2ff 100644
--- a/library/core/src/iter/sources/once_with.rs
+++ b/library/core/src/iter/sources/once_with.rs
@@ -4,7 +4,7 @@ use crate::iter::{FusedIterator, TrustedLen};
/// Creates an iterator that lazily generates a value exactly once by invoking
/// the provided closure.
///
-/// This is commonly used to adapt a single value generator into a [`chain()`] of
+/// This is commonly used to adapt a single value coroutine into a [`chain()`] of
/// other kinds of iteration. Maybe you have an iterator that covers almost
/// everything, but you need an extra special case. Maybe you have a function
/// which works on iterators, but you only need to process one value.
diff --git a/library/core/src/iter/sources/successors.rs b/library/core/src/iter/sources/successors.rs
index 6a6cbe905..7f7b2c775 100644
--- a/library/core/src/iter/sources/successors.rs
+++ b/library/core/src/iter/sources/successors.rs
@@ -17,7 +17,7 @@ where
F: FnMut(&T) -> Option<T>,
{
// If this function returned `impl Iterator<Item=T>`
- // it could be based on `unfold` and not need a dedicated type.
+ // it could be based on `from_fn` and not need a dedicated type.
// However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
Successors { next: first, succ }
}
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index e0ef5071c..0d1cf7941 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -146,6 +146,7 @@ pub trait FromIterator<A>: Sized {
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_diagnostic_item = "from_iter_fn"]
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
}
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index ac1fc26a1..6adea4442 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -27,13 +27,13 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(
- any(_Self = "core::ops::RangeTo<Idx>", _Self = "std::ops::RangeTo<Idx>"),
+ _Self = "core::ops::range::RangeTo<Idx>",
label = "if you meant to iterate until a value, add a starting value",
note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
bounded `Range`: `0..end`"
),
on(
- any(_Self = "core::ops::RangeToInclusive<Idx>", _Self = "std::ops::RangeToInclusive<Idx>"),
+ _Self = "core::ops::range::RangeToInclusive<Idx>",
label = "if you meant to iterate until a value (including it), add a starting value",
note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
to have a bounded `RangeInclusive`: `0..=end`"
@@ -44,7 +44,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
),
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
on(
- any(_Self = "alloc::vec::Vec<T, A>", _Self = "std::vec::Vec<T, A>"),
+ _Self = "alloc::vec::Vec<T, A>",
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
),
on(
@@ -52,7 +52,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
- any(_Self = "alloc::string::String", _Self = "std::string::String"),
+ _Self = "alloc::string::String",
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
@@ -69,6 +69,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
message = "`{Self}` is not an iterator"
)]
#[doc(notable_trait)]
+#[cfg_attr(not(bootstrap), lang = "iterator")]
#[rustc_diagnostic_item = "Iterator"]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub trait Iterator {
@@ -2141,7 +2142,7 @@ pub trait Iterator {
/// passed collection. The collection is then returned, so the call chain
/// can be continued.
///
- /// This is useful when you already have a collection and wants to add
+ /// This is useful when you already have a collection and want to add
/// the iterator items to it.
///
/// This method is a convenience method to call [Extend::extend](trait.Extend.html),
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 8b15e8269..5a6d242a7 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -26,7 +26,8 @@
//! assumptions about their semantics: For `memcpy`, `memmove`, `memset`, `memcmp`, and `bcmp`, if
//! the `n` parameter is 0, the function is assumed to not be UB. Furthermore, for `memcpy`, if
//! source and target pointer are equal, the function is assumed to not be UB.
-//! (Note that these are [standard assumptions](https://reviews.llvm.org/D86993) among compilers.)
+//! (Note that these are standard assumptions among compilers:
+//! [clang](https://reviews.llvm.org/D86993) and [GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=32667) do the same.)
//! These functions are often provided by the system libc, but can also be provided by the
//! [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
//! Note that the library does not guarantee that it will always make these assumptions, so Rust
@@ -68,6 +69,7 @@
test(no_crate_inject, attr(deny(warnings))),
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]
+#![cfg_attr(not(bootstrap), doc(rust_logo))]
#![doc(cfg_hide(
not(test),
any(not(feature = "miri-test-libstd"), test, doctest),
@@ -110,8 +112,6 @@
//
// Library features:
// tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(no_coverage))] // rust-lang/rust#84605
-#![cfg_attr(not(bootstrap), feature(coverage_attribute))] // rust-lang/rust#84605
#![feature(char_indices_offset)]
#![feature(const_align_of_val)]
#![feature(const_align_of_val_raw)]
@@ -126,7 +126,6 @@
#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_char_from_u32_unchecked)]
-#![feature(const_discriminant)]
#![feature(const_eval_select)]
#![feature(const_exact_div)]
#![feature(const_float_bits_conv)]
@@ -135,7 +134,6 @@
#![feature(const_hash)]
#![feature(const_heap)]
#![feature(const_index_range_slice_index)]
-#![feature(const_inherent_unchecked_arith)]
#![feature(const_int_unchecked_arith)]
#![feature(const_intrinsic_forget)]
#![feature(const_ipv4)]
@@ -149,7 +147,6 @@
#![feature(const_option)]
#![feature(const_option_ext)]
#![feature(const_pin)]
-#![feature(const_pointer_byte_offsets)]
#![feature(const_pointer_is_aligned)]
#![feature(const_ptr_as_ref)]
#![feature(const_ptr_is_null)]
@@ -173,6 +170,7 @@
#![feature(const_unsafecell_get_mut)]
#![feature(const_waker)]
#![feature(core_panic)]
+#![feature(coverage_attribute)]
#![feature(duration_consts_float)]
#![feature(internal_impls_macro)]
#![feature(ip)]
@@ -189,6 +187,8 @@
#![feature(str_split_inclusive_remainder)]
#![feature(str_split_remainder)]
#![feature(strict_provenance)]
+#![feature(unchecked_math)]
+#![feature(unchecked_shifts)]
#![feature(utf16_extra)]
#![feature(utf16_extra_const)]
#![feature(variant_count)]
@@ -237,6 +237,7 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(no_core)]
+#![feature(no_sanitize)]
#![feature(platform_intrinsics)]
#![feature(prelude_import)]
#![feature(repr_simd)]
@@ -252,6 +253,7 @@
#![feature(try_blocks)]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
+#![feature(with_negative_coherence)]
// tidy-alphabetical-end
//
// Target features:
@@ -367,6 +369,8 @@ pub mod async_iter;
pub mod cell;
pub mod char;
pub mod ffi;
+#[unstable(feature = "core_io_borrowed_buf", issue = "117693")]
+pub mod io;
pub mod iter;
pub mod net;
pub mod option;
@@ -414,7 +418,8 @@ pub mod primitive;
dead_code,
unused_imports,
unsafe_op_in_unsafe_fn,
- ambiguous_glob_reexports
+ ambiguous_glob_reexports,
+ deprecated_in_future
)]
#[allow(rustdoc::bare_urls)]
// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 123661b35..7f5908e47 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -718,7 +718,8 @@ macro_rules! unreachable {
/// The difference between `unimplemented!` and [`todo!`] is that while `todo!`
/// conveys an intent of implementing the functionality later and the message is "not yet
/// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
-/// Also some IDEs will mark `todo!`s.
+///
+/// Also, some IDEs will mark `todo!`s.
///
/// # Panics
///
@@ -804,11 +805,15 @@ macro_rules! unimplemented {
/// The difference between [`unimplemented!`] and `todo!` is that while `todo!` conveys
/// an intent of implementing the functionality later and the message is "not yet
/// implemented", `unimplemented!` makes no such claims. Its message is "not implemented".
-/// Also some IDEs will mark `todo!`s.
+///
+/// Also, some IDEs will mark `todo!`s.
///
/// # Panics
///
-/// This will always [`panic!`].
+/// This will always [`panic!`] because `todo!` is just a shorthand for `panic!` with a
+/// fixed, specific message.
+///
+/// Like `panic!`, this macro has a second form for displaying custom values.
///
/// # Examples
///
@@ -816,38 +821,47 @@ macro_rules! unimplemented {
///
/// ```
/// trait Foo {
-/// fn bar(&self);
+/// fn bar(&self) -> u8;
/// fn baz(&self);
+/// fn qux(&self) -> Result<u64, ()>;
/// }
/// ```
///
/// We want to implement `Foo` on one of our types, but we also want to work on
/// just `bar()` first. In order for our code to compile, we need to implement
-/// `baz()`, so we can use `todo!`:
+/// `baz()` and `qux()`, so we can use `todo!`:
///
/// ```
/// # trait Foo {
-/// # fn bar(&self);
+/// # fn bar(&self) -> u8;
/// # fn baz(&self);
+/// # fn qux(&self) -> Result<u64, ()>;
/// # }
/// struct MyStruct;
///
/// impl Foo for MyStruct {
-/// fn bar(&self) {
-/// // implementation goes here
+/// fn bar(&self) -> u8 {
+/// 1 + 1
/// }
///
/// fn baz(&self) {
-/// // let's not worry about implementing baz() for now
+/// // Let's not worry about implementing baz() for now
/// todo!();
/// }
+///
+/// fn qux(&self) -> Result<u64, ()> {
+/// // We can add a message to todo! to display our omission.
+/// // This will display:
+/// // "thread 'main' panicked at 'not yet implemented: MyStruct is not yet quxable'".
+/// todo!("MyStruct is not yet quxable");
+/// }
/// }
///
/// fn main() {
/// let s = MyStruct;
/// s.bar();
///
-/// // we aren't even using baz(), so this is fine.
+/// // We aren't even using baz() or qux(), so this is fine.
/// }
/// ```
#[macro_export]
@@ -1030,6 +1044,7 @@ pub(crate) mod builtin {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
+ #[rustc_diagnostic_item = "env_macro"] // useful for external lints
macro_rules! env {
($name:expr $(,)?) => {{ /* compiler built-in */ }};
($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }};
@@ -1060,6 +1075,7 @@ pub(crate) mod builtin {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
+ #[rustc_diagnostic_item = "option_env_macro"] // useful for external lints
macro_rules! option_env {
($name:expr $(,)?) => {{ /* compiler built-in */ }};
}
@@ -1465,6 +1481,7 @@ pub(crate) mod builtin {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
#[macro_export]
+ #[rustc_diagnostic_item = "include_macro"] // useful for external lints
macro_rules! include {
($file:expr $(,)?) => {{ /* compiler built-in */ }};
}
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 5ed82e26a..99762bccd 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -155,12 +155,18 @@ pub trait Sized {
/// Those implementations are:
///
/// - Arrays `[T; N]` implement `Unsize<[T]>`.
-/// - Types implementing a trait `Trait` also implement `Unsize<dyn Trait>`.
-/// - Structs `Foo<..., T, ...>` implement `Unsize<Foo<..., U, ...>>` if all of these conditions
-/// are met:
-/// - `T: Unsize<U>`.
-/// - Only the last field of `Foo` has a type involving `T`.
-/// - `Bar<T>: Unsize<Bar<U>>`, where `Bar<T>` stands for the actual type of that last field.
+/// - A type implements `Unsize<dyn Trait + 'a>` if all of these conditions are met:
+/// - The type implements `Trait`.
+/// - `Trait` is object safe.
+/// - The type is sized.
+/// - The type outlives `'a`.
+/// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize<Foo<..., U1, ..., Un, ...>>`
+/// where any number of (type and const) parameters may be changed if all of these conditions
+/// are met:
+/// - Only the last field of `Foo` has a type involving the parameters `T1`, ..., `Tn`.
+/// - All other parameters of the struct are equal.
+/// - `Field<T1, ..., Tn>: Unsize<Field<U1, ..., Un>>`, where `Field<...>` stands for the actual
+/// type of the struct's last field.
///
/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
/// "user-defined" containers such as [`Rc`] to contain dynamically-sized
@@ -247,6 +253,7 @@ marker_impls! {
///
/// const CFN: Wrap<fn(&())> = Wrap(higher_order);
///
+/// #[allow(pointer_structural_match)]
/// fn main() {
/// match CFN {
/// CFN => {}
@@ -573,59 +580,72 @@ impl<T: ?Sized> Copy for &T {}
#[lang = "sync"]
#[rustc_on_unimplemented(
on(
- any(_Self = "core::cell:OnceCell<T>", _Self = "std::cell::OnceCell<T>"),
+ _Self = "core::cell::once::OnceCell<T>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead"
),
on(
- any(_Self = "core::cell::Cell<u8>", _Self = "std::cell::Cell<u8>"),
+ _Self = "core::cell::Cell<u8>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead",
),
on(
- any(_Self = "core::cell::Cell<u16>", _Self = "std::cell::Cell<u16>"),
+ _Self = "core::cell::Cell<u16>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU16` instead",
),
on(
- any(_Self = "core::cell::Cell<u32>", _Self = "std::cell::Cell<u32>"),
+ _Self = "core::cell::Cell<u32>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU32` instead",
),
on(
- any(_Self = "core::cell::Cell<u64>", _Self = "std::cell::Cell<u64>"),
+ _Self = "core::cell::Cell<u64>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU64` instead",
),
on(
- any(_Self = "core::cell::Cell<usize>", _Self = "std::cell::Cell<usize>"),
+ _Self = "core::cell::Cell<usize>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicUsize` instead",
),
on(
- any(_Self = "core::cell::Cell<i8>", _Self = "std::cell::Cell<i8>"),
+ _Self = "core::cell::Cell<i8>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI8` instead",
),
on(
- any(_Self = "core::cell::Cell<i16>", _Self = "std::cell::Cell<i16>"),
+ _Self = "core::cell::Cell<i16>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI16` instead",
),
on(
- any(_Self = "core::cell::Cell<i32>", _Self = "std::cell::Cell<i32>"),
+ _Self = "core::cell::Cell<i32>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead",
),
on(
- any(_Self = "core::cell::Cell<i64>", _Self = "std::cell::Cell<i64>"),
+ _Self = "core::cell::Cell<i64>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI64` instead",
),
on(
- any(_Self = "core::cell::Cell<isize>", _Self = "std::cell::Cell<isize>"),
+ _Self = "core::cell::Cell<isize>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicIsize` instead",
),
on(
- any(_Self = "core::cell::Cell<bool>", _Self = "std::cell::Cell<bool>"),
+ _Self = "core::cell::Cell<bool>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead",
),
on(
- any(_Self = "core::cell::Cell<T>", _Self = "std::cell::Cell<T>"),
+ all(
+ _Self = "core::cell::Cell<T>",
+ not(_Self = "core::cell::Cell<u8>"),
+ not(_Self = "core::cell::Cell<u16>"),
+ not(_Self = "core::cell::Cell<u32>"),
+ not(_Self = "core::cell::Cell<u64>"),
+ not(_Self = "core::cell::Cell<usize>"),
+ not(_Self = "core::cell::Cell<i8>"),
+ not(_Self = "core::cell::Cell<i16>"),
+ not(_Self = "core::cell::Cell<i32>"),
+ not(_Self = "core::cell::Cell<i64>"),
+ not(_Self = "core::cell::Cell<isize>"),
+ not(_Self = "core::cell::Cell<bool>")
+ ),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`",
),
on(
- any(_Self = "core::cell::RefCell<T>", _Self = "std::cell::RefCell<T>"),
+ _Self = "core::cell::RefCell<T>",
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
),
message = "`{Self}` cannot be shared between threads safely",
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 5f3d66e37..98cff3493 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -4,12 +4,12 @@ use crate::ptr;
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
/// This wrapper is 0-cost.
///
-/// `ManuallyDrop<T>` is guaranteed to have the same layout as `T`, and is subject
-/// to the same layout optimizations as `T`. As a consequence, it has *no effect*
-/// on the assumptions that the compiler makes about its contents. For example,
-/// initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined
-/// behavior. If you need to handle uninitialized data, use [`MaybeUninit<T>`]
-/// instead.
+/// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
+/// `T`, and is subject to the same layout optimizations as `T`. As a consequence,
+/// it has *no effect* on the assumptions that the compiler makes about its
+/// contents. For example, initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`]
+/// is undefined behavior. If you need to handle uninitialized data, use
+/// [`MaybeUninit<T>`] instead.
///
/// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
/// This means that a `ManuallyDrop<T>` whose content has been dropped must not
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index d09a24b4b..8a210c195 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -242,7 +242,7 @@ use crate::slice;
/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that
/// guarantee may evolve.
#[stable(feature = "maybe_uninit", since = "1.36.0")]
-// Lang item so we can wrap other types in it. This is useful for generators.
+// Lang item so we can wrap other types in it. This is useful for coroutines.
#[lang = "maybe_uninit"]
#[derive(Copy)]
#[repr(transparent)]
@@ -374,6 +374,9 @@ impl<T> MaybeUninit<T> {
/// assert_eq!(x, (0, false));
/// ```
///
+ /// This can be used in const contexts, such as to indicate the end of static arrays for
+ /// plugin registration.
+ ///
/// *Incorrect* usage of this function: calling `x.zeroed().assume_init()`
/// when `0` is not a valid bit-pattern for the type:
///
@@ -387,17 +390,19 @@ impl<T> MaybeUninit<T> {
/// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
/// // This is undefined behavior. ⚠️
/// ```
- #[stable(feature = "maybe_uninit", since = "1.36.0")]
- #[rustc_const_unstable(feature = "const_maybe_uninit_zeroed", issue = "91850")]
- #[must_use]
#[inline]
+ #[must_use]
#[rustc_diagnostic_item = "maybe_uninit_zeroed"]
+ #[stable(feature = "maybe_uninit", since = "1.36.0")]
+ // These are OK to allow since we do not leak &mut to user-visible API
+ #[rustc_allow_const_fn_unstable(const_mut_refs)]
+ #[rustc_allow_const_fn_unstable(const_ptr_write)]
+ #[rustc_allow_const_fn_unstable(const_maybe_uninit_as_mut_ptr)]
+ #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "1.75.0")]
pub const fn zeroed() -> MaybeUninit<T> {
let mut u = MaybeUninit::<T>::uninit();
// SAFETY: `u.as_mut_ptr()` points to allocated memory.
- unsafe {
- u.as_mut_ptr().write_bytes(0u8, 1);
- }
+ unsafe { u.as_mut_ptr().write_bytes(0u8, 1) };
u
}
@@ -686,7 +691,10 @@ impl<T> MaybeUninit<T> {
/// // they both get dropped!
/// ```
#[stable(feature = "maybe_uninit_extra", since = "1.60.0")]
- #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init_read", issue = "63567")]
+ #[rustc_const_stable(
+ feature = "const_maybe_uninit_assume_init_read",
+ since = "1.75.0"
+ )]
#[inline(always)]
#[track_caller]
pub const unsafe fn assume_init_read(&self) -> T {
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index e478b217f..eef214528 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -647,7 +647,8 @@ pub const fn needs_drop<T: ?Sized>() -> bool {
#[allow(deprecated)]
#[rustc_diagnostic_item = "mem_zeroed"]
#[track_caller]
-pub unsafe fn zeroed<T>() -> T {
+#[rustc_const_stable(feature = "const_mem_zeroed", since = "1.75.0")]
+pub const unsafe fn zeroed<T>() -> T {
// SAFETY: the caller must guarantee that an all-zero value is valid for `T`.
unsafe {
intrinsics::assert_zero_valid::<T>();
@@ -723,15 +724,12 @@ pub unsafe fn uninitialized<T>() -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+#[rustc_diagnostic_item = "mem_swap"]
pub const fn swap<T>(x: &mut T, y: &mut T) {
// NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary
// reinterpretation of values as (chunkable) byte arrays, and the loop in the
// block optimization in `swap_slice` is hard to rewrite back
// into the (unoptimized) direct swapping implementation, so we disable it.
- // FIXME(eddyb) the block optimization also prevents MIR optimizations from
- // understanding `mem::replace`, `Option::take`, etc. - a better overall
- // solution might be to make `ptr::swap_nonoverlapping` into an intrinsic, which
- // a backend can choose to implement using the block optimization, or not.
#[cfg(not(any(target_arch = "spirv")))]
{
// For types that are larger multiples of their alignment, the simple way
@@ -768,11 +766,14 @@ pub(crate) const fn swap_simple<T>(x: &mut T, y: &mut T) {
// And LLVM actually optimizes it to 3×memcpy if called with
// a type larger than it's willing to keep in a register.
// Having typed reads and writes in MIR here is also good as
- // it lets MIRI and CTFE understand them better, including things
+ // it lets Miri and CTFE understand them better, including things
// like enforcing type validity for them.
// Importantly, read+copy_nonoverlapping+write introduces confusing
// asymmetry to the behaviour where one value went through read+write
// whereas the other was copied over by the intrinsic (see #94371).
+ // Furthermore, using only read+write here benefits limited backends
+ // such as SPIR-V that work on an underlying *typed* view of memory,
+ // and thus have trouble with Rust's untyped memory operations.
// SAFETY: exclusive references are always valid to read/write,
// including being aligned, and nothing here panics so it's drop-safe.
@@ -909,6 +910,10 @@ pub fn take<T: Default>(dest: &mut T) -> T {
#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")]
pub const fn replace<T>(dest: &mut T, src: T) -> T {
+ // It may be tempting to use `swap` to avoid `unsafe` here. Don't!
+ // The compiler optimizes the implementation below to two `memcpy`s
+ // while `swap` would require at least three. See PR#83022 for details.
+
// SAFETY: We read from `dest` but directly write `src` into it afterwards,
// such that the old value is not duplicated. Nothing is dropped and
// nothing here can panic.
@@ -930,7 +935,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
/// This function is not magic; it is literally defined as
///
/// ```
-/// pub fn drop<T>(_x: T) { }
+/// pub fn drop<T>(_x: T) {}
/// ```
///
/// Because `_x` is moved into the function, it is automatically dropped before
@@ -1050,6 +1055,7 @@ pub const fn copy<T: Copy>(x: &T) -> T {
/// ```
#[inline]
#[must_use]
+#[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_transmute_copy", since = "1.74.0")]
pub const unsafe fn transmute_copy<Src, Dst>(src: &Src) -> Dst {
@@ -1204,7 +1210,7 @@ impl<T> fmt::Debug for Discriminant<T> {
/// // assert_eq!(0, unsafe { std::mem::transmute::<_, u8>(std::mem::discriminant(&unit_like)) });
/// ```
#[stable(feature = "discriminant_value", since = "1.21.0")]
-#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
+#[rustc_const_stable(feature = "const_discriminant", since = "1.75.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
@@ -1290,16 +1296,71 @@ impl<T> SizedTypeProperties for T {}
/// Expands to the offset in bytes of a field from the beginning of the given type.
///
-/// Only structs, unions and tuples are supported.
+/// Structs, enums, unions and tuples are supported.
+///
+/// Nested field accesses may be used, but not array indexes.
+///
+/// Enum variants may be traversed as if they were fields. Variants themselves do
+/// not have an offset.
+///
+/// Visibility is respected - all types and fields must be visible to the call site:
+///
+/// ```
+/// #![feature(offset_of)]
+///
+/// mod nested {
+/// #[repr(C)]
+/// pub struct Struct {
+/// private: u8,
+/// }
+/// }
+///
+/// // assert_eq!(mem::offset_of!(nested::Struct, private), 0);
+/// // ^^^ error[E0616]: field `private` of struct `Struct` is private
+/// ```
+///
+/// Note that type layout is, in general, [subject to change and
+/// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If
+/// layout stability is required, consider using an [explicit `repr` attribute].
+///
+/// Rust guarantees that the offset of a given field within a given type will not
+/// change over the lifetime of the program. However, two different compilations of
+/// the same program may result in different layouts. Also, even within a single
+/// program execution, no guarantees are made about types which are *similar* but
+/// not *identical*, e.g.:
+///
+/// ```
+/// #![feature(offset_of)]
+///
+/// struct Wrapper<T, U>(T, U);
+///
+/// type A = Wrapper<u8, u8>;
+/// type B = Wrapper<u8, i8>;
+///
+/// // Not necessarily identical even though `u8` and `i8` have the same layout!
+/// // assert!(mem::offset_of!(A, 1), mem::offset_of!(B, 1));
+///
+/// #[repr(transparent)]
+/// struct U8(u8);
+///
+/// type C = Wrapper<u8, U8>;
+///
+/// // Not necessarily identical even though `u8` and `U8` have the same layout!
+/// // assert!(mem::offset_of!(A, 1), mem::offset_of!(C, 1));
///
-/// Nested field accesses may be used, but not array indexes like in `C`'s `offsetof`.
+/// struct Empty<T>(core::marker::PhantomData<T>);
///
-/// Note that the output of this macro is not stable, except for `#[repr(C)]` types.
+/// // Not necessarily identical even though `PhantomData` always has the same layout!
+/// // assert!(mem::offset_of!(Empty<u8>, 0), mem::offset_of!(Empty<i8>, 0));
+/// ```
+///
+/// [explicit `repr` attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations
///
/// # Examples
///
/// ```
/// #![feature(offset_of)]
+/// # #![cfg_attr(not(bootstrap), feature(offset_of_enum))]
///
/// use std::mem;
/// #[repr(C)]
@@ -1322,6 +1383,20 @@ impl<T> SizedTypeProperties for T {}
/// struct NestedB(u8);
///
/// assert_eq!(mem::offset_of!(NestedA, b.0), 0);
+///
+/// #[repr(u8)]
+/// enum Enum {
+/// A(u8, u16),
+/// B { one: u8, two: u16 },
+/// }
+///
+/// # #[cfg(not(bootstrap))]
+/// assert_eq!(mem::offset_of!(Enum, A.0), 1);
+/// # #[cfg(not(bootstrap))]
+/// assert_eq!(mem::offset_of!(Enum, B.two), 2);
+///
+/// # #[cfg(not(bootstrap))]
+/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
/// ```
#[unstable(feature = "offset_of", issue = "106655")]
#[allow_internal_unstable(builtin_syntax, hint_must_use)]
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index 6a36dfec0..77f85215d 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1,6 +1,8 @@
use crate::cmp::Ordering;
use crate::fmt::{self, Write};
+use crate::iter;
use crate::mem::transmute;
+use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
use super::display_buffer::DisplayBuffer;
@@ -410,9 +412,12 @@ impl IpAddr {
/// # Examples
///
/// ```
- /// #![feature(ip)]
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
+ /// let localhost_v4 = Ipv4Addr::new(127, 0, 0, 1);
+ ///
+ /// assert_eq!(IpAddr::V4(localhost_v4).to_canonical(), localhost_v4);
+ /// assert_eq!(IpAddr::V6(localhost_v4.to_ipv6_mapped()).to_canonical(), localhost_v4);
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true);
@@ -420,11 +425,11 @@ impl IpAddr {
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
- #[unstable(feature = "ip", issue = "27709")]
+ #[stable(feature = "ip_to_canonical", since = "1.75.0")]
+ #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")]
pub const fn to_canonical(&self) -> IpAddr {
match self {
- &v4 @ IpAddr::V4(_) => v4,
+ IpAddr::V4(_) => *self,
IpAddr::V6(v6) => v6.to_canonical(),
}
}
@@ -1748,11 +1753,11 @@ impl Ipv6Addr {
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
/// ```
- #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
- #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
+ #[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
+ #[rustc_const_stable(feature = "const_ipv6_to_ipv4_mapped", since = "1.75.0")]
pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
match self.octets() {
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
@@ -1817,11 +1822,11 @@ impl Ipv6Addr {
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true);
/// ```
- #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
- #[unstable(feature = "ip", issue = "27709")]
+ #[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[stable(feature = "ip_to_canonical", since = "1.75.0")]
+ #[rustc_const_stable(feature = "ip_to_canonical", since = "1.75.0")]
pub const fn to_canonical(&self) -> IpAddr {
if let Some(mapped) = self.to_ipv4_mapped() {
return IpAddr::V4(mapped);
@@ -2122,3 +2127,132 @@ impl From<[u16; 8]> for IpAddr {
IpAddr::V6(Ipv6Addr::from(segments))
}
}
+
+#[stable(feature = "ip_bitops", since = "1.75.0")]
+impl Not for Ipv4Addr {
+ type Output = Ipv4Addr;
+
+ #[inline]
+ fn not(mut self) -> Ipv4Addr {
+ for octet in &mut self.octets {
+ *octet = !*octet;
+ }
+ self
+ }
+}
+
+#[stable(feature = "ip_bitops", since = "1.75.0")]
+impl Not for &'_ Ipv4Addr {
+ type Output = Ipv4Addr;
+
+ #[inline]
+ fn not(self) -> Ipv4Addr {
+ !*self
+ }
+}
+
+#[stable(feature = "ip_bitops", since = "1.75.0")]
+impl Not for Ipv6Addr {
+ type Output = Ipv6Addr;
+
+ #[inline]
+ fn not(mut self) -> Ipv6Addr {
+ for octet in &mut self.octets {
+ *octet = !*octet;
+ }
+ self
+ }
+}
+
+#[stable(feature = "ip_bitops", since = "1.75.0")]
+impl Not for &'_ Ipv6Addr {
+ type Output = Ipv6Addr;
+
+ #[inline]
+ fn not(self) -> Ipv6Addr {
+ !*self
+ }
+}
+
+macro_rules! bitop_impls {
+ ($(
+ $(#[$attr:meta])*
+ impl ($BitOp:ident, $BitOpAssign:ident) for $ty:ty = ($bitop:ident, $bitop_assign:ident);
+ )*) => {
+ $(
+ $(#[$attr])*
+ impl $BitOpAssign for $ty {
+ fn $bitop_assign(&mut self, rhs: $ty) {
+ for (lhs, rhs) in iter::zip(&mut self.octets, rhs.octets) {
+ lhs.$bitop_assign(rhs);
+ }
+ }
+ }
+
+ $(#[$attr])*
+ impl $BitOpAssign<&'_ $ty> for $ty {
+ fn $bitop_assign(&mut self, rhs: &'_ $ty) {
+ self.$bitop_assign(*rhs);
+ }
+ }
+
+ $(#[$attr])*
+ impl $BitOp for $ty {
+ type Output = $ty;
+
+ #[inline]
+ fn $bitop(mut self, rhs: $ty) -> $ty {
+ self.$bitop_assign(rhs);
+ self
+ }
+ }
+
+ $(#[$attr])*
+ impl $BitOp<&'_ $ty> for $ty {
+ type Output = $ty;
+
+ #[inline]
+ fn $bitop(mut self, rhs: &'_ $ty) -> $ty {
+ self.$bitop_assign(*rhs);
+ self
+ }
+ }
+
+ $(#[$attr])*
+ impl $BitOp<$ty> for &'_ $ty {
+ type Output = $ty;
+
+ #[inline]
+ fn $bitop(self, rhs: $ty) -> $ty {
+ let mut lhs = *self;
+ lhs.$bitop_assign(rhs);
+ lhs
+ }
+ }
+
+ $(#[$attr])*
+ impl $BitOp<&'_ $ty> for &'_ $ty {
+ type Output = $ty;
+
+ #[inline]
+ fn $bitop(self, rhs: &'_ $ty) -> $ty {
+ let mut lhs = *self;
+ lhs.$bitop_assign(*rhs);
+ lhs
+ }
+ }
+ )*
+ };
+}
+
+bitop_impls! {
+ #[stable(feature = "ip_bitops", since = "1.75.0")]
+ impl (BitAnd, BitAndAssign) for Ipv4Addr = (bitand, bitand_assign);
+ #[stable(feature = "ip_bitops", since = "1.75.0")]
+ impl (BitOr, BitOrAssign) for Ipv4Addr = (bitor, bitor_assign);
+
+ #[stable(feature = "ip_bitops", since = "1.75.0")]
+ impl (BitAnd, BitAndAssign) for Ipv6Addr = (bitand, bitand_assign);
+ #[stable(feature = "ip_bitops", since = "1.75.0")]
+ impl (BitOr, BitOrAssign) for Ipv6Addr = (bitor, bitor_assign);
+}
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
index 8396aecf9..551162858 100644
--- a/library/core/src/net/socket_addr.rs
+++ b/library/core/src/net/socket_addr.rs
@@ -1,6 +1,4 @@
-use crate::cmp::Ordering;
use crate::fmt::{self, Write};
-use crate::hash;
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use super::display_buffer::DisplayBuffer;
@@ -63,7 +61,7 @@ pub enum SocketAddr {
/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
/// assert_eq!(socket.port(), 8080);
/// ```
-#[derive(Copy, Clone, Eq, PartialEq)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV4 {
ip: Ipv4Addr,
@@ -96,7 +94,7 @@ pub struct SocketAddrV4 {
/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
/// assert_eq!(socket.port(), 8080);
/// ```
-#[derive(Copy, Clone, Eq, PartialEq)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SocketAddrV6 {
ip: Ipv6Addr,
@@ -644,48 +642,3 @@ impl fmt::Debug for SocketAddrV6 {
fmt::Display::fmt(self, fmt)
}
}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialOrd for SocketAddrV4 {
- #[inline]
- fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialOrd for SocketAddrV6 {
- #[inline]
- fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> {
- Some(self.cmp(other))
- }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl Ord for SocketAddrV4 {
- #[inline]
- fn cmp(&self, other: &SocketAddrV4) -> Ordering {
- self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
- }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl Ord for SocketAddrV6 {
- #[inline]
- fn cmp(&self, other: &SocketAddrV6) -> Ordering {
- self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for SocketAddrV4 {
- fn hash<H: hash::Hasher>(&self, s: &mut H) {
- (self.port, self.ip).hash(s)
- }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for SocketAddrV6 {
- fn hash<H: hash::Hasher>(&self, s: &mut H) {
- (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s)
- }
-}
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 290f649f9..f60626b00 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -377,6 +377,13 @@ impl f32 {
pub const MANTISSA_DIGITS: u32 = 24;
/// Approximate number of significant digits in base 10.
+ ///
+ /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
+ /// significant digits can be converted to `f32` and back without loss.
+ ///
+ /// Equal to floor(log<sub>10</sub>&nbsp;2<sup>[`MANTISSA_DIGITS`]&nbsp;&minus;&nbsp;1</sup>).
+ ///
+ /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const DIGITS: u32 = 6;
@@ -384,31 +391,62 @@ impl f32 {
///
/// This is the difference between `1.0` and the next larger representable number.
///
+ /// Equal to 2<sup>1&nbsp;&minus;&nbsp;[`MANTISSA_DIGITS`]</sup>.
+ ///
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
+ /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const EPSILON: f32 = 1.19209290e-07_f32;
/// Smallest finite `f32` value.
+ ///
+ /// Equal to &minus;[`MAX`].
+ ///
+ /// [`MAX`]: f32::MAX
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN: f32 = -3.40282347e+38_f32;
/// Smallest positive normal `f32` value.
+ ///
+ /// Equal to 2<sup>[`MIN_EXP`]&nbsp;&minus;&nbsp;1</sup>.
+ ///
+ /// [`MIN_EXP`]: f32::MIN_EXP
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32;
/// Largest finite `f32` value.
+ ///
+ /// Equal to
+ /// (1&nbsp;&minus;&nbsp;2<sup>&minus;[`MANTISSA_DIGITS`]</sup>)&nbsp;2<sup>[`MAX_EXP`]</sup>.
+ ///
+ /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
+ /// [`MAX_EXP`]: f32::MAX_EXP
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX: f32 = 3.40282347e+38_f32;
/// One greater than the minimum possible normal power of 2 exponent.
+ ///
+ /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
+ /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN_EXP: i32 = -125;
/// Maximum possible power of 2 exponent.
+ ///
+ /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
+ /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX_EXP: i32 = 128;
- /// Minimum possible normal power of 10 exponent.
+ /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+ ///
+ /// Equal to ceil(log<sub>10</sub>&nbsp;[`MIN_POSITIVE`]).
+ ///
+ /// [`MIN_POSITIVE`]: f32::MIN_POSITIVE
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN_10_EXP: i32 = -37;
- /// Maximum possible power of 10 exponent.
+ /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+ ///
+ /// Equal to floor(log<sub>10</sub>&nbsp;[`MAX`]).
+ ///
+ /// [`MAX`]: f32::MAX
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX_10_EXP: i32 = 38;
@@ -820,7 +858,7 @@ impl f32 {
/// let angle = std::f32::consts::PI;
///
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
- ///
+ /// # #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 7569d2cd6..0a87021d8 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -376,6 +376,13 @@ impl f64 {
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MANTISSA_DIGITS: u32 = 53;
/// Approximate number of significant digits in base 10.
+ ///
+ /// This is the maximum <i>x</i> such that any decimal number with <i>x</i>
+ /// significant digits can be converted to `f64` and back without loss.
+ ///
+ /// Equal to floor(log<sub>10</sub>&nbsp;2<sup>[`MANTISSA_DIGITS`]&nbsp;&minus;&nbsp;1</sup>).
+ ///
+ /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const DIGITS: u32 = 15;
@@ -383,31 +390,62 @@ impl f64 {
///
/// This is the difference between `1.0` and the next larger representable number.
///
+ /// Equal to 2<sup>1&nbsp;&minus;&nbsp;[`MANTISSA_DIGITS`]</sup>.
+ ///
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
+ /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
/// Smallest finite `f64` value.
+ ///
+ /// Equal to &minus;[`MAX`].
+ ///
+ /// [`MAX`]: f64::MAX
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN: f64 = -1.7976931348623157e+308_f64;
/// Smallest positive normal `f64` value.
+ ///
+ /// Equal to 2<sup>[`MIN_EXP`]&nbsp;&minus;&nbsp;1</sup>.
+ ///
+ /// [`MIN_EXP`]: f64::MIN_EXP
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64;
/// Largest finite `f64` value.
+ ///
+ /// Equal to
+ /// (1&nbsp;&minus;&nbsp;2<sup>&minus;[`MANTISSA_DIGITS`]</sup>)&nbsp;2<sup>[`MAX_EXP`]</sup>.
+ ///
+ /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
+ /// [`MAX_EXP`]: f64::MAX_EXP
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX: f64 = 1.7976931348623157e+308_f64;
/// One greater than the minimum possible normal power of 2 exponent.
+ ///
+ /// If <i>x</i>&nbsp;=&nbsp;`MIN_EXP`, then normal numbers
+ /// ≥&nbsp;0.5&nbsp;×&nbsp;2<sup><i>x</i></sup>.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN_EXP: i32 = -1021;
/// Maximum possible power of 2 exponent.
+ ///
+ /// If <i>x</i>&nbsp;=&nbsp;`MAX_EXP`, then normal numbers
+ /// &lt;&nbsp;1&nbsp;×&nbsp;2<sup><i>x</i></sup>.
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX_EXP: i32 = 1024;
- /// Minimum possible normal power of 10 exponent.
+ /// Minimum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+ ///
+ /// Equal to ceil(log<sub>10</sub>&nbsp;[`MIN_POSITIVE`]).
+ ///
+ /// [`MIN_POSITIVE`]: f64::MIN_POSITIVE
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN_10_EXP: i32 = -307;
- /// Maximum possible power of 10 exponent.
+ /// Maximum <i>x</i> for which 10<sup><i>x</i></sup> is normal.
+ ///
+ /// Equal to floor(log<sub>10</sub>&nbsp;[`MAX`]).
+ ///
+ /// [`MAX`]: f64::MAX
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX_10_EXP: i32 = 308;
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 3cbb55af3..fd01f1b26 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -471,7 +471,7 @@ macro_rules! int_impl {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
@@ -539,7 +539,7 @@ macro_rules! int_impl {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
@@ -607,7 +607,7 @@ macro_rules! int_impl {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
@@ -740,6 +740,31 @@ macro_rules! int_impl {
if unlikely!(b) {None} else {Some(a)}
}
+ /// Unchecked negation. Computes `-self`, assuming overflow cannot occur.
+ ///
+ /// # Safety
+ ///
+ /// This results in undefined behavior when
+ #[doc = concat!("`self == ", stringify!($SelfT), "::MIN`,")]
+ /// i.e. when [`checked_neg`] would return `None`.
+ ///
+ #[doc = concat!("[`checked_neg`]: ", stringify!($SelfT), "::checked_neg")]
+ #[unstable(
+ feature = "unchecked_neg",
+ reason = "niche optimization path",
+ issue = "85122",
+ )]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[rustc_const_unstable(feature = "unchecked_neg", issue = "85122")]
+ #[inline(always)]
+ #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+ pub const unsafe fn unchecked_neg(self) -> Self {
+ // SAFETY: the caller must uphold the safety contract for
+ // `unchecked_neg`.
+ unsafe { intrinsics::unchecked_sub(0, self) }
+ }
+
/// Checked shift left. Computes `self << rhs`, returning `None` if `rhs` is larger
/// than or equal to the number of bits in `self`.
///
@@ -772,13 +797,13 @@ macro_rules! int_impl {
///
#[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")]
#[unstable(
- feature = "unchecked_math",
+ feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
@@ -820,13 +845,13 @@ macro_rules! int_impl {
///
#[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")]
#[unstable(
- feature = "unchecked_math",
+ feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
@@ -1404,7 +1429,7 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
- #[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
+ #[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
@@ -1434,7 +1459,7 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
- #[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
+ #[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 8b127132c..2a0b31404 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -114,7 +114,7 @@ macro_rules! midpoint_impl {
without modifying the original"]
#[inline]
pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
- // Use the well known branchless algorthim from Hacker's Delight to compute
+ // Use the well known branchless algorithm from Hacker's Delight to compute
// `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`.
((self ^ rhs) >> 1) + (self & rhs)
}
@@ -791,7 +791,7 @@ impl u8 {
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_alphanumeric(&self) -> bool {
- matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z')
+ matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'Z') | matches!(*self, b'a'..=b'z')
}
/// Checks if the value is an ASCII decimal digit:
@@ -894,7 +894,7 @@ impl u8 {
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_hexdigit(&self) -> bool {
- matches!(*self, b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f')
+ matches!(*self, b'0'..=b'9') | matches!(*self, b'A'..=b'F') | matches!(*self, b'a'..=b'f')
}
/// Checks if the value is an ASCII punctuation character:
@@ -932,7 +932,10 @@ impl u8 {
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_punctuation(&self) -> bool {
- matches!(*self, b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~')
+ matches!(*self, b'!'..=b'/')
+ | matches!(*self, b':'..=b'@')
+ | matches!(*self, b'['..=b'`')
+ | matches!(*self, b'{'..=b'~')
}
/// Checks if the value is an ASCII graphic character:
diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs
index d9ccc73c4..d040539eb 100644
--- a/library/core/src/num/saturating.rs
+++ b/library/core/src/num/saturating.rs
@@ -35,9 +35,7 @@ use crate::ops::{Sub, SubAssign};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
#[repr(transparent)]
#[rustc_diagnostic_item = "Saturating"]
-pub struct Saturating<T>(
- #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub T,
-);
+pub struct Saturating<T>(#[stable(feature = "saturating_int_impl", since = "1.74.0")] pub T);
#[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl<T: fmt::Debug> fmt::Debug for Saturating<T> {
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index a9c5312a1..11a53aaf1 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -479,7 +479,7 @@ macro_rules! uint_impl {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
@@ -548,7 +548,7 @@ macro_rules! uint_impl {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
@@ -595,7 +595,7 @@ macro_rules! uint_impl {
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_math", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
@@ -926,13 +926,13 @@ macro_rules! uint_impl {
///
#[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")]
#[unstable(
- feature = "unchecked_math",
+ feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
@@ -974,13 +974,13 @@ macro_rules! uint_impl {
///
#[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")]
#[unstable(
- feature = "unchecked_math",
+ feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[rustc_const_unstable(feature = "const_inherent_unchecked_arith", issue = "85122")]
+ #[rustc_const_unstable(feature = "unchecked_shifts", issue = "85122")]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
@@ -1418,7 +1418,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
- #[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
+ #[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shl(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
@@ -1451,7 +1451,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
- #[rustc_allow_const_fn_unstable(const_inherent_unchecked_arith)]
+ #[rustc_allow_const_fn_unstable(unchecked_shifts)]
pub const fn wrapping_shr(self, rhs: u32) -> Self {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
new file mode 100644
index 000000000..cd5ca988f
--- /dev/null
+++ b/library/core/src/ops/coroutine.rs
@@ -0,0 +1,139 @@
+use crate::marker::Unpin;
+use crate::pin::Pin;
+
+/// The result of a coroutine resumption.
+///
+/// This enum is returned from the `Coroutine::resume` method and indicates the
+/// possible return values of a coroutine. Currently this corresponds to either
+/// a suspension point (`Yielded`) or a termination point (`Complete`).
+#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
+#[cfg_attr(bootstrap, lang = "generator_state")]
+#[cfg_attr(not(bootstrap), lang = "coroutine_state")]
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+pub enum CoroutineState<Y, R> {
+ /// The coroutine suspended with a value.
+ ///
+ /// This state indicates that a coroutine has been suspended, and typically
+ /// corresponds to a `yield` statement. The value provided in this variant
+ /// corresponds to the expression passed to `yield` and allows coroutines to
+ /// provide a value each time they yield.
+ Yielded(Y),
+
+ /// The coroutine completed with a return value.
+ ///
+ /// This state indicates that a coroutine has finished execution with the
+ /// provided value. Once a coroutine has returned `Complete` it is
+ /// considered a programmer error to call `resume` again.
+ Complete(R),
+}
+
+/// The trait implemented by builtin coroutine types.
+///
+/// Coroutines are currently an
+/// experimental language feature in Rust. Added in [RFC 2033] coroutines are
+/// currently intended to primarily provide a building block for async/await
+/// syntax but will likely extend to also providing an ergonomic definition for
+/// iterators and other primitives.
+///
+/// The syntax and semantics for coroutines is unstable and will require a
+/// further RFC for stabilization. At this time, though, the syntax is
+/// closure-like:
+///
+/// ```rust
+/// #![cfg_attr(bootstrap, feature(generators))]
+/// #![cfg_attr(not(bootstrap), feature(coroutines))]
+/// #![feature(coroutine_trait)]
+///
+/// use std::ops::{Coroutine, CoroutineState};
+/// use std::pin::Pin;
+///
+/// fn main() {
+/// let mut coroutine = || {
+/// yield 1;
+/// "foo"
+/// };
+///
+/// match Pin::new(&mut coroutine).resume(()) {
+/// CoroutineState::Yielded(1) => {}
+/// _ => panic!("unexpected return from resume"),
+/// }
+/// match Pin::new(&mut coroutine).resume(()) {
+/// CoroutineState::Complete("foo") => {}
+/// _ => panic!("unexpected return from resume"),
+/// }
+/// }
+/// ```
+///
+/// More documentation of coroutines can be found in the [unstable book].
+///
+/// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
+/// [unstable book]: ../../unstable-book/language-features/coroutines.html
+#[cfg_attr(bootstrap, lang = "generator")]
+#[cfg_attr(not(bootstrap), lang = "coroutine")]
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+#[fundamental]
+pub trait Coroutine<R = ()> {
+ /// The type of value this coroutine yields.
+ ///
+ /// This associated type corresponds to the `yield` expression and the
+ /// values which are allowed to be returned each time a coroutine yields.
+ /// For example an iterator-as-a-coroutine would likely have this type as
+ /// `T`, the type being iterated over.
+ type Yield;
+
+ /// The type of value this coroutine returns.
+ ///
+ /// This corresponds to the type returned from a coroutine either with a
+ /// `return` statement or implicitly as the last expression of a coroutine
+ /// literal. For example futures would use this as `Result<T, E>` as it
+ /// represents a completed future.
+ type Return;
+
+ /// Resumes the execution of this coroutine.
+ ///
+ /// This function will resume execution of the coroutine or start execution
+ /// if it hasn't already. This call will return back into the coroutine's
+ /// last suspension point, resuming execution from the latest `yield`. The
+ /// coroutine will continue executing until it either yields or returns, at
+ /// which point this function will return.
+ ///
+ /// # Return value
+ ///
+ /// The `CoroutineState` enum returned from this function indicates what
+ /// state the coroutine is in upon returning. If the `Yielded` variant is
+ /// returned then the coroutine has reached a suspension point and a value
+ /// has been yielded out. Coroutines in this state are available for
+ /// resumption at a later point.
+ ///
+ /// If `Complete` is returned then the coroutine has completely finished
+ /// with the value provided. It is invalid for the coroutine to be resumed
+ /// again.
+ ///
+ /// # Panics
+ ///
+ /// This function may panic if it is called after the `Complete` variant has
+ /// been returned previously. While coroutine literals in the language are
+ /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
+ /// for all implementations of the `Coroutine` trait.
+ fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>;
+}
+
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+impl<G: ?Sized + Coroutine<R>, R> Coroutine<R> for Pin<&mut G> {
+ type Yield = G::Yield;
+ type Return = G::Return;
+
+ fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
+ G::resume((*self).as_mut(), arg)
+ }
+}
+
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+impl<G: ?Sized + Coroutine<R> + Unpin, R> Coroutine<R> for &mut G {
+ type Yield = G::Yield;
+ type Return = G::Return;
+
+ fn resume(mut self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
+ G::resume(Pin::new(&mut *self), arg)
+ }
+}
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 911761c6e..99adbb915 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -3,40 +3,107 @@
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
-/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
+/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and
+/// mutable deref coercion similarly occurs.
///
-/// Implementing `Deref` for smart pointers makes accessing the data behind them
-/// convenient, which is why they implement `Deref`. On the other hand, the
-/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
-/// accommodate smart pointers. Because of this, **`Deref` should only be
-/// implemented for smart pointers** to avoid confusion.
+/// **Warning:** Deref coercion is a powerful language feature which has
+/// far-reaching implications for every type that implements `Deref`. The
+/// compiler will silently insert calls to `Deref::deref`. For this reason, one
+/// should be careful about implementing `Deref` and only do so when deref
+/// coercion is desirable. See [below][implementing] for advice on when this is
+/// typically desirable or undesirable.
///
-/// For similar reasons, **this trait should never fail**. Failure during
-/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
+/// Types that implement `Deref` or `DerefMut` are often called "smart
+/// pointers" and the mechanism of deref coercion has been specifically designed
+/// to facilitate the pointer-like behaviour that name suggests. Often, the
+/// purpose of a "smart pointer" type is to change the ownership semantics
+/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
+/// storage semantics of a contained value (for example, [`Box`][box]).
///
-/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
-/// specified, but users of the trait must ensure that such logic errors do *not* result in
-/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
-/// method.
+/// # Deref coercion
///
-/// # More on `Deref` coercion
+/// If `T` implements `Deref<Target = U>`, and `v` is a value of type `T`, then:
///
-/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
-///
-/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
-/// is equivalent to `*Deref::deref(&x)`.
+/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw
+/// pointer) is equivalent to `*Deref::deref(&v)`.
/// * Values of type `&T` are coerced to values of type `&U`
-/// * `T` implicitly implements all the (immutable) methods of the type `U`.
+/// * `T` implicitly implements all the methods of the type `U` which take the
+/// `&self` receiver.
///
/// For more details, visit [the chapter in *The Rust Programming Language*][book]
/// as well as the reference sections on [the dereference operator][ref-deref-op],
-/// [method resolution] and [type coercions].
+/// [method resolution], and [type coercions].
+///
+/// # When to implement `Deref` or `DerefMut`
+///
+/// The same advice applies to both deref traits. In general, deref traits
+/// **should** be implemented if:
+///
+/// 1. a value of the type transparently behaves like a value of the target
+/// type;
+/// 1. the implementation of the deref function is cheap; and
+/// 1. users of the type will not be surprised by any deref coercion behaviour.
+///
+/// In general, deref traits **should not** be implemented if:
+///
+/// 1. the deref implementations could fail unexpectedly; or
+/// 1. the type has methods that are likely to collide with methods on the
+/// target type; or
+/// 1. committing to deref coercion as part of the public API is not desirable.
+///
+/// Note that there's a large difference between implementing deref traits
+/// generically over many target types, and doing so only for specific target
+/// types.
+///
+/// Generic implementations, such as for [`Box<T>`][box] (which is generic over
+/// every type and dereferences to `T`) should be careful to provide few or no
+/// methods, since the target type is unknown and therefore every method could
+/// collide with one on the target type, causing confusion for users.
+/// `impl<T> Box<T>` has no methods (though several associated functions),
+/// partly for this reason.
+///
+/// Specific implementations, such as for [`String`][string] (whose `Deref`
+/// implementation has `Target = str`) can have many methods, since avoiding
+/// collision is much easier. `String` and `str` both have many methods, and
+/// `String` additionally behaves as if it has every method of `str` because of
+/// deref coercion. The implementing type may also be generic while the
+/// implementation is still specific in this sense; for example, [`Vec<T>`][vec]
+/// dereferences to `[T]`, so methods of `T` are not applicable.
+///
+/// Consider also that deref coericion means that deref traits are a much larger
+/// part of a type's public API than any other trait as it is implicitly called
+/// by the compiler. Therefore, it is advisable to consider whether this is
+/// something you are comfortable supporting as a public API.
+///
+/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar
+/// signatures to `Deref`. It may be desirable to implement either or both of
+/// these, whether in addition to or rather than deref traits. See their
+/// documentation for details.
+///
+/// # Fallibility
+///
+/// **This trait's method should never unexpectedly fail**. Deref coercion means
+/// the compiler will often insert calls to `Deref::deref` implicitly. Failure
+/// during dereferencing can be extremely confusing when `Deref` is invoked
+/// implicitly. In the majority of uses it should be infallible, though it may
+/// be acceptable to panic if the type is misused through programmer error, for
+/// example.
+///
+/// However, infallibility is not enforced and therefore not guaranteed.
+/// As such, `unsafe` code should not rely on infallibility in general for
+/// soundness.
///
/// [book]: ../../book/ch15-02-deref.html
-/// [more]: #more-on-deref-coercion
+/// [coercion]: #deref-coercion
+/// [implementing]: #when-to-implement-deref-or-derefmut
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
+/// [box]: ../../alloc/boxed/struct.Box.html
+/// [string]: ../../alloc/string/struct.String.html
+/// [vec]: ../../alloc/vec/struct.Vec.html
+/// [rc]: ../../alloc/rc/struct.Rc.html
+/// [cow]: ../../alloc/borrow/enum.Cow.html
///
/// # Examples
///
@@ -107,30 +174,29 @@ impl<T: ?Sized> Deref for &mut T {
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
-/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
-///
-/// Implementing `DerefMut` for smart pointers makes mutating the data behind
-/// them convenient, which is why they implement `DerefMut`. On the other hand,
-/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
-/// accommodate smart pointers. Because of this, **`DerefMut` should only be
-/// implemented for smart pointers** to avoid confusion.
+/// ["mutable deref coercion"][coercion]. In immutable contexts, [`Deref`] is used.
///
-/// For similar reasons, **this trait should never fail**. Failure during
-/// dereferencing can be extremely confusing when `DerefMut` is invoked
-/// implicitly.
+/// **Warning:** Deref coercion is a powerful language feature which has
+/// far-reaching implications for every type that implements `DerefMut`. The
+/// compiler will silently insert calls to `DerefMut::deref_mut`. For this
+/// reason, one should be careful about implementing `DerefMut` and only do so
+/// when mutable deref coercion is desirable. See [the `Deref` docs][implementing]
+/// for advice on when this is typically desirable or undesirable.
///
-/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
-/// specified, but users of the trait must ensure that such logic errors do *not* result in
-/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
-/// method.
+/// Types that implement `DerefMut` or `Deref` are often called "smart
+/// pointers" and the mechanism of deref coercion has been specifically designed
+/// to facilitate the pointer-like behaviour that name suggests. Often, the
+/// purpose of a "smart pointer" type is to change the ownership semantics
+/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
+/// storage semantics of a contained value (for example, [`Box`][box]).
///
-/// # More on `Deref` coercion
+/// # Mutable deref coercion
///
-/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
+/// If `T` implements `DerefMut<Target = U>`, and `v` is a value of type `T`,
/// then:
///
-/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
-/// is equivalent to `*DerefMut::deref_mut(&mut x)`.
+/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer)
+/// is equivalent to `*DerefMut::deref_mut(&mut v)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
@@ -138,11 +204,29 @@ impl<T: ?Sized> Deref for &mut T {
/// as well as the reference sections on [the dereference operator][ref-deref-op],
/// [method resolution] and [type coercions].
///
+/// # Fallibility
+///
+/// **This trait's method should never unexpectedly fail**. Deref coercion means
+/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly.
+/// Failure during dereferencing can be extremely confusing when `DerefMut` is
+/// invoked implicitly. In the majority of uses it should be infallible, though
+/// it may be acceptable to panic if the type is misused through programmer
+/// error, for example.
+///
+/// However, infallibility is not enforced and therefore not guaranteed.
+/// As such, `unsafe` code should not rely on infallibility in general for
+/// soundness.
+///
/// [book]: ../../book/ch15-02-deref.html
-/// [more]: #more-on-deref-coercion
+/// [coercion]: #mutable-deref-coercion
+/// [implementing]: Deref#when-to-implement-deref-or-derefmut
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
+/// [box]: ../../alloc/boxed/struct.Box.html
+/// [string]: ../../alloc/string/struct.String.html
+/// [rc]: ../../alloc/rc/struct.Rc.html
+/// [cow]: ../../alloc/borrow/enum.Cow.html
///
/// # Examples
///
@@ -180,6 +264,7 @@ impl<T: ?Sized> Deref for &mut T {
pub trait DerefMut: Deref {
/// Mutably dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_diagnostic_item = "deref_mut_method"]
fn deref_mut(&mut self) -> &mut Self::Target;
}
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index 20f0bba4c..51e304dd7 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -56,7 +56,7 @@ use crate::marker::Tuple;
#[lang = "fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
-#[rustc_on_unimplemented(
+#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
on(
Args = "()",
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
@@ -67,9 +67,9 @@ use crate::marker::Tuple;
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
),
- message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
- label = "expected an `Fn<{Args}>` closure, found `{Self}`"
-)]
+ message = "expected a `{Trait}` closure, found `{Self}`",
+ label = "expected an `{Trait}` closure, found `{Self}`"
+))]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
// FIXME(effects) #[const_trait]
@@ -143,7 +143,7 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
#[lang = "fn_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
-#[rustc_on_unimplemented(
+#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
on(
Args = "()",
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
@@ -154,9 +154,9 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
),
- message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
- label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
-)]
+ message = "expected a `{Trait}` closure, found `{Self}`",
+ label = "expected an `{Trait}` closure, found `{Self}`"
+))]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
// FIXME(effects) #[const_trait]
@@ -222,7 +222,7 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
#[lang = "fn_once"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
-#[rustc_on_unimplemented(
+#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
on(
Args = "()",
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
@@ -233,9 +233,9 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
),
- message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
- label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
-)]
+ message = "expected a `{Trait}` closure, found `{Self}`",
+ label = "expected an `{Trait}` closure, found `{Self}`"
+))]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
// FIXME(effects) #[const_trait]
diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs
deleted file mode 100644
index fee4beb1e..000000000
--- a/library/core/src/ops/generator.rs
+++ /dev/null
@@ -1,135 +0,0 @@
-use crate::marker::Unpin;
-use crate::pin::Pin;
-
-/// The result of a generator resumption.
-///
-/// This enum is returned from the `Generator::resume` method and indicates the
-/// possible return values of a generator. Currently this corresponds to either
-/// a suspension point (`Yielded`) or a termination point (`Complete`).
-#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
-#[lang = "generator_state"]
-#[unstable(feature = "generator_trait", issue = "43122")]
-pub enum GeneratorState<Y, R> {
- /// The generator suspended with a value.
- ///
- /// This state indicates that a generator has been suspended, and typically
- /// corresponds to a `yield` statement. The value provided in this variant
- /// corresponds to the expression passed to `yield` and allows generators to
- /// provide a value each time they yield.
- Yielded(Y),
-
- /// The generator completed with a return value.
- ///
- /// This state indicates that a generator has finished execution with the
- /// provided value. Once a generator has returned `Complete` it is
- /// considered a programmer error to call `resume` again.
- Complete(R),
-}
-
-/// The trait implemented by builtin generator types.
-///
-/// Generators, also commonly referred to as coroutines, are currently an
-/// experimental language feature in Rust. Added in [RFC 2033] generators are
-/// currently intended to primarily provide a building block for async/await
-/// syntax but will likely extend to also providing an ergonomic definition for
-/// iterators and other primitives.
-///
-/// The syntax and semantics for generators is unstable and will require a
-/// further RFC for stabilization. At this time, though, the syntax is
-/// closure-like:
-///
-/// ```rust
-/// #![feature(generators, generator_trait)]
-///
-/// use std::ops::{Generator, GeneratorState};
-/// use std::pin::Pin;
-///
-/// fn main() {
-/// let mut generator = || {
-/// yield 1;
-/// "foo"
-/// };
-///
-/// match Pin::new(&mut generator).resume(()) {
-/// GeneratorState::Yielded(1) => {}
-/// _ => panic!("unexpected return from resume"),
-/// }
-/// match Pin::new(&mut generator).resume(()) {
-/// GeneratorState::Complete("foo") => {}
-/// _ => panic!("unexpected return from resume"),
-/// }
-/// }
-/// ```
-///
-/// More documentation of generators can be found in the [unstable book].
-///
-/// [RFC 2033]: https://github.com/rust-lang/rfcs/pull/2033
-/// [unstable book]: ../../unstable-book/language-features/generators.html
-#[lang = "generator"]
-#[unstable(feature = "generator_trait", issue = "43122")]
-#[fundamental]
-pub trait Generator<R = ()> {
- /// The type of value this generator yields.
- ///
- /// This associated type corresponds to the `yield` expression and the
- /// values which are allowed to be returned each time a generator yields.
- /// For example an iterator-as-a-generator would likely have this type as
- /// `T`, the type being iterated over.
- type Yield;
-
- /// The type of value this generator returns.
- ///
- /// This corresponds to the type returned from a generator either with a
- /// `return` statement or implicitly as the last expression of a generator
- /// literal. For example futures would use this as `Result<T, E>` as it
- /// represents a completed future.
- type Return;
-
- /// Resumes the execution of this generator.
- ///
- /// This function will resume execution of the generator or start execution
- /// if it hasn't already. This call will return back into the generator's
- /// last suspension point, resuming execution from the latest `yield`. The
- /// generator will continue executing until it either yields or returns, at
- /// which point this function will return.
- ///
- /// # Return value
- ///
- /// The `GeneratorState` enum returned from this function indicates what
- /// state the generator is in upon returning. If the `Yielded` variant is
- /// returned then the generator has reached a suspension point and a value
- /// has been yielded out. Generators in this state are available for
- /// resumption at a later point.
- ///
- /// If `Complete` is returned then the generator has completely finished
- /// with the value provided. It is invalid for the generator to be resumed
- /// again.
- ///
- /// # Panics
- ///
- /// This function may panic if it is called after the `Complete` variant has
- /// been returned previously. While generator literals in the language are
- /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
- /// for all implementations of the `Generator` trait.
- fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
-}
-
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator<R>, R> Generator<R> for Pin<&mut G> {
- type Yield = G::Yield;
- type Return = G::Return;
-
- fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
- G::resume((*self).as_mut(), arg)
- }
-}
-
-#[unstable(feature = "generator_trait", issue = "43122")]
-impl<G: ?Sized + Generator<R> + Unpin, R> Generator<R> for &mut G {
- type Yield = G::Yield;
- type Return = G::Return;
-
- fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
- G::resume(Pin::new(&mut *self), arg)
- }
-}
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index f4649be54..6ceee4637 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -153,7 +153,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
on(
- any(_Self = "alloc::string::String", _Self = "std::string::String"),
+ _Self = "alloc::string::String",
note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 97d9b750d..35654d0b8 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -8,8 +8,8 @@
//! trait, but since the assignment operator (`=`) has no backing trait, there
//! is no way of overloading its semantics. Additionally, this module does not
//! provide any mechanism to create new operators. If traitless overloading or
-//! custom operators are required, you should look toward macros or compiler
-//! plugins to extend Rust's syntax.
+//! custom operators are required, you should look toward macros to extend
+//! Rust's syntax.
//!
//! Implementations of operator traits should be unsurprising in their
//! respective contexts, keeping in mind their usual meanings and
@@ -141,10 +141,10 @@
mod arith;
mod bit;
mod control_flow;
+mod coroutine;
mod deref;
mod drop;
mod function;
-mod generator;
mod index;
mod index_range;
mod range;
@@ -198,8 +198,8 @@ pub use self::try_trait::Residual;
pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit};
-#[unstable(feature = "generator_trait", issue = "43122")]
-pub use self::generator::{Generator, GeneratorState};
+#[unstable(feature = "coroutine_trait", issue = "43122")]
+pub use self::coroutine::{Coroutine, CoroutineState};
#[unstable(feature = "coerce_unsized", issue = "18598")]
pub use self::unsize::CoerceUnsized;
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index cc596293c..b419a738f 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -115,6 +115,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// assert!(!(0.0..f32::NAN).contains(&0.5));
/// assert!(!(f32::NAN..1.0).contains(&0.5));
/// ```
+ #[inline]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
@@ -141,6 +142,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// assert!( (3.0..f32::NAN).is_empty());
/// assert!( (f32::NAN..5.0).is_empty());
/// ```
+ #[inline]
#[stable(feature = "range_is_empty", since = "1.47.0")]
pub fn is_empty(&self) -> bool {
!(self.start < self.end)
@@ -213,6 +215,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// assert!(!(0.0..).contains(&f32::NAN));
/// assert!(!(f32::NAN..).contains(&0.5));
/// ```
+ #[inline]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
@@ -294,6 +297,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// assert!(!(..1.0).contains(&f32::NAN));
/// assert!(!(..f32::NAN).contains(&0.5));
/// ```
+ #[inline]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
@@ -500,6 +504,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// // Precise field values are unspecified here
/// assert!(!r.contains(&3) && !r.contains(&5));
/// ```
+ #[inline]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
@@ -613,6 +618,7 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
/// assert!(!(..=1.0).contains(&f32::NAN));
/// assert!(!(..=f32::NAN).contains(&0.5));
/// ```
+ #[inline]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
@@ -758,6 +764,7 @@ impl<T: Clone> Bound<&T> {
/// `RangeBounds` is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
#[stable(feature = "collections_range", since = "1.28.0")]
+#[rustc_diagnostic_item = "RangeBounds"]
pub trait RangeBounds<T: ?Sized> {
/// Start index bound.
///
@@ -807,6 +814,7 @@ pub trait RangeBounds<T: ?Sized> {
/// assert!(!(0.0..1.0).contains(&f32::NAN));
/// assert!(!(0.0..f32::NAN).contains(&0.5));
/// assert!(!(f32::NAN..1.0).contains(&0.5));
+ #[inline]
#[stable(feature = "range_contains", since = "1.35.0")]
fn contains<U>(&self, item: &U) -> bool
where
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 17625dacc..3f8c8efd4 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -226,14 +226,8 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
- any(
- _Self = "core::result::Result<T, E>",
- _Self = "std::result::Result<T, E>",
- ),
- any(
- R = "core::option::Option<core::convert::Infallible>",
- R = "std::option::Option<std::convert::Infallible>",
- )
+ _Self = "core::result::Result<T, E>",
+ R = "core::option::Option<core::convert::Infallible>",
),
message = "the `?` operator can only be used on `Result`s, not `Option`s, \
in {ItemContext} that returns `Result`",
@@ -243,10 +237,7 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
- any(
- _Self = "core::result::Result<T, E>",
- _Self = "std::result::Result<T, E>",
- )
+ _Self = "core::result::Result<T, E>",
),
// There's a special error message in the trait selection code for
// `From` in `?`, so this is not shown for result-in-result errors,
@@ -259,14 +250,8 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
- any(
- _Self = "core::option::Option<T>",
- _Self = "std::option::Option<T>",
- ),
- any(
- R = "core::result::Result<T, E>",
- R = "std::result::Result<T, E>",
- )
+ _Self = "core::option::Option<T>",
+ R = "core::result::Result<T, E>",
),
message = "the `?` operator can only be used on `Option`s, not `Result`s, \
in {ItemContext} that returns `Option`",
@@ -276,10 +261,7 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
- any(
- _Self = "core::option::Option<T>",
- _Self = "std::option::Option<T>",
- )
+ _Self = "core::option::Option<T>",
),
// `Option`-in-`Option` always works, as there's only one possible
// residual, so this can also be phrased strongly.
@@ -291,14 +273,8 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
- any(
- _Self = "core::ops::ControlFlow<B, C>",
- _Self = "std::ops::ControlFlow<B, C>",
- ),
- any(
- R = "core::ops::ControlFlow<B, C>",
- R = "std::ops::ControlFlow<B, C>",
- )
+ _Self = "core::ops::control_flow::ControlFlow<B, C>",
+ R = "core::ops::control_flow::ControlFlow<B, C>",
),
message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
@@ -309,10 +285,7 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
- any(
- _Self = "core::ops::ControlFlow<B, C>",
- _Self = "std::ops::ControlFlow<B, C>",
- )
+ _Self = "core::ops::control_flow::ControlFlow<B, C>",
// `R` is not a `ControlFlow`, as that case was matched previously
),
message = "the `?` operator can only be used on `ControlFlow`s \
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index f2909a81d..89d4532de 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -119,15 +119,21 @@
//! # Representation
//!
//! Rust guarantees to optimize the following types `T` such that
-//! [`Option<T>`] has the same size and alignment as `T`:
-//!
-//! * [`Box<U>`]
-//! * `&U`
-//! * `&mut U`
-//! * `fn`, `extern "C" fn`[^extern_fn]
-//! * [`num::NonZero*`]
-//! * [`ptr::NonNull<U>`]
-//! * `#[repr(transparent)]` struct around one of the types in this list.
+//! [`Option<T>`] has the same size and alignment as `T`. In some
+//! of these cases, Rust further guarantees that
+//! `transmute::<_, Option<T>>([0u8; size_of::<T>()])` is sound and
+//! produces `Option::<T>::None`. These cases are identified by the
+//! second column:
+//!
+//! | `T` | `transmute::<_, Option<T>>([0u8; size_of::<T>()])` sound? |
+//! |---------------------------------------------------------------------|----------------------------------------------------------------------|
+//! | [`Box<U>`] | when `U: Sized` |
+//! | `&U` | when `U: Sized` |
+//! | `&mut U` | when `U: Sized` |
+//! | `fn`, `extern "C" fn`[^extern_fn] | always |
+//! | [`num::NonZero*`] | always |
+//! | [`ptr::NonNull<U>`] | when `U: Sized` |
+//! | `#[repr(transparent)]` struct around one of the types in this list. | when it holds for the inner type |
//!
//! [^extern_fn]: this remains true for any other ABI: `extern "abi" fn` (_e.g._, `extern "system" fn`)
//!
@@ -743,8 +749,6 @@ impl<T> Option<T> {
/// # Examples
///
/// ```rust
- /// #![feature(option_as_slice)]
- ///
/// assert_eq!(
/// [Some(1234).as_slice(), None.as_slice()],
/// [&[1234][..], &[][..]],
@@ -755,15 +759,13 @@ impl<T> Option<T> {
/// borrowing) [`[_]::first`](slice::first):
///
/// ```rust
- /// #![feature(option_as_slice)]
- ///
/// for i in [Some(1234_u16), None] {
/// assert_eq!(i.as_ref(), i.as_slice().first());
/// }
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "option_as_slice", issue = "108545")]
+ #[stable(feature = "option_as_slice", since = "1.75.0")]
pub fn as_slice(&self) -> &[T] {
// SAFETY: When the `Option` is `Some`, we're using the actual pointer
// to the payload, with a length of 1, so this is equivalent to
@@ -794,8 +796,6 @@ impl<T> Option<T> {
/// # Examples
///
/// ```rust
- /// #![feature(option_as_slice)]
- ///
/// assert_eq!(
/// [Some(1234).as_mut_slice(), None.as_mut_slice()],
/// [&mut [1234][..], &mut [][..]],
@@ -806,8 +806,6 @@ impl<T> Option<T> {
/// our original `Option`:
///
/// ```rust
- /// #![feature(option_as_slice)]
- ///
/// let mut x = Some(1234);
/// x.as_mut_slice()[0] += 1;
/// assert_eq!(x, Some(1235));
@@ -817,13 +815,11 @@ impl<T> Option<T> {
/// is [`[_]::first_mut`](slice::first_mut):
///
/// ```rust
- /// #![feature(option_as_slice)]
- ///
/// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123))
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "option_as_slice", issue = "108545")]
+ #[stable(feature = "option_as_slice", since = "1.75.0")]
pub fn as_mut_slice(&mut self) -> &mut [T] {
// SAFETY: When the `Option` is `Some`, we're using the actual pointer
// to the payload, with a length of 1, so this is equivalent to
@@ -969,6 +965,7 @@ impl<T> Option<T> {
/// assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
/// ```
#[inline]
+ #[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap_or_else<F>(self, f: F) -> T
where
@@ -1485,7 +1482,7 @@ impl<T> Option<T> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn or(self, optb: Option<T>) -> Option<T> {
match self {
- Some(x) => Some(x),
+ x @ Some(_) => x,
None => optb,
}
}
@@ -1510,7 +1507,7 @@ impl<T> Option<T> {
F: FnOnce() -> Option<T>,
{
match self {
- Some(x) => Some(x),
+ x @ Some(_) => x,
None => f(),
}
}
@@ -1540,8 +1537,8 @@ impl<T> Option<T> {
#[stable(feature = "option_xor", since = "1.37.0")]
pub fn xor(self, optb: Option<T>) -> Option<T> {
match (self, optb) {
- (Some(a), None) => Some(a),
- (None, Some(b)) => Some(b),
+ (a @ Some(_), None) => a,
+ (None, b @ Some(_)) => b,
_ => None,
}
}
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 386f5fcbd..a00fd322b 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -47,6 +47,7 @@ pub macro panic_2015 {
#[allow_internal_unstable(core_panic, const_format_args)]
#[rustc_diagnostic_item = "core_panic_2021_macro"]
#[rustc_macro_transparency = "semitransparent"]
+#[cfg(any(bootstrap, feature = "panic_immediate_abort"))]
pub macro panic_2021 {
() => (
$crate::panicking::panic("explicit panic")
@@ -63,6 +64,50 @@ pub macro panic_2021 {
}
#[doc(hidden)]
+#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
+#[allow_internal_unstable(
+ core_panic,
+ core_intrinsics,
+ const_dispatch,
+ const_eval_select,
+ const_format_args,
+ rustc_attrs
+)]
+#[rustc_diagnostic_item = "core_panic_2021_macro"]
+#[rustc_macro_transparency = "semitransparent"]
+#[cfg(not(any(bootstrap, feature = "panic_immediate_abort")))]
+pub macro panic_2021 {
+ () => ({
+ // Create a function so that the argument for `track_caller`
+ // can be moved inside if possible.
+ #[cold]
+ #[track_caller]
+ #[inline(never)]
+ const fn panic_cold_explicit() -> ! {
+ $crate::panicking::panic_explicit()
+ }
+ panic_cold_explicit();
+ }),
+ // Special-case the single-argument case for const_panic.
+ ("{}", $arg:expr $(,)?) => ({
+ #[cold]
+ #[track_caller]
+ #[inline(never)]
+ #[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval
+ #[rustc_do_not_const_check] // hooked by const-eval
+ const fn panic_cold_display<T: $crate::fmt::Display>(arg: &T) -> ! {
+ $crate::panicking::panic_display(arg)
+ }
+ panic_cold_display(&$arg);
+ }),
+ ($($t:tt)+) => ({
+ // Semicolon to prevent temporaries inside the formatting machinery from
+ // being considered alive in the caller after the panic_fmt call.
+ $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
+ }),
+}
+
+#[doc(hidden)]
#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
#[allow_internal_unstable(core_panic)]
#[rustc_diagnostic_item = "unreachable_2015_macro"]
diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs
index 7e7b6b4db..6a53909a8 100644
--- a/library/core/src/panic/unwind_safe.rs
+++ b/library/core/src/panic/unwind_safe.rs
@@ -267,6 +267,7 @@ impl<T> DerefMut for AssertUnwindSafe<T> {
impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
type Output = R;
+ #[inline]
extern "rust-call" fn call_once(self, _args: ()) -> R {
(self.0)()
}
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index e6cdffd96..39a5e8d9f 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -152,6 +152,14 @@ pub const fn panic_str(expr: &str) -> ! {
panic_display(&expr);
}
+#[track_caller]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[rustc_const_unstable(feature = "core_panic", issue = "none")]
+pub const fn panic_explicit() -> ! {
+ panic_display(&"explicit panic");
+}
+
#[inline]
#[track_caller]
#[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint
@@ -161,8 +169,10 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! {
#[inline]
#[track_caller]
-#[lang = "panic_display"] // needed for const-evaluated panics
#[rustc_do_not_const_check] // hooked by const-eval
+#[cfg_attr(bootstrap, lang = "panic_display")]
+// enforce a &&str argument in const-check and hook this by const-eval
+#[cfg_attr(not(bootstrap), rustc_const_panic_str)]
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
panic_fmt(format_args!("{}", *x));
@@ -219,7 +229,6 @@ fn panic_cannot_unwind() -> ! {
/// pass to `panic_nounwind`.
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
-#[cfg(not(bootstrap))]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 94c682b61..bca97d4ee 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1085,17 +1085,19 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// # assert_eq!(42, block_on(async { 42 }));
/// ```
///
-/// ### With `Generator`s
+/// ### With `Coroutine`s
///
/// ```rust
-/// #![feature(generators, generator_trait)]
+/// #![cfg_attr(bootstrap, feature(generators))]
+/// #![cfg_attr(not(bootstrap), feature(coroutines))]
+/// #![feature(coroutine_trait)]
/// use core::{
-/// ops::{Generator, GeneratorState},
+/// ops::{Coroutine, CoroutineState},
/// pin::pin,
/// };
///
-/// fn generator_fn() -> impl Generator<Yield = usize, Return = ()> /* not Unpin */ {
-/// // Allow generator to be self-referential (not `Unpin`)
+/// fn coroutine_fn() -> impl Coroutine<Yield = usize, Return = ()> /* not Unpin */ {
+/// // Allow coroutine to be self-referential (not `Unpin`)
/// // vvvvvv so that locals can cross yield points.
/// static || {
/// let foo = String::from("foo");
@@ -1107,18 +1109,18 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
/// }
///
/// fn main() {
-/// let mut generator = pin!(generator_fn());
-/// match generator.as_mut().resume(()) {
-/// GeneratorState::Yielded(0) => {},
+/// let mut coroutine = pin!(coroutine_fn());
+/// match coroutine.as_mut().resume(()) {
+/// CoroutineState::Yielded(0) => {},
/// _ => unreachable!(),
/// }
-/// match generator.as_mut().resume(()) {
-/// GeneratorState::Yielded(3) => {},
+/// match coroutine.as_mut().resume(()) {
+/// CoroutineState::Yielded(3) => {},
/// _ => unreachable!(),
/// }
-/// match generator.resume(()) {
-/// GeneratorState::Yielded(_) => unreachable!(),
-/// GeneratorState::Complete(()) => {},
+/// match coroutine.resume(()) {
+/// CoroutineState::Yielded(_) => unreachable!(),
+/// CoroutineState::Complete(()) => {},
/// }
/// }
/// ```
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index fd5fe5a04..87e492108 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -283,7 +283,7 @@ mod prim_never {}
/// `char` type. For technical reasons, there is additional, separate
/// documentation in [the `std::char` module](char/index.html) as well.
///
-/// # Validity
+/// # Validity and Layout
///
/// A `char` is a '[Unicode scalar value]', which is any '[Unicode code point]'
/// other than a [surrogate code point]. This has a fixed numerical definition:
@@ -291,7 +291,7 @@ mod prim_never {}
/// Surrogate code points, used by UTF-16, are in the range 0xD800 to 0xDFFF.
///
/// No `char` may be constructed, whether as a literal or at runtime, that is not a
-/// Unicode scalar value:
+/// Unicode scalar value. Violating this rule causes undefined behavior.
///
/// ```compile_fail
/// // Each of these is a compiler error
@@ -308,9 +308,10 @@ mod prim_never {}
/// let _ = unsafe { char::from_u32_unchecked(0x110000) };
/// ```
///
-/// USVs are also the exact set of values that may be encoded in UTF-8. Because
-/// `char` values are USVs and `str` values are valid UTF-8, it is safe to store
-/// any `char` in a `str` or read any character from a `str` as a `char`.
+/// Unicode scalar values are also the exact set of values that may be encoded in UTF-8. Because
+/// `char` values are Unicode scalar values and functions may assume [incoming `str` values are
+/// valid UTF-8](primitive.str.html#invariant), it is safe to store any `char` in a `str` or read
+/// any character from a `str` as a `char`.
///
/// The gap in valid `char` values is understood by the compiler, so in the
/// below example the two ranges are understood to cover the whole range of
@@ -324,11 +325,17 @@ mod prim_never {}
/// };
/// ```
///
-/// All USVs are valid `char` values, but not all of them represent a real
-/// character. Many USVs are not currently assigned to a character, but may be
-/// in the future ("reserved"); some will never be a character
-/// ("noncharacters"); and some may be given different meanings by different
-/// users ("private use").
+/// All Unicode scalar values are valid `char` values, but not all of them represent a real
+/// character. Many Unicode scalar values are not currently assigned to a character, but may be in
+/// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given
+/// different meanings by different users ("private use").
+///
+/// `char` is guaranteed to have the same size and alignment as `u32` on all
+/// platforms.
+/// ```
+/// use std::alloc::Layout;
+/// assert_eq!(Layout::new::<char>(), Layout::new::<u32>());
+/// ```
///
/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
@@ -887,8 +894,6 @@ mod prim_slice {}
/// type. It is usually seen in its borrowed form, `&str`. It is also the type
/// of string literals, `&'static str`.
///
-/// String slices are always valid UTF-8.
-///
/// # Basic Usage
///
/// String literals are string slices:
@@ -942,6 +947,14 @@ mod prim_slice {}
/// Note: This example shows the internals of `&str`. `unsafe` should not be
/// used to get a string slice under normal circumstances. Use `as_str`
/// instead.
+///
+/// # Invariant
+///
+/// Rust libraries may assume that string slices are always valid UTF-8.
+///
+/// Constructing a non-UTF-8 string slice is not immediate undefined behavior, but any function
+/// called on a string slice may assume that it is valid UTF-8, which means that a non-UTF-8 string
+/// slice can lead to undefined behavior down the road.
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_str {}
@@ -1077,26 +1090,6 @@ mod prim_tuple {}
#[doc(hidden)]
impl<T> (T,) {}
-// Fake impl that's only really used for docs.
-#[cfg(doc)]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(fake_variadic)]
-/// This trait is implemented on arbitrary-length tuples.
-impl<T: Clone> Clone for (T,) {
- fn clone(&self) -> Self {
- loop {}
- }
-}
-
-// Fake impl that's only really used for docs.
-#[cfg(doc)]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(fake_variadic)]
-/// This trait is implemented on arbitrary-length tuples.
-impl<T: Copy> Copy for (T,) {
- // empty
-}
-
#[rustc_doc_primitive = "f32"]
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
///
@@ -1142,10 +1135,9 @@ impl<T: Copy> Copy for (T,) {
/// surprising results upon inspecting the bit patterns,
/// as the same calculations might produce NaNs with different bit patterns.
///
-/// When the number resulting from a primitive operation (addition,
-/// subtraction, multiplication, or division) on this type is not exactly
-/// representable as `f32`, it is rounded according to the roundTiesToEven
-/// direction defined in IEEE 754-2008. That means:
+/// When a primitive operation (addition, subtraction, multiplication, or
+/// division) is performed on this type, the result is rounded according to the
+/// roundTiesToEven direction defined in IEEE 754-2008. That means:
///
/// - The result is the representable value closest to the true value, if there
/// is a unique closest representable value.
@@ -1154,6 +1146,9 @@ impl<T: Copy> Copy for (T,) {
/// - If the true value's magnitude is ≥ `f32::MAX` + 2<sup>(`f32::MAX_EXP` −
/// `f32::MANTISSA_DIGITS` − 1)</sup>, the result is ∞ or −∞ (preserving the
/// true value's sign).
+/// - If the result of a sum exactly equals zero, the outcome is +0.0 unless
+/// both arguments were negative, then it is -0.0. Subtraction `a - b` is
+/// regarded as a sum `a + (-b)`.
///
/// For more information on floating point numbers, see [Wikipedia][wikipedia].
///
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 9af8f1228..36685f756 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -480,8 +480,9 @@ impl<T: ?Sized> *const T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset(self, count: isize) -> Self {
// SAFETY: the caller must uphold the safety contract for `offset`.
@@ -560,8 +561,9 @@ impl<T: ?Sized> *const T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
pub const fn wrapping_byte_offset(self, count: isize) -> Self {
self.cast::<u8>().wrapping_offset(count).with_metadata_of(self)
}
@@ -726,8 +728,9 @@ impl<T: ?Sized> *const T {
/// For non-`Sized` pointees this operation considers only the data pointers,
/// ignoring the metadata.
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: *const U) -> isize {
// SAFETY: the caller must uphold the safety contract for `offset_from`.
@@ -842,7 +845,7 @@ impl<T: ?Sized> *const T {
where
T: Sized,
{
- match intrinsics::ptr_guaranteed_cmp(self as _, other as _) {
+ match intrinsics::ptr_guaranteed_cmp(self, other) {
2 => None,
other => Some(other == 1),
}
@@ -952,8 +955,9 @@ impl<T: ?Sized> *const T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_add(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `add`.
@@ -1045,8 +1049,9 @@ impl<T: ?Sized> *const T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_sub(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `sub`.
@@ -1125,8 +1130,9 @@ impl<T: ?Sized> *const T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
pub const fn wrapping_byte_add(self, count: usize) -> Self {
self.cast::<u8>().wrapping_add(count).with_metadata_of(self)
}
@@ -1203,8 +1209,9 @@ impl<T: ?Sized> *const T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
pub const fn wrapping_byte_sub(self, count: usize) -> Self {
self.cast::<u8>().wrapping_sub(count).with_metadata_of(self)
}
@@ -1372,7 +1379,6 @@ impl<T: ?Sized> *const T {
///
/// ```
/// #![feature(pointer_is_aligned)]
- /// #![feature(pointer_byte_offsets)]
///
/// // On some platforms, the alignment of i32 is less than 4.
/// #[repr(align(4))]
@@ -1494,7 +1500,6 @@ impl<T: ?Sized> *const T {
///
/// ```
/// #![feature(pointer_is_aligned)]
- /// #![feature(pointer_byte_offsets)]
///
/// // On some platforms, the alignment of i32 is less than 4.
/// #[repr(align(4))]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index d1286a1de..d71079dd0 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -494,6 +494,7 @@ mod mut_ptr;
#[stable(feature = "drop_in_place", since = "1.8.0")]
#[lang = "drop_in_place"]
#[allow(unconditional_recursion)]
+#[rustc_diagnostic_item = "ptr_drop_in_place"]
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
// Code here does not matter - this is replaced by the
// real drop glue by the compiler.
@@ -504,6 +505,10 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
/// Creates a null raw pointer.
///
+/// This function is equivalent to zero-initializing the pointer:
+/// `MaybeUninit::<*const T>::zeroed().assume_init()`.
+/// The resulting pointer has the address 0.
+///
/// # Examples
///
/// ```
@@ -511,6 +516,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
///
/// let p: *const i32 = ptr::null();
/// assert!(p.is_null());
+/// assert_eq!(p as usize, 0); // this pointer has the address 0
/// ```
#[inline(always)]
#[must_use]
@@ -525,6 +531,10 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
/// Creates a null mutable raw pointer.
///
+/// This function is equivalent to zero-initializing the pointer:
+/// `MaybeUninit::<*mut T>::zeroed().assume_init()`.
+/// The resulting pointer has the address 0.
+///
/// # Examples
///
/// ```
@@ -532,6 +542,7 @@ pub const fn null<T: ?Sized + Thin>() -> *const T {
///
/// let p: *mut i32 = ptr::null_mut();
/// assert!(p.is_null());
+/// assert_eq!(p as usize, 0); // this pointer has the address 0
/// ```
#[inline(always)]
#[must_use]
@@ -698,7 +709,7 @@ where
#[inline(always)]
#[must_use]
#[unstable(feature = "ptr_from_ref", issue = "106116")]
-#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+#[rustc_never_returns_null_ptr]
#[rustc_diagnostic_item = "ptr_from_ref"]
pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
r
@@ -711,7 +722,7 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
#[inline(always)]
#[must_use]
#[unstable(feature = "ptr_from_ref", issue = "106116")]
-#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+#[rustc_never_returns_null_ptr]
pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
r
}
@@ -740,6 +751,7 @@ pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
#[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
#[rustc_allow_const_fn_unstable(ptr_metadata)]
+#[rustc_diagnostic_item = "ptr_slice_from_raw_parts"]
pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
from_raw_parts(data.cast(), len)
}
@@ -772,6 +784,7 @@ pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
#[inline]
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
+#[rustc_diagnostic_item = "ptr_slice_from_raw_parts_mut"]
pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
from_raw_parts_mut(data.cast(), len)
}
@@ -850,6 +863,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+#[rustc_diagnostic_item = "ptr_swap"]
pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
// Give ourselves some scratch space to work with.
// We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
@@ -911,6 +925,7 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
#[inline]
#[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
+#[rustc_diagnostic_item = "ptr_swap_nonoverlapping"]
pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
#[allow(unused)]
macro_rules! attempt_swap_as_chunks {
@@ -1022,6 +1037,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, coun
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+#[rustc_diagnostic_item = "ptr_replace"]
pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
// SAFETY: the caller must guarantee that `dst` is valid to be
// cast to a mutable reference (valid for writes, aligned, initialized),
@@ -1147,6 +1163,7 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_read"]
pub const unsafe fn read<T>(src: *const T) -> T {
// It would be semantically correct to implement this via `copy_nonoverlapping`
// and `MaybeUninit`, as was done before PR #109035. Calling `assume_init`
@@ -1264,6 +1281,7 @@ pub const unsafe fn read<T>(src: *const T) -> T {
#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_read_unaligned"]
pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
let mut tmp = MaybeUninit::<T>::uninit();
// SAFETY: the caller must guarantee that `src` is valid for reads.
@@ -1539,6 +1557,7 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_read_volatile"]
pub unsafe fn read_volatile<T>(src: *const T) -> T {
// SAFETY: the caller must uphold the safety contract for `volatile_load`.
unsafe {
@@ -1864,10 +1883,35 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
/// ```
#[stable(feature = "ptr_eq", since = "1.17.0")]
#[inline(always)]
+#[must_use = "pointer comparison produces a value"]
+#[rustc_diagnostic_item = "ptr_eq"]
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
a == b
}
+/// Compares the *addresses* of the two pointers for equality,
+/// ignoring any metadata in fat pointers.
+///
+/// If the arguments are thin pointers of the same type,
+/// then this is the same as [`eq`].
+///
+/// # Examples
+///
+/// ```
+/// #![feature(ptr_addr_eq)]
+///
+/// let whole: &[i32; 3] = &[1, 2, 3];
+/// let first: &i32 = &whole[0];
+/// assert!(std::ptr::addr_eq(whole, first));
+/// assert!(!std::ptr::eq::<dyn std::fmt::Debug>(whole, first));
+/// ```
+#[unstable(feature = "ptr_addr_eq", issue = "116324")]
+#[inline(always)]
+#[must_use = "pointer comparison produces a value"]
+pub fn addr_eq<T: ?Sized, U: ?Sized>(p: *const T, q: *const U) -> bool {
+ (p as *const ()) == (q as *const ())
+}
+
/// Hash a raw pointer.
///
/// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly)
@@ -1955,9 +1999,18 @@ impl<F: FnPtr> fmt::Debug for F {
/// as all other references. This macro can create a raw pointer *without* creating
/// a reference first.
///
-/// Note, however, that the `expr` in `addr_of!(expr)` is still subject to all
-/// the usual rules. In particular, `addr_of!(*ptr::null())` is Undefined
-/// Behavior because it dereferences a null pointer.
+/// The `expr` in `addr_of!(expr)` is evaluated as a place expression, but never loads
+/// from the place or requires the place to be dereferenceable. This means that
+/// `addr_of!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
+/// Note however that `addr_of!((*ptr).field)` still requires the projection to
+/// `field` to be in-bounds, using the same rules as [`offset`].
+///
+/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
+/// `addr_of!` like everywhere else, in which case a reference is created to call `Deref::deref` or
+/// `Index::index`, respectively. The statements above only apply when no such coercions are
+/// applied.
+///
+/// [`offset`]: pointer::offset
///
/// # Example
///
@@ -1995,9 +2048,18 @@ pub macro addr_of($place:expr) {
/// as all other references. This macro can create a raw pointer *without* creating
/// a reference first.
///
-/// Note, however, that the `expr` in `addr_of_mut!(expr)` is still subject to all
-/// the usual rules. In particular, `addr_of_mut!(*ptr::null_mut())` is Undefined
-/// Behavior because it dereferences a null pointer.
+/// The `expr` in `addr_of_mut!(expr)` is evaluated as a place expression, but never loads
+/// from the place or requires the place to be dereferenceable. This means that
+/// `addr_of_mut!(*ptr)` is defined behavior even if `ptr` is null, dangling, or misaligned.
+/// Note however that `addr_of_mut!((*ptr).field)` still requires the projection to
+/// `field` to be in-bounds, using the same rules as [`offset`].
+///
+/// Note that `Deref`/`Index` coercions (and their mutable counterparts) are applied inside
+/// `addr_of_mut!` like everywhere else, in which case a reference is created to call `Deref::deref`
+/// or `Index::index`, respectively. The statements above only apply when no such coercions are
+/// applied.
+///
+/// [`offset`]: pointer::offset
///
/// # Examples
///
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 109c28692..bc362fb62 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -495,8 +495,9 @@ impl<T: ?Sized> *mut T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset(self, count: isize) -> Self {
// SAFETY: the caller must uphold the safety contract for `offset`.
@@ -574,8 +575,9 @@ impl<T: ?Sized> *mut T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
pub const fn wrapping_byte_offset(self, count: isize) -> Self {
self.cast::<u8>().wrapping_offset(count).with_metadata_of(self)
}
@@ -898,8 +900,9 @@ impl<T: ?Sized> *mut T {
/// For non-`Sized` pointees this operation considers only the data pointers,
/// ignoring the metadata.
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_offset_from<U: ?Sized>(self, origin: *const U) -> isize {
// SAFETY: the caller must uphold the safety contract for `offset_from`.
@@ -1053,8 +1056,9 @@ impl<T: ?Sized> *mut T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_add(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `add`.
@@ -1146,8 +1150,9 @@ impl<T: ?Sized> *mut T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn byte_sub(self, count: usize) -> Self {
// SAFETY: the caller must uphold the safety contract for `sub`.
@@ -1226,8 +1231,9 @@ impl<T: ?Sized> *mut T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
pub const fn wrapping_byte_add(self, count: usize) -> Self {
self.cast::<u8>().wrapping_add(count).with_metadata_of(self)
}
@@ -1304,8 +1310,9 @@ impl<T: ?Sized> *mut T {
/// leaving the metadata untouched.
#[must_use]
#[inline(always)]
- #[unstable(feature = "pointer_byte_offsets", issue = "96283")]
- #[rustc_const_unstable(feature = "const_pointer_byte_offsets", issue = "96283")]
+ #[stable(feature = "pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_const_stable(feature = "const_pointer_byte_offsets", since = "1.75.0")]
+ #[rustc_allow_const_fn_unstable(set_ptr_value)]
pub const fn wrapping_byte_sub(self, count: usize) -> Self {
self.cast::<u8>().wrapping_sub(count).with_metadata_of(self)
}
@@ -1639,7 +1646,6 @@ impl<T: ?Sized> *mut T {
///
/// ```
/// #![feature(pointer_is_aligned)]
- /// #![feature(pointer_byte_offsets)]
///
/// // On some platforms, the alignment of i32 is less than 4.
/// #[repr(align(4))]
@@ -1763,7 +1769,6 @@ impl<T: ?Sized> *mut T {
///
/// ```
/// #![feature(pointer_is_aligned)]
- /// #![feature(pointer_byte_offsets)]
///
/// // On some platforms, the alignment of i32 is less than 4.
/// #[repr(align(4))]
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index d5bd54fd5..ae673b779 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -68,6 +68,7 @@ use crate::slice::{self, SliceIndex};
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
+#[rustc_diagnostic_item = "NonNull"]
pub struct NonNull<T: ?Sized> {
pointer: *const T,
}
@@ -338,7 +339,7 @@ impl<T: ?Sized> NonNull<T> {
/// ```
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
#[must_use]
#[inline(always)]
pub const fn as_ptr(self) -> *mut T {
@@ -598,7 +599,7 @@ impl<T> NonNull<[T]> {
#[must_use]
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn as_mut_ptr(self) -> *mut T {
self.as_non_null_ptr().as_ptr()
}
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 6981abc9b..50127b27f 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1422,6 +1422,7 @@ impl<T, E> Result<T, E> {
/// assert_eq!(Err("foo").unwrap_or_else(count), 3);
/// ```
#[inline]
+ #[track_caller]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T {
match self {
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index d313e8e01..1da3a87e1 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -152,10 +152,7 @@ mod private_slice_index {
#[rustc_on_unimplemented(
on(T = "str", label = "string indices are ranges of `usize`",),
on(
- all(
- any(T = "str", T = "&str", T = "alloc::string::String", T = "std::string::String"),
- _Self = "{integer}"
- ),
+ all(any(T = "str", T = "&str", T = "alloc::string::String"), _Self = "{integer}"),
note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
for more information, see chapter 8 in The Book: \
<https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index cc9313553..5e229bf52 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -59,6 +59,7 @@ impl<'a, T> IntoIterator for &'a mut [T] {
/// [slices]: slice
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[rustc_diagnostic_item = "SliceIter"]
pub struct Iter<'a, T: 'a> {
/// The pointer to the next element to return, or the past-the-end location
/// if the iterator is empty.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index a19fcf93c..6cf5d48a1 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -640,6 +640,11 @@ impl<T> [T] {
/// Calling this method with an out-of-bounds index is *[undefined behavior]*
/// even if the resulting reference is not used.
///
+ /// You can think of this like `.get(index).unwrap_unchecked()`. It's UB
+ /// to call `.get_unchecked(len)`, even if you immediately convert to a
+ /// pointer. And it's UB to call `.get_unchecked(..len + 1)`,
+ /// `.get_unchecked(..=len)`, or similar.
+ ///
/// [`get`]: slice::get
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
@@ -675,6 +680,11 @@ impl<T> [T] {
/// Calling this method with an out-of-bounds index is *[undefined behavior]*
/// even if the resulting reference is not used.
///
+ /// You can think of this like `.get_mut(index).unwrap_unchecked()`. It's
+ /// UB to call `.get_unchecked_mut(len)`, even if you immediately convert
+ /// to a pointer. And it's UB to call `.get_unchecked_mut(..len + 1)`,
+ /// `.get_unchecked_mut(..=len)`, or similar.
+ ///
/// [`get_mut`]: slice::get_mut
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
///
@@ -730,7 +740,7 @@ impl<T> [T] {
/// [`as_mut_ptr`]: slice::as_mut_ptr
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
#[inline(always)]
#[must_use]
pub const fn as_ptr(&self) -> *const T {
@@ -761,7 +771,7 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
#[rustc_allow_const_fn_unstable(const_mut_refs)]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
#[inline(always)]
#[must_use]
pub const fn as_mut_ptr(&mut self) -> *mut T {
@@ -2482,6 +2492,62 @@ impl<T> [T] {
RSplitNMut::new(self.rsplit_mut(pred), n)
}
+ /// Splits the slice on the first element that matches the specified
+ /// predicate.
+ ///
+ /// If any matching elements are resent in the slice, returns the prefix
+ /// before the match and suffix after. The matching element itself is not
+ /// included. If no elements match, returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_split_once)]
+ /// let s = [1, 2, 3, 2, 4];
+ /// assert_eq!(s.split_once(|&x| x == 2), Some((
+ /// &[1][..],
+ /// &[3, 2, 4][..]
+ /// )));
+ /// assert_eq!(s.split_once(|&x| x == 0), None);
+ /// ```
+ #[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")]
+ #[inline]
+ pub fn split_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
+ where
+ F: FnMut(&T) -> bool,
+ {
+ let index = self.iter().position(pred)?;
+ Some((&self[..index], &self[index + 1..]))
+ }
+
+ /// Splits the slice on the last element that matches the specified
+ /// predicate.
+ ///
+ /// If any matching elements are resent in the slice, returns the prefix
+ /// before the match and suffix after. The matching element itself is not
+ /// included. If no elements match, returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_split_once)]
+ /// let s = [1, 2, 3, 2, 4];
+ /// assert_eq!(s.rsplit_once(|&x| x == 2), Some((
+ /// &[1, 2, 3][..],
+ /// &[4][..]
+ /// )));
+ /// assert_eq!(s.rsplit_once(|&x| x == 0), None);
+ /// ```
+ #[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")]
+ #[inline]
+ pub fn rsplit_once<F>(&self, pred: F) -> Option<(&[T], &[T])>
+ where
+ F: FnMut(&T) -> bool,
+ {
+ let index = self.iter().rposition(pred)?;
+ Some((&self[..index], &self[index + 1..]))
+ }
+
/// Returns `true` if the slice contains an element with the given value.
///
/// This operation is *O*(*n*).
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 48a6eb03b..9cdf9b68a 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -90,6 +90,7 @@ use crate::ptr;
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_from_raw_parts", since = "1.64.0")]
#[must_use]
+#[rustc_diagnostic_item = "slice_from_raw_parts"]
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
unsafe {
@@ -136,6 +137,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts_mut", issue = "67456")]
#[must_use]
+#[rustc_diagnostic_item = "slice_from_raw_parts_mut"]
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
unsafe {
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index db76d2625..993a608f4 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -628,9 +628,14 @@ where
let _pivot_guard = InsertionHole { src: &*tmp, dest: pivot };
let pivot = &*tmp;
+ let len = v.len();
+ if len == 0 {
+ return 0;
+ }
+
// Now partition the slice.
let mut l = 0;
- let mut r = v.len();
+ let mut r = len;
loop {
// SAFETY: The unsafety below involves indexing an array.
// For the first one: We already do the bounds checking here with `l < r`.
@@ -643,8 +648,11 @@ where
}
// Find the last element equal to the pivot.
- while l < r && is_less(pivot, v.get_unchecked(r - 1)) {
+ loop {
r -= 1;
+ if l >= r || !is_less(pivot, v.get_unchecked(r)) {
+ break;
+ }
}
// Are we done?
@@ -653,7 +661,6 @@ where
}
// Swap the found pair of out-of-order elements.
- r -= 1;
let ptr = v.as_mut_ptr();
ptr::swap(ptr.add(l), ptr.add(r));
l += 1;
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index cd16810c4..c30f01b3c 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1360,7 +1360,7 @@ impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> {
}
#[stable(feature = "split_inclusive", since = "1.51.0")]
-impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
+impl<'a, P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>> DoubleEndedIterator
for SplitInclusive<'a, P>
{
#[inline]
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index dfa2d4fd5..27178328b 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -81,6 +81,7 @@ use iter::{MatchesInternal, SplitNInternal};
#[cold]
#[track_caller]
#[rustc_allow_const_fn_unstable(const_eval_select)]
+#[cfg(not(feature = "panic_immediate_abort"))]
const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
// SAFETY: panics for both branches
unsafe {
@@ -92,6 +93,11 @@ const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
}
}
+#[cfg(feature = "panic_immediate_abort")]
+const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
+ slice_error_fail_ct(s, begin, end)
+}
+
#[track_caller]
const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! {
panic!("failed to slice string");
@@ -386,7 +392,7 @@ impl str {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
#[must_use]
#[inline(always)]
pub const fn as_ptr(&self) -> *const u8 {
@@ -402,7 +408,7 @@ impl str {
/// It is your responsibility to make sure that the string slice only gets
/// modified in a way that it remains valid UTF-8.
#[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
#[must_use]
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
@@ -808,7 +814,7 @@ impl str {
/// assert_eq!(Some((0, 'y')), char_indices.next()); // not (0, 'y̆')
/// assert_eq!(Some((1, '\u{0306}')), char_indices.next());
///
- /// // note the 3 here - the last character took up two bytes
+ /// // note the 3 here - the previous character took up two bytes
/// assert_eq!(Some((3, 'e')), char_indices.next());
/// assert_eq!(Some((4, 's')), char_indices.next());
///
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index d5d6d60ac..701e61e66 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -806,6 +806,8 @@ unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N>
searcher_methods!(reverse);
}
+impl<'a, const N: usize> DoubleEndedSearcher<'a> for CharArraySearcher<'a, N> {}
+
/// Searches for chars that are equal to any of the [`char`]s in the array.
///
/// # Examples
@@ -826,6 +828,8 @@ unsafe impl<'a, 'b, const N: usize> ReverseSearcher<'a> for CharArrayRefSearcher
searcher_methods!(reverse);
}
+impl<'a, 'b, const N: usize> DoubleEndedSearcher<'a> for CharArrayRefSearcher<'a, 'b, N> {}
+
/////////////////////////////////////////////////////////////////////////////
// Impl for &[char]
/////////////////////////////////////////////////////////////////////////////
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 2b37af66b..16fb1dad7 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -624,6 +624,7 @@ pub trait FromStr: Sized {
/// assert_eq!(5, x);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_diagnostic_item = "from_str_method"]
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index cf1fbe2d3..5f1f41e68 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -4,26 +4,12 @@
//! threads, and are the building blocks of other concurrent
//! types.
//!
-//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`.
-//! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating
-//! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference
-//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not*
-//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.)
-//!
//! This module defines atomic versions of a select number of primitive
//! types, including [`AtomicBool`], [`AtomicIsize`], [`AtomicUsize`],
//! [`AtomicI8`], [`AtomicU16`], etc.
//! Atomic types present operations that, when used correctly, synchronize
//! updates between threads.
//!
-//! Each method takes an [`Ordering`] which represents the strength of
-//! the memory barrier for that operation. These orderings are the
-//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2].
-//!
-//! [cpp]: https://en.cppreference.com/w/cpp/atomic
-//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order
-//! [2]: ../../../nomicon/atomics.html
-//!
//! Atomic variables are safe to share between threads (they implement [`Sync`])
//! but they do not themselves provide the mechanism for sharing and follow the
//! [threading model](../../../std/thread/index.html#the-threading-model) of Rust.
@@ -36,6 +22,75 @@
//! the constant initializers like [`AtomicBool::new`]. Atomic statics
//! are often used for lazy global initialization.
//!
+//! ## Memory model for atomic accesses
+//!
+//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`.
+//! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating
+//! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference
+//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not*
+//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.)
+//!
+//! [cpp]: https://en.cppreference.com/w/cpp/atomic
+//!
+//! Each method takes an [`Ordering`] which represents the strength of
+//! the memory barrier for that operation. These orderings are the
+//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2].
+//!
+//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order
+//! [2]: ../../../nomicon/atomics.html
+//!
+//! Since C++ does not support mixing atomic and non-atomic accesses, or non-synchronized
+//! different-sized accesses to the same data, Rust does not support those operations either.
+//! Note that both of those restrictions only apply if the accesses are non-synchronized.
+//!
+//! ```rust,no_run undefined_behavior
+//! use std::sync::atomic::{AtomicU16, AtomicU8, Ordering};
+//! use std::mem::transmute;
+//! use std::thread;
+//!
+//! let atomic = AtomicU16::new(0);
+//!
+//! thread::scope(|s| {
+//! // This is UB: mixing atomic and non-atomic accesses
+//! s.spawn(|| atomic.store(1, Ordering::Relaxed));
+//! s.spawn(|| unsafe { atomic.as_ptr().write(2) });
+//! });
+//!
+//! thread::scope(|s| {
+//! // This is UB: even reads are not allowed to be mixed
+//! s.spawn(|| atomic.load(Ordering::Relaxed));
+//! s.spawn(|| unsafe { atomic.as_ptr().read() });
+//! });
+//!
+//! thread::scope(|s| {
+//! // This is fine, `join` synchronizes the code in a way such that atomic
+//! // and non-atomic accesses can't happen "at the same time"
+//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed));
+//! handle.join().unwrap();
+//! s.spawn(|| unsafe { atomic.as_ptr().write(2) });
+//! });
+//!
+//! thread::scope(|s| {
+//! // This is UB: using different-sized atomic accesses to the same data
+//! s.spawn(|| atomic.store(1, Ordering::Relaxed));
+//! s.spawn(|| unsafe {
+//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic);
+//! differently_sized.store(2, Ordering::Relaxed);
+//! });
+//! });
+//!
+//! thread::scope(|s| {
+//! // This is fine, `join` synchronizes the code in a way such that
+//! // differently-sized accesses can't happen "at the same time"
+//! let handle = s.spawn(|| atomic.store(1, Ordering::Relaxed));
+//! handle.join().unwrap();
+//! s.spawn(|| unsafe {
+//! let differently_sized = transmute::<&AtomicU16, &AtomicU8>(&atomic);
+//! differently_sized.store(2, Ordering::Relaxed);
+//! });
+//! });
+//! ```
+//!
//! # Portability
//!
//! All atomic types in this module are guaranteed to be [lock-free] if they're
@@ -79,6 +134,40 @@
//!
//! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm
//!
+//! # Atomic accesses to read-only memory
+//!
+//! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting
+//! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only
+//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since
+//! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault
+//! on read-only memory.
+//!
+//! For the purpose of this section, "read-only memory" is defined as memory that is read-only in
+//! the underlying target, i.e., the pages are mapped with a read-only flag and any attempt to write
+//! will cause a page fault. In particular, an `&u128` reference that points to memory that is
+//! read-write mapped is *not* considered to point to "read-only memory". In Rust, almost all memory
+//! is read-write; the only exceptions are memory created by `const` items or `static` items without
+//! interior mutability, and memory that was specifically marked as read-only by the operating
+//! system via platform-specific APIs.
+//!
+//! As an exception from the general rule stated above, "sufficiently small" atomic loads with
+//! `Ordering::Relaxed` are implemented in a way that works on read-only memory, and are hence not
+//! Undefined Behavior. The exact size limit for what makes a load "sufficiently small" varies
+//! depending on the target:
+//!
+//! | `target_arch` | Size limit |
+//! |---------------|---------|
+//! | `x86`, `arm`, `mips`, `mips32r6`, `powerpc`, `riscv32`, `sparc`, `hexagon` | 4 bytes |
+//! | `x86_64`, `aarch64`, `loongarch64`, `mips64`, `mips64r6`, `powerpc64`, `riscv64`, `sparc64`, `s390x` | 8 bytes |
+//!
+//! Atomics loads that are larger than this limit as well as atomic loads with ordering other
+//! than `Relaxed`, as well as *all* atomic loads on targets not listed in the table, might still be
+//! read-only under certain conditions, but that is not a stable guarantee and should not be relied
+//! upon.
+//!
+//! If you need to do an acquire load on read-only memory, you can do a relaxed load followed by an
+//! acquire fence instead.
+//!
//! # Examples
//!
//! A simple spinlock:
@@ -319,7 +408,7 @@ impl AtomicBool {
/// # Examples
///
/// ```
- /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+ /// #![feature(pointer_is_aligned)]
/// use std::sync::atomic::{self, AtomicBool};
/// use std::mem::align_of;
///
@@ -346,13 +435,17 @@ impl AtomicBool {
///
/// # Safety
///
- /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
+ /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can
+ /// be bigger than `align_of::<bool>()`).
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
- /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+ /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
+ /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
+ /// without synchronization.
///
/// [valid]: crate::ptr#safety
- #[unstable(feature = "atomic_from_ptr", issue = "108652")]
- #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+ /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+ #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
+ #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")]
pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
// SAFETY: guaranteed by the caller
unsafe { &*ptr.cast() }
@@ -1018,7 +1111,7 @@ impl AtomicBool {
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut bool {
self.v.get().cast()
}
@@ -1113,7 +1206,7 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
- /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+ /// #![feature(pointer_is_aligned)]
/// use std::sync::atomic::{self, AtomicPtr};
/// use std::mem::align_of;
///
@@ -1140,13 +1233,17 @@ impl<T> AtomicPtr<T> {
///
/// # Safety
///
- /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this can be bigger than `align_of::<*mut T>()`).
+ /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
+ /// can be bigger than `align_of::<*mut T>()`).
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
- /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+ /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
+ /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
+ /// without synchronization.
///
/// [valid]: crate::ptr#safety
- #[unstable(feature = "atomic_from_ptr", issue = "108652")]
- #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+ /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+ #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
+ #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")]
pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
// SAFETY: guaranteed by the caller
unsafe { &*ptr.cast() }
@@ -1954,7 +2051,7 @@ impl<T> AtomicPtr<T> {
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut *mut T {
self.p.get()
}
@@ -2083,7 +2180,7 @@ macro_rules! atomic_int {
/// # Examples
///
/// ```
- /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+ /// #![feature(pointer_is_aligned)]
#[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")]
/// use std::mem::align_of;
///
@@ -2111,14 +2208,18 @@ macro_rules! atomic_int {
///
/// # Safety
///
- /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
- #[doc = concat!(" * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`).")]
+ #[doc = concat!(" * `ptr` must be aligned to \
+ `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this \
+ can be bigger than `align_of::<", stringify!($int_type), ">()`).")]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
- /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+ /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
+ /// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
+ /// without synchronization.
///
/// [valid]: crate::ptr#safety
- #[unstable(feature = "atomic_from_ptr", issue = "108652")]
- #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+ /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
+ #[stable(feature = "atomic_from_ptr", since = "1.75.0")]
+ #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")]
pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
// SAFETY: guaranteed by the caller
unsafe { &*ptr.cast() }
@@ -2893,7 +2994,7 @@ macro_rules! atomic_int {
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
- #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
+ #[rustc_never_returns_null_ptr]
pub const fn as_ptr(&self) -> *mut $int_type {
self.v.get()
}
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index ff538d55c..fa02dd52e 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -3,7 +3,7 @@
use core::fmt;
use core::future::Future;
use core::marker::Tuple;
-use core::ops::{Generator, GeneratorState};
+use core::ops::{Coroutine, CoroutineState};
use core::pin::Pin;
use core::task::{Context, Poll};
@@ -206,16 +206,16 @@ where
}
}
-#[unstable(feature = "generator_trait", issue = "43122")] // also #98407
-impl<R, G> Generator<R> for Exclusive<G>
+#[unstable(feature = "coroutine_trait", issue = "43122")] // also #98407
+impl<R, G> Coroutine<R> for Exclusive<G>
where
- G: Generator<R> + ?Sized,
+ G: Coroutine<R> + ?Sized,
{
type Yield = G::Yield;
type Return = G::Return;
#[inline]
- fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+ fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> {
G::resume(self.get_pin_mut(), arg)
}
}
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index b63fd5c90..817e39942 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -231,6 +231,10 @@ impl fmt::Debug for Context<'_> {
/// this might be done to wake a future when a blocking function call completes on another
/// thread.
///
+/// Note that it is preferable to use `waker.clone_from(&new_waker)` instead
+/// of `*waker = new_waker.clone()`, as the former will avoid cloning the waker
+/// unnecessarily if the two wakers [wake the same task](Self::will_wake).
+///
/// [`Future::poll()`]: core::future::Future::poll
/// [`Poll::Pending`]: core::task::Poll::Pending
#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
@@ -302,7 +306,9 @@ impl Waker {
/// when the `Waker`s would awaken the same task. However, if this function
/// returns `true`, it is guaranteed that the `Waker`s will awaken the same task.
///
- /// This function is primarily used for optimization purposes.
+ /// This function is primarily used for optimization purposes — for example,
+ /// this type's [`clone_from`](Self::clone_from) implementation uses it to
+ /// avoid cloning the waker when they would wake the same task anyway.
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
@@ -382,6 +388,13 @@ impl Clone for Waker {
waker: unsafe { (self.waker.vtable.clone)(self.waker.data) },
}
}
+
+ #[inline]
+ fn clone_from(&mut self, source: &Self) {
+ if !self.will_wake(source) {
+ *self = source.clone();
+ }
+ }
}
#[stable(feature = "futures_api", since = "1.36.0")]
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 1e8d28979..6ef35d841 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -910,6 +910,7 @@ impl Duration {
impl Add for Duration {
type Output = Duration;
+ #[inline]
fn add(self, rhs: Duration) -> Duration {
self.checked_add(rhs).expect("overflow when adding durations")
}
@@ -917,6 +918,7 @@ impl Add for Duration {
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
impl AddAssign for Duration {
+ #[inline]
fn add_assign(&mut self, rhs: Duration) {
*self = *self + rhs;
}
@@ -926,6 +928,7 @@ impl AddAssign for Duration {
impl Sub for Duration {
type Output = Duration;
+ #[inline]
fn sub(self, rhs: Duration) -> Duration {
self.checked_sub(rhs).expect("overflow when subtracting durations")
}
@@ -933,6 +936,7 @@ impl Sub for Duration {
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
impl SubAssign for Duration {
+ #[inline]
fn sub_assign(&mut self, rhs: Duration) {
*self = *self - rhs;
}
@@ -942,6 +946,7 @@ impl SubAssign for Duration {
impl Mul<u32> for Duration {
type Output = Duration;
+ #[inline]
fn mul(self, rhs: u32) -> Duration {
self.checked_mul(rhs).expect("overflow when multiplying duration by scalar")
}
@@ -951,6 +956,7 @@ impl Mul<u32> for Duration {
impl Mul<Duration> for u32 {
type Output = Duration;
+ #[inline]
fn mul(self, rhs: Duration) -> Duration {
rhs * self
}
@@ -958,6 +964,7 @@ impl Mul<Duration> for u32 {
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
impl MulAssign<u32> for Duration {
+ #[inline]
fn mul_assign(&mut self, rhs: u32) {
*self = *self * rhs;
}
@@ -967,6 +974,7 @@ impl MulAssign<u32> for Duration {
impl Div<u32> for Duration {
type Output = Duration;
+ #[inline]
fn div(self, rhs: u32) -> Duration {
self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar")
}
@@ -974,6 +982,7 @@ impl Div<u32> for Duration {
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
impl DivAssign<u32> for Duration {
+ #[inline]
fn div_assign(&mut self, rhs: u32) {
*self = *self / rhs;
}