Importing rustc-1.53.0
Bug: 194400612
Change-Id: Id2f38eeabc8325fff960e46b89b1cc7216f5227c
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 8b95b70..0e7667d 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -93,7 +93,7 @@
/// This function is unsafe as it does not verify the preconditions from
/// [`Layout::from_size_align`].
#[stable(feature = "alloc_layout", since = "1.28.0")]
- #[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")]
+ #[rustc_const_stable(feature = "alloc_layout", since = "1.36.0")]
#[inline]
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
// SAFETY: the caller must ensure that `align` is greater than zero.
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 98c34f3..5e1725c 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -141,7 +141,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for dyn Any {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("Any")
+ f.debug_struct("Any").finish_non_exhaustive()
}
}
@@ -151,14 +151,14 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for dyn Any + Send {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("Any")
+ f.debug_struct("Any").finish_non_exhaustive()
}
}
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
impl fmt::Debug for dyn Any + Send + Sync {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("Any")
+ f.debug_struct("Any").finish_non_exhaustive()
}
}
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 4472fba..61ab1b1 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -2,7 +2,7 @@
use crate::{
fmt,
- iter::{ExactSizeIterator, FusedIterator, TrustedLen},
+ iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
mem::{self, MaybeUninit},
ops::Range,
ptr,
@@ -192,7 +192,7 @@
let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 };
// Clone all alive elements.
- for (src, dst) in self.as_slice().iter().zip(&mut new.data) {
+ for (src, dst) in iter::zip(self.as_slice(), &mut new.data) {
// Write a clone into the new array, then update its alive range.
// If cloning panics, we'll correctly drop the previous items.
dst.write(src.clone());
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 8f52985..8b56c95 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -12,7 +12,6 @@
use crate::fmt;
use crate::hash::{self, Hash};
use crate::iter::TrustedLen;
-use crate::marker::Unsize;
use crate::mem::{self, MaybeUninit};
use crate::ops::{Index, IndexMut};
use crate::slice::{Iter, IterMut};
@@ -23,54 +22,19 @@
pub use iter::IntoIter;
/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
-#[unstable(feature = "array_from_ref", issue = "77101")]
+#[stable(feature = "array_from_ref", since = "1.53.0")]
pub fn from_ref<T>(s: &T) -> &[T; 1] {
// SAFETY: Converting `&T` to `&[T; 1]` is sound.
unsafe { &*(s as *const T).cast::<[T; 1]>() }
}
/// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying).
-#[unstable(feature = "array_from_ref", issue = "77101")]
+#[stable(feature = "array_from_ref", since = "1.53.0")]
pub fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
// SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound.
unsafe { &mut *(s as *mut T).cast::<[T; 1]>() }
}
-/// Utility trait implemented only on arrays of fixed size
-///
-/// This trait can be used to implement other traits on fixed-size arrays
-/// without causing much metadata bloat.
-///
-/// The trait is marked unsafe in order to restrict implementors to fixed-size
-/// arrays. A user of this trait can assume that implementors have the exact
-/// layout in memory of a fixed size array (for example, for unsafe
-/// initialization).
-///
-/// Note that the traits [`AsRef`] and [`AsMut`] provide similar methods for types that
-/// may not be fixed-size arrays. Implementors should prefer those traits
-/// instead.
-#[unstable(feature = "fixed_size_array", issue = "27778")]
-pub unsafe trait FixedSizeArray<T> {
- /// Converts the array to immutable slice
- #[unstable(feature = "fixed_size_array", issue = "27778")]
- fn as_slice(&self) -> &[T];
- /// Converts the array to mutable slice
- #[unstable(feature = "fixed_size_array", issue = "27778")]
- fn as_mut_slice(&mut self) -> &mut [T];
-}
-
-#[unstable(feature = "fixed_size_array", issue = "27778")]
-unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
- #[inline]
- fn as_slice(&self) -> &[T] {
- self
- }
- #[inline]
- fn as_mut_slice(&mut self) -> &mut [T] {
- self
- }
-}
-
/// The error type returned when a conversion from a slice to an array fails.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Debug, Copy, Clone)]
@@ -191,6 +155,28 @@
}
}
+// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator`
+// hides this implementation from explicit `.into_iter()` calls on editions < 2021,
+// so those calls will still resolve to the slice implementation, by reference.
+#[cfg(not(bootstrap))]
+#[stable(feature = "array_into_iter_impl", since = "1.53.0")]
+impl<T, const N: usize> IntoIterator for [T; N] {
+ type Item = T;
+ type IntoIter = IntoIter<T, N>;
+
+ /// Creates a consuming iterator, that is, one that moves each value out of
+ /// the array (from start to end). The array cannot be used after calling
+ /// this unless `T` implements `Copy`, so the whole array is copied.
+ ///
+ /// Arrays have special behavior when calling `.into_iter()` prior to the
+ /// 2021 edition -- see the [array] Editions section for more information.
+ ///
+ /// [array]: prim@array
+ fn into_iter(self) -> Self::IntoIter {
+ IntoIter::new(self)
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
type Item = &'a T;
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index a8a25f9..4780d8d 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -145,6 +145,6 @@
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("EscapeDefault { .. }")
+ f.debug_struct("EscapeDefault").finish_non_exhaustive()
}
}
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 2fbbeb3..4820588 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -188,7 +188,7 @@
//! [`Rc<T>`]: ../../std/rc/struct.Rc.html
//! [`RwLock<T>`]: ../../std/sync/struct.RwLock.html
//! [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
-//! [`atomic`]: ../../core/sync/atomic/index.html
+//! [`atomic`]: crate::sync::atomic
#![stable(feature = "rust1", since = "1.0.0")]
@@ -325,7 +325,7 @@
/// let c = Cell::new(5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_cell_new", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_cell_new", since = "1.24.0")]
#[inline]
pub const fn new(value: T) -> Cell<T> {
Cell { value: UnsafeCell::new(value) }
@@ -575,6 +575,12 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RefCell<T: ?Sized> {
borrow: Cell<BorrowFlag>,
+ // Stores the location of the earliest currently active borrow.
+ // This gets updated whenver we go from having zero borrows
+ // to having a single borrow. When a borrow occurs, this gets included
+ // in the generated `BorroeError/`BorrowMutError`
+ #[cfg(feature = "debug_refcell")]
+ borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
value: UnsafeCell<T>,
}
@@ -582,12 +588,19 @@
#[stable(feature = "try_borrow", since = "1.13.0")]
pub struct BorrowError {
_private: (),
+ #[cfg(feature = "debug_refcell")]
+ location: &'static crate::panic::Location<'static>,
}
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Debug for BorrowError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("BorrowError").finish()
+ let mut builder = f.debug_struct("BorrowError");
+
+ #[cfg(feature = "debug_refcell")]
+ builder.field("location", self.location);
+
+ builder.finish()
}
}
@@ -602,12 +615,19 @@
#[stable(feature = "try_borrow", since = "1.13.0")]
pub struct BorrowMutError {
_private: (),
+ #[cfg(feature = "debug_refcell")]
+ location: &'static crate::panic::Location<'static>,
}
#[stable(feature = "try_borrow", since = "1.13.0")]
impl Debug for BorrowMutError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("BorrowMutError").finish()
+ let mut builder = f.debug_struct("BorrowMutError");
+
+ #[cfg(feature = "debug_refcell")]
+ builder.field("location", self.location);
+
+ builder.finish()
}
}
@@ -655,10 +675,15 @@
/// let c = RefCell::new(5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_refcell_new", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_refcell_new", since = "1.24.0")]
#[inline]
pub const fn new(value: T) -> RefCell<T> {
- RefCell { value: UnsafeCell::new(value), borrow: Cell::new(UNUSED) }
+ RefCell {
+ value: UnsafeCell::new(value),
+ borrow: Cell::new(UNUSED),
+ #[cfg(feature = "debug_refcell")]
+ borrowed_at: Cell::new(None),
+ }
}
/// Consumes the `RefCell`, returning the wrapped value.
@@ -823,12 +848,29 @@
/// ```
#[stable(feature = "try_borrow", since = "1.13.0")]
#[inline]
+ #[cfg_attr(feature = "debug_refcell", track_caller)]
pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
match BorrowRef::new(&self.borrow) {
- // SAFETY: `BorrowRef` ensures that there is only immutable access
- // to the value while borrowed.
- Some(b) => Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }),
- None => Err(BorrowError { _private: () }),
+ Some(b) => {
+ #[cfg(feature = "debug_refcell")]
+ {
+ // `borrowed_at` is always the *first* active borrow
+ if b.borrow.get() == 1 {
+ self.borrowed_at.set(Some(crate::panic::Location::caller()));
+ }
+ }
+
+ // SAFETY: `BorrowRef` ensures that there is only immutable access
+ // to the value while borrowed.
+ Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b })
+ }
+ None => Err(BorrowError {
+ _private: (),
+ // If a borrow occured, then we must already have an outstanding borrow,
+ // so `borrowed_at` will be `Some`
+ #[cfg(feature = "debug_refcell")]
+ location: self.borrowed_at.get().unwrap(),
+ }),
}
}
@@ -896,11 +938,25 @@
/// ```
#[stable(feature = "try_borrow", since = "1.13.0")]
#[inline]
+ #[cfg_attr(feature = "debug_refcell", track_caller)]
pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
match BorrowRefMut::new(&self.borrow) {
- // SAFETY: `BorrowRef` guarantees unique access.
- Some(b) => Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }),
- None => Err(BorrowMutError { _private: () }),
+ Some(b) => {
+ #[cfg(feature = "debug_refcell")]
+ {
+ self.borrowed_at.set(Some(crate::panic::Location::caller()));
+ }
+
+ // SAFETY: `BorrowRef` guarantees unique access.
+ Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b })
+ }
+ None => Err(BorrowMutError {
+ _private: (),
+ // If a borrow occured, then we must already have an outstanding borrow,
+ // so `borrowed_at` will be `Some`
+ #[cfg(feature = "debug_refcell")]
+ location: self.borrowed_at.get().unwrap(),
+ }),
}
}
@@ -1016,7 +1072,13 @@
// and is thus guaranteed to be valid for the lifetime of `self`.
Ok(unsafe { &*self.value.get() })
} else {
- Err(BorrowError { _private: () })
+ Err(BorrowError {
+ _private: (),
+ // If a borrow occured, then we must already have an outstanding borrow,
+ // so `borrowed_at` will be `Some`
+ #[cfg(feature = "debug_refcell")]
+ location: self.borrowed_at.get().unwrap(),
+ })
}
}
}
@@ -1753,7 +1815,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_unsafe_cell_new", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn new(value: T) -> UnsafeCell<T> {
UnsafeCell { value }
}
@@ -1769,7 +1831,7 @@
///
/// let five = uc.into_inner();
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
pub const fn into_inner(self) -> T {
@@ -1794,7 +1856,7 @@
///
/// let five = uc.get();
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")]
pub const fn get(&self) -> *mut T {
@@ -1819,7 +1881,7 @@
///
/// assert_eq!(*c.get_mut(), 6);
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")]
pub fn get_mut(&mut self) -> &mut T {
&mut self.value
@@ -1852,7 +1914,7 @@
///
/// assert_eq!(uc.into_inner(), 5);
/// ```
- #[inline]
+ #[inline(always)]
#[unstable(feature = "unsafe_cell_raw_get", issue = "66358")]
pub const fn raw_get(this: *const Self) -> *mut T {
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 87a3d37..dcab2cd 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -403,16 +403,20 @@
}
/// An extended version of `escape_debug` that optionally permits escaping
- /// Extended Grapheme codepoints. This allows us to format characters like
- /// nonspacing marks better when they're at the start of a string.
+ /// Extended Grapheme codepoints, single quotes, and double quotes. This
+ /// allows us to format characters like nonspacing marks better when they're
+ /// at the start of a string, and allows escaping single quotes in
+ /// characters, and double quotes in strings.
#[inline]
- pub(crate) fn escape_debug_ext(self, escape_grapheme_extended: bool) -> EscapeDebug {
+ pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
let init_state = match self {
'\t' => EscapeDefaultState::Backslash('t'),
'\r' => EscapeDefaultState::Backslash('r'),
'\n' => EscapeDefaultState::Backslash('n'),
- '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
- _ if escape_grapheme_extended && self.is_grapheme_extended() => {
+ '\\' => EscapeDefaultState::Backslash(self),
+ '"' if args.escape_double_quote => EscapeDefaultState::Backslash(self),
+ '\'' if args.escape_single_quote => EscapeDefaultState::Backslash(self),
+ _ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
EscapeDefaultState::Unicode(self.escape_unicode())
}
_ if is_printable(self) => EscapeDefaultState::Char(self),
@@ -458,7 +462,7 @@
#[stable(feature = "char_escape_debug", since = "1.20.0")]
#[inline]
pub fn escape_debug(self) -> EscapeDebug {
- self.escape_debug_ext(true)
+ self.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)
}
/// Returns an iterator that yields the literal escape code of a character
@@ -1565,6 +1569,25 @@
}
}
+pub(crate) struct EscapeDebugExtArgs {
+ /// Escape Extended Grapheme codepoints?
+ pub(crate) escape_grapheme_extended: bool,
+
+ /// Escape single quotes?
+ pub(crate) escape_single_quote: bool,
+
+ /// Escape double quotes?
+ pub(crate) escape_double_quote: bool,
+}
+
+impl EscapeDebugExtArgs {
+ pub(crate) const ESCAPE_ALL: Self = Self {
+ escape_grapheme_extended: true,
+ escape_single_quote: true,
+ escape_double_quote: true,
+ };
+}
+
#[inline]
const fn len_utf8(code: u32) -> usize {
if code < MAX_ONE_B {
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 788fafa..25a7c1d 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -45,6 +45,8 @@
use crate::fmt::{self, Write};
use crate::iter::FusedIterator;
+pub(crate) use self::methods::EscapeDebugExtArgs;
+
// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 5bab1fb..f8b16b6 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -274,6 +274,7 @@
//
// This should never be implemented by hand.
#[doc(hidden)]
+ #[cfg_attr(not(bootstrap), no_coverage)] // rust-lang/rust#84605
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn assert_receiver_is_total_eq(&self) {}
@@ -282,7 +283,7 @@
/// Derive macro generating an impl of the trait `Eq`.
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
+#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match, no_coverage)]
pub macro Eq($item:item) {
/* compiler built-in */
}
@@ -334,7 +335,6 @@
/// # Examples
///
/// ```
- /// #![feature(ordering_helpers)]
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_eq(), false);
@@ -343,7 +343,8 @@
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "ordering_helpers", issue = "79885")]
+ #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
+ #[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_eq(self) -> bool {
matches!(self, Equal)
}
@@ -353,7 +354,6 @@
/// # Examples
///
/// ```
- /// #![feature(ordering_helpers)]
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_ne(), true);
@@ -362,7 +362,8 @@
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "ordering_helpers", issue = "79885")]
+ #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
+ #[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_ne(self) -> bool {
!matches!(self, Equal)
}
@@ -372,7 +373,6 @@
/// # Examples
///
/// ```
- /// #![feature(ordering_helpers)]
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_lt(), true);
@@ -381,7 +381,8 @@
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "ordering_helpers", issue = "79885")]
+ #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
+ #[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_lt(self) -> bool {
matches!(self, Less)
}
@@ -391,7 +392,6 @@
/// # Examples
///
/// ```
- /// #![feature(ordering_helpers)]
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_gt(), false);
@@ -400,7 +400,8 @@
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "ordering_helpers", issue = "79885")]
+ #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
+ #[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_gt(self) -> bool {
matches!(self, Greater)
}
@@ -410,7 +411,6 @@
/// # Examples
///
/// ```
- /// #![feature(ordering_helpers)]
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_le(), true);
@@ -419,7 +419,8 @@
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "ordering_helpers", issue = "79885")]
+ #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
+ #[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_le(self) -> bool {
!matches!(self, Greater)
}
@@ -429,7 +430,6 @@
/// # Examples
///
/// ```
- /// #![feature(ordering_helpers)]
/// use std::cmp::Ordering;
///
/// assert_eq!(Ordering::Less.is_ge(), false);
@@ -438,7 +438,8 @@
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "ordering_helpers", issue = "79885")]
+ #[rustc_const_stable(feature = "ordering_helpers", since = "1.53.0")]
+ #[stable(feature = "ordering_helpers", since = "1.53.0")]
pub const fn is_ge(self) -> bool {
!matches!(self, Less)
}
@@ -981,7 +982,11 @@
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
fn le(&self, other: &Rhs) -> bool {
- matches!(self.partial_cmp(other), Some(Less | Equal))
+ // Pattern `Some(Less | Eq)` optimizes worse than negating `None | Some(Greater)`.
+ // FIXME: The root cause was fixed upstream in LLVM with:
+ // https://github.com/llvm/llvm-project/commit/9bad7de9a3fb844f1ca2965f35d0c2a3d1e11775
+ // Revert this workaround once support for LLVM 12 gets dropped.
+ !matches!(self.partial_cmp(other), None | Some(Greater))
}
/// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
@@ -1058,8 +1063,6 @@
/// # Examples
///
/// ```
-/// #![feature(cmp_min_max_by)]
-///
/// use std::cmp;
///
/// assert_eq!(cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 1);
@@ -1067,7 +1070,7 @@
/// ```
#[inline]
#[must_use]
-#[unstable(feature = "cmp_min_max_by", issue = "64460")]
+#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
@@ -1082,8 +1085,6 @@
/// # Examples
///
/// ```
-/// #![feature(cmp_min_max_by)]
-///
/// use std::cmp;
///
/// assert_eq!(cmp::min_by_key(-2, 1, |x: &i32| x.abs()), 1);
@@ -1091,7 +1092,7 @@
/// ```
#[inline]
#[must_use]
-#[unstable(feature = "cmp_min_max_by", issue = "64460")]
+#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
@@ -1124,8 +1125,6 @@
/// # Examples
///
/// ```
-/// #![feature(cmp_min_max_by)]
-///
/// use std::cmp;
///
/// assert_eq!(cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2);
@@ -1133,7 +1132,7 @@
/// ```
#[inline]
#[must_use]
-#[unstable(feature = "cmp_min_max_by", issue = "64460")]
+#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
@@ -1148,8 +1147,6 @@
/// # Examples
///
/// ```
-/// #![feature(cmp_min_max_by)]
-///
/// use std::cmp;
///
/// assert_eq!(cmp::max_by_key(-2, 1, |x: &i32| x.abs()), -2);
@@ -1157,7 +1154,7 @@
/// ```
#[inline]
#[must_use]
-#[unstable(feature = "cmp_min_max_by", issue = "64460")]
+#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 5b11361..a522b7d 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -45,8 +45,10 @@
macro_rules! impl_from {
($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
#[$attr]
- #[doc = $doc]
impl From<$Small> for $Large {
+ // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+ // Rustdocs on functions do not.
+ #[doc = $doc]
#[inline]
fn from(small: $Small) -> Self {
small as Self
@@ -383,8 +385,10 @@
macro_rules! nzint_impl_from {
($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
#[$attr]
- #[doc = $doc]
impl From<$Small> for $Large {
+ // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+ // Rustdocs on functions do not.
+ #[doc = $doc]
#[inline]
fn from(small: $Small) -> Self {
// SAFETY: input type guarantees the value is non-zero
@@ -450,10 +454,12 @@
macro_rules! nzint_impl_try_from_int {
($Int: ty, $NonZeroInt: ty, #[$attr:meta], $doc: expr) => {
#[$attr]
- #[doc = $doc]
impl TryFrom<$Int> for $NonZeroInt {
type Error = TryFromIntError;
+ // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+ // Rustdocs on functions do not.
+ #[doc = $doc]
#[inline]
fn try_from(value: $Int) -> Result<Self, Self::Error> {
Self::new(value).ok_or(TryFromIntError(()))
@@ -489,10 +495,12 @@
macro_rules! nzint_impl_try_from_nzint {
($From:ty => $To:ty, $doc: expr) => {
#[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")]
- #[doc = $doc]
impl TryFrom<$From> for $To {
type Error = TryFromIntError;
+ // Rustdocs on the impl block show a "[+] show undocumented items" toggle.
+ // Rustdocs on functions do not.
+ #[doc = $doc]
#[inline]
fn try_from(value: $From) -> Result<Self, Self::Error> {
TryFrom::try_from(value.get()).map(|v| {
diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs
index 9302baa..b208ddd 100644
--- a/library/core/src/ffi.rs
+++ b/library/core/src/ffi.rs
@@ -53,7 +53,7 @@
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for c_void {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("c_void")
+ f.debug_struct("c_void").finish()
}
}
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index d95d43f..b660788 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -165,7 +165,6 @@
/// # Examples
///
/// ```
- /// # #![feature(debug_non_exhaustive)]
/// use std::fmt;
///
/// struct Bar {
@@ -186,31 +185,22 @@
/// "Bar { bar: 10, .. }",
/// );
/// ```
- #[unstable(feature = "debug_non_exhaustive", issue = "67364")]
+ #[stable(feature = "debug_non_exhaustive", since = "1.53.0")]
pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
self.result = self.result.and_then(|_| {
- // Draw non-exhaustive dots (`..`), and open brace if necessary (no fields).
- if self.is_pretty() {
- if !self.has_fields {
- self.fmt.write_str(" {\n")?;
- }
- let mut slot = None;
- let mut state = Default::default();
- let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
- writer.write_str("..\n")?;
- } else {
- if self.has_fields {
- self.fmt.write_str(", ..")?;
+ if self.has_fields {
+ if self.is_pretty() {
+ let mut slot = None;
+ let mut state = Default::default();
+ let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
+ writer.write_str("..\n")?;
+ self.fmt.write_str("}")
} else {
- self.fmt.write_str(" { ..")?;
+ self.fmt.write_str(", .. }")
}
- }
- if self.is_pretty() {
- self.fmt.write_str("}")?
} else {
- self.fmt.write_str(" }")?;
+ self.fmt.write_str(" { .. }")
}
- Ok(())
});
self.result
}
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 5908da4..ece3cde 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -54,21 +54,14 @@
}
// Common code of floating point Debug and Display.
-fn float_to_decimal_common<T>(
- fmt: &mut Formatter<'_>,
- num: &T,
- negative_zero: bool,
- min_precision: usize,
-) -> Result
+fn float_to_decimal_common<T>(fmt: &mut Formatter<'_>, num: &T, min_precision: usize) -> Result
where
T: flt2dec::DecodableFloat,
{
let force_sign = fmt.sign_plus();
- let sign = match (force_sign, negative_zero) {
- (false, false) => flt2dec::Sign::Minus,
- (false, true) => flt2dec::Sign::MinusRaw,
- (true, false) => flt2dec::Sign::MinusPlus,
- (true, true) => flt2dec::Sign::MinusPlusRaw,
+ let sign = match force_sign {
+ false => flt2dec::Sign::Minus,
+ true => flt2dec::Sign::MinusPlus,
};
if let Some(precision) = fmt.precision {
@@ -156,14 +149,14 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for $ty {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
- float_to_decimal_common(fmt, self, true, 1)
+ float_to_decimal_common(fmt, self, 1)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Display for $ty {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
- float_to_decimal_common(fmt, self, false, 0)
+ float_to_decimal_common(fmt, self, 0)
}
}
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 2df5e56..87042d9 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -3,6 +3,8 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
+use crate::char::EscapeDebugExtArgs;
+use crate::iter;
use crate::marker::PhantomData;
use crate::mem;
use crate::num::flt2dec;
@@ -1087,7 +1089,7 @@
match args.fmt {
None => {
// We can use default formatting parameters for all arguments.
- for (arg, piece) in args.args.iter().zip(args.pieces.iter()) {
+ for (arg, piece) in iter::zip(args.args, args.pieces) {
formatter.buf.write_str(*piece)?;
(arg.formatter)(arg.value, &mut formatter)?;
idx += 1;
@@ -1096,7 +1098,7 @@
Some(fmt) => {
// Every spec has a corresponding argument that is preceded by
// a string piece.
- for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
+ for (arg, piece) in iter::zip(fmt, args.pieces) {
formatter.buf.write_str(*piece)?;
// SAFETY: arg and args.args come from the same Arguments,
// which guarantees the indexes are always within bounds.
@@ -2054,7 +2056,11 @@
f.write_char('"')?;
let mut from = 0;
for (i, c) in self.char_indices() {
- let esc = c.escape_debug();
+ let esc = c.escape_debug_ext(EscapeDebugExtArgs {
+ escape_grapheme_extended: true,
+ escape_single_quote: false,
+ escape_double_quote: true,
+ });
// If char needs escaping, flush backlog so far and write, else skip
if esc.len() != 1 {
f.write_str(&self[from..i])?;
@@ -2080,7 +2086,11 @@
impl Debug for char {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.write_char('\'')?;
- for c in self.escape_debug() {
+ for c in self.escape_debug_ext(EscapeDebugExtArgs {
+ escape_grapheme_extended: true,
+ escape_single_quote: true,
+ escape_double_quote: false,
+ }) {
f.write_char(c)?
}
f.write_char('\'')
@@ -2210,7 +2220,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Debug for PhantomData<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
- f.pad("PhantomData")
+ f.debug_struct("PhantomData").finish()
}
}
@@ -2258,9 +2268,9 @@
}
#[stable(feature = "core_impl_debug", since = "1.9.0")]
-impl<T: ?Sized + Debug> Debug for UnsafeCell<T> {
+impl<T: ?Sized> Debug for UnsafeCell<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
- f.pad("UnsafeCell")
+ f.debug_struct("UnsafeCell").finish_non_exhaustive()
}
}
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index e9a99dd..cc4cf54 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -24,7 +24,8 @@
/// `.await` the value.
///
/// [`Waker`]: crate::task::Waker
-#[doc(spotlight)]
+#[cfg_attr(bootstrap, doc(spotlight))]
+#[cfg_attr(not(bootstrap), doc(notable_trait))]
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[stable(feature = "futures_api", since = "1.36.0")]
#[lang = "future_trait"]
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 7bfa58d..77d3a35 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -175,6 +175,21 @@
/// Feeds a slice of this type into the given [`Hasher`].
///
+ /// This method is meant as a convenience, but its implementation is
+ /// also explicitly left unspecified. It isn't guaranteed to be
+ /// equivalent to repeated calls of [`hash`] and implementations of
+ /// [`Hash`] should keep that in mind and call [`hash`] themselves
+ /// if the slice isn't treated as a whole unit in the [`PartialEq`]
+ /// implementation.
+ ///
+ /// For example, a [`VecDeque`] implementation might naïvely call
+ /// [`as_slices`] and then [`hash_slice`] on each slice, but this
+ /// is wrong since the two slices can change with a call to
+ /// [`make_contiguous`] without affecting the [`PartialEq`]
+ /// result. Since these slices aren't treated as singular
+ /// units, and instead part of a larger deque, this method cannot
+ /// be used.
+ ///
/// # Examples
///
/// ```
@@ -186,6 +201,12 @@
/// Hash::hash_slice(&numbers, &mut hasher);
/// println!("Hash is {:x}!", hasher.finish());
/// ```
+ ///
+ /// [`VecDeque`]: ../../std/collections/struct.VecDeque.html
+ /// [`as_slices`]: ../../std/collections/struct.VecDeque.html#method.as_slices
+ /// [`make_contiguous`]: ../../std/collections/struct.VecDeque.html#method.make_contiguous
+ /// [`hash`]: Hash::hash
+ /// [`hash_slice`]: Hash::hash_slice
#[stable(feature = "hash_slice", since = "1.3.0")]
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
where
@@ -221,6 +242,11 @@
/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher`
/// instances are used in conjunction with the [`Hash`] trait.
///
+/// This trait makes no assumptions about how the various `write_*` methods are
+/// defined and implementations of [`Hash`] should not assume that they work one
+/// way or another. You cannot assume, for example, that a [`write_u32`] call is
+/// equivalent to four calls of [`write_u8`].
+///
/// # Examples
///
/// ```
@@ -240,6 +266,7 @@
/// [`finish`]: Hasher::finish
/// [`write`]: Hasher::write
/// [`write_u8`]: Hasher::write_u8
+/// [`write_u32`]: Hasher::write_u32
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
/// Returns the hash value for the values written so far.
@@ -507,7 +534,7 @@
#[stable(since = "1.9.0", feature = "core_impl_debug")]
impl<H> fmt::Debug for BuildHasherDefault<H> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("BuildHasherDefault")
+ f.debug_struct("BuildHasherDefault").finish()
}
}
@@ -691,29 +718,9 @@
impl<T: ?Sized> Hash for *const T {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
- #[cfg(not(bootstrap))]
- {
- let (address, metadata) = self.to_raw_parts();
- state.write_usize(address as usize);
- metadata.hash(state);
- }
- #[cfg(bootstrap)]
- {
- if mem::size_of::<Self>() == mem::size_of::<usize>() {
- // Thin pointer
- state.write_usize(*self as *const () as usize);
- } else {
- // Fat pointer
- // SAFETY: we are accessing the memory occupied by `self`
- // which is guaranteed to be valid.
- // This assumes a fat pointer can be represented by a `(usize, usize)`,
- // which is safe to do in `std` because it is shipped and kept in sync
- // with the implementation of fat pointers in `rustc`.
- let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
- state.write_usize(a);
- state.write_usize(b);
- }
- }
+ let (address, metadata) = self.to_raw_parts();
+ state.write_usize(address as usize);
+ metadata.hash(state);
}
}
@@ -721,29 +728,9 @@
impl<T: ?Sized> Hash for *mut T {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
- #[cfg(not(bootstrap))]
- {
- let (address, metadata) = self.to_raw_parts();
- state.write_usize(address as usize);
- metadata.hash(state);
- }
- #[cfg(bootstrap)]
- {
- if mem::size_of::<Self>() == mem::size_of::<usize>() {
- // Thin pointer
- state.write_usize(*self as *const () as usize);
- } else {
- // Fat pointer
- // SAFETY: we are accessing the memory occupied by `self`
- // which is guaranteed to be valid.
- // This assumes a fat pointer can be represented by a `(usize, usize)`,
- // which is safe to do in `std` because it is shipped and kept in sync
- // with the implementation of fat pointers in `rustc`.
- let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
- state.write_usize(a);
- state.write_usize(b);
- }
- }
+ let (address, metadata) = self.to_raw_parts();
+ state.write_usize(address as usize);
+ metadata.hash(state);
}
}
}
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 3137295..f7aec73 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -154,7 +154,7 @@
/// [`std::convert::identity`]: crate::convert::identity
#[cfg_attr(not(miri), inline)]
#[cfg_attr(miri, inline(never))]
-#[unstable(feature = "test", issue = "50297")]
+#[unstable(feature = "bench_black_box", issue = "64102")]
#[cfg_attr(miri, allow(unused_mut))]
pub fn black_box<T>(mut dummy: T) -> T {
// We need to "use" the argument in some way LLVM can't introspect, and on
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 073210c..175fc2e 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1543,7 +1543,7 @@
/// let num_trailing = unsafe { cttz_nonzero(x) };
/// assert_eq!(num_trailing, 3);
/// ```
- #[rustc_const_unstable(feature = "const_cttz", issue = "none")]
+ #[rustc_const_stable(feature = "const_cttz", since = "1.53.0")]
pub fn cttz_nonzero<T: Copy>(x: T) -> T;
/// Reverses the bytes in an integer type `T`.
@@ -1843,7 +1843,7 @@
pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
extern "rust-intrinsic" {
#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
- fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
}
// FIXME: Perform these checks only at run time
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index 41a7b13..61d8351 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -51,6 +51,9 @@
#[unstable(feature = "trusted_random_access", issue = "none")]
pub use self::zip::TrustedRandomAccess;
+#[unstable(feature = "iter_zip", issue = "83574")]
+pub use self::zip::zip;
+
/// This trait provides transitive access to source-stage in an interator-adapter pipeline
/// under the conditions that
/// * the iterator source `S` itself implements `SourceIter<Source = S>`
@@ -191,3 +194,26 @@
self.try_fold(init, ok(fold)).unwrap()
}
}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<S: Iterator, I, E> SourceIter for ResultShunt<'_, I, E>
+where
+ I: SourceIter<Source = S>,
+{
+ type Source = S;
+
+ #[inline]
+ unsafe fn as_inner(&mut self) -> &mut S {
+ // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+ unsafe { SourceIter::as_inner(&mut self.iter) }
+ }
+}
+
+// SAFETY: ResultShunt::next calls I::find, which has to advance `iter` in order to
+// return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's guaranteed that
+// at least one item will be moved out from the underlying source.
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl<I, T, E> InPlaceIterable for ResultShunt<'_, I, E> where
+ I: Iterator<Item = Result<T, E>> + InPlaceIterable
+{
+}
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
index 4330144..0d860ae 100644
--- a/library/core/src/iter/adapters/peekable.rs
+++ b/library/core/src/iter/adapters/peekable.rs
@@ -1,4 +1,4 @@
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
+use crate::iter::{adapters::SourceIter, FusedIterator, TrustedLen};
use crate::ops::Try;
/// An iterator with a `peek()` that returns an optional reference to the next
@@ -233,7 +233,6 @@
/// Basic usage:
///
/// ```
- /// #![feature(peekable_peek_mut)]
/// let mut iter = [1, 2, 3].iter().peekable();
///
/// // Like with `peek()`, we can see into the future without advancing the iterator.
@@ -251,7 +250,7 @@
/// assert_eq!(iter.collect::<Vec<_>>(), vec![&5, &3]);
/// ```
#[inline]
- #[unstable(feature = "peekable_peek_mut", issue = "78302")]
+ #[stable(feature = "peekable_peek_mut", since = "1.53.0")]
pub fn peek_mut(&mut self) -> Option<&mut I::Item> {
let iter = &mut self.iter;
self.peeked.get_or_insert_with(|| iter.next()).as_mut()
@@ -334,6 +333,3 @@
unsafe { SourceIter::as_inner(&mut self.iter) }
}
}
-
-#[unstable(issue = "none", feature = "inplace_iteration")]
-unsafe impl<I: InPlaceIterable> InPlaceIterable for Peekable<I> {}
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index ea7a809..2f8f504 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -5,8 +5,8 @@
/// An iterator that iterates two other iterators simultaneously.
///
-/// This `struct` is created by [`Iterator::zip`]. See its documentation
-/// for more.
+/// This `struct` is created by [`zip`] or [`Iterator::zip`].
+/// See their documentation for more.
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -33,6 +33,37 @@
}
}
+/// Converts the arguments to iterators and zips them.
+///
+/// See the documentation of [`Iterator::zip`] for more.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(iter_zip)]
+/// use std::iter::zip;
+///
+/// let xs = [1, 2, 3];
+/// let ys = [4, 5, 6];
+/// for (x, y) in zip(&xs, &ys) {
+/// println!("x:{}, y:{}", x, y);
+/// }
+///
+/// // Nested zips are also possible:
+/// let zs = [7, 8, 9];
+/// for ((x, y), z) in zip(zip(&xs, &ys), &zs) {
+/// println!("x:{}, y:{}, z:{}", x, y, z);
+/// }
+/// ```
+#[unstable(feature = "iter_zip", issue = "83574")]
+pub fn zip<A, B>(a: A, b: B) -> Zip<A::IntoIter, B::IntoIter>
+where
+ A: IntoIterator,
+ B: IntoIterator,
+{
+ ZipImpl::new(a.into_iter(), b.into_iter())
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> Iterator for Zip<A, B>
where
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index c57ba2b..2a179f0 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -389,6 +389,8 @@
DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
};
+#[unstable(feature = "iter_zip", issue = "83574")]
+pub use self::adapters::zip;
#[stable(feature = "iter_cloned", since = "1.1.0")]
pub use self::adapters::Cloned;
#[stable(feature = "iter_copied", since = "1.36.0")]
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index cc80e06..4b293c5 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -3,7 +3,7 @@
use crate::mem;
use crate::ops::{self, Try};
-use super::{FusedIterator, TrustedLen};
+use super::{FusedIterator, TrustedLen, TrustedRandomAccess};
/// Objects that have a notion of *successor* and *predecessor* operations.
///
@@ -493,6 +493,18 @@
)*)
}
+/// Safety: This macro must only be used on types that are `Copy` and result in ranges
+/// which have an exact `size_hint()` where the upper bound must not be `None`.
+macro_rules! unsafe_range_trusted_random_access_impl {
+ ($($t:ty)*) => ($(
+ #[doc(hidden)]
+ #[unstable(feature = "trusted_random_access", issue = "none")]
+ unsafe impl TrustedRandomAccess for ops::Range<$t> {
+ const MAY_HAVE_SIDE_EFFECT: bool = false;
+ }
+ )*)
+}
+
macro_rules! range_incl_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "inclusive_range", since = "1.26.0")]
@@ -553,6 +565,18 @@
fn max(mut self) -> Option<A> {
self.next_back()
}
+
+ #[inline]
+ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
+ where
+ Self: TrustedRandomAccess,
+ {
+ // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index
+ // that is in bounds.
+ // Additionally Self: TrustedRandomAccess is only implemented for Copy types
+ // which means even repeated reads of the same index would be safe.
+ unsafe { Step::forward_unchecked(self.start.clone(), idx) }
+ }
}
// These macros generate `ExactSizeIterator` impls for various range types.
@@ -574,6 +598,23 @@
u32
i32
}
+
+unsafe_range_trusted_random_access_impl! {
+ usize u8 u16
+ isize i8 i16
+}
+
+#[cfg(target_pointer_width = "32")]
+unsafe_range_trusted_random_access_impl! {
+ u32 i32
+}
+
+#[cfg(target_pointer_width = "64")]
+unsafe_range_trusted_random_access_impl! {
+ u32 i32
+ u64 i64
+}
+
range_incl_exact_iter_impl! {
u8
i8
diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs
index 5d4a9fe..919c564 100644
--- a/library/core/src/iter/sources/empty.rs
+++ b/library/core/src/iter/sources/empty.rs
@@ -36,7 +36,7 @@
#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<T> fmt::Debug for Empty<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("Empty")
+ f.debug_struct("Empty").finish()
}
}
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 1ae6d15..13a2e24 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -198,6 +198,7 @@
/// }
/// ```
#[rustc_diagnostic_item = "IntoIterator"]
+#[cfg_attr(not(bootstrap), rustc_skip_array_during_method_dispatch)]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
/// The type of the elements being iterated over.
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index a07750f..da9e5fd 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -81,8 +81,8 @@
),
on(
_Self = "[]",
- label = "borrow the array with `&` or call `.iter()` on it to iterate over it",
- note = "arrays are not iterators, but slices like the following are: `&[1, 2, 3]`"
+ label = "arrays do not yet implement `IntoIterator`; try using `std::array::IntoIter::new(arr)`",
+ note = "see <https://github.com/rust-lang/rust/pull/65819> for more details"
),
on(
_Self = "{integral}",
@@ -92,7 +92,8 @@
label = "`{Self}` is not an iterator",
message = "`{Self}` is not an iterator"
)]
-#[doc(spotlight)]
+#[cfg_attr(bootstrap, doc(spotlight))]
+#[cfg_attr(not(bootstrap), doc(notable_trait))]
#[rustc_diagnostic_item = "Iterator"]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub trait Iterator {
@@ -936,20 +937,16 @@
Enumerate::new(self)
}
- /// Creates an iterator which can use [`peek`] to look at the next element of
- /// the iterator without consuming it.
+ /// Creates an iterator which can use the [`peek`] and [`peek_mut`] methods
+ /// to look at the next element of the iterator without consuming it. See
+ /// their documentation for more information.
///
- /// Adds a [`peek`] method to an iterator. See its documentation for
- /// more information.
+ /// Note that the underlying iterator is still advanced when [`peek`] or
+ /// [`peek_mut`] are called for the first time: In order to retrieve the
+ /// next element, [`next`] is called on the underlying iterator, hence any
+ /// side effects (i.e. anything other than fetching the next value) of
+ /// the [`next`] method will occur.
///
- /// Note that the underlying iterator is still advanced when [`peek`] is
- /// called for the first time: In order to retrieve the next element,
- /// [`next`] is called on the underlying iterator, hence any side effects (i.e.
- /// anything other than fetching the next value) of the [`next`] method
- /// will occur.
- ///
- /// [`peek`]: Peekable::peek
- /// [`next`]: Iterator::next
///
/// # Examples
///
@@ -976,6 +973,32 @@
/// assert_eq!(iter.peek(), None);
/// assert_eq!(iter.next(), None);
/// ```
+ ///
+ /// Using [`peek_mut`] to mutate the next item without advancing the
+ /// iterator:
+ ///
+ /// ```
+ /// let xs = [1, 2, 3];
+ ///
+ /// let mut iter = xs.iter().peekable();
+ ///
+ /// // `peek_mut()` lets us see into the future
+ /// assert_eq!(iter.peek_mut(), Some(&mut &1));
+ /// assert_eq!(iter.peek_mut(), Some(&mut &1));
+ /// assert_eq!(iter.next(), Some(&1));
+ ///
+ /// if let Some(mut p) = iter.peek_mut() {
+ /// assert_eq!(*p, &2);
+ /// // put a value into the iterator
+ /// *p = &1000;
+ /// }
+ ///
+ /// // The value reappears as the iterator continues
+ /// assert_eq!(iter.collect::<Vec<_>>(), vec![&1000, &3]);
+ /// ```
+ /// [`peek`]: Peekable::peek
+ /// [`peek_mut`]: Peekable::peek_mut
+ /// [`next`]: Iterator::next
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn peekable(self) -> Peekable<Self>
@@ -1228,7 +1251,11 @@
/// Creates an iterator that skips the first `n` elements.
///
- /// After they have been consumed, the rest of the elements are yielded.
+ /// `skip(n)` skips elements until `n` elements are skipped or the end of the
+ /// iterator is reached (whichever happens first). After that, all the remaining
+ /// elements are yielded. In particular, if the original iterator is too short,
+ /// then the returned iterator is empty.
+ ///
/// Rather than overriding this method directly, instead override the `nth` method.
///
/// # Examples
@@ -1252,7 +1279,14 @@
Skip::new(self, n)
}
- /// Creates an iterator that yields its first `n` elements.
+ /// Creates an iterator that yields the first `n` elements, or fewer
+ /// if the underlying iterator ends sooner.
+ ///
+ /// `take(n)` yields elements until `n` elements are yielded or the end of
+ /// the iterator is reached (whichever happens first).
+ /// The returned iterator is a prefix of length `n` if the original iterator
+ /// contains at least `n` elements, otherwise it contains all of the
+ /// (fewer than `n`) elements of the original iterator.
///
/// # Examples
///
@@ -1461,7 +1495,12 @@
/// [`Some(T)`] again. `fuse()` adapts an iterator, ensuring that after a
/// [`None`] is given, it will always return [`None`] forever.
///
+ /// Note that the [`Fuse`] wrapper is a no-op on iterators that implement
+ /// the [`FusedIterator`] trait. `fuse()` may therefore behave incorrectly
+ /// if the [`FusedIterator`] trait is improperly implemented.
+ ///
/// [`Some(T)`]: Some
+ /// [`FusedIterator`]: crate::iter::FusedIterator
///
/// # Examples
///
@@ -1612,31 +1651,16 @@
/// Basic usage:
///
/// ```
- /// let a = [1, 2, 3];
+ /// let mut words = vec!["hello", "world", "of", "Rust"].into_iter();
///
- /// let iter = a.iter();
+ /// // Take the first two words.
+ /// let hello_world: Vec<_> = words.by_ref().take(2).collect();
+ /// assert_eq!(hello_world, vec!["hello", "world"]);
///
- /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i);
- ///
- /// assert_eq!(sum, 6);
- ///
- /// // if we try to use iter again, it won't work. The following line
- /// // gives "error: use of moved value: `iter`
- /// // assert_eq!(iter.next(), None);
- ///
- /// // let's try that again
- /// let a = [1, 2, 3];
- ///
- /// let mut iter = a.iter();
- ///
- /// // instead, we add in a .by_ref()
- /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i);
- ///
- /// assert_eq!(sum, 3);
- ///
- /// // now this is just fine:
- /// assert_eq!(iter.next(), Some(&3));
- /// assert_eq!(iter.next(), None);
+ /// // Collect the rest of the words.
+ /// // We can only do this because we used `by_ref` earlier.
+ /// let of_rust: Vec<_> = words.collect();
+ /// assert_eq!(of_rust, vec!["of", "Rust"]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn by_ref(&mut self) -> &mut Self
@@ -2109,7 +2133,6 @@
/// ```
///
/// [`reduce()`]: Iterator::reduce
- #[doc(alias = "reduce")]
#[doc(alias = "inject")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 8e35adc..d1329b8 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -79,14 +79,14 @@
#![feature(const_int_unchecked_arith)]
#![feature(const_mut_refs)]
#![feature(const_refs_to_cell)]
-#![feature(const_cttz)]
#![feature(const_panic)]
#![feature(const_pin)]
-#![feature(const_fn)]
+#![cfg_attr(bootstrap, feature(const_fn))]
#![feature(const_fn_union)]
#![feature(const_impl_trait)]
#![feature(const_fn_floating_point_arithmetic)]
#![feature(const_fn_fn_ptr_basics)]
+#![cfg_attr(not(bootstrap), feature(const_fn_trait_bound))]
#![feature(const_option)]
#![feature(const_precise_live_drops)]
#![feature(const_ptr_offset)]
@@ -109,9 +109,9 @@
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
-#![feature(doc_spotlight)]
+#![cfg_attr(bootstrap, feature(doc_spotlight))]
+#![cfg_attr(not(bootstrap), feature(doc_notable_trait))]
#![feature(duration_consts_2)]
-#![feature(duration_saturating_ops)]
#![feature(extended_key_value_attributes)]
#![feature(extern_types)]
#![feature(fundamental)]
@@ -126,9 +126,9 @@
#![feature(exhaustive_patterns)]
#![feature(no_core)]
#![feature(auto_traits)]
-#![feature(or_patterns)]
+#![cfg_attr(bootstrap, feature(or_patterns))]
#![feature(prelude_import)]
-#![cfg_attr(not(bootstrap), feature(ptr_metadata))]
+#![feature(ptr_metadata)]
#![feature(repr_simd, platform_intrinsics)]
#![feature(rustc_attrs)]
#![feature(simd_ffi)]
@@ -138,6 +138,7 @@
#![feature(stmt_expr_attributes)]
#![feature(str_split_as_str)]
#![feature(str_split_inclusive_as_str)]
+#![feature(char_indices_offset)]
#![feature(trait_alias)]
#![feature(transparent_unions)]
#![feature(try_blocks)]
@@ -165,8 +166,8 @@
#![feature(const_caller_location)]
#![feature(slice_ptr_get)]
#![feature(no_niche)] // rust-lang/rust#68303
+#![cfg_attr(not(bootstrap), feature(no_coverage))] // rust-lang/rust#84605
#![feature(int_error_matching)]
-#![cfg_attr(bootstrap, feature(unsafe_block_in_unsafe_fn))]
#![deny(unsafe_op_in_unsafe_fn)]
#[prelude_import]
@@ -298,8 +299,8 @@
unused_imports,
unsafe_op_in_unsafe_fn
)]
-#[cfg_attr(bootstrap, allow(non_autolinks))]
-#[cfg_attr(not(bootstrap), allow(rustdoc::non_autolinks))]
+#[cfg_attr(bootstrap, allow(rustdoc::non_autolinks))]
+#[cfg_attr(not(bootstrap), allow(rustdoc::bare_urls))]
// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet.
#[allow(clashing_extern_declarations)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index a0a8eec..66efa3c 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1301,7 +1301,6 @@
}
/// Attribute macro used to apply derive macros.
- #[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_builtin_macro]
pub macro derive($item:item) {
@@ -1363,7 +1362,6 @@
}
/// Expands all `#[cfg]` and `#[cfg_attr]` attributes in the code fragment it's applied to.
- #[cfg(not(bootstrap))]
#[unstable(
feature = "cfg_eval",
issue = "82679",
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 85e0e72..fb95734 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -765,7 +765,7 @@
/// [`pin` module]: crate::pin
#[stable(feature = "pin", since = "1.33.0")]
#[rustc_on_unimplemented(
- on(_Self = "std::future::Future", note = "consider using `Box::pin`",),
+ note = "consider using `Box::pin`",
message = "`{Self}` cannot be unpinned"
)]
#[lang = "unpin"]
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index cb07293..4d7d475 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -190,6 +190,8 @@
/// let ptr = uninit.as_mut_ptr();
///
/// // Initializing the `name` field
+/// // Using `write` instead of assignment via `=` to not call `drop` on the
+/// // old, uninitialized value.
/// unsafe { addr_of_mut!((*ptr).name).write("Bob".to_string()); }
///
/// // Initializing the `list` field
@@ -319,9 +321,9 @@
/// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
///
/// Note: in a future Rust version this method may become unnecessary
- /// when array literal syntax allows
- /// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147).
- /// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`.
+ /// when Rust allows
+ /// [inline const expressions](https://github.com/rust-lang/rust/issues/76001).
+ /// The example below could then use `let mut buf = [const { MaybeUninit::<u8>::uninit() }; 32];`.
///
/// # Examples
///
@@ -734,22 +736,22 @@
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
- /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] }
+ /// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 1024]) { *buf = [0; 1024] }
/// # #[cfg(FALSE)]
/// extern "C" {
/// /// Initializes *all* the bytes of the input buffer.
- /// fn initialize_buffer(buf: *mut [u8; 2048]);
+ /// fn initialize_buffer(buf: *mut [u8; 1024]);
/// }
///
- /// let mut buf = MaybeUninit::<[u8; 2048]>::uninit();
+ /// let mut buf = MaybeUninit::<[u8; 1024]>::uninit();
///
/// // Initialize `buf`:
/// unsafe { initialize_buffer(buf.as_mut_ptr()); }
/// // Now we know that `buf` has been initialized, so we could `.assume_init()` it.
- /// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes.
+ /// // However, using `.assume_init()` may trigger a `memcpy` of the 1024 bytes.
/// // To assert our buffer has been initialized without copying it, we upgrade
- /// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`:
- /// let buf: &mut [u8; 2048] = unsafe {
+ /// // the `&mut MaybeUninit<[u8; 1024]>` to a `&mut [u8; 1024]`:
+ /// let buf: &mut [u8; 1024] = unsafe {
/// // SAFETY: `buf` has been initialized.
/// buf.assume_init_mut()
/// };
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index c4f0d91..c6750c5 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -297,7 +297,7 @@
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
-#[rustc_const_stable(feature = "const_size_of", since = "1.32.0")]
+#[rustc_const_stable(feature = "const_size_of", since = "1.24.0")]
pub const fn size_of<T>() -> usize {
intrinsics::size_of::<T>()
}
@@ -440,7 +440,7 @@
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
-#[rustc_const_stable(feature = "const_align_of", since = "1.32.0")]
+#[rustc_const_stable(feature = "const_align_of", since = "1.24.0")]
pub const fn align_of<T>() -> usize {
intrinsics::min_align_of::<T>()
}
@@ -884,7 +884,6 @@
/// ```
///
/// [`RefCell`]: crate::cell::RefCell
-#[doc(alias = "delete")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn drop<T>(_x: T) {}
diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs
index 6a1a1e1..197b85f 100644
--- a/library/core/src/num/bignum.rs
+++ b/library/core/src/num/bignum.rs
@@ -181,11 +181,12 @@
/// Adds `other` to itself and returns its own mutable reference.
pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name {
use crate::cmp;
+ use crate::iter;
use crate::num::bignum::FullOps;
let mut sz = cmp::max(self.size, other.size);
let mut carry = false;
- for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
+ for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) {
let (c, v) = (*a).full_add(*b, carry);
*a = v;
carry = c;
@@ -219,11 +220,12 @@
/// Subtracts `other` from itself and returns its own mutable reference.
pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name {
use crate::cmp;
+ use crate::iter;
use crate::num::bignum::FullOps;
let sz = cmp::max(self.size, other.size);
let mut noborrow = true;
- for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
+ for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) {
let (c, v) = (*a).full_add(!*b, noborrow);
*a = v;
noborrow = c;
diff --git a/library/core/src/num/dec2flt/algorithm.rs b/library/core/src/num/dec2flt/algorithm.rs
index a5fbdc6..313b687 100644
--- a/library/core/src/num/dec2flt/algorithm.rs
+++ b/library/core/src/num/dec2flt/algorithm.rs
@@ -62,10 +62,9 @@
// any `u16`
unsafe {
asm!(
- "fldcw ({})",
+ "fldcw word ptr [{}]",
in(reg) &cw,
- // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
- options(att_syntax, nostack),
+ options(nostack),
)
}
}
@@ -87,10 +86,9 @@
// any `u16`
unsafe {
asm!(
- "fnstcw ({})",
+ "fnstcw word ptr [{}]",
in(reg) &mut cw,
- // FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
- options(att_syntax, nostack),
+ options(nostack),
)
}
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index 20ac165..f008a64 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -239,13 +239,15 @@
ParseResult::Valid(decimal) => convert(decimal)?,
ParseResult::ShortcutToInf => T::INFINITY,
ParseResult::ShortcutToZero => T::ZERO,
- ParseResult::Invalid => match s {
- "inf" => T::INFINITY,
- "NaN" => T::NAN,
- _ => {
+ ParseResult::Invalid => {
+ if s.eq_ignore_ascii_case("nan") {
+ T::NAN
+ } else if s.eq_ignore_ascii_case("inf") || s.eq_ignore_ascii_case("infinity") {
+ T::INFINITY
+ } else {
return Err(pfe_invalid());
}
- },
+ }
};
match sign {
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 690247b..0d6d919 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -500,7 +500,6 @@
/// Returns `true` if the number is [subnormal].
///
/// ```
- /// #![feature(is_subnormal)]
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
/// let max = f32::MAX;
/// let lower_than_min = 1.0e-40_f32;
@@ -516,7 +515,7 @@
/// assert!(lower_than_min.is_subnormal());
/// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
- #[unstable(feature = "is_subnormal", issue = "79288")]
+ #[stable(feature = "is_subnormal", since = "1.53.0")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
#[inline]
pub const fn is_subnormal(self) -> bool {
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 6d37372..42214e7 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -499,7 +499,6 @@
/// Returns `true` if the number is [subnormal].
///
/// ```
- /// #![feature(is_subnormal)]
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308_f64
/// let max = f64::MAX;
/// let lower_than_min = 1.0e-308_f64;
@@ -515,7 +514,7 @@
/// assert!(lower_than_min.is_subnormal());
/// ```
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
- #[unstable(feature = "is_subnormal", issue = "79288")]
+ #[stable(feature = "is_subnormal", since = "1.53.0")]
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
#[inline]
pub const fn is_subnormal(self) -> bool {
diff --git a/library/core/src/num/flt2dec/mod.rs b/library/core/src/num/flt2dec/mod.rs
index e8f9d65..93bdf50 100644
--- a/library/core/src/num/flt2dec/mod.rs
+++ b/library/core/src/num/flt2dec/mod.rs
@@ -399,14 +399,10 @@
/// Sign formatting options.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Sign {
- /// Prints `-` only for the negative non-zero values.
- Minus, // -inf -1 0 0 1 inf nan
- /// Prints `-` only for any negative values (including the negative zero).
- MinusRaw, // -inf -1 -0 0 1 inf nan
- /// Prints `-` for the negative non-zero values, or `+` otherwise.
- MinusPlus, // -inf -1 +0 +0 +1 +inf nan
- /// Prints `-` for any negative values (including the negative zero), or `+` otherwise.
- MinusPlusRaw, // -inf -1 -0 +0 +1 +inf nan
+ /// Prints `-` for any negative value.
+ Minus, // -inf -1 -0 0 1 inf nan
+ /// Prints `-` for any negative value, or `+` otherwise.
+ MinusPlus, // -inf -1 -0 +0 +1 +inf nan
}
/// Returns the static byte string corresponding to the sign to be formatted.
@@ -414,30 +410,14 @@
fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str {
match (*decoded, sign) {
(FullDecoded::Nan, _) => "",
- (FullDecoded::Zero, Sign::Minus) => "",
- (FullDecoded::Zero, Sign::MinusRaw) => {
+ (_, Sign::Minus) => {
if negative {
"-"
} else {
""
}
}
- (FullDecoded::Zero, Sign::MinusPlus) => "+",
- (FullDecoded::Zero, Sign::MinusPlusRaw) => {
- if negative {
- "-"
- } else {
- "+"
- }
- }
- (_, Sign::Minus | Sign::MinusRaw) => {
- if negative {
- "-"
- } else {
- ""
- }
- }
- (_, Sign::MinusPlus | Sign::MinusPlusRaw) => {
+ (_, Sign::MinusPlus) => {
if negative {
"-"
} else {
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index ce9dca3..4b34113 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -32,10 +32,9 @@
/// # Examples
///
/// ```
- /// #![feature(int_bits_const)]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
- #[unstable(feature = "int_bits_const", issue = "76904")]
+ #[stable(feature = "int_bits_const", since = "1.53.0")]
pub const BITS: u32 = $BITS;
/// Converts a string slice in a given base to an integer.
@@ -80,7 +79,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[doc(alias = "popcount")]
#[doc(alias = "popcnt")]
- #[inline]
+ #[inline(always)]
pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
/// Returns the number of zeros in the binary representation of `self`.
@@ -94,7 +93,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn count_zeros(self) -> u32 {
(!self).count_ones()
}
@@ -112,7 +111,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn leading_zeros(self) -> u32 {
(self as $UnsignedT).leading_zeros()
}
@@ -130,7 +129,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn trailing_zeros(self) -> u32 {
(self as $UnsignedT).trailing_zeros()
}
@@ -148,7 +147,7 @@
/// ```
#[stable(feature = "leading_trailing_ones", since = "1.46.0")]
#[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
- #[inline]
+ #[inline(always)]
pub const fn leading_ones(self) -> u32 {
(self as $UnsignedT).leading_ones()
}
@@ -166,7 +165,7 @@
/// ```
#[stable(feature = "leading_trailing_ones", since = "1.46.0")]
#[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
- #[inline]
+ #[inline(always)]
pub const fn trailing_ones(self) -> u32 {
(self as $UnsignedT).trailing_ones()
}
@@ -190,7 +189,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn rotate_left(self, n: u32) -> Self {
(self as $UnsignedT).rotate_left(n) as Self
}
@@ -215,7 +214,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn rotate_right(self, n: u32) -> Self {
(self as $UnsignedT).rotate_right(n) as Self
}
@@ -235,7 +234,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn swap_bytes(self) -> Self {
(self as $UnsignedT).swap_bytes() as Self
}
@@ -255,8 +254,8 @@
#[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")]
/// ```
#[stable(feature = "reverse_bits", since = "1.37.0")]
- #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
- #[inline]
+ #[rustc_const_stable(feature = "const_int_methods", since = "1.37.0")]
+ #[inline(always)]
#[must_use]
pub const fn reverse_bits(self) -> Self {
(self as $UnsignedT).reverse_bits() as Self
@@ -417,7 +416,7 @@
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub unsafe fn unchecked_add(self, rhs: Self) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_add`.
@@ -455,7 +454,7 @@
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub unsafe fn unchecked_sub(self, rhs: Self) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_sub`.
@@ -493,7 +492,7 @@
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub unsafe fn unchecked_mul(self, rhs: Self) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_mul`.
@@ -742,7 +741,7 @@
#[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn saturating_add(self, rhs: Self) -> Self {
intrinsics::saturating_add(self, rhs)
}
@@ -763,7 +762,7 @@
#[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn saturating_sub(self, rhs: Self) -> Self {
intrinsics::saturating_sub(self, rhs)
}
@@ -784,7 +783,7 @@
#[stable(feature = "saturating_neg", since = "1.45.0")]
#[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
- #[inline]
+ #[inline(always)]
pub const fn saturating_neg(self) -> Self {
intrinsics::saturating_sub(0, self)
}
@@ -884,7 +883,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_add(self, rhs: Self) -> Self {
intrinsics::wrapping_add(self, rhs)
}
@@ -904,7 +903,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_sub(self, rhs: Self) -> Self {
intrinsics::wrapping_sub(self, rhs)
}
@@ -924,7 +923,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_mul(self, rhs: Self) -> Self {
intrinsics::wrapping_mul(self, rhs)
}
@@ -1082,7 +1081,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
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
@@ -1111,7 +1110,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
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
@@ -1226,7 +1225,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
@@ -1250,7 +1249,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
@@ -1273,7 +1272,7 @@
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
@@ -1589,11 +1588,11 @@
/// Calculates the quotient of Euclidean division of `self` by `rhs`.
///
- /// This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`,
- /// with `0 <= self.rem_euclid(rhs) < rhs`.
+ /// This computes the integer `q` such that `self = q * rhs + r`, with
+ /// `r = self.rem_euclid(rhs)` and `0 <= r < abs(rhs)`.
///
- /// In other words, the result is `self / rhs` rounded to the integer `n`
- /// such that `self >= n * rhs`.
+ /// In other words, the result is `self / rhs` rounded to the integer `q`
+ /// such that `self >= q * rhs`.
/// If `self > 0`, this is equal to round towards zero (the default in Rust);
/// if `self < 0`, this is equal to round towards +/- infinity.
///
@@ -1726,7 +1725,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_sign", since = "1.47.0")]
- #[inline]
+ #[inline(always)]
pub const fn signum(self) -> Self {
match self {
n if n > 0 => 1,
@@ -1748,7 +1747,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn is_positive(self) -> bool { self > 0 }
/// Returns `true` if `self` is negative and `false` if the number is zero or
@@ -1764,7 +1763,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn is_negative(self) -> bool { self < 0 }
/// Return the memory representation of this integer as a byte array in
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index f0bd976..6032dc9 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -2,6 +2,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
+use crate::ascii;
use crate::intrinsics;
use crate::mem;
use crate::str::FromStr;
@@ -661,6 +662,31 @@
pub const fn is_ascii_control(&self) -> bool {
matches!(*self, b'\0'..=b'\x1F' | b'\x7F')
}
+
+ /// Returns an iterator that produces an escaped version of a `u8`,
+ /// treating it as an ASCII character.
+ ///
+ /// The behavior is identical to [`ascii::escape_default`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(inherent_ascii_escape)]
+ ///
+ /// assert_eq!("0", b'0'.escape_ascii().to_string());
+ /// assert_eq!("\\t", b'\t'.escape_ascii().to_string());
+ /// assert_eq!("\\r", b'\r'.escape_ascii().to_string());
+ /// assert_eq!("\\n", b'\n'.escape_ascii().to_string());
+ /// assert_eq!("\\'", b'\''.escape_ascii().to_string());
+ /// assert_eq!("\\\"", b'"'.escape_ascii().to_string());
+ /// assert_eq!("\\\\", b'\\'.escape_ascii().to_string());
+ /// assert_eq!("\\x9d", b'\x9d'.escape_ascii().to_string());
+ /// ```
+ #[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+ #[inline]
+ pub fn escape_ascii(&self) -> ascii::EscapeDefault {
+ ascii::escape_default(*self)
+ }
}
#[lang = "u16"]
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 111feb7..6b9b435 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -23,7 +23,7 @@
}
macro_rules! nonzero_integers {
- ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => {
+ ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => {
$(
/// An integer that is known not to equal zero.
///
@@ -48,7 +48,7 @@
///
/// The value must not be zero.
#[$stability]
- #[rustc_const_stable(feature = "nonzero", since = "1.34.0")]
+ #[$const_new_unchecked_stability]
#[inline]
pub const unsafe fn new_unchecked(n: $Int) -> Self {
// SAFETY: this is guaranteed to be safe by the caller.
@@ -146,18 +146,18 @@
}
nonzero_integers! {
- #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
- #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
- #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
- #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
- #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
- #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
- #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
- #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
- #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
- #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
- #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
- #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
+ #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
+ #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
+ #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
+ #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
+ #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
+ #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
}
macro_rules! from_str_radix_nzint_impl {
@@ -191,13 +191,12 @@
/// Basic usage:
///
/// ```
- /// #![feature(nonzero_leading_trailing_zeros)]
#[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")]
///
/// assert_eq!(n.leading_zeros(), 0);
/// ```
- #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
- #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
+ #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
+ #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
#[inline]
pub const fn leading_zeros(self) -> u32 {
// SAFETY: since `self` can not be zero it is safe to call ctlz_nonzero
@@ -214,13 +213,12 @@
/// Basic usage:
///
/// ```
- /// #![feature(nonzero_leading_trailing_zeros)]
#[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")]
///
/// assert_eq!(n.trailing_zeros(), 3);
/// ```
- #[unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
- #[rustc_const_unstable(feature = "nonzero_leading_trailing_zeros", issue = "79143")]
+ #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
+ #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")]
#[inline]
pub const fn trailing_zeros(self) -> u32 {
// SAFETY: since `self` can not be zero it is safe to call cttz_nonzero
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 7393e7f..08d9161 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -32,10 +32,9 @@
/// # Examples
///
/// ```
- /// #![feature(int_bits_const)]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
- #[unstable(feature = "int_bits_const", issue = "76904")]
+ #[stable(feature = "int_bits_const", since = "1.53.0")]
pub const BITS: u32 = $BITS;
/// Converts a string slice in a given base to an integer.
@@ -80,7 +79,7 @@
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
#[doc(alias = "popcount")]
#[doc(alias = "popcnt")]
- #[inline]
+ #[inline(always)]
pub const fn count_ones(self) -> u32 {
intrinsics::ctpop(self as $ActualT) as u32
}
@@ -96,7 +95,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn count_zeros(self) -> u32 {
(!self).count_ones()
}
@@ -114,7 +113,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn leading_zeros(self) -> u32 {
intrinsics::ctlz(self as $ActualT) as u32
}
@@ -133,7 +132,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn trailing_zeros(self) -> u32 {
intrinsics::cttz(self) as u32
}
@@ -151,7 +150,7 @@
/// ```
#[stable(feature = "leading_trailing_ones", since = "1.46.0")]
#[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
- #[inline]
+ #[inline(always)]
pub const fn leading_ones(self) -> u32 {
(!self).leading_zeros()
}
@@ -170,7 +169,7 @@
/// ```
#[stable(feature = "leading_trailing_ones", since = "1.46.0")]
#[rustc_const_stable(feature = "leading_trailing_ones", since = "1.46.0")]
- #[inline]
+ #[inline(always)]
pub const fn trailing_ones(self) -> u32 {
(!self).trailing_zeros()
}
@@ -194,7 +193,7 @@
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn rotate_left(self, n: u32) -> Self {
intrinsics::rotate_left(self, n as $SelfT)
}
@@ -219,7 +218,7 @@
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn rotate_right(self, n: u32) -> Self {
intrinsics::rotate_right(self, n as $SelfT)
}
@@ -238,7 +237,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn swap_bytes(self) -> Self {
intrinsics::bswap(self as $ActualT) as Self
}
@@ -258,8 +257,8 @@
#[doc = concat!("assert_eq!(0, 0", stringify!($SelfT), ".reverse_bits());")]
/// ```
#[stable(feature = "reverse_bits", since = "1.37.0")]
- #[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[rustc_const_stable(feature = "const_math", since = "1.37.0")]
+ #[inline(always)]
#[must_use]
pub const fn reverse_bits(self) -> Self {
intrinsics::bitreverse(self as $ActualT) as Self
@@ -285,7 +284,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn from_be(x: Self) -> Self {
#[cfg(target_endian = "big")]
{
@@ -317,7 +316,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn from_le(x: Self) -> Self {
#[cfg(target_endian = "little")]
{
@@ -349,7 +348,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn to_be(self) -> Self { // or not to be?
#[cfg(target_endian = "big")]
{
@@ -381,7 +380,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_math", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn to_le(self) -> Self {
#[cfg(target_endian = "little")]
{
@@ -427,7 +426,7 @@
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub unsafe fn unchecked_add(self, rhs: Self) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_add`.
@@ -465,7 +464,7 @@
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub unsafe fn unchecked_sub(self, rhs: Self) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_sub`.
@@ -503,7 +502,7 @@
)]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub unsafe fn unchecked_mul(self, rhs: Self) -> Self {
// SAFETY: the caller must uphold the safety contract for
// `unchecked_mul`.
@@ -728,7 +727,7 @@
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
- #[inline]
+ #[inline(always)]
pub const fn saturating_add(self, rhs: Self) -> Self {
intrinsics::saturating_add(self, rhs)
}
@@ -748,7 +747,7 @@
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[rustc_const_stable(feature = "const_saturating_int_methods", since = "1.47.0")]
- #[inline]
+ #[inline(always)]
pub const fn saturating_sub(self, rhs: Self) -> Self {
intrinsics::saturating_sub(self, rhs)
}
@@ -814,7 +813,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_add(self, rhs: Self) -> Self {
intrinsics::wrapping_add(self, rhs)
}
@@ -834,7 +833,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_sub(self, rhs: Self) -> Self {
intrinsics::wrapping_sub(self, rhs)
}
@@ -857,7 +856,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_mul(self, rhs: Self) -> Self {
intrinsics::wrapping_mul(self, rhs)
}
@@ -879,7 +878,7 @@
#[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_div(self, rhs: Self) -> Self {
self / rhs
}
@@ -904,7 +903,7 @@
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
self / rhs
}
@@ -927,7 +926,7 @@
#[rustc_const_stable(feature = "const_wrapping_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_rem(self, rhs: Self) -> Self {
self % rhs
}
@@ -953,7 +952,7 @@
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
self % rhs
}
@@ -1009,7 +1008,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
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
@@ -1041,7 +1040,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
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
@@ -1107,7 +1106,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
@@ -1132,7 +1131,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
@@ -1159,7 +1158,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
(a as Self, b)
@@ -1183,7 +1182,7 @@
/// ```
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")]
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "wrapping", since = "1.7.0")]
#[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
@@ -1213,7 +1212,7 @@
/// ```
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));")]
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "euclidean_division", since = "1.38.0")]
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
@@ -1240,7 +1239,7 @@
/// ```
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")]
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "wrapping", since = "1.7.0")]
#[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
@@ -1270,7 +1269,7 @@
/// ```
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));")]
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "euclidean_division", since = "1.38.0")]
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
@@ -1294,7 +1293,7 @@
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_neg(), (0, false));")]
#[doc = concat!("assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2i32 as ", stringify!($SelfT), ", true));")]
/// ```
- #[inline]
+ #[inline(always)]
#[stable(feature = "wrapping", since = "1.7.0")]
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
pub const fn overflowing_neg(self) -> (Self, bool) {
@@ -1321,7 +1320,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
}
@@ -1346,7 +1345,7 @@
#[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
}
@@ -1459,7 +1458,7 @@
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
#[rustc_inherit_overflow_checks]
pub const fn div_euclid(self, rhs: Self) -> Self {
self / rhs
@@ -1487,7 +1486,7 @@
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[inline]
+ #[inline(always)]
#[rustc_inherit_overflow_checks]
pub const fn rem_euclid(self, rhs: Self) -> Self {
self % rhs
@@ -1505,7 +1504,7 @@
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_is_power_of_two", since = "1.32.0")]
- #[inline]
+ #[inline(always)]
pub const fn is_power_of_two(self) -> bool {
self.count_ones() == 1
}
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index 92090d8..a0577b2 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -456,9 +456,13 @@
}
macro_rules! div_impl_integer {
- ($($t:ty)*) => ($(
+ ($(($($t:ty)*) => $panic:expr),*) => ($($(
/// This operation rounds towards zero, truncating any
/// fractional part of the exact result.
+ ///
+ /// # Panics
+ ///
+ #[doc = $panic]
#[stable(feature = "rust1", since = "1.0.0")]
impl Div for $t {
type Output = $t;
@@ -468,10 +472,13 @@
}
forward_ref_binop! { impl Div, div for $t, $t }
- )*)
+ )*)*)
}
-div_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+div_impl_integer! {
+ (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.",
+ (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or the division results in overflow."
+}
macro_rules! div_impl_float {
($($t:ty)*) => ($(
@@ -549,9 +556,13 @@
}
macro_rules! rem_impl_integer {
- ($($t:ty)*) => ($(
+ ($(($($t:ty)*) => $panic:expr),*) => ($($(
/// This operation satisfies `n % d == n - (n / d) * d`. The
/// result has the same sign as the left operand.
+ ///
+ /// # Panics
+ ///
+ #[doc = $panic]
#[stable(feature = "rust1", since = "1.0.0")]
impl Rem for $t {
type Output = $t;
@@ -561,10 +572,13 @@
}
forward_ref_binop! { impl Rem, rem for $t, $t }
- )*)
+ )*)*)
}
-rem_impl_integer! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+rem_impl_integer! {
+ (usize u8 u16 u32 u64 u128) => "This operation will panic if `other == 0`.",
+ (isize i8 i16 i32 i64 i128) => "This operation will panic if `other == 0` or if `self / other` results in overflow."
+}
macro_rules! rem_impl_float {
($($t:ty)*) => ($(
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index 2f78ba8..ecaff05 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -1,4 +1,5 @@
-use crate::ops::Try;
+use crate::convert;
+use crate::ops::{self, Try};
/// Used to tell an operation whether it should exit early or go on as usual.
///
@@ -81,6 +82,35 @@
}
}
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<B, C> ops::TryV2 for ControlFlow<B, C> {
+ type Output = C;
+ type Residual = ControlFlow<B, convert::Infallible>;
+
+ #[inline]
+ fn from_output(output: Self::Output) -> Self {
+ ControlFlow::Continue(output)
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ ControlFlow::Continue(c) => ControlFlow::Continue(c),
+ ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<B, C> ops::FromResidual for ControlFlow<B, C> {
+ #[inline]
+ fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
+ match residual {
+ ControlFlow::Break(b) => ControlFlow::Break(b),
+ }
+ }
+}
+
impl<B, C> ControlFlow<B, C> {
/// Returns `true` if this is a `Break` variant.
///
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 10e3ce6..dcf3ce0 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -65,7 +65,7 @@
/// The resulting type after dereferencing.
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "deref_target"]
- #[cfg_attr(not(bootstrap), lang = "deref_target")]
+ #[lang = "deref_target"]
type Target: ?Sized;
/// Dereferences the value.
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index ce7d1c3..f4b1ec3 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -78,7 +78,7 @@
///
/// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error.
///
-/// If you'd like explicitly call the destructor of a value, [`mem::drop`] can be used instead.
+/// If you'd like to explicitly call the destructor of a value, [`mem::drop`] can be used instead.
///
/// [`mem::drop`]: drop
///
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index a8dea4e..964378c 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -61,6 +61,10 @@
type Output: ?Sized;
/// Performs the indexing (`container[index]`) operation.
+ ///
+ /// # Panics
+ ///
+ /// May panic if the index is out of bounds.
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
fn index(&self, index: Idx) -> &Self::Output;
@@ -161,6 +165,10 @@
#[doc(alias = "[]")]
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
/// Performs the mutable indexing (`container[index]`) operation.
+ ///
+ /// # Panics
+ ///
+ /// May panic if the index is out of bounds.
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 354ad6b..1b07936 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -148,6 +148,7 @@
mod index;
mod range;
mod r#try;
+mod try_trait;
mod unsize;
#[stable(feature = "rust1", since = "1.0.0")]
@@ -184,6 +185,12 @@
#[unstable(feature = "try_trait", issue = "42327")]
pub use self::r#try::Try;
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+pub use self::try_trait::FromResidual;
+
+#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
+pub use self::try_trait::Try as TryV2;
+
#[unstable(feature = "generator_trait", issue = "43122")]
pub use self::generator::{Generator, GeneratorState};
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
new file mode 100644
index 0000000..0c819b0
--- /dev/null
+++ b/library/core/src/ops/try_trait.rs
@@ -0,0 +1,243 @@
+use crate::ops::ControlFlow;
+
+/// The `?` operator and `try {}` blocks.
+///
+/// `try_*` methods typically involve a type implementing this trait. For
+/// example, the closures passed to [`Iterator::try_fold`] and
+/// [`Iterator::try_for_each`] must return such a type.
+///
+/// `Try` types are typically those containing two or more categories of values,
+/// some subset of which are so commonly handled via early returns that it's
+/// worth providing a terse (but still visible) syntax to make that easy.
+///
+/// This is most often seen for error handling with [`Result`] and [`Option`].
+/// The quintessential implementation of this trait is on [`ControlFlow`].
+///
+/// # Using `Try` in Generic Code
+///
+/// `Iterator::try_fold` was stabilized to call back in Rust 1.27, but
+/// this trait is much newer. To illustrate the various associated types and
+/// methods, let's implement our own version.
+///
+/// As a reminder, an infallible version of a fold looks something like this:
+/// ```
+/// fn simple_fold<A, T>(
+/// iter: impl Iterator<Item = T>,
+/// mut accum: A,
+/// mut f: impl FnMut(A, T) -> A,
+/// ) -> A {
+/// for x in iter {
+/// accum = f(accum, x);
+/// }
+/// accum
+/// }
+/// ```
+///
+/// So instead of `f` returning just an `A`, we'll need it to return some other
+/// type that produces an `A` in the "don't short circuit" path. Conveniently,
+/// that's also the type we need to return from the function.
+///
+/// Let's add a new generic parameter `R` for that type, and bound it to the
+/// output type that we want:
+/// ```
+/// # #![feature(try_trait_v2)]
+/// # #![feature(try_trait_transition)]
+/// # use std::ops::TryV2 as Try;
+/// fn simple_try_fold_1<A, T, R: Try<Output = A>>(
+/// iter: impl Iterator<Item = T>,
+/// mut accum: A,
+/// mut f: impl FnMut(A, T) -> R,
+/// ) -> R {
+/// todo!()
+/// }
+/// ```
+///
+/// If we get through the entire iterator, we need to wrap up the accumulator
+/// into the return type using [`Try::from_output`]:
+/// ```
+/// # #![feature(try_trait_v2)]
+/// # #![feature(try_trait_transition)]
+/// # #![feature(control_flow_enum)]
+/// # use std::ops::{ControlFlow, TryV2 as Try};
+/// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
+/// iter: impl Iterator<Item = T>,
+/// mut accum: A,
+/// mut f: impl FnMut(A, T) -> R,
+/// ) -> R {
+/// for x in iter {
+/// let cf = f(accum, x).branch();
+/// match cf {
+/// ControlFlow::Continue(a) => accum = a,
+/// ControlFlow::Break(_) => todo!(),
+/// }
+/// }
+/// R::from_output(accum)
+/// }
+/// ```
+///
+/// We'll also need [`FromResidual::from_residual`] to turn the residual back
+/// into the original type. But because it's a supertrait of `Try`, we don't
+/// need to mention it in the bounds. All types which implement `Try` can be
+/// recreated from their corresponding residual, so we'll just call it:
+/// ```
+/// # #![feature(try_trait_v2)]
+/// # #![feature(try_trait_transition)]
+/// # #![feature(control_flow_enum)]
+/// # use std::ops::{ControlFlow, TryV2 as Try};
+/// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
+/// iter: impl Iterator<Item = T>,
+/// mut accum: A,
+/// mut f: impl FnMut(A, T) -> R,
+/// ) -> R {
+/// for x in iter {
+/// let cf = f(accum, x).branch();
+/// match cf {
+/// ControlFlow::Continue(a) => accum = a,
+/// ControlFlow::Break(r) => return R::from_residual(r),
+/// }
+/// }
+/// R::from_output(accum)
+/// }
+/// ```
+///
+/// But this "call `branch`, then `match` on it, and `return` if it was a
+/// `Break`" is exactly what happens inside the `?` operator. So rather than
+/// do all this manually, we can just use `?` instead:
+/// ```compile_fail (enable again once ? converts to the new trait)
+/// # #![feature(try_trait_v2)]
+/// # #![feature(try_trait_transition)]
+/// # use std::ops::TryV2 as Try;
+/// fn simple_try_fold<A, T, R: Try<Output = A>>(
+/// iter: impl Iterator<Item = T>,
+/// mut accum: A,
+/// mut f: impl FnMut(A, T) -> R,
+/// ) -> R {
+/// for x in iter {
+/// accum = f(accum, x)?;
+/// }
+/// R::from_output(accum)
+/// }
+/// ```
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+pub trait Try: FromResidual {
+ /// The type of the value produced by `?` when *not* short-circuiting.
+ #[unstable(feature = "try_trait_v2", issue = "84277")]
+ type Output;
+
+ /// The type of the value passed to [`FromResidual::from_residual`]
+ /// as part of `?` when short-circuiting.
+ ///
+ /// This represents the possible values of the `Self` type which are *not*
+ /// represented by the `Output` type.
+ ///
+ /// # Note to Implementors
+ ///
+ /// The choice of this type is critical to interconversion.
+ /// Unlike the `Output` type, which will often be a raw generic type,
+ /// this type is typically a newtype of some sort to "color" the type
+ /// so that it's distinguishable from the residuals of other types.
+ ///
+ /// This is why `Result<T, E>::Residual` is not `E`, but `Result<Infallible, E>`.
+ /// That way it's distinct from `ControlFlow<E>::Residual`, for example,
+ /// and thus `?` on `ControlFlow` cannot be used in a method returning `Result`.
+ ///
+ /// If you're making a generic type `Foo<T>` that implements `Try<Output = T>`,
+ /// then typically you can use `Foo<std::convert::Infallible>` as its `Residual`
+ /// type: that type will have a "hole" in the correct place, and will maintain the
+ /// "foo-ness" of the residual so other types need to opt-in to interconversion.
+ #[unstable(feature = "try_trait_v2", issue = "84277")]
+ type Residual;
+
+ /// Constructs the type from its `Output` type.
+ ///
+ /// This should be implemented consistently with the `branch` method
+ /// such that applying the `?` operator will get back the original value:
+ /// `Try::from_output(x).branch() --> ControlFlow::Continue(x)`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(try_trait_v2)]
+ /// #![feature(control_flow_enum)]
+ /// #![feature(try_trait_transition)]
+ /// use std::ops::TryV2 as Try;
+ ///
+ /// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
+ /// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
+ /// assert_eq!(
+ /// <std::ops::ControlFlow<String, _> as Try>::from_output(5),
+ /// std::ops::ControlFlow::Continue(5),
+ /// );
+ ///
+ /// # fn make_question_mark_work() -> Option<()> {
+ /// assert_eq!(Option::from_output(4)?, 4);
+ /// # None }
+ /// # make_question_mark_work();
+ ///
+ /// // This is used, for example, on the accumulator in `try_fold`:
+ /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
+ /// assert_eq!(r, Some(4));
+ /// ```
+ #[unstable(feature = "try_trait_v2", issue = "84277")]
+ fn from_output(output: Self::Output) -> Self;
+
+ /// Used in `?` to decide whether the operator should produce a value
+ /// (because this returned [`ControlFlow::Continue`])
+ /// or propagate a value back to the caller
+ /// (because this returned [`ControlFlow::Break`]).
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(try_trait_v2)]
+ /// #![feature(control_flow_enum)]
+ /// #![feature(try_trait_transition)]
+ /// use std::ops::{ControlFlow, TryV2 as Try};
+ ///
+ /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
+ /// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
+ ///
+ /// assert_eq!(Some(3).branch(), ControlFlow::Continue(3));
+ /// assert_eq!(None::<String>.branch(), ControlFlow::Break(None));
+ ///
+ /// assert_eq!(ControlFlow::<String, _>::Continue(3).branch(), ControlFlow::Continue(3));
+ /// assert_eq!(
+ /// ControlFlow::<_, String>::Break(3).branch(),
+ /// ControlFlow::Break(ControlFlow::Break(3)),
+ /// );
+ /// ```
+ #[unstable(feature = "try_trait_v2", issue = "84277")]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
+}
+
+/// Used to specify which residuals can be converted into which [`Try`] types.
+///
+/// Every `Try` type needs to be recreatable from its own associated
+/// `Residual` type, but can also have additional `FromResidual` implementations
+/// to support interconversion with other `Try` types.
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+pub trait FromResidual<R = <Self as Try>::Residual> {
+ /// Constructs the type from a compatible `Residual` type.
+ ///
+ /// This should be implemented consistently with the `branch` method such
+ /// that applying the `?` operator will get back an equivalent residual:
+ /// `FromResidual::from_residual(r).branch() --> ControlFlow::Break(r)`.
+ /// (It may not be an *identical* residual when interconversion is involved.)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(try_trait_v2)]
+ /// #![feature(control_flow_enum)]
+ /// use std::ops::{ControlFlow, FromResidual};
+ ///
+ /// assert_eq!(Result::<String, i64>::from_residual(Err(3_u8)), Err(3));
+ /// assert_eq!(Option::<String>::from_residual(None), None);
+ /// assert_eq!(
+ /// ControlFlow::<_, String>::from_residual(ControlFlow::Break(5)),
+ /// ControlFlow::Break(5),
+ /// );
+ /// ```
+ #[unstable(feature = "try_trait_v2", issue = "84277")]
+ fn from_residual(residual: R) -> Self;
+}
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index f1a0f45..04551dd 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -150,8 +150,8 @@
use crate::iter::{FromIterator, FusedIterator, TrustedLen};
use crate::pin::Pin;
use crate::{
- fmt, hint, mem,
- ops::{self, Deref, DerefMut},
+ convert, hint, mem,
+ ops::{self, ControlFlow, Deref, DerefMut},
};
/// The `Option` type. See [the module level documentation](self) for more.
@@ -489,8 +489,8 @@
}
}
- /// Applies a function to the contained value (if any),
- /// or returns the provided default (if not).
+ /// Returns the provided default result (if none),
+ /// or applies a function to the contained value (if any).
///
/// Arguments passed to `map_or` are eagerly evaluated; if you are passing
/// the result of a function call, it is recommended to use [`map_or_else`],
@@ -516,8 +516,8 @@
}
}
- /// Applies a function to the contained value (if any),
- /// or computes a default (if not).
+ /// Computes a default function result (if none), or
+ /// applies a different function to the contained value (if any).
///
/// # Examples
///
@@ -594,36 +594,6 @@
}
}
- /// Inserts `value` into the option then returns a mutable reference to it.
- ///
- /// If the option already contains a value, the old value is dropped.
- ///
- /// # Example
- ///
- /// ```
- /// #![feature(option_insert)]
- ///
- /// let mut opt = None;
- /// let val = opt.insert(1);
- /// assert_eq!(*val, 1);
- /// assert_eq!(opt.unwrap(), 1);
- /// let val = opt.insert(2);
- /// assert_eq!(*val, 2);
- /// *val = 3;
- /// assert_eq!(opt.unwrap(), 3);
- /// ```
- #[inline]
- #[unstable(feature = "option_insert", reason = "newly added", issue = "78271")]
- pub fn insert(&mut self, value: T) -> &mut T {
- *self = Some(value);
-
- match self {
- Some(v) => v,
- // SAFETY: the code above just filled the option
- None => unsafe { hint::unreachable_unchecked() },
- }
- }
-
/////////////////////////////////////////////////////////////////////////
// Iterator constructors
/////////////////////////////////////////////////////////////////////////
@@ -851,12 +821,46 @@
}
/////////////////////////////////////////////////////////////////////////
- // Entry-like operations to insert if None and return a reference
+ // Entry-like operations to insert a value and return a reference
/////////////////////////////////////////////////////////////////////////
+ /// Inserts `value` into the option then returns a mutable reference to it.
+ ///
+ /// If the option already contains a value, the old value is dropped.
+ ///
+ /// See also [`Option::get_or_insert`], which doesn't update the value if
+ /// the option already contains [`Some`].
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// let mut opt = None;
+ /// let val = opt.insert(1);
+ /// assert_eq!(*val, 1);
+ /// assert_eq!(opt.unwrap(), 1);
+ /// let val = opt.insert(2);
+ /// assert_eq!(*val, 2);
+ /// *val = 3;
+ /// assert_eq!(opt.unwrap(), 3);
+ /// ```
+ #[inline]
+ #[stable(feature = "option_insert", since = "1.53.0")]
+ pub fn insert(&mut self, value: T) -> &mut T {
+ *self = Some(value);
+
+ match self {
+ Some(v) => v,
+ // SAFETY: the code above just filled the option
+ None => unsafe { hint::unreachable_unchecked() },
+ }
+ }
+
/// Inserts `value` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
+ /// See also [`Option::insert`], which updates the value even if
+ /// the option already contains [`Some`].
+ ///
/// # Examples
///
/// ```
@@ -1121,90 +1125,6 @@
}
}
-impl<T: fmt::Debug> Option<T> {
- /// Consumes `self` while expecting [`None`] and returning nothing.
- ///
- /// # Panics
- ///
- /// Panics if the value is a [`Some`], with a panic message including the
- /// passed message, and the content of the [`Some`].
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(option_expect_none)]
- ///
- /// use std::collections::HashMap;
- /// let mut squares = HashMap::new();
- /// for i in -10..=10 {
- /// // This will not panic, since all keys are unique.
- /// squares.insert(i, i * i).expect_none("duplicate key");
- /// }
- /// ```
- ///
- /// ```should_panic
- /// #![feature(option_expect_none)]
- ///
- /// use std::collections::HashMap;
- /// let mut sqrts = HashMap::new();
- /// for i in -10..=10 {
- /// // This will panic, since both negative and positive `i` will
- /// // insert the same `i * i` key, returning the old `Some(i)`.
- /// sqrts.insert(i * i, i).expect_none("duplicate key");
- /// }
- /// ```
- #[inline]
- #[track_caller]
- #[unstable(feature = "option_expect_none", reason = "newly added", issue = "62633")]
- pub fn expect_none(self, msg: &str) {
- if let Some(val) = self {
- expect_none_failed(msg, &val);
- }
- }
-
- /// Consumes `self` while expecting [`None`] and returning nothing.
- ///
- /// # Panics
- ///
- /// Panics if the value is a [`Some`], with a custom panic message provided
- /// by the [`Some`]'s value.
- ///
- /// [`Some(v)`]: Some
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(option_unwrap_none)]
- ///
- /// use std::collections::HashMap;
- /// let mut squares = HashMap::new();
- /// for i in -10..=10 {
- /// // This will not panic, since all keys are unique.
- /// squares.insert(i, i * i).unwrap_none();
- /// }
- /// ```
- ///
- /// ```should_panic
- /// #![feature(option_unwrap_none)]
- ///
- /// use std::collections::HashMap;
- /// let mut sqrts = HashMap::new();
- /// for i in -10..=10 {
- /// // This will panic, since both negative and positive `i` will
- /// // insert the same `i * i` key, returning the old `Some(i)`.
- /// sqrts.insert(i * i, i).unwrap_none();
- /// }
- /// ```
- #[inline]
- #[track_caller]
- #[unstable(feature = "option_unwrap_none", reason = "newly added", issue = "62633")]
- pub fn unwrap_none(self) {
- if let Some(val) = self {
- expect_none_failed("called `Option::unwrap_none()` on a `Some` value", &val);
- }
- }
-}
-
impl<T: Default> Option<T> {
/// Returns the contained [`Some`] value or a default
///
@@ -1321,14 +1241,6 @@
panic!("{}", msg)
}
-// This is a separate function to reduce the code size of .expect_none() itself.
-#[inline(never)]
-#[cold]
-#[track_caller]
-fn expect_none_failed(msg: &str, value: &dyn fmt::Debug) -> ! {
- panic!("{}: {:?}", msg, value)
-}
-
/////////////////////////////////////////////////////////////////////////////
// Trait implementations
/////////////////////////////////////////////////////////////////////////////
@@ -1752,6 +1664,35 @@
}
}
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T> ops::TryV2 for Option<T> {
+ type Output = T;
+ type Residual = Option<convert::Infallible>;
+
+ #[inline]
+ fn from_output(output: Self::Output) -> Self {
+ Some(output)
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Some(v) => ControlFlow::Continue(v),
+ None => ControlFlow::Break(None),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T> ops::FromResidual for Option<T> {
+ #[inline]
+ fn from_residual(residual: Option<convert::Infallible>) -> Self {
+ match residual {
+ None => None,
+ }
+ }
+}
+
impl<T> Option<Option<T>> {
/// Converts from `Option<Option<T>>` to `Option<T>`
///
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index b2de0e1..3d88829 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -6,7 +6,7 @@
//! as moving an object with pointers to itself will invalidate them, which could cause undefined
//! behavior.
//!
-//! At a high level, a [`Pin<P>`] ensures that the pointee of any pointer type
+//! At a high level, a <code>[Pin]\<P></code> ensures that the pointee of any pointer type
//! `P` has a stable location in memory, meaning it cannot be moved elsewhere
//! and its memory cannot be deallocated until it gets dropped. We say that the
//! pointee is "pinned". Things get more subtle when discussing types that
@@ -14,13 +14,15 @@
//! for more details.
//!
//! By default, all types in Rust are movable. Rust allows passing all types by-value,
-//! and common smart-pointer types such as [`Box<T>`] and `&mut T` allow replacing and
-//! moving the values they contain: you can move out of a [`Box<T>`], or you can use [`mem::swap`].
-//! [`Pin<P>`] wraps a pointer type `P`, so [`Pin`]`<`[`Box`]`<T>>` functions much like a regular
-//! [`Box<T>`]: when a [`Pin`]`<`[`Box`]`<T>>` gets dropped, so do its contents, and the memory gets
-//! deallocated. Similarly, [`Pin`]`<&mut T>` is a lot like `&mut T`. However, [`Pin<P>`] does
-//! not let clients actually obtain a [`Box<T>`] or `&mut T` to pinned data, which implies that you
-//! cannot use operations such as [`mem::swap`]:
+//! and common smart-pointer types such as <code>[Box]\<T></code> and <code>[&mut] T</code> allow
+//! replacing and moving the values they contain: you can move out of a <code>[Box]\<T></code>,
+//! or you can use [`mem::swap`]. <code>[Pin]\<P></code> wraps a pointer type `P`, so
+//! <code>[Pin]<[Box]\<T>></code> functions much like a regular <code>[Box]\<T></code>:
+//! when a <code>[Pin]<[Box]\<T>></code> gets dropped, so do its contents, and the memory gets
+//! deallocated. Similarly, <code>[Pin]<[&mut] T></code> is a lot like <code>[&mut] T</code>.
+//! However, <code>[Pin]\<P></code> does not let clients actually obtain a <code>[Box]\<T></code>
+//! or <code>[&mut] T</code> to pinned data, which implies that you cannot use operations such
+//! as [`mem::swap`]:
//!
//! ```
//! use std::pin::Pin;
@@ -32,18 +34,18 @@
//! }
//! ```
//!
-//! It is worth reiterating that [`Pin<P>`] does *not* change the fact that a Rust compiler
-//! considers all types movable. [`mem::swap`] remains callable for any `T`. Instead, [`Pin<P>`]
-//! prevents certain *values* (pointed to by pointers wrapped in [`Pin<P>`]) from being
-//! moved by making it impossible to call methods that require `&mut T` on them
-//! (like [`mem::swap`]).
+//! It is worth reiterating that <code>[Pin]\<P></code> does *not* change the fact that a Rust
+//! compiler considers all types movable. [`mem::swap`] remains callable for any `T`. Instead,
+//! <code>[Pin]\<P></code> prevents certain *values* (pointed to by pointers wrapped in
+//! <code>[Pin]\<P></code>) from being moved by making it impossible to call methods that require
+//! <code>[&mut] T</code> on them (like [`mem::swap`]).
//!
-//! [`Pin<P>`] can be used to wrap any pointer type `P`, and as such it interacts with
-//! [`Deref`] and [`DerefMut`]. A [`Pin<P>`] where `P: Deref` should be considered
-//! as a "`P`-style pointer" to a pinned `P::Target` -- so, a [`Pin`]`<`[`Box`]`<T>>` is
-//! an owned pointer to a pinned `T`, and a [`Pin`]`<`[`Rc`]`<T>>` is a reference-counted
-//! pointer to a pinned `T`.
-//! For correctness, [`Pin<P>`] relies on the implementations of [`Deref`] and
+//! <code>[Pin]\<P></code> can be used to wrap any pointer type `P`, and as such it interacts with
+//! [`Deref`] and [`DerefMut`]. A <code>[Pin]\<P></code> where <code>P: [Deref]</code> should be
+//! considered as a "`P`-style pointer" to a pinned <code>P::[Target]</code> – so, a
+//! <code>[Pin]<[Box]\<T>></code> is an owned pointer to a pinned `T`, and a
+//! <code>[Pin]<[Rc]\<T>></code> is a reference-counted pointer to a pinned `T`.
+//! For correctness, <code>[Pin]\<P></code> relies on the implementations of [`Deref`] and
//! [`DerefMut`] not to move out of their `self` parameter, and only ever to
//! return a pointer to pinned data when they are called on a pinned pointer.
//!
@@ -53,19 +55,19 @@
//! rely on having a stable address. This includes all the basic types (like
//! [`bool`], [`i32`], and references) as well as types consisting solely of these
//! types. Types that do not care about pinning implement the [`Unpin`]
-//! auto-trait, which cancels the effect of [`Pin<P>`]. For `T: Unpin`,
-//! [`Pin`]`<`[`Box`]`<T>>` and [`Box<T>`] function identically, as do [`Pin`]`<&mut T>` and
-//! `&mut T`.
+//! auto-trait, which cancels the effect of <code>[Pin]\<P></code>. For <code>T: [Unpin]</code>,
+//! <code>[Pin]<[Box]\<T>></code> and <code>[Box]\<T></code> function identically, as do
+//! <code>[Pin]<[&mut] T></code> and <code>[&mut] T</code>.
//!
-//! Note that pinning and [`Unpin`] only affect the pointed-to type `P::Target`, not the pointer
-//! type `P` itself that got wrapped in [`Pin<P>`]. For example, whether or not [`Box<T>`] is
-//! [`Unpin`] has no effect on the behavior of [`Pin`]`<`[`Box`]`<T>>` (here, `T` is the
-//! pointed-to type).
+//! Note that pinning and [`Unpin`] only affect the pointed-to type <code>P::[Target]</code>,
+//! not the pointer type `P` itself that got wrapped in <code>[Pin]\<P></code>. For example,
+//! whether or not <code>[Box]\<T></code> is [`Unpin`] has no effect on the behavior of
+//! <code>[Pin]<[Box]\<T>></code> (here, `T` is the pointed-to type).
//!
//! # Example: self-referential struct
//!
//! Before we go into more details to explain the guarantees and choices
-//! associated with `Pin<T>`, we discuss some examples for how it might be used.
+//! associated with <code>[Pin]\<P></code>, we discuss some examples for how it might be used.
//! Feel free to [skip to where the theoretical discussion continues](#drop-guarantee).
//!
//! ```rust
@@ -129,7 +131,7 @@
//!
//! To make this work, every element has pointers to its predecessor and successor in
//! the list. Elements can only be added when they are pinned, because moving the elements
-//! around would invalidate the pointers. Moreover, the [`Drop`] implementation of a linked
+//! around would invalidate the pointers. Moreover, the [`Drop`][Drop] implementation of a linked
//! list element will patch the pointers of its predecessor and successor to remove itself
//! from the list.
//!
@@ -149,8 +151,8 @@
//! when [`drop`] is called*. Only once [`drop`] returns or panics, the memory may be reused.
//!
//! Memory can be "invalidated" by deallocation, but also by
-//! replacing a [`Some(v)`] by [`None`], or calling [`Vec::set_len`] to "kill" some elements
-//! off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without
+//! replacing a <code>[Some]\(v)</code> by [`None`], or calling [`Vec::set_len`] to "kill" some
+//! elements off of a vector. It can be repurposed by using [`ptr::write`] to overwrite it without
//! calling the destructor first. None of this is allowed for pinned data without calling [`drop`].
//!
//! This is exactly the kind of guarantee that the intrusive linked list from the previous
@@ -158,25 +160,25 @@
//!
//! Notice that this guarantee does *not* mean that memory does not leak! It is still
//! completely okay not ever to call [`drop`] on a pinned element (e.g., you can still
-//! call [`mem::forget`] on a [`Pin`]`<`[`Box`]`<T>>`). In the example of the doubly-linked
+//! call [`mem::forget`] on a <code>[Pin]<[Box]\<T>></code>). In the example of the doubly-linked
//! list, that element would just stay in the list. However you may not free or reuse the storage
//! *without calling [`drop`]*.
//!
//! # `Drop` implementation
//!
//! If your type uses pinning (such as the two examples above), you have to be careful
-//! when implementing [`Drop`]. The [`drop`] function takes `&mut self`, but this
+//! when implementing [`Drop`][Drop]. The [`drop`] function takes <code>[&mut] self</code>, but this
//! is called *even if your type was previously pinned*! It is as if the
//! compiler automatically called [`Pin::get_unchecked_mut`].
//!
//! This can never cause a problem in safe code because implementing a type that
//! relies on pinning requires unsafe code, but be aware that deciding to make
//! use of pinning in your type (for example by implementing some operation on
-//! [`Pin`]`<&Self>` or [`Pin`]`<&mut Self>`) has consequences for your [`Drop`]
-//! implementation as well: if an element of your type could have been pinned,
-//! you must treat [`Drop`] as implicitly taking [`Pin`]`<&mut Self>`.
+//! <code>[Pin]<[&]Self></code> or <code>[Pin]<[&mut] Self></code>) has consequences for your
+//! [`Drop`][Drop]implementation as well: if an element of your type could have been pinned,
+//! you must treat [`Drop`][Drop] as implicitly taking <code>[Pin]<[&mut] Self></code>.
//!
-//! For example, you could implement `Drop` as follows:
+//! For example, you could implement [`Drop`][Drop] as follows:
//!
//! ```rust,no_run
//! # use std::pin::Pin;
@@ -204,18 +206,18 @@
//! # Projections and Structural Pinning
//!
//! When working with pinned structs, the question arises how one can access the
-//! fields of that struct in a method that takes just [`Pin`]`<&mut Struct>`.
+//! fields of that struct in a method that takes just <code>[Pin]<[&mut] Struct></code>.
//! The usual approach is to write helper methods (so called *projections*)
-//! that turn [`Pin`]`<&mut Struct>` into a reference to the field, but what
-//! type should that reference have? Is it [`Pin`]`<&mut Field>` or `&mut Field`?
+//! that turn <code>[Pin]<[&mut] Struct></code> into a reference to the field, but what type should
+//! that reference have? Is it <code>[Pin]<[&mut] Field></code> or <code>[&mut] Field</code>?
//! The same question arises with the fields of an `enum`, and also when considering
-//! container/wrapper types such as [`Vec<T>`], [`Box<T>`], or [`RefCell<T>`].
-//! (This question applies to both mutable and shared references, we just
-//! use the more common case of mutable references here for illustration.)
+//! container/wrapper types such as <code>[Vec]\<T></code>, <code>[Box]\<T></code>,
+//! or <code>[RefCell]\<T></code>. (This question applies to both mutable and shared references,
+//! we just use the more common case of mutable references here for illustration.)
//!
-//! It turns out that it is actually up to the author of the data structure
-//! to decide whether the pinned projection for a particular field turns
-//! [`Pin`]`<&mut Struct>` into [`Pin`]`<&mut Field>` or `&mut Field`. There are some
+//! It turns out that it is actually up to the author of the data structure to decide whether
+//! the pinned projection for a particular field turns <code>[Pin]<[&mut] Struct></code>
+//! into <code>[Pin]<[&mut] Field></code> or <code>[&mut] Field</code>. There are some
//! constraints though, and the most important constraint is *consistency*:
//! every field can be *either* projected to a pinned reference, *or* have
//! pinning removed as part of the projection. If both are done for the same field,
@@ -230,12 +232,12 @@
//! ## Pinning *is not* structural for `field`
//!
//! It may seem counter-intuitive that the field of a pinned struct might not be pinned,
-//! but that is actually the easiest choice: if a [`Pin`]`<&mut Field>` is never created,
+//! but that is actually the easiest choice: if a <code>[Pin]<[&mut] Field></code> is never created,
//! nothing can go wrong! So, if you decide that some field does not have structural pinning,
//! all you have to ensure is that you never create a pinned reference to that field.
//!
//! Fields without structural pinning may have a projection method that turns
-//! [`Pin`]`<&mut Struct>` into `&mut Field`:
+//! <code>[Pin]<[&mut] Struct></code> into <code>[&mut] Field</code>:
//!
//! ```rust,no_run
//! # use std::pin::Pin;
@@ -249,16 +251,16 @@
//! }
//! ```
//!
-//! You may also `impl Unpin for Struct` *even if* the type of `field`
+//! You may also <code>impl [Unpin] for Struct</code> *even if* the type of `field`
//! is not [`Unpin`]. What that type thinks about pinning is not relevant
-//! when no [`Pin`]`<&mut Field>` is ever created.
+//! when no <code>[Pin]<[&mut] Field></code> is ever created.
//!
//! ## Pinning *is* structural for `field`
//!
//! The other option is to decide that pinning is "structural" for `field`,
//! meaning that if the struct is pinned then so is the field.
//!
-//! This allows writing a projection that creates a [`Pin`]`<&mut Field>`, thus
+//! This allows writing a projection that creates a <code>[Pin]<[&mut] Field></code>, thus
//! witnessing that the field is pinned:
//!
//! ```rust,no_run
@@ -278,34 +280,36 @@
//! 1. The struct must only be [`Unpin`] if all the structural fields are
//! [`Unpin`]. This is the default, but [`Unpin`] is a safe trait, so as the author of
//! the struct it is your responsibility *not* to add something like
-//! `impl<T> Unpin for Struct<T>`. (Notice that adding a projection operation
+//! <code>impl\<T> [Unpin] for Struct\<T></code>. (Notice that adding a projection operation
//! requires unsafe code, so the fact that [`Unpin`] is a safe trait does not break
-//! the principle that you only have to worry about any of this if you use `unsafe`.)
+//! the principle that you only have to worry about any of this if you use [`unsafe`].)
//! 2. The destructor of the struct must not move structural fields out of its argument. This
-//! is the exact point that was raised in the [previous section][drop-impl]: `drop` takes
-//! `&mut self`, but the struct (and hence its fields) might have been pinned before.
-//! You have to guarantee that you do not move a field inside your [`Drop`] implementation.
-//! In particular, as explained previously, this means that your struct must *not*
-//! be `#[repr(packed)]`.
+//! is the exact point that was raised in the [previous section][drop-impl]: [`drop`] takes
+//! <code>[&mut] self</code>, but the struct (and hence its fields) might have been pinned
+//! before. You have to guarantee that you do not move a field inside your [`Drop`][Drop]
+//! implementation. In particular, as explained previously, this means that your struct
+//! must *not* be `#[repr(packed)]`.
//! See that section for how to write [`drop`] in a way that the compiler can help you
//! not accidentally break pinning.
//! 3. You must make sure that you uphold the [`Drop` guarantee][drop-guarantee]:
//! once your struct is pinned, the memory that contains the
//! content is not overwritten or deallocated without calling the content's destructors.
-//! This can be tricky, as witnessed by [`VecDeque<T>`]: the destructor of [`VecDeque<T>`]
-//! can fail to call [`drop`] on all elements if one of the destructors panics. This violates
-//! the [`Drop`] guarantee, because it can lead to elements being deallocated without
-//! their destructor being called. ([`VecDeque<T>`] has no pinning projections, so this
+//! This can be tricky, as witnessed by <code>[VecDeque]\<T></code>: the destructor of
+//! <code>[VecDeque]\<T></code> can fail to call [`drop`] on all elements if one of the
+//! destructors panics. This violates the [`Drop`][Drop] guarantee, because it can lead to
+//! elements being deallocated without their destructor being called.
+//! (<code>[VecDeque]\<T></code> has no pinning projections, so this
//! does not cause unsoundness.)
//! 4. You must not offer any other operations that could lead to data being moved out of
//! the structural fields when your type is pinned. For example, if the struct contains an
-//! [`Option<T>`] and there is a `take`-like operation with type
-//! `fn(Pin<&mut Struct<T>>) -> Option<T>`,
-//! that operation can be used to move a `T` out of a pinned `Struct<T>` -- which means
+//! <code>[Option]\<T></code> and there is a [`take`][Option::take]-like operation with type
+//! <code>fn([Pin]<[&mut] Struct\<T>>) -> [Option]\<T></code>,
+//! that operation can be used to move a `T` out of a pinned `Struct<T>` – which means
//! pinning cannot be structural for the field holding this data.
//!
-//! For a more complex example of moving data out of a pinned type, imagine if [`RefCell<T>`]
-//! had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`.
+//! For a more complex example of moving data out of a pinned type,
+//! imagine if <code>[RefCell]\<T></code> had a method
+//! <code>fn get_pin_mut(self: [Pin]<[&mut] Self>) -> [Pin]<[&mut] T></code>.
//! Then we could do the following:
//! ```compile_fail
//! fn exploit_ref_cell<T>(rc: Pin<&mut RefCell<T>>) {
@@ -315,60 +319,65 @@
//! let content = &mut *b; // And here we have `&mut T` to the same data.
//! }
//! ```
-//! This is catastrophic, it means we can first pin the content of the [`RefCell<T>`]
-//! (using `RefCell::get_pin_mut`) and then move that content using the mutable
-//! reference we got later.
+//! This is catastrophic, it means we can first pin the content of the
+//! <code>[RefCell]\<T></code> (using <code>[RefCell]::get_pin_mut</code>) and then move that
+//! content using the mutable reference we got later.
//!
//! ## Examples
//!
-//! For a type like [`Vec<T>`], both possibilities (structural pinning or not) make sense.
-//! A [`Vec<T>`] with structural pinning could have `get_pin`/`get_pin_mut` methods to get
-//! pinned references to elements. However, it could *not* allow calling
-//! [`pop`][Vec::pop] on a pinned [`Vec<T>`] because that would move the (structurally pinned)
-//! contents! Nor could it allow [`push`][Vec::push], which might reallocate and thus also move the
-//! contents.
+//! For a type like <code>[Vec]\<T></code>, both possibilities (structural pinning or not) make
+//! sense. A <code>[Vec]\<T></code> with structural pinning could have `get_pin`/`get_pin_mut`
+//! methods to get pinned references to elements. However, it could *not* allow calling
+//! [`pop`][Vec::pop] on a pinned <code>[Vec]\<T></code> because that would move the (structurally
+//! pinned) contents! Nor could it allow [`push`][Vec::push], which might reallocate and thus also
+//! move the contents.
//!
-//! A [`Vec<T>`] without structural pinning could `impl<T> Unpin for Vec<T>`, because the contents
-//! are never pinned and the [`Vec<T>`] itself is fine with being moved as well.
+//! A <code>[Vec]\<T></code> without structural pinning could
+//! <code>impl\<T> [Unpin] for [Vec]\<T></code>, because the contents are never pinned
+//! and the <code>[Vec]\<T></code> itself is fine with being moved as well.
//! At that point pinning just has no effect on the vector at all.
//!
//! In the standard library, pointer types generally do not have structural pinning,
-//! and thus they do not offer pinning projections. This is why `Box<T>: Unpin` holds for all `T`.
-//! It makes sense to do this for pointer types, because moving the `Box<T>`
-//! does not actually move the `T`: the [`Box<T>`] can be freely movable (aka `Unpin`) even if
-//! the `T` is not. In fact, even [`Pin`]`<`[`Box`]`<T>>` and [`Pin`]`<&mut T>` are always
-//! [`Unpin`] themselves, for the same reason: their contents (the `T`) are pinned, but the
-//! pointers themselves can be moved without moving the pinned data. For both [`Box<T>`] and
-//! [`Pin`]`<`[`Box`]`<T>>`, whether the content is pinned is entirely independent of whether the
+//! and thus they do not offer pinning projections. This is why <code>[Box]\<T>: [Unpin]</code>
+//! holds for all `T`. It makes sense to do this for pointer types, because moving the
+//! <code>[Box]\<T></code> does not actually move the `T`: the <code>[Box]\<T></code> can be freely
+//! movable (aka [`Unpin`]) even if the `T` is not. In fact, even <code>[Pin]<[Box]\<T>></code> and
+//! <code>[Pin]<[&mut] T></code> are always [`Unpin`] themselves, for the same reason:
+//! their contents (the `T`) are pinned, but the pointers themselves can be moved without moving
+//! the pinned data. For both <code>[Box]\<T></code> and <code>[Pin]<[Box]\<T>></code>,
+//! whether the content is pinned is entirely independent of whether the
//! pointer is pinned, meaning pinning is *not* structural.
//!
//! When implementing a [`Future`] combinator, you will usually need structural pinning
//! for the nested futures, as you need to get pinned references to them to call [`poll`].
//! But if your combinator contains any other data that does not need to be pinned,
//! you can make those fields not structural and hence freely access them with a
-//! mutable reference even when you just have [`Pin`]`<&mut Self>` (such as in your own
+//! mutable reference even when you just have <code>[Pin]<[&mut] Self></code> (such as in your own
//! [`poll`] implementation).
//!
-//! [`Deref`]: crate::ops::Deref
-//! [`DerefMut`]: crate::ops::DerefMut
-//! [`mem::swap`]: crate::mem::swap
-//! [`mem::forget`]: crate::mem::forget
-//! [`Box<T>`]: ../../std/boxed/struct.Box.html
-//! [`Vec<T>`]: ../../std/vec/struct.Vec.html
-//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len
-//! [`Box`]: ../../std/boxed/struct.Box.html
-//! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop
-//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push
-//! [`Rc`]: ../../std/rc/struct.Rc.html
-//! [`RefCell<T>`]: crate::cell::RefCell
-//! [`drop`]: Drop::drop
-//! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html
-//! [`Some(v)`]: Some
-//! [`ptr::write`]: crate::ptr::write
-//! [`Future`]: crate::future::Future
+//! [Deref]: crate::ops::Deref "ops::Deref"
+//! [`Deref`]: crate::ops::Deref "ops::Deref"
+//! [Target]: crate::ops::Deref::Target "ops::Deref::Target"
+//! [`DerefMut`]: crate::ops::DerefMut "ops::DerefMut"
+//! [`mem::swap`]: crate::mem::swap "mem::swap"
+//! [`mem::forget`]: crate::mem::forget "mem::forget"
+//! [Vec]: ../../std/vec/struct.Vec.html "Vec"
+//! [`Vec::set_len`]: ../../std/vec/struct.Vec.html#method.set_len "Vec::set_len"
+//! [Box]: ../../std/boxed/struct.Box.html "Box"
+//! [Vec::pop]: ../../std/vec/struct.Vec.html#method.pop "Vec::pop"
+//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push "Vec::push"
+//! [Rc]: ../../std/rc/struct.Rc.html "rc::Rc"
+//! [RefCell]: crate::cell::RefCell "cell::RefCell"
+//! [`drop`]: Drop::drop "Drop::drop"
+//! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque"
+//! [`ptr::write`]: crate::ptr::write "ptr::write"
+//! [`Future`]: crate::future::Future "future::Future"
//! [drop-impl]: #drop-implementation
//! [drop-guarantee]: #drop-guarantee
-//! [`poll`]: crate::future::Future::poll
+//! [`poll`]: crate::future::Future::poll "future::Future::poll"
+//! [&]: ../../std/primitive.reference.html "shared reference"
+//! [&mut]: ../../std/primitive.reference.html "mutable reference"
+//! [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe"
#![stable(feature = "pin", since = "1.33.0")]
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index 7d33ca8..c89fe57 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -67,7 +67,6 @@
bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
};
-#[cfg(not(bootstrap))]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[doc(no_inline)]
pub use crate::macros::builtin::derive;
@@ -80,7 +79,6 @@
#[doc(no_inline)]
pub use crate::macros::builtin::cfg_accessible;
-#[cfg(not(bootstrap))]
#[unstable(
feature = "cfg_eval",
issue = "82679",
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index b511466..b9b2ba9 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -51,7 +51,6 @@
/// Decompose a (possibly wide) pointer into is address and metadata components.
///
/// The pointer can be later reconstructed with [`from_raw_parts`].
- #[cfg(not(bootstrap))]
#[unstable(feature = "ptr_metadata", issue = "81513")]
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
@@ -184,8 +183,7 @@
/// Behavior:
///
/// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
@@ -210,6 +208,7 @@
/// enables more aggressive compiler optimizations.
///
/// [`wrapping_offset`]: #method.wrapping_offset
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -227,7 +226,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const unsafe fn offset(self, count: isize) -> *const T
where
T: Sized,
@@ -245,9 +244,8 @@
///
/// This operation itself is always safe, but using the resulting pointer is not.
///
- /// The resulting pointer remains attached to the same allocated object that `self` points to.
- /// It may *not* be used to access a different allocated object. Note that in Rust, every
- /// (stack-allocated) variable is considered a separate allocated object.
+ /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
+ /// be used to read or write other allocated objects.
///
/// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
@@ -265,10 +263,8 @@
/// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
/// words, leaving the allocated object and then re-entering it later is permitted.
///
- /// If you need to cross object boundaries, cast the pointer to an integer and
- /// do the arithmetic there.
- ///
/// [`offset`]: #method.offset
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -292,7 +288,7 @@
#[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_offset(self, count: isize) -> *const T
where
T: Sized,
@@ -314,8 +310,7 @@
/// Behavior:
///
/// * Both the starting and other pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * Both pointers must be *derived from* a pointer to the same object.
/// (See below for an example.)
@@ -345,6 +340,7 @@
/// such large allocations either.)
///
/// [`add`]: #method.add
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Panics
///
@@ -468,8 +464,7 @@
/// Behavior:
///
/// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
@@ -494,6 +489,7 @@
/// enables more aggressive compiler optimizations.
///
/// [`wrapping_add`]: #method.wrapping_add
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -511,7 +507,7 @@
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const unsafe fn add(self, count: usize) -> Self
where
T: Sized,
@@ -532,8 +528,7 @@
/// Behavior:
///
/// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
///
@@ -558,6 +553,7 @@
/// enables more aggressive compiler optimizations.
///
/// [`wrapping_sub`]: #method.wrapping_sub
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -594,9 +590,8 @@
///
/// This operation itself is always safe, but using the resulting pointer is not.
///
- /// The resulting pointer remains attached to the same allocated object that `self` points to.
- /// It may *not* be used to access a different allocated object. Note that in Rust, every
- /// (stack-allocated) variable is considered a separate allocated object.
+ /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
+ /// be used to read or write other allocated objects.
///
/// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
@@ -614,10 +609,8 @@
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
/// allocated object and then re-entering it later is permitted.
///
- /// If you need to cross object boundaries, cast the pointer to an integer and
- /// do the arithmetic there.
- ///
/// [`add`]: #method.add
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -641,7 +634,7 @@
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_add(self, count: usize) -> Self
where
T: Sized,
@@ -659,9 +652,8 @@
///
/// This operation itself is always safe, but using the resulting pointer is not.
///
- /// The resulting pointer remains attached to the same allocated object that `self` points to.
- /// It may *not* be used to access a different allocated object. Note that in Rust, every
- /// (stack-allocated) variable is considered a separate allocated object.
+ /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
+ /// be used to read or write other allocated objects.
///
/// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
@@ -679,10 +671,8 @@
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
/// allocated object and then re-entering it later is permitted.
///
- /// If you need to cross object boundaries, cast the pointer to an integer and
- /// do the arithmetic there.
- ///
/// [`sub`]: #method.sub
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -734,7 +724,7 @@
/// #![feature(set_ptr_value)]
/// # use core::fmt::Debug;
/// let arr: [i32; 3] = [1, 2, 3];
- /// let mut ptr = &arr[0] as *const dyn Debug;
+ /// let mut ptr = arr.as_ptr() as *const dyn Debug;
/// let thin = ptr as *const u8;
/// unsafe {
/// ptr = ptr.set_ptr_value(thin.add(8));
@@ -924,13 +914,6 @@
#[unstable(feature = "slice_ptr_len", issue = "71146")]
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
pub const fn len(self) -> usize {
- #[cfg(bootstrap)]
- {
- // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
- // Only `std` can make this guarantee.
- unsafe { Repr { rust: self }.raw }.len
- }
- #[cfg(not(bootstrap))]
metadata(self)
}
@@ -997,7 +980,7 @@
/// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
/// and it must be properly aligned. This means in particular:
///
- /// * The entire memory range of this slice must be contained within a single allocated object!
+ /// * The entire memory range of this slice must be contained within a single [allocated object]!
/// Slices can never span across multiple allocated objects.
///
/// * The pointer must be aligned even for zero-length slices. One
@@ -1019,6 +1002,7 @@
/// See also [`slice::from_raw_parts`][].
///
/// [valid]: crate::ptr#safety
+ /// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index fd24469..28044e0 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -55,6 +55,14 @@
//! has size 0, i.e., even if memory is not actually touched. Consider using
//! [`NonNull::dangling`] in such cases.
//!
+//! ## Allocated object
+//!
+//! For several operations, such as [`offset`] or field projections (`expr.field`), the notion of an
+//! "allocated object" becomes relevant. An allocated object is a contiguous region of memory.
+//! Common examples of allocated objects include stack-allocated variables (each variable is a
+//! separate allocated object), heap allocations (each allocation created by the global allocator is
+//! a separate allocated object), and `static` variables.
+//!
//! [aliasing]: ../../nomicon/aliasing.html
//! [book]: ../../book/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
//! [ub]: ../../reference/behavior-considered-undefined.html
@@ -82,11 +90,8 @@
#[doc(inline)]
pub use crate::intrinsics::write_bytes;
-#[cfg(not(bootstrap))]
mod metadata;
-#[cfg(not(bootstrap))]
pub(crate) use metadata::PtrRepr;
-#[cfg(not(bootstrap))]
#[unstable(feature = "ptr_metadata", issue = "81513")]
pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin};
@@ -205,7 +210,8 @@
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
-#[rustc_const_stable(feature = "const_ptr_null", since = "1.32.0")]
+#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_diagnostic_item = "ptr_null"]
pub const fn null<T>() -> *const T {
0 as *const T
}
@@ -223,38 +229,12 @@
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_promotable]
-#[rustc_const_stable(feature = "const_ptr_null", since = "1.32.0")]
+#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")]
+#[rustc_diagnostic_item = "ptr_null_mut"]
pub const fn null_mut<T>() -> *mut T {
0 as *mut T
}
-#[cfg(bootstrap)]
-#[repr(C)]
-pub(crate) union Repr<T> {
- pub(crate) rust: *const [T],
- rust_mut: *mut [T],
- pub(crate) raw: FatPtr<T>,
-}
-
-#[cfg(bootstrap)]
-#[repr(C)]
-pub(crate) struct FatPtr<T> {
- data: *const T,
- pub(crate) len: usize,
-}
-
-#[cfg(bootstrap)]
-// Manual impl needed to avoid `T: Clone` bound.
-impl<T> Clone for FatPtr<T> {
- fn clone(&self) -> Self {
- *self
- }
-}
-
-#[cfg(bootstrap)]
-// Manual impl needed to avoid `T: Copy` bound.
-impl<T> Copy for FatPtr<T> {}
-
/// Forms a raw slice from a pointer and a length.
///
/// The `len` argument is the number of **elements**, not the number of bytes.
@@ -279,14 +259,6 @@
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
pub const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
- #[cfg(bootstrap)]
- {
- // SAFETY: Accessing the value from the `Repr` union is safe since *const [T]
- // and FatPtr have the same memory layouts. Only std can make this
- // guarantee.
- unsafe { Repr { raw: FatPtr { data, len } }.rust }
- }
- #[cfg(not(bootstrap))]
from_raw_parts(data.cast(), len)
}
@@ -319,13 +291,6 @@
#[stable(feature = "slice_from_raw_parts", since = "1.42.0")]
#[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")]
pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
- #[cfg(bootstrap)]
- {
- // SAFETY: Accessing the value from the `Repr` union is safe since *mut [T]
- // and FatPtr have the same memory layouts
- unsafe { Repr { raw: FatPtr { data, len } }.rust_mut }
- }
- #[cfg(not(bootstrap))]
from_raw_parts_mut(data.cast(), len)
}
@@ -464,19 +429,32 @@
#[inline]
pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
- // For types smaller than the block optimization below,
- // just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
- // SAFETY: the caller must guarantee that `x` and `y` are valid
- // for writes, properly aligned, and non-overlapping.
- unsafe {
- let z = read(x);
- copy_nonoverlapping(y, x, 1);
- write(y, z);
+ // 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_nonoverlapping_bytes` 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 `swap_nonoverlapping` into an intrinsic, which
+ // a backend can choose to implement using the block optimization, or not.
+ #[cfg(not(target_arch = "spirv"))]
+ {
+ // Only apply the block optimization in `swap_nonoverlapping_bytes` for types
+ // at least as large as the block size, to avoid pessimizing codegen.
+ if mem::size_of::<T>() >= 32 {
+ // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`.
+ unsafe { swap_nonoverlapping(x, y, 1) };
+ return;
}
- } else {
- // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`.
- unsafe { swap_nonoverlapping(x, y, 1) };
+ }
+
+ // Direct swapping, for the cases not going through the block optimization.
+ // SAFETY: the caller must guarantee that `x` and `y` are valid
+ // for writes, properly aligned, and non-overlapping.
+ unsafe {
+ let z = read(x);
+ copy_nonoverlapping(y, x, 1);
+ write(y, z);
}
}
@@ -765,6 +743,7 @@
/// unaligned: 0x01020304,
/// };
///
+/// #[allow(unaligned_references)]
/// let v = unsafe {
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
/// let unaligned =
@@ -962,6 +941,7 @@
/// let v = 0x01020304;
/// let mut packed: Packed = unsafe { std::mem::zeroed() };
///
+/// #[allow(unaligned_references)]
/// let v = unsafe {
/// // Here we attempt to take the address of a 32-bit integer which is not aligned.
/// let unaligned =
@@ -1516,6 +1496,10 @@
/// 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.
+///
/// # Example
///
/// ```
@@ -1532,6 +1516,10 @@
/// let raw_f2 = ptr::addr_of!(packed.f2);
/// assert_eq!(unsafe { raw_f2.read_unaligned() }, 2);
/// ```
+///
+/// See [`addr_of_mut`] for how to create a pointer to unininitialized data.
+/// Doing that with `addr_of` would not make much sense since one could only
+/// read the data, and that would be Undefined Behavior.
#[stable(feature = "raw_ref_macros", since = "1.51.0")]
#[rustc_macro_transparency = "semitransparent"]
#[allow_internal_unstable(raw_ref_op)]
@@ -1548,7 +1536,13 @@
/// as all other references. This macro can create a raw pointer *without* creating
/// a reference first.
///
-/// # Example
+/// 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.
+///
+/// # Examples
+///
+/// **Creating a pointer to unaligned data:**
///
/// ```
/// use std::ptr;
@@ -1565,6 +1559,23 @@
/// unsafe { raw_f2.write_unaligned(42); }
/// assert_eq!({packed.f2}, 42); // `{...}` forces copying the field instead of creating a reference.
/// ```
+///
+/// **Creating a pointer to uninitialized data:**
+///
+/// ```rust
+/// use std::{ptr, mem::MaybeUninit};
+///
+/// struct Demo {
+/// field: bool,
+/// }
+///
+/// let mut uninit = MaybeUninit::<Demo>::uninit();
+/// // `&uninit.as_mut().field` would create a reference to an uninitialized `bool`,
+/// // and thus be Undefined Behavior!
+/// let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) };
+/// unsafe { f1_ptr.write(true); }
+/// let init = unsafe { uninit.assume_init() };
+/// ```
#[stable(feature = "raw_ref_macros", since = "1.51.0")]
#[rustc_macro_transparency = "semitransparent"]
#[allow_internal_unstable(raw_ref_op)]
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index a9de233..16f6efc 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -50,7 +50,6 @@
/// Decompose a (possibly wide) pointer into is address and metadata components.
///
/// The pointer can be later reconstructed with [`from_raw_parts_mut`].
- #[cfg(not(bootstrap))]
#[unstable(feature = "ptr_metadata", issue = "81513")]
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
@@ -189,8 +188,7 @@
/// Behavior:
///
/// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
@@ -215,6 +213,7 @@
/// enables more aggressive compiler optimizations.
///
/// [`wrapping_offset`]: #method.wrapping_offset
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -232,7 +231,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const unsafe fn offset(self, count: isize) -> *mut T
where
T: Sized,
@@ -251,9 +250,8 @@
///
/// This operation itself is always safe, but using the resulting pointer is not.
///
- /// The resulting pointer remains attached to the same allocated object that `self` points to.
- /// It may *not* be used to access a different allocated object. Note that in Rust, every
- /// (stack-allocated) variable is considered a separate allocated object.
+ /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
+ /// be used to read or write other allocated objects.
///
/// In other words, `let z = x.wrapping_offset((y as isize) - (x as isize))` does *not* make `z`
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
@@ -271,10 +269,8 @@
/// `x.wrapping_offset(o).wrapping_offset(o.wrapping_neg())` is always the same as `x`. In other
/// words, leaving the allocated object and then re-entering it later is permitted.
///
- /// If you need to cross object boundaries, cast the pointer to an integer and
- /// do the arithmetic there.
- ///
/// [`offset`]: #method.offset
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -298,7 +294,7 @@
#[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_offset(self, count: isize) -> *mut T
where
T: Sized,
@@ -485,8 +481,7 @@
/// Behavior:
///
/// * Both the starting and other pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * Both pointers must be *derived from* a pointer to the same object.
/// (See below for an example.)
@@ -516,6 +511,7 @@
/// such large allocations either.)
///
/// [`add`]: #method.add
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Panics
///
@@ -575,8 +571,7 @@
/// Behavior:
///
/// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
///
@@ -618,7 +613,7 @@
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const unsafe fn add(self, count: usize) -> Self
where
T: Sized,
@@ -639,8 +634,7 @@
/// Behavior:
///
/// * Both the starting and resulting pointer must be either in bounds or one
- /// byte past the end of the same allocated object. Note that in Rust,
- /// every (stack-allocated) variable is considered a separate allocated object.
+ /// byte past the end of the same [allocated object].
///
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
///
@@ -665,6 +659,7 @@
/// enables more aggressive compiler optimizations.
///
/// [`wrapping_sub`]: #method.wrapping_sub
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -701,9 +696,8 @@
///
/// This operation itself is always safe, but using the resulting pointer is not.
///
- /// The resulting pointer remains attached to the same allocated object that `self` points to.
- /// It may *not* be used to access a different allocated object. Note that in Rust, every
- /// (stack-allocated) variable is considered a separate allocated object.
+ /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
+ /// be used to read or write other allocated objects.
///
/// In other words, `let z = x.wrapping_add((y as usize) - (x as usize))` does *not* make `z`
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
@@ -721,10 +715,8 @@
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
/// allocated object and then re-entering it later is permitted.
///
- /// If you need to cross object boundaries, cast the pointer to an integer and
- /// do the arithmetic there.
- ///
/// [`add`]: #method.add
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -748,7 +740,7 @@
#[stable(feature = "pointer_methods", since = "1.26.0")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
- #[inline]
+ #[inline(always)]
pub const fn wrapping_add(self, count: usize) -> Self
where
T: Sized,
@@ -766,9 +758,8 @@
///
/// This operation itself is always safe, but using the resulting pointer is not.
///
- /// The resulting pointer remains attached to the same allocated object that `self` points to.
- /// It may *not* be used to access a different allocated object. Note that in Rust, every
- /// (stack-allocated) variable is considered a separate allocated object.
+ /// The resulting pointer "remembers" the [allocated object] that `self` points to; it may not
+ /// be used to read or write other allocated objects.
///
/// In other words, `let z = x.wrapping_sub((x as usize) - (y as usize))` does *not* make `z`
/// the same as `y` even if we assume `T` has size `1` and there is no overflow: `z` is still
@@ -786,10 +777,8 @@
/// `x.wrapping_add(o).wrapping_sub(o)` is always the same as `x`. In other words, leaving the
/// allocated object and then re-entering it later is permitted.
///
- /// If you need to cross object boundaries, cast the pointer to an integer and
- /// do the arithmetic there.
- ///
/// [`sub`]: #method.sub
+ /// [allocated object]: crate::ptr#allocated-object
///
/// # Examples
///
@@ -841,7 +830,7 @@
/// #![feature(set_ptr_value)]
/// # use core::fmt::Debug;
/// let mut arr: [i32; 3] = [1, 2, 3];
- /// let mut ptr = &mut arr[0] as *mut dyn Debug;
+ /// let mut ptr = arr.as_mut_ptr() as *mut dyn Debug;
/// let thin = ptr as *mut u8;
/// unsafe {
/// ptr = ptr.set_ptr_value(thin.add(8));
@@ -1184,13 +1173,6 @@
#[unstable(feature = "slice_ptr_len", issue = "71146")]
#[rustc_const_unstable(feature = "const_slice_ptr_len", issue = "71146")]
pub const fn len(self) -> usize {
- #[cfg(bootstrap)]
- {
- // SAFETY: this is safe because `*const [T]` and `FatPtr<T>` have the same layout.
- // Only `std` can make this guarantee.
- unsafe { Repr { rust_mut: self }.raw }.len
- }
- #[cfg(not(bootstrap))]
metadata(self)
}
@@ -1260,7 +1242,7 @@
/// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::<T>()` many bytes,
/// and it must be properly aligned. This means in particular:
///
- /// * The entire memory range of this slice must be contained within a single allocated object!
+ /// * The entire memory range of this slice must be contained within a single [allocated object]!
/// Slices can never span across multiple allocated objects.
///
/// * The pointer must be aligned even for zero-length slices. One
@@ -1282,6 +1264,7 @@
/// See also [`slice::from_raw_parts`][].
///
/// [valid]: crate::ptr#safety
+ /// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
@@ -1310,7 +1293,7 @@
/// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::<T>()`
/// many bytes, and it must be properly aligned. This means in particular:
///
- /// * The entire memory range of this slice must be contained within a single allocated object!
+ /// * The entire memory range of this slice must be contained within a single [allocated object]!
/// Slices can never span across multiple allocated objects.
///
/// * The pointer must be aligned even for zero-length slices. One
@@ -1332,6 +1315,7 @@
/// See also [`slice::from_raw_parts_mut`][].
///
/// [valid]: crate::ptr#safety
+ /// [allocated object]: crate::ptr#allocated-object
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 8d533cd..e525f61 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -72,7 +72,7 @@
/// sentinel value. Types that lazily allocate must track initialization by
/// some other means.
#[stable(feature = "nonnull", since = "1.25.0")]
- #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_nonnull_dangling", since = "1.36.0")]
#[inline]
pub const fn dangling() -> Self {
// SAFETY: mem::align_of() returns a non-zero usize which is then casted
@@ -110,7 +110,7 @@
/// [the module documentation]: crate::ptr#safety
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_ref(&self) -> &MaybeUninit<T> {
+ pub unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit<T> {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { &*self.cast().as_ptr() }
@@ -142,7 +142,7 @@
/// [the module documentation]: crate::ptr#safety
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_mut(&mut self) -> &mut MaybeUninit<T> {
+ pub unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit<T> {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { &mut *self.cast().as_ptr() }
@@ -156,7 +156,7 @@
///
/// `ptr` must be non-null.
#[stable(feature = "nonnull", since = "1.25.0")]
- #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_nonnull_new_unchecked", since = "1.25.0")]
#[inline]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
// SAFETY: the caller must guarantee that `ptr` is non-null.
@@ -181,7 +181,6 @@
/// See the documentation of [`std::ptr::from_raw_parts`] for more details.
///
/// [`std::ptr::from_raw_parts`]: crate::ptr::from_raw_parts
- #[cfg(not(bootstrap))]
#[unstable(feature = "ptr_metadata", issue = "81513")]
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
@@ -198,7 +197,6 @@
/// Decompose a (possibly wide) pointer into is address and metadata components.
///
/// The pointer can be later reconstructed with [`NonNull::from_raw_parts`].
- #[cfg(not(bootstrap))]
#[unstable(feature = "ptr_metadata", issue = "81513")]
#[rustc_const_unstable(feature = "ptr_metadata", issue = "81513")]
#[inline]
@@ -244,7 +242,7 @@
/// [the module documentation]: crate::ptr#safety
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
- pub unsafe fn as_ref(&self) -> &T {
+ pub unsafe fn as_ref<'a>(&self) -> &'a T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a reference.
unsafe { &*self.as_ptr() }
@@ -280,7 +278,7 @@
/// [the module documentation]: crate::ptr#safety
#[stable(feature = "nonnull", since = "1.25.0")]
#[inline]
- pub unsafe fn as_mut(&mut self) -> &mut T {
+ pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
// SAFETY: the caller must guarantee that `self` meets all the
// requirements for a mutable reference.
unsafe { &mut *self.as_ptr() }
@@ -288,7 +286,7 @@
/// Casts to a pointer of another type.
#[stable(feature = "nonnull_cast", since = "1.27.0")]
- #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_nonnull_cast", since = "1.36.0")]
#[inline]
pub const fn cast<U>(self) -> NonNull<U> {
// SAFETY: `self` is a `NonNull` pointer which is necessarily non-null
@@ -427,7 +425,7 @@
/// [valid]: crate::ptr#safety
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_slice(&self) -> &[MaybeUninit<T>] {
+ pub unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit<T>] {
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice`.
unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) }
}
@@ -488,7 +486,7 @@
/// ```
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
- pub unsafe fn as_uninit_slice_mut(&self) -> &mut [MaybeUninit<T>] {
+ pub unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit<T>] {
// SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`.
unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) }
}
diff --git a/library/core/src/raw.rs b/library/core/src/raw.rs
index 1227d9b..6d1e28f 100644
--- a/library/core/src/raw.rs
+++ b/library/core/src/raw.rs
@@ -1,5 +1,9 @@
#![allow(missing_docs)]
#![unstable(feature = "raw", issue = "27751")]
+#![rustc_deprecated(
+ since = "1.53.0",
+ reason = "use pointer metadata APIs instead https://github.com/rust-lang/rust/issues/81513"
+)]
//! Contains struct definitions for the layout of compiler built-in types.
//!
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 2ce8a70..e0071f8 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -228,7 +228,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
-use crate::ops::{self, Deref, DerefMut};
+use crate::ops::{self, ControlFlow, Deref, DerefMut};
use crate::{convert, fmt, hint};
/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
@@ -506,8 +506,8 @@
}
}
- /// Applies a function to the contained value (if [`Ok`]),
- /// or returns the provided default (if [`Err`]).
+ /// Returns the provided default (if [`Err`]), or
+ /// applies a function to the contained value (if [`Ok`]),
///
/// Arguments passed to `map_or` are eagerly evaluated; if you are passing
/// the result of a function call, it is recommended to use [`map_or_else`],
@@ -533,9 +533,9 @@
}
}
- /// Maps a `Result<T, E>` to `U` by applying a function to a
- /// contained [`Ok`] value, or a fallback function to a
- /// contained [`Err`] value.
+ /// Maps a `Result<T, E>` to `U` by applying a fallback function to a
+ /// contained [`Err`] value, or a default function to a
+ /// contained [`Ok`] value.
///
/// This function can be used to unpack a successful result
/// while handling an error.
@@ -1167,6 +1167,42 @@
}
}
+#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")]
+impl<T: Into<!>, E> Result<T, E> {
+ /// Returns the contained [`Err`] value, but never panics.
+ ///
+ /// Unlike [`unwrap_err`], this method is known to never panic on the
+ /// result types it is implemented for. Therefore, it can be used
+ /// instead of `unwrap_err` as a maintainability safeguard that will fail
+ /// to compile if the ok type of the `Result` is later changed
+ /// to a type that can actually occur.
+ ///
+ /// [`unwrap_err`]: Result::unwrap_err
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ ///
+ /// ```
+ /// # #![feature(never_type)]
+ /// # #![feature(unwrap_infallible)]
+ ///
+ /// fn only_bad_news() -> Result<!, String> {
+ /// Err("Oops, it failed".into())
+ /// }
+ ///
+ /// let error: String = only_bad_news().into_err();
+ /// println!("{}", error);
+ /// ```
+ #[inline]
+ pub fn into_err(self) -> E {
+ match self {
+ Ok(x) => x.into(),
+ Err(e) => e,
+ }
+ }
+}
+
impl<T: Deref, E> Result<T, E> {
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&<T as Deref>::Target, &E>`.
///
@@ -1610,3 +1646,32 @@
Err(v)
}
}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E> ops::TryV2 for Result<T, E> {
+ type Output = T;
+ type Residual = Result<convert::Infallible, E>;
+
+ #[inline]
+ fn from_output(output: Self::Output) -> Self {
+ Ok(output)
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Ok(v) => ControlFlow::Continue(v),
+ Err(e) => ControlFlow::Break(Err(e)),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Result<T, F> {
+ #[inline]
+ fn from_residual(residual: Result<convert::Infallible, E>) -> Self {
+ match residual {
+ Err(e) => Err(From::from(e)),
+ }
+ }
+}
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 42032bc..906dcb1 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -1,6 +1,10 @@
//! Operations on ASCII `[u8]`.
+use crate::ascii;
+use crate::fmt::{self, Write};
+use crate::iter;
use crate::mem;
+use crate::ops;
#[lang = "slice_u8"]
#[cfg(not(test))]
@@ -19,7 +23,7 @@
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
- self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq_ignore_ascii_case(b))
+ self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b))
}
/// Converts this slice to its ASCII upper case equivalent in-place.
@@ -55,6 +59,95 @@
byte.make_ascii_lowercase();
}
}
+
+ /// Returns an iterator that produces an escaped version of this slice,
+ /// treating it as an ASCII string.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(inherent_ascii_escape)]
+ ///
+ /// let s = b"0\t\r\n'\"\\\x9d";
+ /// let escaped = s.escape_ascii().to_string();
+ /// assert_eq!(escaped, "0\\t\\r\\n\\'\\\"\\\\\\x9d");
+ /// ```
+ #[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+ pub fn escape_ascii(&self) -> EscapeAscii<'_> {
+ EscapeAscii { inner: self.iter().flat_map(EscapeByte) }
+ }
+}
+
+impl_fn_for_zst! {
+ #[derive(Clone)]
+ struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault {
+ ascii::escape_default(*byte)
+ };
+}
+
+/// An iterator over the escaped version of a byte slice.
+///
+/// This `struct` is created by the [`slice::escape_ascii`] method. See its
+/// documentation for more information.
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+#[derive(Clone)]
+pub struct EscapeAscii<'a> {
+ inner: iter::FlatMap<super::Iter<'a, u8>, ascii::EscapeDefault, EscapeByte>,
+}
+
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::Iterator for EscapeAscii<'a> {
+ type Item = u8;
+ #[inline]
+ fn next(&mut self) -> Option<u8> {
+ self.inner.next()
+ }
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.inner.size_hint()
+ }
+ #[inline]
+ fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
+ where
+ Fold: FnMut(Acc, Self::Item) -> R,
+ R: ops::Try<Ok = Acc>,
+ {
+ self.inner.try_fold(init, fold)
+ }
+ #[inline]
+ fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
+ where
+ Fold: FnMut(Acc, Self::Item) -> Acc,
+ {
+ self.inner.fold(init, fold)
+ }
+ #[inline]
+ fn last(mut self) -> Option<u8> {
+ self.next_back()
+ }
+}
+
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::DoubleEndedIterator for EscapeAscii<'a> {
+ fn next_back(&mut self) -> Option<u8> {
+ self.inner.next_back()
+ }
+}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::ExactSizeIterator for EscapeAscii<'a> {}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> iter::FusedIterator for EscapeAscii<'a> {}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> fmt::Display for EscapeAscii<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.clone().try_for_each(|b| f.write_char(b as char))
+ }
+}
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+impl<'a> fmt::Debug for EscapeAscii<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("EscapeAscii").finish_non_exhaustive()
+ }
}
/// Returns `true` if any byte in the word `v` is nonascii (>= 128). Snarfed
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index c92b37b..f722430 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -81,6 +81,8 @@
impl Sealed for ops::RangeInclusive<usize> {}
#[stable(feature = "slice_get_slice", since = "1.28.0")]
impl Sealed for ops::RangeToInclusive<usize> {}
+ #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
+ impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
}
/// A helper trait used for indexing operations.
@@ -546,3 +548,113 @@
ops::Range { start, end }
}
+
+/// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
+fn into_range_unchecked(
+ len: usize,
+ (start, end): (ops::Bound<usize>, ops::Bound<usize>),
+) -> ops::Range<usize> {
+ use ops::Bound;
+ let start = match start {
+ Bound::Included(i) => i,
+ Bound::Excluded(i) => i + 1,
+ Bound::Unbounded => 0,
+ };
+ let end = match end {
+ Bound::Included(i) => i + 1,
+ Bound::Excluded(i) => i,
+ Bound::Unbounded => len,
+ };
+ start..end
+}
+
+/// Convert pair of `ops::Bound`s into `ops::Range`.
+/// Returns `None` on overflowing indices.
+fn into_range(
+ len: usize,
+ (start, end): (ops::Bound<usize>, ops::Bound<usize>),
+) -> Option<ops::Range<usize>> {
+ use ops::Bound;
+ let start = match start {
+ Bound::Included(start) => start,
+ Bound::Excluded(start) => start.checked_add(1)?,
+ Bound::Unbounded => 0,
+ };
+
+ let end = match end {
+ Bound::Included(end) => end.checked_add(1)?,
+ Bound::Excluded(end) => end,
+ Bound::Unbounded => len,
+ };
+
+ // Don't bother with checking `start < end` and `end <= len`
+ // since these checks are handled by `Range` impls
+
+ Some(start..end)
+}
+
+/// Convert pair of `ops::Bound`s into `ops::Range`.
+/// Panics on overflowing indices.
+fn into_slice_range(
+ len: usize,
+ (start, end): (ops::Bound<usize>, ops::Bound<usize>),
+) -> ops::Range<usize> {
+ use ops::Bound;
+ let start = match start {
+ Bound::Included(start) => start,
+ Bound::Excluded(start) => {
+ start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
+ }
+ Bound::Unbounded => 0,
+ };
+
+ let end = match end {
+ Bound::Included(end) => {
+ end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
+ }
+ Bound::Excluded(end) => end,
+ Bound::Unbounded => len,
+ };
+
+ // Don't bother with checking `start < end` and `end <= len`
+ // since these checks are handled by `Range` impls
+
+ start..end
+}
+
+#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
+unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) {
+ type Output = [T];
+
+ #[inline]
+ fn get(self, slice: &[T]) -> Option<&Self::Output> {
+ into_range(slice.len(), self)?.get(slice)
+ }
+
+ #[inline]
+ fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
+ into_range(slice.len(), self)?.get_mut(slice)
+ }
+
+ #[inline]
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
+ // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
+ unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) }
+ }
+
+ #[inline]
+ unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
+ // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
+ unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) }
+ }
+
+ #[inline]
+ fn index(self, slice: &[T]) -> &Self::Output {
+ into_slice_range(slice.len(), self).index(slice)
+ }
+
+ #[inline]
+ fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
+ into_slice_range(slice.len(), self).index_mut(slice)
+ }
+}
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index c82b76d..1ee662c 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -286,7 +286,6 @@
/// Basic usage:
///
/// ```
- /// # #![feature(slice_iter_mut_as_slice)]
/// let mut slice: &mut [usize] = &mut [1, 2, 3];
///
/// // First, we get the iterator:
@@ -299,12 +298,19 @@
/// // Now `as_slice` returns "[2, 3]":
/// assert_eq!(iter.as_slice(), &[2, 3]);
/// ```
- #[unstable(feature = "slice_iter_mut_as_slice", reason = "recently added", issue = "58957")]
+ #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
pub fn as_slice(&self) -> &[T] {
self.make_slice()
}
}
+#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
+impl<T> AsRef<[T]> for IterMut<'_, T> {
+ fn as_ref(&self) -> &[T] {
+ self.as_slice()
+ }
+}
+
iterator! {struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}}
/// An internal abstraction over the splitting iterators, so that
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 417a106..ec28cdd 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -81,6 +81,9 @@
#[unstable(feature = "slice_range", issue = "76393")]
pub use index::range;
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+pub use ascii::EscapeAscii;
+
#[lang = "slice"]
#[cfg(not(test))]
impl<T> [T] {
@@ -94,28 +97,19 @@
/// ```
#[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")]
#[inline]
// SAFETY: const sound because we transmute out the length field as a usize (which it must be)
#[rustc_allow_const_fn_unstable(const_fn_union)]
pub const fn len(&self) -> usize {
- #[cfg(bootstrap)]
- {
- // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
- // Only `std` can make this guarantee.
- unsafe { crate::ptr::Repr { rust: self }.raw.len }
- }
- #[cfg(not(bootstrap))]
- {
- // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
- // As of this writing this causes a "Const-stable functions can only call other
- // const-stable functions" error.
+ // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
+ // As of this writing this causes a "Const-stable functions can only call other
+ // const-stable functions" error.
- // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
- // and PtrComponents<T> have the same memory layouts. Only std can make this
- // guarantee.
- unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
- }
+ // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
+ // and PtrComponents<T> have the same memory layouts. Only std can make this
+ // guarantee.
+ unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
}
/// Returns `true` if the slice has a length of 0.
@@ -127,7 +121,7 @@
/// assert!(!a.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_slice_is_empty", since = "1.39.0")]
#[inline]
pub const fn is_empty(&self) -> bool {
self.len() == 0
@@ -145,8 +139,9 @@
/// assert_eq!(None, w.first());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn first(&self) -> Option<&T> {
+ pub const fn first(&self) -> Option<&T> {
if let [first, ..] = self { Some(first) } else { None }
}
@@ -163,8 +158,9 @@
/// assert_eq!(x, &[5, 1, 2]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn first_mut(&mut self) -> Option<&mut T> {
+ pub const fn first_mut(&mut self) -> Option<&mut T> {
if let [first, ..] = self { Some(first) } else { None }
}
@@ -181,8 +177,9 @@
/// }
/// ```
#[stable(feature = "slice_splits", since = "1.5.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn split_first(&self) -> Option<(&T, &[T])> {
+ pub const fn split_first(&self) -> Option<(&T, &[T])> {
if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
}
@@ -201,8 +198,9 @@
/// assert_eq!(x, &[3, 4, 5]);
/// ```
#[stable(feature = "slice_splits", since = "1.5.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+ pub const fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
}
@@ -219,8 +217,9 @@
/// }
/// ```
#[stable(feature = "slice_splits", since = "1.5.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn split_last(&self) -> Option<(&T, &[T])> {
+ pub const fn split_last(&self) -> Option<(&T, &[T])> {
if let [init @ .., last] = self { Some((last, init)) } else { None }
}
@@ -239,8 +238,9 @@
/// assert_eq!(x, &[4, 5, 3]);
/// ```
#[stable(feature = "slice_splits", since = "1.5.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
+ pub const fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
if let [init @ .., last] = self { Some((last, init)) } else { None }
}
@@ -256,8 +256,9 @@
/// assert_eq!(None, w.last());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn last(&self) -> Option<&T> {
+ pub const fn last(&self) -> Option<&T> {
if let [.., last] = self { Some(last) } else { None }
}
@@ -274,8 +275,9 @@
/// assert_eq!(x, &[0, 1, 10]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_slice_first_last", issue = "83570")]
#[inline]
- pub fn last_mut(&mut self) -> Option<&mut T> {
+ pub const fn last_mut(&mut self) -> Option<&mut T> {
if let [.., last] = self { Some(last) } else { None }
}
@@ -2204,6 +2206,8 @@
} else if cmp == Greater {
right = mid;
} else {
+ // SAFETY: same as the `get_unchecked` above
+ unsafe { crate::intrinsics::assume(mid < self.len()) };
return Ok(mid);
}
@@ -2252,8 +2256,7 @@
// in crate `alloc`, and as such doesn't exists yet when building `core`.
// links to downstream crate: #74481. Since primitives are only documented in
// libstd (#73423), this never leads to broken links in practice.
- #[cfg_attr(not(bootstrap), allow(rustdoc::broken_intra_doc_links))]
- #[cfg_attr(bootstrap, allow(broken_intra_doc_links))]
+ #[allow(rustdoc::broken_intra_doc_links)]
#[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
#[inline]
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
diff --git a/library/core/src/slice/specialize.rs b/library/core/src/slice/specialize.rs
index 16a9588..425cf71 100644
--- a/library/core/src/slice/specialize.rs
+++ b/library/core/src/slice/specialize.rs
@@ -1,3 +1,4 @@
+use crate::mem::{size_of, transmute_copy};
use crate::ptr::write_bytes;
pub(super) trait SpecFill<T> {
@@ -17,42 +18,18 @@
}
impl<T: Copy> SpecFill<T> for [T] {
- default fn spec_fill(&mut self, value: T) {
- for item in self.iter_mut() {
- *item = value;
- }
- }
-}
-
-impl SpecFill<u8> for [u8] {
- fn spec_fill(&mut self, value: u8) {
- // SAFETY: this is slice of u8
- unsafe {
- let ptr = self.as_mut_ptr();
- let len = self.len();
- write_bytes(ptr, value, len);
- }
- }
-}
-
-impl SpecFill<i8> for [i8] {
- fn spec_fill(&mut self, value: i8) {
- // SAFETY: this is slice of i8
- unsafe {
- let ptr = self.as_mut_ptr();
- let len = self.len();
- write_bytes(ptr, value as u8, len);
- }
- }
-}
-
-impl SpecFill<bool> for [bool] {
- fn spec_fill(&mut self, value: bool) {
- // SAFETY: this is slice of bool
- unsafe {
- let ptr = self.as_mut_ptr();
- let len = self.len();
- write_bytes(ptr, value as u8, len);
+ fn spec_fill(&mut self, value: T) {
+ if size_of::<T>() == 1 {
+ // SAFETY: The size_of check above ensures that values are 1 byte wide, as required
+ // for the transmute and write_bytes
+ unsafe {
+ let value: u8 = transmute_copy(&value);
+ write_bytes(self.as_mut_ptr(), value, self.len());
+ }
+ } else {
+ for item in self.iter_mut() {
+ *item = value;
+ }
}
}
}
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 4eac017..724137a 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -189,6 +189,30 @@
pub fn as_str(&self) -> &'a str {
self.iter.as_str()
}
+
+ /// Returns the byte position of the next character, or the length
+ /// of the underlying string if there are no more characters.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(char_indices_offset)]
+ /// let mut chars = "a楽".char_indices();
+ ///
+ /// assert_eq!(chars.offset(), 0);
+ /// assert_eq!(chars.next(), Some((0, 'a')));
+ ///
+ /// assert_eq!(chars.offset(), 1);
+ /// assert_eq!(chars.next(), Some((1, '楽')));
+ ///
+ /// assert_eq!(chars.offset(), 4);
+ /// assert_eq!(chars.next(), None);
+ /// ```
+ #[inline]
+ #[unstable(feature = "char_indices_offset", issue = "83871")]
+ pub fn offset(&self) -> usize {
+ self.front_offset
+ }
}
/// An iterator over the bytes of a string slice.
@@ -1359,7 +1383,7 @@
#[stable(feature = "collection_debug", since = "1.17.0")]
impl fmt::Debug for EncodeUtf16<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.pad("EncodeUtf16 { .. }")
+ f.debug_struct("EncodeUtf16").finish_non_exhaustive()
}
}
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 67c074b..95dd549 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -15,7 +15,7 @@
use self::pattern::Pattern;
use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
-use crate::char;
+use crate::char::{self, EscapeDebugExtArgs};
use crate::mem;
use crate::slice::{self, SliceIndex};
@@ -140,7 +140,7 @@
/// ```
#[doc(alias = "length")]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_str_len", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")]
#[inline]
pub const fn len(&self) -> usize {
self.as_bytes().len()
@@ -161,7 +161,7 @@
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_str_is_empty", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_str_is_empty", since = "1.39.0")]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
@@ -217,7 +217,7 @@
/// assert_eq!(b"bors", bytes);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
+ #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")]
#[inline(always)]
#[allow(unused_attributes)]
#[rustc_allow_const_fn_unstable(const_fn_transmute)]
@@ -2342,7 +2342,7 @@
EscapeDebug {
inner: chars
.next()
- .map(|first| first.escape_debug_ext(true))
+ .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL))
.into_iter()
.flatten()
.chain(chars.flat_map(CharEscapeDebugContinue)),
@@ -2460,7 +2460,11 @@
#[derive(Clone)]
struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug {
- c.escape_debug_ext(false)
+ c.escape_debug_ext(EscapeDebugExtArgs {
+ escape_grapheme_extended: false,
+ escape_single_quote: true,
+ escape_double_quote: true
+ })
};
#[derive(Clone)]
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index ca39224..f1a1155 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -78,7 +78,7 @@
//! ```
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicUsize, Ordering};
-//! use std::thread;
+//! use std::{hint, thread};
//!
//! fn main() {
//! let spinlock = Arc::new(AtomicUsize::new(1));
@@ -89,7 +89,9 @@
//! });
//!
//! // Wait for the other thread to release the lock
-//! while spinlock.load(Ordering::SeqCst) != 0 {}
+//! while spinlock.load(Ordering::SeqCst) != 0 {
+//! hint::spin_loop();
+//! }
//!
//! if let Err(panic) = thread.join() {
//! println!("Thread had an error: {:?}", panic);
@@ -283,7 +285,7 @@
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_atomic_new", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")]
pub const fn new(v: bool) -> AtomicBool {
AtomicBool { v: UnsafeCell::new(v as u8) }
}
@@ -837,7 +839,6 @@
/// # Examples
///
/// ```rust
- /// #![feature(atomic_fetch_update)]
/// use std::sync::atomic::{AtomicBool, Ordering};
///
/// let x = AtomicBool::new(false);
@@ -847,7 +848,7 @@
/// assert_eq!(x.load(Ordering::SeqCst), false);
/// ```
#[inline]
- #[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")]
+ #[stable(feature = "atomic_fetch_update", since = "1.53.0")]
#[cfg(target_has_atomic = "8")]
pub fn fetch_update<F>(
&self,
@@ -883,7 +884,7 @@
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_stable(feature = "const_atomic_new", since = "1.32.0")]
+ #[rustc_const_stable(feature = "const_atomic_new", since = "1.24.0")]
pub const fn new(p: *mut T) -> AtomicPtr<T> {
AtomicPtr { p: UnsafeCell::new(p) }
}
@@ -898,8 +899,10 @@
/// ```
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
- /// let mut atomic_ptr = AtomicPtr::new(&mut 10);
- /// *atomic_ptr.get_mut() = &mut 5;
+ /// let mut data = 10;
+ /// let mut atomic_ptr = AtomicPtr::new(&mut data);
+ /// let mut other_data = 5;
+ /// *atomic_ptr.get_mut() = &mut other_data;
/// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
/// ```
#[inline]
@@ -916,9 +919,11 @@
/// #![feature(atomic_from_mut)]
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
- /// let mut some_ptr = &mut 123 as *mut i32;
+ /// let mut data = 123;
+ /// let mut some_ptr = &mut data as *mut i32;
/// let a = AtomicPtr::from_mut(&mut some_ptr);
- /// a.store(&mut 456, Ordering::Relaxed);
+ /// let mut other_data = 456;
+ /// a.store(&mut other_data, Ordering::Relaxed);
/// assert_eq!(unsafe { *some_ptr }, 456);
/// ```
#[inline]
@@ -944,7 +949,8 @@
/// ```
/// use std::sync::atomic::AtomicPtr;
///
- /// let atomic_ptr = AtomicPtr::new(&mut 5);
+ /// let mut data = 5;
+ /// let atomic_ptr = AtomicPtr::new(&mut data);
/// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
/// ```
#[inline]
@@ -1220,7 +1226,6 @@
/// # Examples
///
/// ```rust
- /// #![feature(atomic_fetch_update)]
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr: *mut _ = &mut 5;
@@ -1239,7 +1244,7 @@
/// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
/// ```
#[inline]
- #[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")]
+ #[stable(feature = "atomic_fetch_update", since = "1.53.0")]
#[cfg(target_has_atomic = "ptr")]
pub fn fetch_update<F>(
&self,
@@ -2276,7 +2281,7 @@
stable(feature = "atomic_access", since = "1.15.0"),
stable(feature = "atomic_from", since = "1.23.0"),
stable(feature = "atomic_nand", since = "1.27.0"),
- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
+ rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"),
stable(feature = "rust1", since = "1.0.0"),
"isize",
"",
@@ -2296,7 +2301,7 @@
stable(feature = "atomic_access", since = "1.15.0"),
stable(feature = "atomic_from", since = "1.23.0"),
stable(feature = "atomic_nand", since = "1.27.0"),
- rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"),
+ rustc_const_stable(feature = "const_integer_atomics", since = "1.24.0"),
stable(feature = "rust1", since = "1.0.0"),
"usize",
"",
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 42c9d9f..2765c21 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -1,6 +1,7 @@
#![stable(feature = "futures_api", since = "1.36.0")]
-use crate::ops::Try;
+use crate::convert;
+use crate::ops::{self, ControlFlow, Try};
use crate::result::Result;
/// Indicates whether a value is available or if the current task has been
@@ -152,6 +153,36 @@
}
}
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E> ops::TryV2 for Poll<Result<T, E>> {
+ type Output = Poll<T>;
+ type Residual = Result<convert::Infallible, E>;
+
+ #[inline]
+ fn from_output(c: Self::Output) -> Self {
+ c.map(Ok)
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
+ Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
+ Poll::Pending => ControlFlow::Continue(Poll::Pending),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
+ #[inline]
+ fn from_residual(x: Result<convert::Infallible, E>) -> Self {
+ match x {
+ Err(e) => Poll::Ready(Err(From::from(e))),
+ }
+ }
+}
+
#[stable(feature = "futures_api", since = "1.36.0")]
impl<T, E> Try for Poll<Option<Result<T, E>>> {
type Ok = Poll<Option<T>>;
@@ -177,3 +208,36 @@
x.map(|x| x.map(Ok))
}
}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> {
+ type Output = Poll<Option<T>>;
+ type Residual = Result<convert::Infallible, E>;
+
+ #[inline]
+ fn from_output(c: Self::Output) -> Self {
+ c.map(|x| x.map(Ok))
+ }
+
+ #[inline]
+ fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+ match self {
+ Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
+ Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
+ Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
+ Poll::Pending => ControlFlow::Continue(Poll::Pending),
+ }
+ }
+}
+
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>>
+ for Poll<Option<Result<T, F>>>
+{
+ #[inline]
+ fn from_residual(x: Result<convert::Infallible, E>) -> Self {
+ match x {
+ Err(e) => Poll::Ready(Some(Err(From::from(e)))),
+ }
+ }
+}
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 8c0848c..bfea39e 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -124,29 +124,32 @@
/// # Examples
///
/// ```
- /// #![feature(duration_zero)]
/// use std::time::Duration;
///
/// let duration = Duration::ZERO;
/// assert!(duration.is_zero());
/// assert_eq!(duration.as_nanos(), 0);
/// ```
- #[unstable(feature = "duration_zero", issue = "73544")]
+ #[stable(feature = "duration_zero", since = "1.53.0")]
pub const ZERO: Duration = Duration::from_nanos(0);
/// The maximum duration.
///
- /// It is roughly equal to a duration of 584,942,417,355 years.
+ /// May vary by platform as necessary. Must be able to contain the difference between
+ /// two instances of [`Instant`] or two instances of [`SystemTime`].
+ /// This constraint gives it a value of about 584,942,417,355 years in practice,
+ /// which is currently used on all platforms.
///
/// # Examples
///
/// ```
- /// #![feature(duration_constants)]
/// use std::time::Duration;
///
/// assert_eq!(Duration::MAX, Duration::new(u64::MAX, 1_000_000_000 - 1));
/// ```
- #[unstable(feature = "duration_constants", issue = "57391")]
+ /// [`Instant`]: ../../std/time/struct.Instant.html
+ /// [`SystemTime`]: ../../std/time/struct.SystemTime.html
+ #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
pub const MAX: Duration = Duration::new(u64::MAX, NANOS_PER_SEC - 1);
/// Creates a new `Duration` from the specified number of whole seconds and
@@ -269,7 +272,6 @@
/// # Examples
///
/// ```
- /// #![feature(duration_zero)]
/// use std::time::Duration;
///
/// assert!(Duration::ZERO.is_zero());
@@ -281,7 +283,8 @@
/// assert!(!Duration::from_nanos(1).is_zero());
/// assert!(!Duration::from_secs(1).is_zero());
/// ```
- #[unstable(feature = "duration_zero", issue = "73544")]
+ #[stable(feature = "duration_zero", since = "1.53.0")]
+ #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")]
#[inline]
pub const fn is_zero(&self) -> bool {
self.secs == 0 && self.nanos == 0
@@ -479,14 +482,13 @@
/// # Examples
///
/// ```
- /// #![feature(duration_saturating_ops)]
/// #![feature(duration_constants)]
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 0).saturating_add(Duration::new(0, 1)), Duration::new(0, 1));
/// assert_eq!(Duration::new(1, 0).saturating_add(Duration::new(u64::MAX, 0)), Duration::MAX);
/// ```
- #[unstable(feature = "duration_saturating_ops", issue = "76416")]
+ #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
#[inline]
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn saturating_add(self, rhs: Duration) -> Duration {
@@ -537,14 +539,12 @@
/// # Examples
///
/// ```
- /// #![feature(duration_saturating_ops)]
- /// #![feature(duration_zero)]
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 1).saturating_sub(Duration::new(0, 0)), Duration::new(0, 1));
/// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO);
/// ```
- #[unstable(feature = "duration_saturating_ops", issue = "76416")]
+ #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
#[inline]
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn saturating_sub(self, rhs: Duration) -> Duration {
@@ -590,14 +590,13 @@
/// # Examples
///
/// ```
- /// #![feature(duration_saturating_ops)]
/// #![feature(duration_constants)]
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 500_000_001).saturating_mul(2), Duration::new(1, 2));
/// assert_eq!(Duration::new(u64::MAX - 1, 0).saturating_mul(2), Duration::MAX);
/// ```
- #[unstable(feature = "duration_saturating_ops", issue = "76416")]
+ #[stable(feature = "duration_saturating_ops", since = "1.53.0")]
#[inline]
#[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")]
pub const fn saturating_mul(self, rhs: u32) -> Duration {