Importing rustc-1.49.0
Bug: 176888219
Change-Id: Ib0805d37e7b485cd420bbff8a8b000cf87e7ede0
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index 6d09b4f..c61c19c 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -89,13 +89,11 @@
pub unsafe trait AllocRef {
/// Attempts to allocate a block of memory.
///
- /// On success, returns a [`NonNull<[u8]>`] meeting the size and alignment guarantees of `layout`.
+ /// On success, returns a [`NonNull<[u8]>`][NonNull] meeting the size and alignment guarantees of `layout`.
///
/// The returned block may have a larger size than specified by `layout.size()`, and may or may
/// not have its contents initialized.
///
- /// [`NonNull<[u8]>`]: NonNull
- ///
/// # Errors
///
/// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
@@ -146,7 +144,7 @@
/// Attempts to extend the memory block.
///
- /// Returns a new [`NonNull<[u8]>`] containing a pointer and the actual size of the allocated
+ /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
/// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
/// this, the allocator may extend the allocation referenced by `ptr` to fit the new layout.
///
@@ -158,8 +156,6 @@
/// If this method returns `Err`, then ownership of the memory block has not been transferred to
/// this allocator, and the contents of the memory block are unaltered.
///
- /// [`NonNull<[u8]>`]: NonNull
- ///
/// # Safety
///
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
@@ -271,7 +267,7 @@
/// Attempts to shrink the memory block.
///
- /// Returns a new [`NonNull<[u8]>`] containing a pointer and the actual size of the allocated
+ /// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
/// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
/// this, the allocator may shrink the allocation referenced by `ptr` to fit the new layout.
///
@@ -283,8 +279,6 @@
/// If this method returns `Err`, then ownership of the memory block has not been transferred to
/// this allocator, and the contents of the memory block are unaltered.
///
- /// [`NonNull<[u8]>`]: NonNull
- ///
/// # Safety
///
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 966272c..123a191 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -344,7 +344,7 @@
}
}
-/// Implements comparison of arrays lexicographically.
+/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord, const N: usize> Ord for [T; N] {
#[inline]
@@ -353,8 +353,9 @@
}
}
-// The Default impls cannot be generated using the array_impls! macro because
-// they require array literals.
+// The Default impls cannot be done with const generics because `[T; 0]` doesn't
+// require Default to be implemented, and having different impl blocks for
+// different numbers isn't supported yet.
macro_rules! array_impl_default {
{$n:expr, $t:ident $($ts:ident)*} => {
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 15ec13c..b2afb70 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -226,7 +226,7 @@
/// assert_eq!(my_struct.special_field.get(), new_value);
/// ```
///
-/// See the [module-level documentation](index.html) for more.
+/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
#[repr(transparent)]
pub struct Cell<T: ?Sized> {
@@ -406,7 +406,8 @@
/// assert_eq!(five, 5);
/// ```
#[stable(feature = "move_cell", since = "1.17.0")]
- pub fn into_inner(self) -> T {
+ #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ pub const fn into_inner(self) -> T {
self.value.into_inner()
}
}
@@ -566,14 +567,14 @@
/// A mutable memory location with dynamically checked borrow rules
///
-/// See the [module-level documentation](index.html) for more.
+/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RefCell<T: ?Sized> {
borrow: Cell<BorrowFlag>,
value: UnsafeCell<T>,
}
-/// An error returned by [`RefCell::try_borrow`](struct.RefCell.html#method.try_borrow).
+/// An error returned by [`RefCell::try_borrow`].
#[stable(feature = "try_borrow", since = "1.13.0")]
pub struct BorrowError {
_private: (),
@@ -593,7 +594,7 @@
}
}
-/// An error returned by [`RefCell::try_borrow_mut`](struct.RefCell.html#method.try_borrow_mut).
+/// An error returned by [`RefCell::try_borrow_mut`].
#[stable(feature = "try_borrow", since = "1.13.0")]
pub struct BorrowMutError {
_private: (),
@@ -668,12 +669,11 @@
/// let five = c.into_inner();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
#[inline]
- pub fn into_inner(self) -> T {
+ pub const fn into_inner(self) -> T {
// Since this function takes `self` (the `RefCell`) by value, the
// compiler statically verifies that it is not currently borrowed.
- // Therefore the following assertion is just a `debug_assert!`.
- debug_assert!(self.borrow.get() == UNUSED);
self.value.into_inner()
}
@@ -1203,7 +1203,7 @@
/// Wraps a borrowed reference to a value in a `RefCell` box.
/// A wrapper type for an immutably borrowed value from a `RefCell<T>`.
///
-/// See the [module-level documentation](index.html) for more.
+/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Ref<'b, T: ?Sized + 'b> {
value: &'b T,
@@ -1493,7 +1493,7 @@
/// A wrapper type for a mutably borrowed value from a `RefCell<T>`.
///
-/// See the [module-level documentation](index.html) for more.
+/// See the [module-level documentation](self) for more.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RefMut<'b, T: ?Sized + 'b> {
value: &'b mut T,
@@ -1682,7 +1682,8 @@
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn into_inner(self) -> T {
+ #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ pub const fn into_inner(self) -> T {
self.value
}
}
@@ -1733,8 +1734,7 @@
#[inline]
#[unstable(feature = "unsafe_cell_get_mut", issue = "76943")]
pub fn get_mut(&mut self) -> &mut T {
- // SAFETY: (outer) `&mut` guarantees unique access.
- unsafe { &mut *self.get() }
+ &mut self.value
}
/// Gets a mutable pointer to the wrapped value.
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 2603ecf..1b847ad 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1229,10 +1229,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_alphabetic(&self) -> bool {
- match *self {
- 'A'..='Z' | 'a'..='z' => true,
- _ => false,
- }
+ matches!(*self, 'A'..='Z' | 'a'..='z')
}
/// Checks if the value is an ASCII uppercase character:
@@ -1265,10 +1262,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_uppercase(&self) -> bool {
- match *self {
- 'A'..='Z' => true,
- _ => false,
- }
+ matches!(*self, 'A'..='Z')
}
/// Checks if the value is an ASCII lowercase character:
@@ -1301,10 +1295,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_lowercase(&self) -> bool {
- match *self {
- 'a'..='z' => true,
- _ => false,
- }
+ matches!(*self, 'a'..='z')
}
/// Checks if the value is an ASCII alphanumeric character:
@@ -1340,10 +1331,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_alphanumeric(&self) -> bool {
- match *self {
- '0'..='9' | 'A'..='Z' | 'a'..='z' => true,
- _ => false,
- }
+ matches!(*self, '0'..='9' | 'A'..='Z' | 'a'..='z')
}
/// Checks if the value is an ASCII decimal digit:
@@ -1376,10 +1364,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_digit(&self) -> bool {
- match *self {
- '0'..='9' => true,
- _ => false,
- }
+ matches!(*self, '0'..='9')
}
/// Checks if the value is an ASCII hexadecimal digit:
@@ -1415,10 +1400,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_hexdigit(&self) -> bool {
- match *self {
- '0'..='9' | 'A'..='F' | 'a'..='f' => true,
- _ => false,
- }
+ matches!(*self, '0'..='9' | 'A'..='F' | 'a'..='f')
}
/// Checks if the value is an ASCII punctuation character:
@@ -1455,10 +1437,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_punctuation(&self) -> bool {
- match *self {
- '!'..='/' | ':'..='@' | '['..='`' | '{'..='~' => true,
- _ => false,
- }
+ matches!(*self, '!'..='/' | ':'..='@' | '['..='`' | '{'..='~')
}
/// Checks if the value is an ASCII graphic character:
@@ -1491,10 +1470,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_graphic(&self) -> bool {
- match *self {
- '!'..='~' => true,
- _ => false,
- }
+ matches!(*self, '!'..='~')
}
/// Checks if the value is an ASCII whitespace character:
@@ -1544,10 +1520,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_whitespace(&self) -> bool {
- match *self {
- '\t' | '\n' | '\x0C' | '\r' | ' ' => true,
- _ => false,
- }
+ matches!(*self, '\t' | '\n' | '\x0C' | '\r' | ' ')
}
/// Checks if the value is an ASCII control character:
@@ -1582,10 +1555,7 @@
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
#[inline]
pub const fn is_ascii_control(&self) -> bool {
- match *self {
- '\0'..='\x1F' | '\x7F' => true,
- _ => false,
- }
+ matches!(*self, '\0'..='\x1F' | '\x7F')
}
}
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index ee79a94..bbb3a3d 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -29,7 +29,7 @@
///
/// This trait allows for partial equality, for types that do not have a full
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
-/// so floating point types implement `PartialEq` but not [`Eq`](Eq).
+/// so floating point types implement `PartialEq` but not [`Eq`].
///
/// Formally, the equality must be (for all `a`, `b` and `c`):
///
@@ -506,9 +506,19 @@
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
-/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members.
+/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the top-to-bottom declaration order of the struct's members.
/// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order.
///
+/// ## Lexicographical comparison
+///
+/// Lexicographical comparison is an operation with the following properties:
+/// - Two sequences are compared element by element.
+/// - The first mismatching element defines which sequence is lexicographically less or greater than the other.
+/// - If one sequence is a prefix of another, the shorter sequence is lexicographically less than the other.
+/// - If two sequence have equivalent elements and are of the same length, then the sequences are lexicographically equal.
+/// - An empty sequence is lexicographically less than any non-empty sequence.
+/// - Two empty sequences are lexicographically equal.
+///
/// ## How can I implement `Ord`?
///
/// `Ord` requires that the type also be [`PartialOrd`] and [`Eq`] (which requires [`PartialEq`]).
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 2bfeb49..3f7110b 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -134,6 +134,7 @@
/// want to accept all references that can be converted to [`&str`] as an argument.
/// Since both [`String`] and [`&str`] implement `AsRef<str>` we can accept both as input argument.
///
+/// [`&str`]: primitive@str
/// [`Option<T>`]: Option
/// [`Result<T, E>`]: Result
/// [`Borrow`]: crate::borrow::Borrow
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 336c0b2..2dd5e81 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -485,3 +485,49 @@
nzint_impl_try_from_int! { i64, NonZeroI64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
nzint_impl_try_from_int! { i128, NonZeroI128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
+
+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;
+
+ #[inline]
+ fn try_from(value: $From) -> Result<Self, Self::Error> {
+ TryFrom::try_from(value.get()).map(|v| {
+ // SAFETY: $From is a NonZero type, so v is not zero.
+ unsafe { Self::new_unchecked(v) }
+ })
+ }
+ }
+ };
+ ($To:ty: $($From: ty),*) => {$(
+ nzint_impl_try_from_nzint!(
+ $From => $To,
+ concat!(
+ "Attempts to convert `",
+ stringify!($From),
+ "` to `",
+ stringify!($To),
+ "`.",
+ )
+ );
+ )*};
+}
+
+// Non-zero int -> non-zero unsigned int
+nzint_impl_try_from_nzint! { NonZeroU8: NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroU16: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroU32: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroU64: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroU128: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroUsize: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroIsize }
+
+// Non-zero int -> non-zero signed int
+nzint_impl_try_from_nzint! { NonZeroI8: NonZeroU8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroI16: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroI32: NonZeroU32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroI64: NonZeroU64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroI128: NonZeroU128, NonZeroUsize, NonZeroIsize }
+nzint_impl_try_from_nzint! { NonZeroIsize: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize }
diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs
index 4525ba7..4b303ac 100644
--- a/library/core/src/ffi.rs
+++ b/library/core/src/ffi.rs
@@ -62,7 +62,7 @@
// The name is WIP, using `VaListImpl` for now.
#[cfg(any(
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
- all(target_arch = "aarch64", target_os = "ios"),
+ all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_arch = "wasm32",
target_arch = "asmjs",
windows
@@ -85,7 +85,7 @@
#[cfg(any(
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
- all(target_arch = "aarch64", target_os = "ios"),
+ all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_arch = "wasm32",
target_arch = "asmjs",
windows
@@ -107,7 +107,11 @@
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
-#[cfg(all(target_arch = "aarch64", not(target_os = "ios"), not(windows)))]
+#[cfg(all(
+ target_arch = "aarch64",
+ not(any(target_os = "macos", target_os = "ios")),
+ not(windows)
+))]
#[repr(C)]
#[derive(Debug)]
#[unstable(
@@ -181,7 +185,7 @@
not(target_arch = "powerpc"),
not(target_arch = "x86_64")
),
- all(target_arch = "aarch64", target_os = "ios"),
+ all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_arch = "wasm32",
target_arch = "asmjs",
windows
@@ -190,7 +194,7 @@
#[cfg(all(
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
- any(not(target_arch = "aarch64"), not(target_os = "ios")),
+ any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
not(target_arch = "wasm32"),
not(target_arch = "asmjs"),
not(windows)
@@ -202,7 +206,7 @@
#[cfg(any(
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
- all(target_arch = "aarch64", target_os = "ios"),
+ all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
target_arch = "wasm32",
target_arch = "asmjs",
windows
@@ -223,7 +227,7 @@
#[cfg(all(
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
- any(not(target_arch = "aarch64"), not(target_os = "ios")),
+ any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
not(target_arch = "wasm32"),
not(target_arch = "asmjs"),
not(windows)
@@ -280,7 +284,7 @@
// within a private module. Once RFC 2145 has been implemented look into
// improving this.
mod sealed_trait {
- /// Trait which permits the allowed types to be used with [VaList::arg].
+ /// Trait which permits the allowed types to be used with [super::VaListImpl::arg].
#[unstable(
feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index 63866a5..d95d43f 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -1,4 +1,6 @@
-use crate::fmt;
+#![allow(unused_imports)]
+
+use crate::fmt::{self, Debug, Formatter};
struct PadAdapter<'buf, 'state> {
buf: &'buf mut (dyn fmt::Write + 'buf),
@@ -53,14 +55,12 @@
}
}
-/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+/// A struct to help with [`fmt::Debug`](Debug) implementations.
///
/// This is useful when you wish to output a formatted struct as a part of your
-/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+/// [`Debug::fmt`] implementation.
///
-/// This can be constructed by the
-/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
-/// method.
+/// This can be constructed by the [`Formatter::debug_struct`] method.
///
/// # Examples
///
@@ -257,14 +257,12 @@
}
}
-/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+/// A struct to help with [`fmt::Debug`](Debug) implementations.
///
/// This is useful when you wish to output a formatted tuple as a part of your
-/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+/// [`Debug::fmt`] implementation.
///
-/// This can be constructed by the
-/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
-/// method.
+/// This can be constructed by the [`Formatter::debug_tuple`] method.
///
/// # Examples
///
@@ -428,14 +426,12 @@
}
}
-/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+/// A struct to help with [`fmt::Debug`](Debug) implementations.
///
/// This is useful when you wish to output a formatted set of items as a part
-/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+/// of your [`Debug::fmt`] implementation.
///
-/// This can be constructed by the
-/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
-/// method.
+/// This can be constructed by the [`Formatter::debug_set`] method.
///
/// # Examples
///
@@ -560,14 +556,12 @@
}
}
-/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+/// A struct to help with [`fmt::Debug`](Debug) implementations.
///
/// This is useful when you wish to output a formatted list of items as a part
-/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+/// of your [`Debug::fmt`] implementation.
///
-/// This can be constructed by the
-/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
-/// method.
+/// This can be constructed by the [`Formatter::debug_list`] method.
///
/// # Examples
///
@@ -692,14 +686,12 @@
}
}
-/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+/// A struct to help with [`fmt::Debug`](Debug) implementations.
///
/// This is useful when you wish to output a formatted map as a part of your
-/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+/// [`Debug::fmt`] implementation.
///
-/// This can be constructed by the
-/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
-/// method.
+/// This can be constructed by the [`Formatter::debug_map`] method.
///
/// # Examples
///
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index c1038ce..506d778 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -92,18 +92,14 @@
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Error;
-/// A collection of methods that are required to format a message into a stream.
+/// A trait for writing or formatting into Unicode-accepting buffers or streams.
///
-/// This trait is the type which this modules requires when formatting
-/// information. This is similar to the standard library's [`io::Write`] trait,
-/// but it is only intended for use in libcore.
+/// This trait only accepts UTF-8–encoded data and is not [flushable]. If you only
+/// want to accept Unicode and you don't need flushing, you should implement this trait;
+/// otherwise you should implement [`std::io::Write`].
///
-/// This trait should generally not be implemented by consumers of the standard
-/// library. The [`write!`] macro accepts an instance of [`io::Write`], and the
-/// [`io::Write`] trait is favored over implementing this trait.
-///
-/// [`write!`]: ../../std/macro.write.html
-/// [`io::Write`]: ../../std/io/trait.Write.html
+/// [`std::io::Write`]: ../../std/io/trait.Write.html
+/// [flushable]: ../../std/io/trait.Write.html#tymethod.flush
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Write {
/// Writes a string slice into this writer, returning whether the write
@@ -924,9 +920,11 @@
/// assert_eq!(&l_ptr[..2], "0x");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "pointer_trait"]
pub trait Pointer {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_diagnostic_item = "pointer_trait_fmt"]
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
}
@@ -1058,7 +1056,7 @@
/// assert_eq!(output, "Hello world!");
/// ```
///
-/// [`write!`]: ../../std/macro.write.html
+/// [`write!`]: crate::write!
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
let mut formatter = Formatter {
@@ -1886,7 +1884,7 @@
/// assert_eq!(format!("{:?}", Foo(vec![10, 11])), "{10, 11}");
/// ```
///
- /// [`format_args!`]: ../../std/macro.format_args.html
+ /// [`format_args!`]: crate::format_args
///
/// In this more complex example, we use [`format_args!`] and `.debug_set()`
/// to build a list of match arms:
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index ae3d0dd..7a98210 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -9,7 +9,7 @@
use crate::str;
#[doc(hidden)]
-trait Int:
+trait DisplayInt:
PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
{
fn zero() -> Self;
@@ -21,22 +21,39 @@
fn to_u128(&self) -> u128;
}
-macro_rules! doit {
- ($($t:ident)*) => ($(impl Int for $t {
- fn zero() -> Self { 0 }
- fn from_u8(u: u8) -> Self { u as Self }
- fn to_u8(&self) -> u8 { *self as u8 }
- fn to_u16(&self) -> u16 { *self as u16 }
- fn to_u32(&self) -> u32 { *self as u32 }
- fn to_u64(&self) -> u64 { *self as u64 }
- fn to_u128(&self) -> u128 { *self as u128 }
- })*)
+macro_rules! impl_int {
+ ($($t:ident)*) => (
+ $(impl DisplayInt for $t {
+ fn zero() -> Self { 0 }
+ fn from_u8(u: u8) -> Self { u as Self }
+ fn to_u8(&self) -> u8 { *self as u8 }
+ fn to_u16(&self) -> u16 { *self as u16 }
+ fn to_u32(&self) -> u32 { *self as u32 }
+ fn to_u64(&self) -> u64 { *self as u64 }
+ fn to_u128(&self) -> u128 { *self as u128 }
+ })*
+ )
}
-doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
+macro_rules! impl_uint {
+ ($($t:ident)*) => (
+ $(impl DisplayInt for $t {
+ fn zero() -> Self { 0 }
+ fn from_u8(u: u8) -> Self { u as Self }
+ fn to_u8(&self) -> u8 { *self as u8 }
+ fn to_u16(&self) -> u16 { *self as u16 }
+ fn to_u32(&self) -> u32 { *self as u32 }
+ fn to_u64(&self) -> u64 { *self as u64 }
+ fn to_u128(&self) -> u128 { *self as u128 }
+ })*
+ )
+}
+
+impl_int! { i8 i16 i32 i64 i128 isize }
+impl_uint! { u8 u16 u32 u64 u128 usize }
/// A type that represents a specific radix
#[doc(hidden)]
-trait GenericRadix {
+trait GenericRadix: Sized {
/// The number of digits.
const BASE: u8;
@@ -47,7 +64,7 @@
fn digit(x: u8) -> u8;
/// Format an integer using the radix using a formatter.
- fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// The radix can be as low as 2, so we need a buffer of at least 128
// characters for a base 2 number.
let zero = T::zero();
@@ -127,13 +144,11 @@
radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x }
radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x }
-radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x,
-x @ 10 ..= 15 => b'a' + (x - 10) }
-radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x,
-x @ 10 ..= 15 => b'A' + (x - 10) }
+radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) }
+radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) }
macro_rules! int_base {
- ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
+ (fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::$Trait for $T {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -143,8 +158,27 @@
};
}
+macro_rules! integer {
+ ($Int:ident, $Uint:ident) => {
+ int_base! { fmt::Binary for $Int as $Uint -> Binary }
+ int_base! { fmt::Octal for $Int as $Uint -> Octal }
+ int_base! { fmt::LowerHex for $Int as $Uint -> LowerHex }
+ int_base! { fmt::UpperHex for $Int as $Uint -> UpperHex }
+
+ int_base! { fmt::Binary for $Uint as $Uint -> Binary }
+ int_base! { fmt::Octal for $Uint as $Uint -> Octal }
+ int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex }
+ int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex }
+ };
+}
+integer! { isize, usize }
+integer! { i8, u8 }
+integer! { i16, u16 }
+integer! { i32, u32 }
+integer! { i64, u64 }
+integer! { i128, u128 }
macro_rules! debug {
- ($T:ident) => {
+ ($($T:ident)*) => {$(
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for $T {
#[inline]
@@ -158,31 +192,14 @@
}
}
}
- };
+ )*};
+}
+debug! {
+ i8 i16 i32 i64 i128 isize
+ u8 u16 u32 u64 u128 usize
}
-macro_rules! integer {
- ($Int:ident, $Uint:ident) => {
- int_base! { Binary for $Int as $Uint -> Binary }
- int_base! { Octal for $Int as $Uint -> Octal }
- int_base! { LowerHex for $Int as $Uint -> LowerHex }
- int_base! { UpperHex for $Int as $Uint -> UpperHex }
- debug! { $Int }
-
- int_base! { Binary for $Uint as $Uint -> Binary }
- int_base! { Octal for $Uint as $Uint -> Octal }
- int_base! { LowerHex for $Uint as $Uint -> LowerHex }
- int_base! { UpperHex for $Uint as $Uint -> UpperHex }
- debug! { $Uint }
- };
-}
-integer! { isize, usize }
-integer! { i8, u8 }
-integer! { i16, u16 }
-integer! { i32, u32 }
-integer! { i64, u64 }
-integer! { i128, u128 }
-
+// 2 digit decimal look up table
static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
@@ -256,21 +273,20 @@
f.pad_integral(is_nonnegative, "", buf_slice)
}
- $(
- #[stable(feature = "rust1", since = "1.0.0")]
- impl fmt::Display for $t {
- #[allow(unused_comparisons)]
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let is_nonnegative = *self >= 0;
- let n = if is_nonnegative {
- self.$conv_fn()
- } else {
- // convert the negative num to positive by summing 1 to it's 2 complement
- (!self.$conv_fn()).wrapping_add(1)
- };
- $name(n, is_nonnegative, f)
- }
- })*
+ $(#[stable(feature = "rust1", since = "1.0.0")]
+ impl fmt::Display for $t {
+ #[allow(unused_comparisons)]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let is_nonnegative = *self >= 0;
+ let n = if is_nonnegative {
+ self.$conv_fn()
+ } else {
+ // convert the negative num to positive by summing 1 to it's 2 complement
+ (!self.$conv_fn()).wrapping_add(1)
+ };
+ $name(n, is_nonnegative, f)
+ }
+ })*
};
}
@@ -461,6 +477,191 @@
impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
}
-
-impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128);
impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
+
+/// Helper function for writing a u64 into `buf` going from last to first, with `curr`.
+fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut isize) {
+ let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf);
+ let lut_ptr = DEC_DIGITS_LUT.as_ptr();
+ assert!(*curr > 19);
+
+ // SAFETY:
+ // Writes at most 19 characters into the buffer. Guaranteed that any ptr into LUT is at most
+ // 198, so will never OOB. There is a check above that there are at least 19 characters
+ // remaining.
+ unsafe {
+ if n >= 1e16 as u64 {
+ let to_parse = n % 1e16 as u64;
+ n /= 1e16 as u64;
+
+ // Some of these are nops but it looks more elegant this way.
+ let d1 = ((to_parse / 1e14 as u64) % 100) << 1;
+ let d2 = ((to_parse / 1e12 as u64) % 100) << 1;
+ let d3 = ((to_parse / 1e10 as u64) % 100) << 1;
+ let d4 = ((to_parse / 1e8 as u64) % 100) << 1;
+ let d5 = ((to_parse / 1e6 as u64) % 100) << 1;
+ let d6 = ((to_parse / 1e4 as u64) % 100) << 1;
+ let d7 = ((to_parse / 1e2 as u64) % 100) << 1;
+ let d8 = ((to_parse / 1e0 as u64) % 100) << 1;
+
+ *curr -= 16;
+
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d5 as isize), buf_ptr.offset(*curr + 8), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d6 as isize), buf_ptr.offset(*curr + 10), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d7 as isize), buf_ptr.offset(*curr + 12), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d8 as isize), buf_ptr.offset(*curr + 14), 2);
+ }
+ if n >= 1e8 as u64 {
+ let to_parse = n % 1e8 as u64;
+ n /= 1e8 as u64;
+
+ // Some of these are nops but it looks more elegant this way.
+ let d1 = ((to_parse / 1e6 as u64) % 100) << 1;
+ let d2 = ((to_parse / 1e4 as u64) % 100) << 1;
+ let d3 = ((to_parse / 1e2 as u64) % 100) << 1;
+ let d4 = ((to_parse / 1e0 as u64) % 100) << 1;
+ *curr -= 8;
+
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
+ }
+ // `n` < 1e8 < (1 << 32)
+ let mut n = n as u32;
+ if n >= 1e4 as u32 {
+ let to_parse = n % 1e4 as u32;
+ n /= 1e4 as u32;
+
+ let d1 = (to_parse / 100) << 1;
+ let d2 = (to_parse % 100) << 1;
+ *curr -= 4;
+
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
+ }
+
+ // `n` < 1e4 < (1 << 16)
+ let mut n = n as u16;
+ if n >= 100 {
+ let d1 = (n % 100) << 1;
+ n /= 100;
+ *curr -= 2;
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
+ }
+
+ // decode last 1 or 2 chars
+ if n < 10 {
+ *curr -= 1;
+ *buf_ptr.offset(*curr) = (n as u8) + b'0';
+ } else {
+ let d1 = n << 1;
+ *curr -= 2;
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for u128 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt_u128(*self, true, f)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for i128 {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let is_nonnegative = *self >= 0;
+ let n = if is_nonnegative {
+ self.to_u128()
+ } else {
+ // convert the negative num to positive by summing 1 to it's 2 complement
+ (!self.to_u128()).wrapping_add(1)
+ };
+ fmt_u128(n, is_nonnegative, f)
+ }
+}
+
+/// Specialized optimization for u128. Instead of taking two items at a time, it splits
+/// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1.
+/// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas
+/// 10^20 > 2^64 > 10^19.
+fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // 2^128 is about 3*10^38, so 39 gives an extra byte of space
+ let mut buf = [MaybeUninit::<u8>::uninit(); 39];
+ let mut curr = buf.len() as isize;
+
+ let (n, rem) = udiv_1e19(n);
+ parse_u64_into(rem, &mut buf, &mut curr);
+
+ if n != 0 {
+ // 0 pad up to point
+ let target = (buf.len() - 19) as isize;
+ // SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
+ // remaining since it has length 39
+ unsafe {
+ ptr::write_bytes(
+ MaybeUninit::slice_as_mut_ptr(&mut buf).offset(target),
+ b'0',
+ (curr - target) as usize,
+ );
+ }
+ curr = target;
+
+ let (n, rem) = udiv_1e19(n);
+ parse_u64_into(rem, &mut buf, &mut curr);
+ // Should this following branch be annotated with unlikely?
+ if n != 0 {
+ let target = (buf.len() - 38) as isize;
+ // The raw `buf_ptr` pointer is only valid until `buf` is used the next time,
+ // buf `buf` is not used in this scope so we are good.
+ let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
+ // SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
+ // There can only be at most 1 digit remaining.
+ unsafe {
+ ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
+ curr = target - 1;
+ *buf_ptr.offset(curr) = (n as u8) + b'0';
+ }
+ }
+ }
+
+ // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
+ // UTF-8 since `DEC_DIGITS_LUT` is
+ let buf_slice = unsafe {
+ str::from_utf8_unchecked(slice::from_raw_parts(
+ MaybeUninit::slice_as_mut_ptr(&mut buf).offset(curr),
+ buf.len() - curr as usize,
+ ))
+ };
+ f.pad_integral(is_nonnegative, "", buf_slice)
+}
+
+/// Partition of `n` into n > 1e19 and rem <= 1e19
+fn udiv_1e19(n: u128) -> (u128, u64) {
+ const DIV: u64 = 1e19 as u64;
+ let high = (n >> 64) as u64;
+ if high == 0 {
+ let low = n as u64;
+ return ((low / DIV) as u128, low % DIV);
+ }
+ let sr = 65 - high.leading_zeros();
+ let mut q = n << (128 - sr);
+ let mut r = n >> sr;
+ let mut carry = 0;
+
+ for _ in 0..sr {
+ r = (r << 1) | (q >> 127);
+ q = (q << 1) | carry as u128;
+
+ let s = (DIV as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127;
+ carry = (s & 1) as u64;
+ r -= (DIV as u128) & s as u128;
+ }
+ ((q << 1) | carry as u128, r as u64)
+}
diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs
index fa5655c..cdde094 100644
--- a/library/core/src/future/mod.rs
+++ b/library/core/src/future/mod.rs
@@ -32,7 +32,7 @@
/// This type is needed because:
///
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
-/// a raw pointer (see https://github.com/rust-lang/rust/issues/68923).
+/// a raw pointer (see <https://github.com/rust-lang/rust/issues/68923>).
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
/// non-Send/Sync as well, and we don't want that.
///
diff --git a/library/core/src/hash/sip.rs b/library/core/src/hash/sip.rs
index a9882d5..6178b0a 100644
--- a/library/core/src/hash/sip.rs
+++ b/library/core/src/hash/sip.rs
@@ -111,7 +111,7 @@
debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
let mut data = 0 as $int_ty;
ptr::copy_nonoverlapping(
- $buf.get_unchecked($i),
+ $buf.as_ptr().add($i),
&mut data as *mut _ as *mut u8,
mem::size_of::<$int_ty>(),
);
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 4eb47dd..979a5f8 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -1,6 +1,7 @@
#![stable(feature = "core_hint", since = "1.27.0")]
//! Hints to compiler that affects how code should be emitted or optimized.
+//! Hints may be compile time or runtime.
use crate::intrinsics;
@@ -24,7 +25,6 @@
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
-///
/// # Example
///
/// ```
@@ -51,18 +51,62 @@
unsafe { intrinsics::unreachable() }
}
-/// Emits a machine instruction hinting to the processor that it is running in busy-wait
-/// spin-loop ("spin lock").
+/// Emits a machine instruction to signal the processor that it is running in
+/// a busy-wait spin-loop ("spin lock").
///
-/// For a discussion of different locking strategies and their trade-offs, see
-/// [`core::sync::atomic::spin_loop_hint`].
+/// Upon receiving the spin-loop signal the processor can optimize its behavior by,
+/// for example, saving power or switching hyper-threads.
///
-/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
-/// do anything at all.
+/// This function is different from [`thread::yield_now`] which directly
+/// yields to the system's scheduler, whereas `spin_loop` does not interact
+/// with the operating system.
///
-/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
+/// A common use case for `spin_loop` is implementing bounded optimistic
+/// spinning in a CAS loop in synchronization primitives. To avoid problems
+/// like priority inversion, it is strongly recommended that the spin loop is
+/// terminated after a finite amount of iterations and an appropriate blocking
+/// syscall is made.
+///
+/// **Note**: On platforms that do not support receiving spin-loop hints this
+/// function does not do anything at all.
+///
+/// # Examples
+///
+/// ```
+/// use std::sync::atomic::{AtomicBool, Ordering};
+/// use std::sync::Arc;
+/// use std::{hint, thread};
+///
+/// // A shared atomic value that threads will use to coordinate
+/// let live = Arc::new(AtomicBool::new(false));
+///
+/// // In a background thread we'll eventually set the value
+/// let bg_work = {
+/// let live = live.clone();
+/// thread::spawn(move || {
+/// // Do some work, then make the value live
+/// do_some_work();
+/// live.store(true, Ordering::Release);
+/// })
+/// };
+///
+/// // Back on our current thread, we wait for the value to be set
+/// while live.load(Ordering::Acquire) {
+/// // The spin loop is a hint to the CPU that we're waiting, but probably
+/// // not for very long
+/// hint::spin_loop();
+/// }
+///
+/// // The value is now set
+/// # fn do_some_work() {}
+/// do_some_work();
+/// bg_work.join()?;
+/// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
+/// ```
+///
+/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
#[inline]
-#[unstable(feature = "renamed_spin_loop", issue = "55002")]
+#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
pub fn spin_loop() {
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
{
@@ -98,8 +142,6 @@
/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
/// `black_box` could do.
///
-/// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html
-///
/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
@@ -108,6 +150,8 @@
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
+///
+/// [`std::convert::identity`]: crate::convert::identity
#[cfg_attr(not(miri), inline)]
#[cfg_attr(miri, inline(never))]
#[unstable(feature = "test", issue = "50297")]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 426cdb1..433f012 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -9,7 +9,7 @@
//! This includes changes in the stability of the constness.
//!
//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
-//! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to
+//! from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs> to
//! `compiler/rustc_mir/src/interpret/intrinsics.rs` and add a
//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
//!
@@ -719,7 +719,7 @@
/// macro, which panics when it is executed, it is *undefined behavior* to
/// reach code marked with this function.
///
- /// The stabilized version of this intrinsic is [`crate::hint::unreachable_unchecked`].
+ /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`](crate::hint::unreachable_unchecked).
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
pub fn unreachable() -> !;
@@ -764,7 +764,7 @@
/// More specifically, this is the offset in bytes between successive
/// items of the same type, including alignment padding.
///
- /// The stabilized version of this intrinsic is [`size_of`].
+ /// The stabilized version of this intrinsic is [`core::mem::size_of`](crate::mem::size_of).
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
pub fn size_of<T>() -> usize;
@@ -772,12 +772,12 @@
///
/// Drop glue is not run on the destination.
///
- /// The stabilized version of this intrinsic is [`crate::ptr::write`].
+ /// The stabilized version of this intrinsic is [`core::ptr::write`](crate::ptr::write).
pub fn move_val_init<T>(dst: *mut T, src: T);
/// The minimum alignment of a type.
///
- /// The stabilized version of this intrinsic is [`crate::mem::align_of`].
+ /// The stabilized version of this intrinsic is [`core::mem::align_of`](crate::mem::align_of).
#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
pub fn min_align_of<T>() -> usize;
/// The preferred alignment of a type.
@@ -788,18 +788,18 @@
/// The size of the referenced value in bytes.
///
- /// The stabilized version of this intrinsic is [`size_of_val`].
+ /// The stabilized version of this intrinsic is [`mem::size_of_val`].
#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
/// The required alignment of the referenced value.
///
- /// The stabilized version of this intrinsic is [`crate::mem::align_of_val`].
+ /// The stabilized version of this intrinsic is [`core::mem::align_of_val`](crate::mem::align_of_val).
#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
/// Gets a static string slice containing the name of a type.
///
- /// The stabilized version of this intrinsic is [`crate::any::type_name`].
+ /// The stabilized version of this intrinsic is [`core::any::type_name`](crate::any::type_name).
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
pub fn type_name<T: ?Sized>() -> &'static str;
@@ -807,7 +807,7 @@
/// function will return the same value for a type regardless of whichever
/// crate it is invoked in.
///
- /// The stabilized version of this intrinsic is [`crate::any::TypeId::of`].
+ /// The stabilized version of this intrinsic is [`core::any::TypeId::of`](crate::any::TypeId::of).
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
pub fn type_id<T: ?Sized + 'static>() -> u64;
@@ -831,7 +831,7 @@
/// Gets a reference to a static `Location` indicating where it was called.
///
- /// Consider using [`crate::panic::Location::caller`] instead.
+ /// Consider using [`core::panic::Location::caller`](crate::panic::Location::caller) instead.
#[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
pub fn caller_location() -> &'static crate::panic::Location<'static>;
@@ -1072,7 +1072,7 @@
// NOTE: While this makes the intrinsic const stable, we have some custom code in const fn
// checks that prevent its use within `const fn`.
#[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
- #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "transmute")]
+ #[rustc_diagnostic_item = "transmute"]
pub fn transmute<T, U>(e: T) -> U;
/// Returns `true` if the actual type given as `T` requires drop
@@ -1082,7 +1082,7 @@
/// If the actual type neither requires drop glue nor implements
/// `Copy`, then the return value of this function is unspecified.
///
- /// The stabilized version of this intrinsic is [`needs_drop`].
+ /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
pub fn needs_drop<T>() -> bool;
@@ -1152,11 +1152,11 @@
/// Performs a volatile load from the `src` pointer.
///
- /// The stabilized version of this intrinsic is [`crate::ptr::read_volatile`].
+ /// The stabilized version of this intrinsic is [`core::ptr::read_volatile`](crate::ptr::read_volatile).
pub fn volatile_load<T>(src: *const T) -> T;
/// Performs a volatile store to the `dst` pointer.
///
- /// The stabilized version of this intrinsic is [`crate::ptr::write_volatile`].
+ /// The stabilized version of this intrinsic is [`core::ptr::write_volatile`](crate::ptr::write_volatile).
pub fn volatile_store<T>(dst: *mut T, val: T);
/// Performs a volatile load from the `src` pointer
@@ -1660,22 +1660,22 @@
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
///
/// The stabilized versions of this intrinsic are available on the integer
- /// primitives via the `checked_add` method. For example,
- /// [`u32::checked_add`]
+ /// primitives via the `wrapping_add` method. For example,
+ /// [`u32::wrapping_add`]
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
///
/// The stabilized versions of this intrinsic are available on the integer
- /// primitives via the `checked_sub` method. For example,
- /// [`u32::checked_sub`]
+ /// primitives via the `wrapping_sub` method. For example,
+ /// [`u32::wrapping_sub`]
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
///
/// The stabilized versions of this intrinsic are available on the integer
- /// primitives via the `checked_mul` method. For example,
- /// [`u32::checked_mul`]
+ /// primitives via the `wrapping_mul` method. For example,
+ /// [`u32::wrapping_mul`]
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
@@ -1697,14 +1697,14 @@
/// Returns the value of the discriminant for the variant in 'v',
/// cast to a `u64`; if `T` has no discriminant, returns 0.
///
- /// The stabilized version of this intrinsic is [`crate::mem::discriminant`].
+ /// The stabilized version of this intrinsic is [`core::mem::discriminant`](crate::mem::discriminant).
#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
/// Returns the number of variants of the type `T` cast to a `usize`;
/// if `T` has no variants, returns 0. Uninhabited variants will be counted.
///
- /// The to-be-stabilized version of this intrinsic is [`variant_count`].
+ /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
pub fn variant_count<T>() -> usize;
diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs
index ac27ec1..2e070d7 100644
--- a/library/core/src/iter/adapters/chain.rs
+++ b/library/core/src/iter/adapters/chain.rs
@@ -109,7 +109,7 @@
acc = b.try_fold(acc, f)?;
// we don't fuse the second iterator
}
- Try::from_ok(acc)
+ try { acc }
}
fn fold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
@@ -126,16 +126,42 @@
}
#[inline]
- fn nth(&mut self, mut n: usize) -> Option<A::Item> {
+ fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+ let mut rem = n;
+
if let Some(ref mut a) = self.a {
- while let Some(x) = a.next() {
- if n == 0 {
- return Some(x);
- }
- n -= 1;
+ match a.advance_by(rem) {
+ Ok(()) => return Ok(()),
+ Err(k) => rem -= k,
}
self.a = None;
}
+
+ if let Some(ref mut b) = self.b {
+ match b.advance_by(rem) {
+ Ok(()) => return Ok(()),
+ Err(k) => rem -= k,
+ }
+ // we don't fuse the second iterator
+ }
+
+ if rem == 0 { Ok(()) } else { Err(n - rem) }
+ }
+
+ #[inline]
+ fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
+ if let Some(ref mut a) = self.a {
+ match a.advance_by(n) {
+ Ok(()) => match a.next() {
+ None => n = 0,
+ x => return x,
+ },
+ Err(k) => n -= k,
+ }
+
+ self.a = None;
+ }
+
maybe!(self.b.nth(n))
}
@@ -202,16 +228,42 @@
}
#[inline]
- fn nth_back(&mut self, mut n: usize) -> Option<A::Item> {
+ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+ let mut rem = n;
+
if let Some(ref mut b) = self.b {
- while let Some(x) = b.next_back() {
- if n == 0 {
- return Some(x);
- }
- n -= 1;
+ match b.advance_back_by(rem) {
+ Ok(()) => return Ok(()),
+ Err(k) => rem -= k,
}
self.b = None;
}
+
+ if let Some(ref mut a) = self.a {
+ match a.advance_back_by(rem) {
+ Ok(()) => return Ok(()),
+ Err(k) => rem -= k,
+ }
+ // we don't fuse the second iterator
+ }
+
+ if rem == 0 { Ok(()) } else { Err(n - rem) }
+ }
+
+ #[inline]
+ fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
+ if let Some(ref mut b) = self.b {
+ match b.advance_back_by(n) {
+ Ok(()) => match b.next_back() {
+ None => n = 0,
+ x => return x,
+ },
+ Err(k) => n -= k,
+ }
+
+ self.b = None;
+ }
+
maybe!(self.a.nth_back(n))
}
@@ -240,7 +292,7 @@
acc = a.try_rfold(acc, f)?;
// we don't fuse the second iterator
}
- Try::from_ok(acc)
+ try { acc }
}
fn rfold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index ddb1aae..96d0a60 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -121,7 +121,7 @@
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`flatten`]: trait.Iterator.html#method.flatten
+/// [`flatten`]: Iterator::flatten
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
@@ -317,7 +317,7 @@
}
self.backiter = None;
- Try::from_ok(init)
+ try { init }
}
#[inline]
@@ -397,7 +397,7 @@
}
self.frontiter = None;
- Try::from_ok(init)
+ try { init }
}
#[inline]
diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs
index a78da36..60ac352 100644
--- a/library/core/src/iter/adapters/fuse.rs
+++ b/library/core/src/iter/adapters/fuse.rs
@@ -303,7 +303,7 @@
acc = iter.try_fold(acc, fold)?;
self.iter = None;
}
- Try::from_ok(acc)
+ try { acc }
}
#[inline]
@@ -353,7 +353,7 @@
acc = iter.try_rfold(acc, fold)?;
self.iter = None;
}
- Try::from_ok(acc)
+ try { acc }
}
#[inline]
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index a725fb0..9586284 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -85,7 +85,7 @@
/// * whatever remains in the source after iteration has stopped
/// * the memory that has become unused by advancing a consuming iterator
///
- /// [`next()`]: trait.Iterator.html#method.next
+ /// [`next()`]: Iterator::next
unsafe fn as_inner(&mut self) -> &mut Self::Source;
}
@@ -94,7 +94,7 @@
/// This `struct` is created by the [`rev`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`rev`]: trait.Iterator.html#method.rev
+/// [`rev`]: Iterator::rev
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -228,7 +228,7 @@
/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`copied`]: trait.Iterator.html#method.copied
+/// [`copied`]: Iterator::copied
/// [`Iterator`]: trait.Iterator.html
#[stable(feature = "iter_copied", since = "1.36.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -380,7 +380,7 @@
/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`cloned`]: trait.Iterator.html#method.cloned
+/// [`cloned`]: Iterator::cloned
/// [`Iterator`]: trait.Iterator.html
#[stable(feature = "iter_cloned", since = "1.1.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -515,7 +515,7 @@
/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`cycle`]: trait.Iterator.html#method.cycle
+/// [`cycle`]: Iterator::cycle
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -579,7 +579,7 @@
})?;
if is_empty {
- return Try::from_ok(acc);
+ return try { acc };
}
loop {
@@ -600,7 +600,7 @@
/// This `struct` is created by the [`step_by`] method on [`Iterator`]. See
/// its documentation for more.
///
-/// [`step_by`]: trait.Iterator.html#method.step_by
+/// [`step_by`]: Iterator::step_by
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_step_by", since = "1.28.0")]
@@ -715,7 +715,7 @@
if self.first_take {
self.first_take = false;
match self.iter.next() {
- None => return Try::from_ok(acc),
+ None => return try { acc },
Some(x) => acc = f(acc, x)?,
}
}
@@ -792,7 +792,7 @@
}
match self.next_back() {
- None => Try::from_ok(init),
+ None => try { init },
Some(x) => {
let acc = f(init, x)?;
from_fn(nth_back(&mut self.iter, self.step)).try_fold(acc, f)
@@ -833,7 +833,7 @@
/// This `struct` is created by the [`map`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`map`]: trait.Iterator.html#method.map
+/// [`map`]: Iterator::map
/// [`Iterator`]: trait.Iterator.html
///
/// # Notes about side effects
@@ -1042,7 +1042,7 @@
/// This `struct` is created by the [`filter`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`filter`]: trait.Iterator.html#method.filter
+/// [`filter`]: Iterator::filter
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1075,7 +1075,7 @@
predicate: &'a mut impl FnMut(&T) -> bool,
mut fold: impl FnMut(Acc, T) -> R + 'a,
) -> impl FnMut(Acc, T) -> R + 'a {
- move |acc, item| if predicate(&item) { fold(acc, item) } else { R::from_ok(acc) }
+ move |acc, item| if predicate(&item) { fold(acc, item) } else { try { acc } }
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1191,7 +1191,7 @@
/// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`filter_map`]: trait.Iterator.html#method.filter_map
+/// [`filter_map`]: Iterator::filter_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1229,7 +1229,7 @@
) -> impl FnMut(Acc, T) -> R + 'a {
move |acc, item| match f(item) {
Some(x) => fold(acc, x),
- None => R::from_ok(acc),
+ None => try { acc },
}
}
@@ -1338,7 +1338,7 @@
/// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`enumerate`]: trait.Iterator.html#method.enumerate
+/// [`enumerate`]: Iterator::enumerate
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -1574,7 +1574,7 @@
/// This `struct` is created by the [`peekable`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`peekable`]: trait.Iterator.html#method.peekable
+/// [`peekable`]: Iterator::peekable
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -1660,7 +1660,7 @@
R: Try<Ok = B>,
{
let acc = match self.peeked.take() {
- Some(None) => return Try::from_ok(init),
+ Some(None) => return try { init },
Some(Some(v)) => f(init, v)?,
None => init,
};
@@ -1703,7 +1703,7 @@
R: Try<Ok = B>,
{
match self.peeked.take() {
- Some(None) => Try::from_ok(init),
+ Some(None) => try { init },
Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {
Ok(acc) => f(acc, v),
Err(e) => {
@@ -1743,7 +1743,7 @@
/// Like [`next`], if there is a value, it is wrapped in a `Some(T)`.
/// But if the iteration is over, `None` is returned.
///
- /// [`next`]: trait.Iterator.html#tymethod.next
+ /// [`next`]: Iterator::next
///
/// Because `peek()` returns a reference, and many iterators iterate over
/// references, there can be a possibly confusing situation where the
@@ -1871,7 +1871,7 @@
/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`skip_while`]: trait.Iterator.html#method.skip_while
+/// [`skip_while`]: Iterator::skip_while
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1938,7 +1938,7 @@
if !self.flag {
match self.next() {
Some(v) => init = fold(init, v)?,
- None => return Try::from_ok(init),
+ None => return try { init },
}
}
self.iter.try_fold(init, fold)
@@ -1993,7 +1993,7 @@
/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`take_while`]: trait.Iterator.html#method.take_while
+/// [`take_while`]: Iterator::take_while
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2065,13 +2065,13 @@
ControlFlow::from_try(fold(acc, x))
} else {
*flag = true;
- ControlFlow::Break(Try::from_ok(acc))
+ ControlFlow::Break(try { acc })
}
}
}
if self.flag {
- Try::from_ok(init)
+ try { init }
} else {
let flag = &mut self.flag;
let p = &mut self.predicate;
@@ -2128,7 +2128,7 @@
/// This `struct` is created by the [`map_while`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`map_while`]: trait.Iterator.html#method.map_while
+/// [`map_while`]: Iterator::map_while
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
@@ -2180,7 +2180,7 @@
let Self { iter, predicate } = self;
iter.try_fold(init, |acc, x| match predicate(x) {
Some(item) => ControlFlow::from_try(fold(acc, item)),
- None => ControlFlow::Break(Try::from_ok(acc)),
+ None => ControlFlow::Break(try { acc }),
})
.into_try()
}
@@ -2226,7 +2226,7 @@
/// This `struct` is created by the [`skip`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`skip`]: trait.Iterator.html#method.skip
+/// [`skip`]: Iterator::skip
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -2316,7 +2316,7 @@
if n > 0 {
// nth(n) skips n+1
if self.iter.nth(n - 1).is_none() {
- return Try::from_ok(init);
+ return try { init };
}
}
self.iter.try_fold(init, fold)
@@ -2381,11 +2381,7 @@
}
let n = self.len();
- if n == 0 {
- Try::from_ok(init)
- } else {
- self.iter.try_rfold(init, check(n, fold)).into_try()
- }
+ if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() }
}
fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
@@ -2426,7 +2422,7 @@
/// This `struct` is created by the [`take`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`take`]: trait.Iterator.html#method.take
+/// [`take`]: Iterator::take
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
@@ -2509,7 +2505,7 @@
}
if self.n == 0 {
- Try::from_ok(init)
+ try { init }
} else {
let n = &mut self.n;
self.iter.try_fold(init, check(n, fold)).into_try()
@@ -2587,11 +2583,11 @@
R: Try<Ok = Acc>,
{
if self.n == 0 {
- Try::from_ok(init)
+ try { init }
} else {
let len = self.iter.len();
if len > self.n && self.iter.nth_back(len - self.n - 1).is_none() {
- Try::from_ok(init)
+ try { init }
} else {
self.iter.try_rfold(init, fold)
}
@@ -2631,7 +2627,7 @@
/// This `struct` is created by the [`scan`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`scan`]: trait.Iterator.html#method.scan
+/// [`scan`]: Iterator::scan
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2687,7 +2683,7 @@
mut fold: impl FnMut(Acc, B) -> R + 'a,
) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
move |acc, x| match f(state, x) {
- None => ControlFlow::Break(Try::from_ok(acc)),
+ None => ControlFlow::Break(try { acc }),
Some(x) => ControlFlow::from_try(fold(acc, x)),
}
}
@@ -2739,7 +2735,7 @@
/// This `struct` is created by the [`inspect`] method on [`Iterator`]. See its
/// documentation for more.
///
-/// [`inspect`]: trait.Iterator.html#method.inspect
+/// [`inspect`]: Iterator::inspect
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2951,7 +2947,7 @@
Ok(x) => ControlFlow::from_try(f(acc, x)),
Err(e) => {
*error = Err(e);
- ControlFlow::Break(Try::from_ok(acc))
+ ControlFlow::Break(try { acc })
}
})
.into_try()
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 9f34aee..cd8ab11 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -713,7 +713,7 @@
R: Try<Ok = B>,
{
if self.is_empty() {
- return Try::from_ok(init);
+ return try { init };
}
let mut accum = init;
@@ -731,7 +731,7 @@
accum = f(accum, self.start.clone())?;
}
- Try::from_ok(accum)
+ try { accum }
}
#[inline]
@@ -818,7 +818,7 @@
R: Try<Ok = B>,
{
if self.is_empty() {
- return Try::from_ok(init);
+ return try { init };
}
let mut accum = init;
@@ -836,7 +836,7 @@
accum = f(accum, self.start.clone())?;
}
- Try::from_ok(accum)
+ try { accum }
}
#[inline]
diff --git a/library/core/src/iter/sources.rs b/library/core/src/iter/sources.rs
index 97562cf..44da8f4 100644
--- a/library/core/src/iter/sources.rs
+++ b/library/core/src/iter/sources.rs
@@ -501,9 +501,9 @@
///
/// # Examples
///
-/// Let’s re-implement the counter iterator from [module-level documentation]:
+/// Let’s re-implement the counter iterator from the [module-level documentation]:
///
-/// [module-level documentation]: index.html
+/// [module-level documentation]: super
///
/// ```
/// let mut count = 0;
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 41a503c..1ae6d15 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -94,7 +94,7 @@
///
/// See the [module-level documentation] for more.
///
- /// [module-level documentation]: index.html
+ /// [module-level documentation]: crate::iter
///
/// # Examples
///
@@ -120,7 +120,7 @@
/// collection of some kind.
///
/// One benefit of implementing `IntoIterator` is that your type will [work
-/// with Rust's `for` loop syntax](index.html#for-loops-and-intoiterator).
+/// with Rust's `for` loop syntax](crate::iter#for-loops-and-intoiterator).
///
/// See also: [`FromIterator`].
///
@@ -212,7 +212,7 @@
///
/// See the [module-level documentation] for more.
///
- /// [module-level documentation]: index.html
+ /// [module-level documentation]: crate::iter
///
/// # Examples
///
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index 2280799..6f8cb6b 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -122,6 +122,9 @@
/// assert_eq!(iter.advance_back_by(0), Ok(()));
/// assert_eq!(iter.advance_back_by(100), Err(1)); // only `&3` was skipped
/// ```
+ ///
+ /// [`Ok(())`]: Ok
+ /// [`Err(k)`]: Err
#[inline]
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
@@ -221,7 +224,7 @@
while let Some(x) = self.next_back() {
accum = f(accum, x)?;
}
- Try::from_ok(accum)
+ try { accum }
}
/// An iterator method that reduces the iterator's elements to a single,
diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs
index 33ace60..eadbdf4 100644
--- a/library/core/src/iter/traits/exact_size.rs
+++ b/library/core/src/iter/traits/exact_size.rs
@@ -26,10 +26,10 @@
/// assert_eq!(5, five.len());
/// ```
///
-/// In the [module level docs][moddocs], we implemented an [`Iterator`],
-/// `Counter`. Let's implement `ExactSizeIterator` for it as well:
+/// In the [module-level docs], we implemented an [`Iterator`], `Counter`.
+/// Let's implement `ExactSizeIterator` for it as well:
///
-/// [moddocs]: index.html
+/// [module-level docs]: crate::iter
///
/// ```
/// # struct Counter {
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index a1d8deb..19484bf 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -289,12 +289,12 @@
/// This method will eagerly skip `n` elements by calling [`next`] up to `n`
/// times until [`None`] is encountered.
///
- /// `advance_by(n)` will return [`Ok(())`] if the iterator successfully advances by
- /// `n` elements, or [`Err(k)`] if [`None`] is encountered, where `k` is the number
+ /// `advance_by(n)` will return [`Ok(())`][Ok] if the iterator successfully advances by
+ /// `n` elements, or [`Err(k)`][Err] if [`None`] is encountered, where `k` is the number
/// of elements the iterator is advanced by before running out of elements (i.e. the
/// length of the iterator). Note that `k` is always less than `n`.
///
- /// Calling `advance_by(0)` does not consume any elements and always returns [`Ok(())`].
+ /// Calling `advance_by(0)` does not consume any elements and always returns [`Ok(())`][Ok].
///
/// [`next`]: Iterator::next
///
@@ -1887,7 +1887,7 @@
while let Some(x) = self.next() {
accum = f(accum, x)?;
}
- Try::from_ok(accum)
+ try { accum }
}
/// An iterator method that applies a fallible function to each item in the
@@ -2851,7 +2851,7 @@
Product::product(self)
}
- /// Lexicographically compares the elements of this [`Iterator`] with those
+ /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
/// of another.
///
/// # Examples
@@ -2873,7 +2873,7 @@
self.cmp_by(other, |x, y| x.cmp(&y))
}
- /// Lexicographically compares the elements of this [`Iterator`] with those
+ /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
/// of another with respect to the specified comparison function.
///
/// # Examples
@@ -2925,7 +2925,7 @@
}
}
- /// Lexicographically compares the elements of this [`Iterator`] with those
+ /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
/// of another.
///
/// # Examples
@@ -2949,7 +2949,7 @@
self.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
}
- /// Lexicographically compares the elements of this [`Iterator`] with those
+ /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
/// of another with respect to the specified comparison function.
///
/// # Examples
@@ -3089,7 +3089,7 @@
!self.eq(other)
}
- /// Determines if the elements of this [`Iterator`] are lexicographically
+ /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison)
/// less than those of another.
///
/// # Examples
@@ -3110,7 +3110,7 @@
self.partial_cmp(other) == Some(Ordering::Less)
}
- /// Determines if the elements of this [`Iterator`] are lexicographically
+ /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison)
/// less or equal to those of another.
///
/// # Examples
@@ -3131,7 +3131,7 @@
matches!(self.partial_cmp(other), Some(Ordering::Less | Ordering::Equal))
}
- /// Determines if the elements of this [`Iterator`] are lexicographically
+ /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison)
/// greater than those of another.
///
/// # Examples
@@ -3152,7 +3152,7 @@
self.partial_cmp(other) == Some(Ordering::Greater)
}
- /// Determines if the elements of this [`Iterator`] are lexicographically
+ /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison)
/// greater than or equal to those of another.
///
/// # Examples
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 22bf2b1..4120254 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -63,12 +63,14 @@
#![warn(missing_debug_implementations)]
#![allow(explicit_outlives_requirements)]
#![allow(incomplete_features)]
+#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(asm)]
#![feature(cfg_target_has_atomic)]
#![feature(const_alloc_layout)]
#![feature(const_discriminant)]
+#![feature(const_cell_into_inner)]
#![feature(const_checked_int_methods)]
#![feature(const_euclidean_int_methods)]
#![feature(const_float_classify)]
@@ -80,10 +82,11 @@
#![feature(constctlz)]
#![feature(const_panic)]
#![feature(const_pin)]
-#![feature(const_fn_union)]
#![feature(const_fn)]
-#![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))]
-#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))]
+#![feature(const_fn_union)]
+#![cfg_attr(not(bootstrap), feature(const_impl_trait))]
+#![feature(const_fn_floating_point_arithmetic)]
+#![feature(const_fn_fn_ptr_basics)]
#![feature(const_generics)]
#![feature(const_option)]
#![feature(const_precise_live_drops)]
@@ -125,13 +128,16 @@
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stmt_expr_attributes)]
+#![feature(str_split_as_str)]
+#![feature(str_split_inclusive_as_str)]
#![feature(transparent_unions)]
+#![feature(try_blocks)]
#![feature(unboxed_closures)]
-#![feature(unsized_locals)]
-#![feature(untagged_unions)]
+#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
+#![cfg_attr(bootstrap, feature(unsized_locals))]
+#![cfg_attr(bootstrap, feature(untagged_unions))]
#![feature(unwind_attributes)]
#![feature(variant_count)]
-#![cfg_attr(bootstrap, feature(doc_alias))]
#![feature(tbm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(arm_target_feature)]
@@ -153,6 +159,7 @@
#![feature(slice_ptr_get)]
#![feature(no_niche)] // rust-lang/rust#68303
#![feature(unsafe_block_in_unsafe_fn)]
+#![feature(int_error_matching)]
#![deny(unsafe_op_in_unsafe_fn)]
#[prelude_import]
@@ -282,6 +289,7 @@
unused_imports,
unsafe_op_in_unsafe_fn
)]
+#[cfg_attr(not(bootstrap), allow(non_autolinks))]
// 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 a1b0821..fe3eff0 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -6,14 +6,11 @@
() => (
$crate::panic!("explicit panic")
);
- ($msg:literal) => (
+ ($msg:literal $(,)?) => (
$crate::panicking::panic($msg)
);
- ($msg:expr) => (
- $crate::panic!("{}", $crate::convert::identity::<&str>($msg))
- );
- ($msg:expr,) => (
- $crate::panic!($msg)
+ ($msg:expr $(,)?) => (
+ $crate::panicking::panic_str($msg)
);
($fmt:expr, $($arg:tt)+) => (
$crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+))
@@ -40,7 +37,7 @@
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert_eq {
- ($left:expr, $right:expr) => ({
+ ($left:expr, $right:expr $(,)?) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
@@ -54,9 +51,6 @@
}
}
});
- ($left:expr, $right:expr,) => ({
- $crate::assert_eq!($left, $right)
- });
($left:expr, $right:expr, $($arg:tt)+) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
@@ -94,7 +88,7 @@
#[macro_export]
#[stable(feature = "assert_ne", since = "1.13.0")]
macro_rules! assert_ne {
- ($left:expr, $right:expr) => ({
+ ($left:expr, $right:expr $(,)?) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if *left_val == *right_val {
@@ -108,9 +102,6 @@
}
}
});
- ($left:expr, $right:expr,) => {
- $crate::assert_ne!($left, $right)
- };
($left:expr, $right:expr, $($arg:tt)+) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
@@ -315,7 +306,7 @@
#[rustc_deprecated(since = "1.39.0", reason = "use the `?` operator instead")]
#[doc(alias = "?")]
macro_rules! r#try {
- ($expr:expr) => {
+ ($expr:expr $(,)?) => {
match $expr {
$crate::result::Result::Ok(val) => val,
$crate::result::Result::Err(err) => {
@@ -323,14 +314,11 @@
}
}
};
- ($expr:expr,) => {
- $crate::r#try!($expr)
- };
}
/// Writes formatted data into a buffer.
///
-/// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be
+/// This macro accepts a 'writer', a format string, and a list of arguments. Arguments will be
/// formatted according to the specified format string and the result will be passed to the writer.
/// The writer may be any value with a `write_fmt` method; generally this comes from an
/// implementation of either the [`fmt::Write`] or the [`io::Write`] trait. The macro
@@ -339,7 +327,7 @@
///
/// See [`std::fmt`] for more information on the format string syntax.
///
-/// [`std::fmt`]: crate::fmt
+/// [`std::fmt`]: ../std/fmt/index.html
/// [`fmt::Write`]: crate::fmt::Write
/// [`io::Write`]: ../std/io/trait.Write.html
/// [`fmt::Result`]: crate::fmt::Result
@@ -451,12 +439,9 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(format_args_nl)]
macro_rules! writeln {
- ($dst:expr) => (
+ ($dst:expr $(,)?) => (
$crate::write!($dst, "\n")
);
- ($dst:expr,) => (
- $crate::writeln!($dst)
- );
($dst:expr, $($arg:tt)*) => (
$dst.write_fmt($crate::format_args_nl!($($arg)*))
);
@@ -517,12 +502,9 @@
() => ({
panic!("internal error: entered unreachable code")
});
- ($msg:expr) => ({
+ ($msg:expr $(,)?) => ({
$crate::unreachable!("{}", $msg)
});
- ($msg:expr,) => ({
- $crate::unreachable!($msg)
- });
($fmt:expr, $($arg:tt)*) => ({
panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
});
@@ -711,8 +693,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! compile_error {
- ($msg:expr) => {{ /* compiler built-in */ }};
- ($msg:expr,) => {{ /* compiler built-in */ }};
+ ($msg:expr $(,)?) => {{ /* compiler built-in */ }};
}
/// Constructs parameters for the other string-formatting macros.
@@ -816,8 +797,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! env {
- ($name:expr) => {{ /* compiler built-in */ }};
- ($name:expr,) => {{ /* compiler built-in */ }};
+ ($name:expr $(,)?) => {{ /* compiler built-in */ }};
}
/// Optionally inspects an environment variable at compile time.
@@ -841,8 +821,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! option_env {
- ($name:expr) => {{ /* compiler built-in */ }};
- ($name:expr,) => {{ /* compiler built-in */ }};
+ ($name:expr $(,)?) => {{ /* compiler built-in */ }};
}
/// Concatenates identifiers into one identifier.
@@ -877,8 +856,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! concat_idents {
- ($($e:ident),+) => {{ /* compiler built-in */ }};
- ($($e:ident,)+) => {{ /* compiler built-in */ }};
+ ($($e:ident),+ $(,)?) => {{ /* compiler built-in */ }};
}
/// Concatenates literals into a static string slice.
@@ -900,8 +878,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! concat {
- ($($e:expr),*) => {{ /* compiler built-in */ }};
- ($($e:expr,)*) => {{ /* compiler built-in */ }};
+ ($($e:expr),* $(,)?) => {{ /* compiler built-in */ }};
}
/// Expands to the line number on which it was invoked.
@@ -1043,8 +1020,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! include_str {
- ($file:expr) => {{ /* compiler built-in */ }};
- ($file:expr,) => {{ /* compiler built-in */ }};
+ ($file:expr $(,)?) => {{ /* compiler built-in */ }};
}
/// Includes a file as a reference to a byte array.
@@ -1083,8 +1059,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! include_bytes {
- ($file:expr) => {{ /* compiler built-in */ }};
- ($file:expr,) => {{ /* compiler built-in */ }};
+ ($file:expr $(,)?) => {{ /* compiler built-in */ }};
}
/// Expands to a string that represents the current module path.
@@ -1191,8 +1166,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! include {
- ($file:expr) => {{ /* compiler built-in */ }};
- ($file:expr,) => {{ /* compiler built-in */ }};
+ ($file:expr $(,)?) => {{ /* compiler built-in */ }};
}
/// Asserts that a boolean expression is `true` at runtime.
@@ -1242,8 +1216,7 @@
#[rustc_builtin_macro]
#[macro_export]
macro_rules! assert {
- ($cond:expr) => {{ /* compiler built-in */ }};
- ($cond:expr,) => {{ /* compiler built-in */ }};
+ ($cond:expr $(,)?) => {{ /* compiler built-in */ }};
($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
}
@@ -1365,6 +1338,8 @@
}
/// Attribute macro applied to a static to register it as a global allocator.
+ ///
+ /// See also [`std::alloc::GlobalAlloc`](../std/alloc/trait.GlobalAlloc.html).
#[stable(feature = "global_allocator", since = "1.28.0")]
#[allow_internal_unstable(rustc_attrs)]
#[rustc_builtin_macro]
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index e629d28..660b7db 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -246,6 +246,14 @@
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
///
+ /// # Example
+ ///
+ /// ```
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let v: MaybeUninit<Vec<u8>> = MaybeUninit::new(vec![42]);
+ /// ```
+ ///
/// [`assume_init`]: MaybeUninit::assume_init
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
@@ -259,9 +267,15 @@
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
///
- /// See the [type-level documentation][type] for some examples.
+ /// See the [type-level documentation][MaybeUninit] for some examples.
///
- /// [type]: union.MaybeUninit.html
+ /// # Example
+ ///
+ /// ```
+ /// use std::mem::MaybeUninit;
+ ///
+ /// let v: MaybeUninit<String> = MaybeUninit::uninit();
+ /// ```
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
#[inline(always)]
@@ -828,13 +842,13 @@
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
- this as *const [MaybeUninit<T>] as *const T
+ this.as_ptr() as *const T
}
/// Gets a mutable pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
pub fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
- this as *mut [MaybeUninit<T>] as *mut T
+ this.as_mut_ptr() as *mut T
}
}
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index aa1b552..e84014c 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -568,6 +568,7 @@
#[inline]
#[stable(feature = "needs_drop", since = "1.21.0")]
#[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")]
+#[rustc_diagnostic_item = "needs_drop"]
pub const fn needs_drop<T>() -> bool {
intrinsics::needs_drop::<T>()
}
@@ -883,10 +884,10 @@
/// Interprets `src` as having type `&U`, and then reads `src` without moving
/// the contained value.
///
-/// This function will unsafely assume the pointer `src` is valid for
-/// [`size_of::<U>`][size_of] bytes by transmuting `&T` to `&U` and then reading
-/// the `&U`. It will also unsafely create a copy of the contained value instead of
-/// moving out of `src`.
+/// This function will unsafely assume the pointer `src` is valid for [`size_of::<U>`][size_of]
+/// bytes by transmuting `&T` to `&U` and then reading the `&U` (except that this is done in a way
+/// that is correct even when `&U` makes stricter alignment requirements than `&T`). It will also
+/// unsafely create a copy of the contained value instead of moving out of `src`.
///
/// It is not a compile-time error if `T` and `U` have different sizes, but it
/// is highly encouraged to only invoke this function where `T` and `U` have the
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index 6f3a3a8..039112e 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -33,7 +33,7 @@
//!
//! Primarily, this module and its children implement the algorithms described in:
//! "How to Read Floating Point Numbers Accurately" by William D. Clinger,
-//! available online: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152
+//! available online: <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152>
//!
//! In addition, there are numerous helper functions that are used in the paper but not available
//! in Rust (or at least in core). Our version is additionally complicated by the need to handle
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index aab1715..9d8c8c8 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -98,15 +98,18 @@
///
/// Among other causes, this variant will be constructed when parsing an empty string.
Empty,
- /// Contains an invalid digit.
+ /// Contains an invalid digit in its context.
///
/// Among other causes, this variant will be constructed when parsing a string that
- /// contains a letter.
+ /// contains a non-ASCII char.
+ ///
+ /// This variant is also constructed when a `+` or `-` is misplaced within a string
+ /// either on its own or in the middle of a number.
InvalidDigit,
/// Integer is too large to store in target integer type.
- Overflow,
+ PosOverflow,
/// Integer is too small to store in target integer type.
- Underflow,
+ NegOverflow,
/// Value was Zero
///
/// This variant will be emitted when the parsing string has a value of zero, which
@@ -119,7 +122,7 @@
#[unstable(
feature = "int_error_matching",
reason = "it can be useful to match errors when making error messages \
- for integer parsing",
+ for integer parsing",
issue = "22639"
)]
pub fn kind(&self) -> &IntErrorKind {
@@ -136,8 +139,8 @@
match self.kind {
IntErrorKind::Empty => "cannot parse integer from empty string",
IntErrorKind::InvalidDigit => "invalid digit found in string",
- IntErrorKind::Overflow => "number too large to fit in target type",
- IntErrorKind::Underflow => "number too small to fit in target type",
+ IntErrorKind::PosOverflow => "number too large to fit in target type",
+ IntErrorKind::NegOverflow => "number too small to fit in target type",
IntErrorKind::Zero => "number would be zero for non-zero type",
}
}
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 043f0b1..86e6352 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -773,6 +773,35 @@
self.to_bits().to_ne_bytes()
}
+ /// Return the memory representation of this floating point number as a byte array in
+ /// native byte order.
+ ///
+ /// [`to_ne_bytes`] should be preferred over this whenever possible.
+ ///
+ /// [`to_ne_bytes`]: #method.to_ne_bytes
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(num_as_ne_bytes)]
+ /// let num = 12.5f32;
+ /// let bytes = num.as_ne_bytes();
+ /// assert_eq!(
+ /// bytes,
+ /// if cfg!(target_endian = "big") {
+ /// &[0x41, 0x48, 0x00, 0x00]
+ /// } else {
+ /// &[0x00, 0x00, 0x48, 0x41]
+ /// }
+ /// );
+ /// ```
+ #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
+ #[inline]
+ pub fn as_ne_bytes(&self) -> &[u8; 4] {
+ // SAFETY: `f32` is a plain old datatype so we can always transmute to it
+ unsafe { &*(self as *const Self as *const _) }
+ }
+
/// Create a floating point value from its representation as a byte array in big endian.
///
/// # Examples
@@ -847,6 +876,10 @@
/// - Positive signaling NaN
/// - Positive quiet NaN
///
+ /// Note that this function does not always agree with the [`PartialOrd`]
+ /// and [`PartialEq`] implementations of `f32`. In particular, they regard
+ /// negative and positive zero as equal, while `total_cmp` doesn't.
+ ///
/// # Example
/// ```
/// #![feature(total_cmp)]
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 24624b8..9b1405b 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -787,6 +787,35 @@
self.to_bits().to_ne_bytes()
}
+ /// Return the memory representation of this floating point number as a byte array in
+ /// native byte order.
+ ///
+ /// [`to_ne_bytes`] should be preferred over this whenever possible.
+ ///
+ /// [`to_ne_bytes`]: #method.to_ne_bytes
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(num_as_ne_bytes)]
+ /// let num = 12.5f64;
+ /// let bytes = num.as_ne_bytes();
+ /// assert_eq!(
+ /// bytes,
+ /// if cfg!(target_endian = "big") {
+ /// &[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ /// } else {
+ /// &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
+ /// }
+ /// );
+ /// ```
+ #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
+ #[inline]
+ pub fn as_ne_bytes(&self) -> &[u8; 8] {
+ // SAFETY: `f64` is a plain old datatype so we can always transmute to it
+ unsafe { &*(self as *const Self as *const _) }
+ }
+
/// Create a floating point value from its representation as a byte array in big endian.
///
/// # Examples
@@ -861,6 +890,10 @@
/// - Positive signaling NaN
/// - Positive quiet NaN
///
+ /// Note that this function does not always agree with the [`PartialOrd`]
+ /// and [`PartialEq`] implementations of `f64`. In particular, they regard
+ /// negative and positive zero as equal, while `total_cmp` doesn't.
+ ///
/// # Example
/// ```
/// #![feature(total_cmp)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 369175f..728381b 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -274,7 +274,8 @@
}
doc_comment! {
- concat!("Reverses the bit pattern of the integer.
+ concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
+ second least-significant bit becomes second most-significant bit, etc.
# Examples
@@ -285,6 +286,7 @@
let m = n.reverse_bits();
assert_eq!(m, ", $reversed, ");
+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")]
@@ -2045,7 +2047,8 @@
#[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
// SAFETY: const sound because integers are plain old datatypes so we can always
// transmute them to arrays of bytes
- #[allow_internal_unstable(const_fn_transmute)]
+ #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+ #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
#[inline]
pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
// SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -2054,6 +2057,41 @@
}
}
+ doc_comment! {
+ concat!("
+Return the memory representation of this integer as a byte array in
+native byte order.
+
+[`to_ne_bytes`] should be preferred over this whenever possible.
+
+[`to_ne_bytes`]: #method.to_ne_bytes
+",
+
+"
+# Examples
+
+```
+#![feature(num_as_ne_bytes)]
+let num = ", $swap_op, stringify!($SelfT), ";
+let bytes = num.as_ne_bytes();
+assert_eq!(
+ bytes,
+ if cfg!(target_endian = \"big\") {
+ &", $be_bytes, "
+ } else {
+ &", $le_bytes, "
+ }
+);
+```"),
+ #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
+ #[inline]
+ pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::<Self>()] {
+ // SAFETY: integers are plain old datatypes so we can always transmute them to
+ // arrays of bytes
+ unsafe { &*(self as *const Self as *const _) }
+ }
+ }
+
doc_comment! {
concat!("Create an integer value from its representation as a byte array in
big endian.
@@ -2158,7 +2196,8 @@
#[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
// SAFETY: const sound because integers are plain old datatypes so we can always
// transmute to them
- #[allow_internal_unstable(const_fn_transmute)]
+ #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+ #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
#[inline]
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
// SAFETY: integers are plain old datatypes so we can always transmute to them
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 4f64e30..9f5ae57 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -63,7 +63,12 @@
#[stable(feature = "try_from", since = "1.34.0")]
pub use error::TryFromIntError;
-#[unstable(feature = "int_error_matching", issue = "22639")]
+#[unstable(
+ feature = "int_error_matching",
+ reason = "it can be useful to match errors when making error messages \
+ for integer parsing",
+ issue = "22639"
+)]
pub use error::IntErrorKind;
macro_rules! usize_isize_to_xe_bytes_doc {
@@ -130,7 +135,7 @@
#[cfg(target_pointer_width = "16")]
#[lang = "isize"]
impl isize {
- int_impl! { isize, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234",
+ int_impl! { isize, i16, usize, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234",
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
}
@@ -138,7 +143,7 @@
#[cfg(target_pointer_width = "32")]
#[lang = "isize"]
impl isize {
- int_impl! { isize, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
+ int_impl! { isize, i32, usize, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@@ -147,7 +152,7 @@
#[cfg(target_pointer_width = "64")]
#[lang = "isize"]
impl isize {
- int_impl! { isize, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "",
+ int_impl! { isize, i64, usize, 64, -9223372036854775808, 9223372036854775807, "", "",
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
@@ -830,15 +835,14 @@
let src = src.as_bytes();
let (is_positive, digits) = match src[0] {
+ b'+' | b'-' if src[1..].is_empty() => {
+ return Err(PIE { kind: InvalidDigit });
+ }
b'+' => (true, &src[1..]),
b'-' if is_signed_ty => (false, &src[1..]),
_ => (true, src),
};
- if digits.is_empty() {
- return Err(PIE { kind: Empty });
- }
-
let mut result = T::from_u32(0);
if is_positive {
// The number is positive
@@ -849,11 +853,11 @@
};
result = match result.checked_mul(radix) {
Some(result) => result,
- None => return Err(PIE { kind: Overflow }),
+ None => return Err(PIE { kind: PosOverflow }),
};
result = match result.checked_add(x) {
Some(result) => result,
- None => return Err(PIE { kind: Overflow }),
+ None => return Err(PIE { kind: PosOverflow }),
};
}
} else {
@@ -865,11 +869,11 @@
};
result = match result.checked_mul(radix) {
Some(result) => result,
- None => return Err(PIE { kind: Underflow }),
+ None => return Err(PIE { kind: NegOverflow }),
};
result = match result.checked_sub(x) {
Some(result) => result,
- None => return Err(PIE { kind: Underflow }),
+ None => return Err(PIE { kind: NegOverflow }),
};
}
}
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 382f799..5a9fd90 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -92,6 +92,7 @@
doc_comment! {
concat!(
"Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`"),
+ #[inline]
fn from(nonzero: $Ty) -> Self {
nonzero.0
}
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 234c309..adcbbf9 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -272,7 +272,8 @@
}
doc_comment! {
- concat!("Reverses the bit pattern of the integer.
+ concat!("Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
+ second least-significant bit becomes second most-significant bit, etc.
# Examples
@@ -283,6 +284,7 @@
let m = n.reverse_bits();
assert_eq!(m, ", $reversed, ");
+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")]
@@ -1803,7 +1805,8 @@
#[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
// SAFETY: const sound because integers are plain old datatypes so we can always
// transmute them to arrays of bytes
- #[allow_internal_unstable(const_fn_transmute)]
+ #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+ #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
#[inline]
pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
// SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -1813,6 +1816,41 @@
}
doc_comment! {
+ concat!("
+Return the memory representation of this integer as a byte array in
+native byte order.
+
+[`to_ne_bytes`] should be preferred over this whenever possible.
+
+[`to_ne_bytes`]: #method.to_ne_bytes
+",
+
+"
+# Examples
+
+```
+#![feature(num_as_ne_bytes)]
+let num = ", $swap_op, stringify!($SelfT), ";
+let bytes = num.as_ne_bytes();
+assert_eq!(
+ bytes,
+ if cfg!(target_endian = \"big\") {
+ &", $be_bytes, "
+ } else {
+ &", $le_bytes, "
+ }
+);
+```"),
+ #[unstable(feature = "num_as_ne_bytes", issue = "76976")]
+ #[inline]
+ pub fn as_ne_bytes(&self) -> &[u8; mem::size_of::<Self>()] {
+ // SAFETY: integers are plain old datatypes so we can always transmute them to
+ // arrays of bytes
+ unsafe { &*(self as *const Self as *const _) }
+ }
+ }
+
+ doc_comment! {
concat!("Create a native endian integer value from its representation
as a byte array in big endian.
",
@@ -1916,7 +1954,8 @@
#[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
// SAFETY: const sound because integers are plain old datatypes so we can always
// transmute to them
- #[allow_internal_unstable(const_fn_transmute)]
+ #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+ #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
#[inline]
pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
// SAFETY: integers are plain old datatypes so we can always transmute to them
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index 19f86ce..92090d8 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -302,7 +302,7 @@
#[lang = "mul"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
- message = "cannot multiply `{Rhs}` to `{Self}`",
+ message = "cannot multiply `{Self}` by `{Rhs}`",
label = "no implementation for `{Self} * {Rhs}`"
)]
#[doc(alias = "*")]
@@ -826,7 +826,7 @@
#[lang = "mul_assign"]
#[stable(feature = "op_assign_traits", since = "1.8.0")]
#[rustc_on_unimplemented(
- message = "cannot multiply-assign `{Rhs}` to `{Self}`",
+ message = "cannot multiply-assign `{Self}` by `{Rhs}`",
label = "no implementation for `{Self} *= {Rhs}`"
)]
#[doc(alias = "*")]
diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs
index 6120da5..51f8043 100644
--- a/library/core/src/ops/bit.rs
+++ b/library/core/src/ops/bit.rs
@@ -109,10 +109,12 @@
/// fn bitand(self, Self(rhs): Self) -> Self::Output {
/// let Self(lhs) = self;
/// assert_eq!(lhs.len(), rhs.len());
-/// Self(lhs.iter()
+/// Self(
+/// lhs.iter()
/// .zip(rhs.iter())
-/// .map(|(x, y)| *x && *y)
-/// .collect())
+/// .map(|(x, y)| *x & *y)
+/// .collect()
+/// )
/// }
/// }
///
@@ -207,7 +209,12 @@
/// fn bitor(self, Self(rhs): Self) -> Self::Output {
/// let Self(lhs) = self;
/// assert_eq!(lhs.len(), rhs.len());
-/// Self(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect())
+/// Self(
+/// lhs.iter()
+/// .zip(rhs.iter())
+/// .map(|(x, y)| *x | *y)
+/// .collect()
+/// )
/// }
/// }
///
@@ -302,10 +309,12 @@
/// fn bitxor(self, Self(rhs): Self) -> Self::Output {
/// let Self(lhs) = self;
/// assert_eq!(lhs.len(), rhs.len());
-/// Self(lhs.iter()
+/// Self(
+/// lhs.iter()
/// .zip(rhs.iter())
-/// .map(|(x, y)| (*x || *y) && !(*x && *y))
-/// .collect())
+/// .map(|(x, y)| *x ^ *y)
+/// .collect()
+/// )
/// }
/// }
///
@@ -643,11 +652,13 @@
/// // `rhs` is the "right-hand side" of the expression `a &= b`.
/// fn bitand_assign(&mut self, rhs: Self) {
/// assert_eq!(self.0.len(), rhs.0.len());
-/// *self = Self(self.0
-/// .iter()
-/// .zip(rhs.0.iter())
-/// .map(|(x, y)| *x && *y)
-/// .collect());
+/// *self = Self(
+/// self.0
+/// .iter()
+/// .zip(rhs.0.iter())
+/// .map(|(x, y)| *x & *y)
+/// .collect()
+/// );
/// }
/// }
///
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index 2eaf760..1d67e65 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -1,5 +1,9 @@
use crate::fmt;
use crate::hash::Hash;
+use crate::slice::index::{
+ slice_end_index_len_fail, slice_end_index_overflow_fail, slice_index_order_fail,
+ slice_start_index_overflow_fail,
+};
/// An unbounded range (`..`).
///
@@ -19,7 +23,7 @@
///
/// ```compile_fail,E0277
/// for i in .. {
-/// // ...
+/// // ...
/// }
/// ```
///
@@ -27,12 +31,12 @@
///
/// ```
/// let arr = [0, 1, 2, 3, 4];
-/// assert_eq!(arr[ .. ], [0,1,2,3,4]); // RangeFull
-/// assert_eq!(arr[ .. 3], [0,1,2 ]);
-/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
-/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
-/// assert_eq!(arr[1.. 3], [ 1,2 ]);
-/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
+/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); // This is the `RangeFull`
+/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
+/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
+/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
+/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
+/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
/// ```
///
/// [slicing index]: crate::slice::SliceIndex
@@ -52,22 +56,26 @@
/// A (half-open) range bounded inclusively below and exclusively above
/// (`start..end`).
///
-/// The `Range` `start..end` contains all values with `x >= start` and
-/// `x < end`. It is empty unless `start < end`.
+/// The range `start..end` contains all values with `start <= x < end`.
+/// It is empty if `start >= end`.
///
/// # Examples
///
+/// The `start..end` syntax is a `Range`:
+///
/// ```
/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, (3..6).sum());
+/// ```
///
+/// ```
/// let arr = [0, 1, 2, 3, 4];
-/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
-/// assert_eq!(arr[ .. 3], [0,1,2 ]);
-/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
-/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
-/// assert_eq!(arr[1.. 3], [ 1,2 ]); // Range
-/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
+/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
+/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
+/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
+/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
+/// assert_eq!(arr[1.. 3], [ 1, 2 ]); // This is a `Range`
+/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
/// ```
#[lang = "Range"]
#[doc(alias = "..")]
@@ -160,17 +168,21 @@
///
/// # Examples
///
+/// The `start..` syntax is a `RangeFrom`:
+///
/// ```
/// assert_eq!((2..), std::ops::RangeFrom { start: 2 });
/// assert_eq!(2 + 3 + 4, (2..).take(3).sum());
+/// ```
///
+/// ```
/// let arr = [0, 1, 2, 3, 4];
-/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
-/// assert_eq!(arr[ .. 3], [0,1,2 ]);
-/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
-/// assert_eq!(arr[1.. ], [ 1,2,3,4]); // RangeFrom
-/// assert_eq!(arr[1.. 3], [ 1,2 ]);
-/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
+/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
+/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
+/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
+/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); // This is a `RangeFrom`
+/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
+/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
/// ```
#[lang = "RangeFrom"]
#[doc(alias = "..")]
@@ -244,12 +256,12 @@
///
/// ```
/// let arr = [0, 1, 2, 3, 4];
-/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
-/// assert_eq!(arr[ .. 3], [0,1,2 ]); // RangeTo
-/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
-/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
-/// assert_eq!(arr[1.. 3], [ 1,2 ]);
-/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
+/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
+/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); // This is a `RangeTo`
+/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
+/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
+/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
+/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
/// ```
///
/// [slicing index]: crate::slice::SliceIndex
@@ -310,17 +322,21 @@
///
/// # Examples
///
+/// The `start..=end` syntax is a `RangeInclusive`:
+///
/// ```
/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
/// assert_eq!(3 + 4 + 5, (3..=5).sum());
+/// ```
///
+/// ```
/// let arr = [0, 1, 2, 3, 4];
-/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
-/// assert_eq!(arr[ .. 3], [0,1,2 ]);
-/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
-/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
-/// assert_eq!(arr[1.. 3], [ 1,2 ]);
-/// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive
+/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
+/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
+/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
+/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
+/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
+/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); // This is a `RangeInclusive`
/// ```
#[lang = "RangeInclusive"]
#[doc(alias = "..=")]
@@ -430,6 +446,20 @@
}
}
+impl RangeInclusive<usize> {
+ /// Converts to an exclusive `Range` for `SliceIndex` implementations.
+ /// The caller is responsible for dealing with `end == usize::MAX`.
+ #[inline]
+ pub(crate) fn into_slice_range(self) -> Range<usize> {
+ // If we're not exhausted, we want to simply slice `start..end + 1`.
+ // If we are exhausted, then slicing with `end + 1..end + 1` gives us an
+ // empty range that is still subject to bounds-checks for that endpoint.
+ let exclusive_end = self.end + 1;
+ let start = if self.exhausted { exclusive_end } else { self.start };
+ start..exclusive_end
+ }
+}
+
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -463,6 +493,16 @@
/// assert!(!(0.0..=f32::NAN).contains(&0.0));
/// assert!(!(f32::NAN..=1.0).contains(&1.0));
/// ```
+ ///
+ /// This method always returns `false` after iteration has finished:
+ ///
+ /// ```
+ /// let mut r = 3..=5;
+ /// assert!(r.contains(&3) && r.contains(&5));
+ /// for _ in r.by_ref() {}
+ /// // Precise field values are unspecified here
+ /// assert!(!r.contains(&3) && !r.contains(&5));
+ /// ```
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
@@ -534,12 +574,12 @@
///
/// ```
/// let arr = [0, 1, 2, 3, 4];
-/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
-/// assert_eq!(arr[ .. 3], [0,1,2 ]);
-/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); // RangeToInclusive
-/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
-/// assert_eq!(arr[1.. 3], [ 1,2 ]);
-/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
+/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
+/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
+/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive`
+/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
+/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
+/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
/// ```
///
/// [slicing index]: crate::slice::SliceIndex
@@ -661,9 +701,9 @@
}
}
-#[stable(feature = "collections_range", since = "1.28.0")]
/// `RangeBounds` is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
+#[stable(feature = "collections_range", since = "1.28.0")]
pub trait RangeBounds<T: ?Sized> {
/// Start index bound.
///
@@ -701,6 +741,92 @@
#[stable(feature = "collections_range", since = "1.28.0")]
fn end_bound(&self) -> Bound<&T>;
+ /// Performs bounds-checking of this range.
+ ///
+ /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
+ /// [`slice::get_unchecked_mut`] for slices of the given length.
+ ///
+ /// [`slice::get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
+ /// [`slice::get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
+ ///
+ /// # Panics
+ ///
+ /// Panics if the range would be out of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(range_bounds_assert_len)]
+ ///
+ /// use std::ops::RangeBounds;
+ ///
+ /// let v = [10, 40, 30];
+ /// assert_eq!(1..2, (1..2).assert_len(v.len()));
+ /// assert_eq!(0..2, (..2).assert_len(v.len()));
+ /// assert_eq!(1..3, (1..).assert_len(v.len()));
+ /// ```
+ ///
+ /// Panics when [`Index::index`] would panic:
+ ///
+ /// ```should_panic
+ /// #![feature(range_bounds_assert_len)]
+ ///
+ /// use std::ops::RangeBounds;
+ ///
+ /// (2..1).assert_len(3);
+ /// ```
+ ///
+ /// ```should_panic
+ /// #![feature(range_bounds_assert_len)]
+ ///
+ /// use std::ops::RangeBounds;
+ ///
+ /// (1..4).assert_len(3);
+ /// ```
+ ///
+ /// ```should_panic
+ /// #![feature(range_bounds_assert_len)]
+ ///
+ /// use std::ops::RangeBounds;
+ ///
+ /// (1..=usize::MAX).assert_len(3);
+ /// ```
+ ///
+ /// [`Index::index`]: crate::ops::Index::index
+ #[track_caller]
+ #[unstable(feature = "range_bounds_assert_len", issue = "76393")]
+ fn assert_len(self, len: usize) -> Range<usize>
+ where
+ Self: RangeBounds<usize>,
+ {
+ let start: Bound<&usize> = self.start_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: Bound<&usize> = self.end_bound();
+ 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,
+ };
+
+ if start > end {
+ slice_index_order_fail(start, end);
+ }
+ if end > len {
+ slice_end_index_len_fail(end, len);
+ }
+
+ Range { start, end }
+ }
+
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
@@ -779,7 +905,13 @@
Included(&self.start)
}
fn end_bound(&self) -> Bound<&T> {
- Included(&self.end)
+ if self.exhausted {
+ // When the iterator is exhausted, we usually have start == end,
+ // but we want the range to appear empty, containing nothing.
+ Excluded(&self.end)
+ } else {
+ Included(&self.end)
+ }
}
}
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 0cfb4af..3daf262 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -141,6 +141,9 @@
//! ```
//!
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
+//! [`Box<U>`]: ../../std/boxed/struct.Box.html
+//! [`num::NonZero*`]: crate::num
+//! [`ptr::NonNull<U>`]: crate::ptr::NonNull
#![stable(feature = "rust1", since = "1.0.0")]
@@ -559,6 +562,36 @@
}
}
+ /// 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
/////////////////////////////////////////////////////////////////////////
@@ -684,6 +717,7 @@
/// assert_eq!(Some(4).filter(is_even), Some(4));
/// ```
///
+ /// [`Some(t)`]: Some
#[inline]
#[stable(feature = "option_filter", since = "1.27.0")]
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
@@ -788,7 +822,7 @@
// Entry-like operations to insert if None and return a reference
/////////////////////////////////////////////////////////////////////////
- /// Inserts `v` into the option if it is [`None`], then
+ /// Inserts `value` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
/// # Examples
@@ -807,12 +841,12 @@
/// ```
#[inline]
#[stable(feature = "option_entry", since = "1.20.0")]
- pub fn get_or_insert(&mut self, v: T) -> &mut T {
- self.get_or_insert_with(|| v)
+ pub fn get_or_insert(&mut self, value: T) -> &mut T {
+ self.get_or_insert_with(|| value)
}
- /// Inserts a value computed from `f` into the option if it is [`None`], then
- /// returns a mutable reference to the contained value.
+ /// Inserts a value computed from `f` into the option if it is [`None`],
+ /// then returns a mutable reference to the contained value.
///
/// # Examples
///
@@ -835,8 +869,8 @@
*self = Some(f());
}
- match *self {
- Some(ref mut v) => v,
+ match self {
+ Some(v) => v,
// SAFETY: a `None` variant for `self` would have been replaced by a `Some`
// variant in the code above.
None => unsafe { hint::unreachable_unchecked() },
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 15fd638..09dd19b 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -50,6 +50,13 @@
panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
}
+#[inline]
+#[track_caller]
+#[cfg_attr(not(bootstrap), lang = "panic_str")] // needed for const-evaluated panics
+pub fn panic_str(expr: &str) -> ! {
+ panic_fmt(format_args!("{}", expr));
+}
+
#[cold]
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
#[track_caller]
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index b73cd04..0b9c733 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -786,7 +786,7 @@
///
/// This is safe, because `T` is borrowed for the `'static` lifetime, which
/// never ends.
- #[unstable(feature = "pin_static_ref", issue = "none")]
+ #[unstable(feature = "pin_static_ref", issue = "78186")]
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
pub const fn static_ref(r: &'static T) -> Pin<&'static T> {
// SAFETY: The 'static borrow guarantees the data will not be
@@ -800,7 +800,7 @@
///
/// This is safe, because `T` is borrowed for the `'static` lifetime, which
/// never ends.
- #[unstable(feature = "pin_static_ref", issue = "none")]
+ #[unstable(feature = "pin_static_ref", issue = "78186")]
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> {
// SAFETY: The 'static borrow guarantees the data will not be
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 92c4f2c..9de2758 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -99,9 +99,9 @@
/// dropped normally.
///
/// * It is friendlier to the optimizer to do this over [`ptr::read`] when
-/// dropping manually allocated memory (e.g., when writing Box/Rc/Vec),
-/// as the compiler doesn't need to prove that it's sound to elide the
-/// copy.
+/// dropping manually allocated memory (e.g., in the implementations of
+/// `Box`/`Rc`/`Vec`), as the compiler doesn't need to prove that it's
+/// sound to elide the copy.
///
/// * It can be used to drop [pinned] data when `T` is not `repr(packed)`
/// (pinned data must not be moved before it is dropped).
@@ -229,6 +229,16 @@
pub(crate) len: usize,
}
+// Manual impl needed to avoid `T: Clone` bound.
+impl<T> Clone for FatPtr<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+// 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.
@@ -1133,7 +1143,9 @@
pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
// FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
// 1, where the method versions of these operations are not inlined.
- use intrinsics::{unchecked_shl, unchecked_shr, unchecked_sub, wrapping_mul, wrapping_sub};
+ use intrinsics::{
+ unchecked_shl, unchecked_shr, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub,
+ };
/// Calculate multiplicative modular inverse of `x` modulo `m`.
///
@@ -1188,8 +1200,17 @@
// SAFETY: `a` is a power-of-two, therefore non-zero.
let a_minus_one = unsafe { unchecked_sub(a, 1) };
if stride == 1 {
- // `stride == 1` case can be computed more efficiently through `-p (mod a)`.
- return wrapping_sub(0, p as usize) & a_minus_one;
+ // `stride == 1` case can be computed more simply through `-p (mod a)`, but doing so
+ // inhibits LLVM's ability to select instructions like `lea`. Instead we compute
+ //
+ // round_up_to_next_alignment(p, a) - p
+ //
+ // which distributes operations around the load-bearing, but pessimizing `and` sufficiently
+ // for LLVM to be able to utilize the various optimizations it knows about.
+ return wrapping_sub(
+ wrapping_add(p as usize, a_minus_one) & wrapping_sub(0, a),
+ p as usize,
+ );
}
let pmoda = p as usize & a_minus_one;
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 5cec183..b6d9f13 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -233,7 +233,7 @@
/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
///
-/// See the [`std::result`](index.html) module documentation for details.
+/// See the [module documentation](self) for details.
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[must_use = "this `Result` may be an `Err` variant, which should be handled"]
#[rustc_diagnostic_item = "result_type"]
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index ed26c59..18073f4 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -35,7 +35,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Eq> Eq for [T] {}
-/// Implements comparison of vectors lexicographically.
+/// Implements comparison of vectors [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Ord for [T] {
fn cmp(&self, other: &[T]) -> Ordering {
@@ -43,7 +43,7 @@
}
}
-/// Implements comparison of vectors lexicographically.
+/// Implements comparison of vectors [lexicographically](Ord#lexicographical-comparison).
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd> PartialOrd for [T] {
fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 16fcb62..660c8a2 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -1,6 +1,6 @@
//! Indexing implementations for `[T]`.
-use crate::ops::{self, Bound, Range, RangeBounds};
+use crate::ops;
use crate::ptr;
#[stable(feature = "rust1", since = "1.0.0")]
@@ -37,104 +37,31 @@
#[inline(never)]
#[cold]
#[track_caller]
-pub(super) fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
+pub(crate) fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
panic!("range end index {} out of range for slice of length {}", index, len);
}
#[inline(never)]
#[cold]
#[track_caller]
-pub(super) fn slice_index_order_fail(index: usize, end: usize) -> ! {
+pub(crate) fn slice_index_order_fail(index: usize, end: usize) -> ! {
panic!("slice index starts at {} but ends at {}", index, end);
}
#[inline(never)]
#[cold]
#[track_caller]
-pub(super) fn slice_start_index_overflow_fail() -> ! {
+pub(crate) fn slice_start_index_overflow_fail() -> ! {
panic!("attempted to index slice from after maximum usize");
}
#[inline(never)]
#[cold]
#[track_caller]
-pub(super) fn slice_end_index_overflow_fail() -> ! {
+pub(crate) fn slice_end_index_overflow_fail() -> ! {
panic!("attempted to index slice up to maximum usize");
}
-/// Performs bounds-checking of the given range.
-/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
-/// for slices of the given length.
-///
-/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
-/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
-///
-/// # Panics
-///
-/// Panics if the range is out of bounds.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(slice_check_range)]
-/// use std::slice;
-///
-/// let v = [10, 40, 30];
-/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
-/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
-/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
-/// ```
-///
-/// Panics when [`Index::index`] would panic:
-///
-/// ```should_panic
-/// #![feature(slice_check_range)]
-///
-/// std::slice::check_range(3, 2..1);
-/// ```
-///
-/// ```should_panic
-/// #![feature(slice_check_range)]
-///
-/// std::slice::check_range(3, 1..4);
-/// ```
-///
-/// ```should_panic
-/// #![feature(slice_check_range)]
-///
-/// std::slice::check_range(3, 1..=usize::MAX);
-/// ```
-///
-/// [`Index::index`]: ops::Index::index
-#[track_caller]
-#[unstable(feature = "slice_check_range", issue = "76393")]
-pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
- let start = match range.start_bound() {
- 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 range.end_bound() {
- Bound::Included(end) => {
- end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
- }
- Bound::Excluded(&end) => end,
- Bound::Unbounded => len,
- };
-
- if start > end {
- slice_index_order_fail(start, end);
- }
- if end > len {
- slice_end_index_len_fail(end, len);
- }
-
- Range { start, end }
-}
-
mod private_slice_index {
use super::ops;
#[stable(feature = "slice_get_slice", since = "1.28.0")]
@@ -449,28 +376,24 @@
#[inline]
fn get(self, slice: &[T]) -> Option<&[T]> {
- if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) }
+ if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
}
#[inline]
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
- if *self.end() == usize::MAX {
- None
- } else {
- (*self.start()..self.end() + 1).get_mut(slice)
- }
+ if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
}
#[inline]
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
- unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
+ unsafe { self.into_slice_range().get_unchecked(slice) }
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
- unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
+ unsafe { self.into_slice_range().get_unchecked_mut(slice) }
}
#[inline]
@@ -478,7 +401,7 @@
if *self.end() == usize::MAX {
slice_end_index_overflow_fail();
}
- (*self.start()..self.end() + 1).index(slice)
+ self.into_slice_range().index(slice)
}
#[inline]
@@ -486,7 +409,7 @@
if *self.end() == usize::MAX {
slice_end_index_overflow_fail();
}
- (*self.start()..self.end() + 1).index_mut(slice)
+ self.into_slice_range().index_mut(slice)
}
}
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 793cbf9..e373936 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -10,6 +10,7 @@
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
use crate::marker::{PhantomData, Send, Sized, Sync};
use crate::mem;
+use crate::num::NonZeroUsize;
use crate::ptr::NonNull;
use super::{from_raw_parts, from_raw_parts_mut};
@@ -1187,12 +1188,12 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Windows<'a, T: 'a> {
v: &'a [T],
- size: usize,
+ size: NonZeroUsize,
}
impl<'a, T: 'a> Windows<'a, T> {
#[inline]
- pub(super) fn new(slice: &'a [T], size: usize) -> Self {
+ pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self {
Self { v: slice, size }
}
}
@@ -1211,10 +1212,10 @@
#[inline]
fn next(&mut self) -> Option<&'a [T]> {
- if self.size > self.v.len() {
+ if self.size.get() > self.v.len() {
None
} else {
- let ret = Some(&self.v[..self.size]);
+ let ret = Some(&self.v[..self.size.get()]);
self.v = &self.v[1..];
ret
}
@@ -1222,10 +1223,10 @@
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- if self.size > self.v.len() {
+ if self.size.get() > self.v.len() {
(0, Some(0))
} else {
- let size = self.v.len() - self.size + 1;
+ let size = self.v.len() - self.size.get() + 1;
(size, Some(size))
}
}
@@ -1237,7 +1238,7 @@
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
- let (end, overflow) = self.size.overflowing_add(n);
+ let (end, overflow) = self.size.get().overflowing_add(n);
if end > self.v.len() || overflow {
self.v = &[];
None
@@ -1250,10 +1251,10 @@
#[inline]
fn last(self) -> Option<Self::Item> {
- if self.size > self.v.len() {
+ if self.size.get() > self.v.len() {
None
} else {
- let start = self.v.len() - self.size;
+ let start = self.v.len() - self.size.get();
Some(&self.v[start..])
}
}
@@ -1264,7 +1265,7 @@
// which means that `i` cannot overflow an `isize`, and the
// slice created by `from_raw_parts` is a subslice of `self.v`
// thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
- unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size) }
+ unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size.get()) }
}
}
@@ -1272,10 +1273,10 @@
impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
- if self.size > self.v.len() {
+ if self.size.get() > self.v.len() {
None
} else {
- let ret = Some(&self.v[self.v.len() - self.size..]);
+ let ret = Some(&self.v[self.v.len() - self.size.get()..]);
self.v = &self.v[..self.v.len() - 1];
ret
}
@@ -1284,11 +1285,11 @@
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let (end, overflow) = self.v.len().overflowing_sub(n);
- if end < self.size || overflow {
+ if end < self.size.get() || overflow {
self.v = &[];
None
} else {
- let ret = &self.v[end - self.size..end];
+ let ret = &self.v[end - self.size.get()..end];
self.v = &self.v[..end - 1];
Some(ret)
}
@@ -2102,13 +2103,8 @@
impl<'a, T, const N: usize> ArrayChunks<'a, T, N> {
#[inline]
pub(super) fn new(slice: &'a [T]) -> Self {
- let len = slice.len() / N;
- let (fst, snd) = slice.split_at(len * N);
- // SAFETY: We cast a slice of `len * N` elements into
- // a slice of `len` many `N` elements chunks.
- let array_slice: &[[T; N]] = unsafe { from_raw_parts(fst.as_ptr().cast(), len) };
-
- Self { iter: array_slice.iter(), rem: snd }
+ let (array_slice, rem) = slice.as_chunks();
+ Self { iter: array_slice.iter(), rem }
}
/// Returns the remainder of the original slice that is not going to be
@@ -2229,14 +2225,8 @@
impl<'a, T, const N: usize> ArrayChunksMut<'a, T, N> {
#[inline]
pub(super) fn new(slice: &'a mut [T]) -> Self {
- let len = slice.len() / N;
- let (fst, snd) = slice.split_at_mut(len * N);
- // SAFETY: We cast a slice of `len * N` elements into
- // a slice of `len` many `N` elements chunks.
- unsafe {
- let array_slice: &mut [[T; N]] = from_raw_parts_mut(fst.as_mut_ptr().cast(), len);
- Self { iter: array_slice.iter_mut(), rem: snd }
- }
+ let (array_slice, rem) = slice.as_chunks_mut();
+ Self { iter: array_slice.iter_mut(), rem }
}
/// Returns the remainder of the original slice that is not going to be
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index b1ca093..79ae1d5 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -11,6 +11,7 @@
use crate::cmp::Ordering::{self, Equal, Greater, Less};
use crate::marker::Copy;
use crate::mem;
+use crate::num::NonZeroUsize;
use crate::ops::{FnMut, Range, RangeBounds};
use crate::option::Option;
use crate::option::Option::{None, Some};
@@ -28,7 +29,7 @@
mod ascii;
mod cmp;
-mod index;
+pub(crate) mod index;
mod iter;
mod raw;
mod rotate;
@@ -72,9 +73,6 @@
#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub use index::SliceIndex;
-#[unstable(feature = "slice_check_range", issue = "76393")]
-pub use index::check_range;
-
#[lang = "slice"]
#[cfg(not(test))]
impl<T> [T] {
@@ -90,7 +88,8 @@
#[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")]
#[inline]
// SAFETY: const sound because we transmute out the length field as a usize (which it must be)
- #[allow_internal_unstable(const_fn_union)]
+ #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_union))]
+ #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_union))]
pub const fn len(&self) -> usize {
// SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
// Only `std` can make this guarantee.
@@ -728,7 +727,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn windows(&self, size: usize) -> Windows<'_, T> {
- assert_ne!(size, 0);
+ let size = NonZeroUsize::new(size).expect("size is zero");
Windows::new(self, size)
}
@@ -883,6 +882,36 @@
ChunksExactMut::new(self, chunk_size)
}
+ /// Splits the slice into a slice of `N`-element arrays,
+ /// starting at the beginning of the slice,
+ /// and a remainder slice with length strictly less than `N`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `N` is 0. This check will most probably get changed to a compile time
+ /// error before this method gets stabilized.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_as_chunks)]
+ /// let slice = ['l', 'o', 'r', 'e', 'm'];
+ /// let (chunks, remainder) = slice.as_chunks();
+ /// assert_eq!(chunks, &[['l', 'o'], ['r', 'e']]);
+ /// assert_eq!(remainder, &['m']);
+ /// ```
+ #[unstable(feature = "slice_as_chunks", issue = "74985")]
+ #[inline]
+ pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
+ assert_ne!(N, 0);
+ let len = self.len() / N;
+ let (multiple_of_n, remainder) = self.split_at(len * N);
+ // SAFETY: We cast a slice of `len * N` elements into
+ // a slice of `len` many `N` elements chunks.
+ let array_slice: &[[T; N]] = unsafe { from_raw_parts(multiple_of_n.as_ptr().cast(), len) };
+ (array_slice, remainder)
+ }
+
/// Returns an iterator over `N` elements of the slice at a time, starting at the
/// beginning of the slice.
///
@@ -917,6 +946,43 @@
ArrayChunks::new(self)
}
+ /// Splits the slice into a slice of `N`-element arrays,
+ /// starting at the beginning of the slice,
+ /// and a remainder slice with length strictly less than `N`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `N` is 0. This check will most probably get changed to a compile time
+ /// error before this method gets stabilized.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(slice_as_chunks)]
+ /// let v = &mut [0, 0, 0, 0, 0];
+ /// let mut count = 1;
+ ///
+ /// let (chunks, remainder) = v.as_chunks_mut();
+ /// remainder[0] = 9;
+ /// for chunk in chunks {
+ /// *chunk = [count; 2];
+ /// count += 1;
+ /// }
+ /// assert_eq!(v, &[1, 1, 2, 2, 9]);
+ /// ```
+ #[unstable(feature = "slice_as_chunks", issue = "74985")]
+ #[inline]
+ pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
+ assert_ne!(N, 0);
+ let len = self.len() / N;
+ let (multiple_of_n, remainder) = self.split_at_mut(len * N);
+ let array_slice: &mut [[T; N]] =
+ // SAFETY: We cast a slice of `len * N` elements into
+ // a slice of `len` many `N` elements chunks.
+ unsafe { from_raw_parts_mut(multiple_of_n.as_mut_ptr().cast(), len) };
+ (array_slice, remainder)
+ }
+
/// Returns an iterator over `N` elements of the slice at a time, starting at the
/// beginning of the slice.
///
@@ -1702,8 +1768,10 @@
/// Returns a subslice with the prefix removed.
///
- /// This method returns [`None`] if slice does not start with `prefix`.
- /// Also it returns the original slice if `prefix` is an empty slice.
+ /// If the slice starts with `prefix`, returns the subslice after the prefix, wrapped in `Some`.
+ /// If `prefix` is empty, simply returns the original slice.
+ ///
+ /// If the slice does not start with `prefix`, returns `None`.
///
/// # Examples
///
@@ -1733,8 +1801,10 @@
/// Returns a subslice with the suffix removed.
///
- /// This method returns [`None`] if slice does not end with `suffix`.
- /// Also it returns the original slice if `suffix` is an empty slice
+ /// If the slice ends with `suffix`, returns the subslice before the suffix, wrapped in `Some`.
+ /// If `suffix` is empty, simply returns the original slice.
+ ///
+ /// If the slice does not end with `suffix`, returns `None`.
///
/// # Examples
///
@@ -1947,10 +2017,10 @@
///
/// The comparator function must define a total ordering for the elements in the slice. If
/// the ordering is not total, the order of the elements is unspecified. An order is a
- /// total order if it is (for all a, b and c):
+ /// total order if it is (for all `a`, `b` and `c`):
///
- /// * total and antisymmetric: exactly one of a < b, a == b or a > b is true; and
- /// * transitive, a < b and b < c implies a < c. The same must hold for both == and >.
+ /// * total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true, and
+ /// * transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
/// For example, while [`f64`] doesn't implement [`Ord`] because `NaN != NaN`, we can use
/// `partial_cmp` as our sort function when we know the slice doesn't contain a `NaN`.
@@ -2034,6 +2104,50 @@
}
/// Reorder the slice such that the element at `index` is at its final sorted position.
+ #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+ #[rustc_deprecated(since = "1.49.0", reason = "use the select_nth_unstable() instead")]
+ #[inline]
+ pub fn partition_at_index(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T])
+ where
+ T: Ord,
+ {
+ self.select_nth_unstable(index)
+ }
+
+ /// Reorder the slice with a comparator function such that the element at `index` is at its
+ /// final sorted position.
+ #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+ #[rustc_deprecated(since = "1.49.0", reason = "use select_nth_unstable_by() instead")]
+ #[inline]
+ pub fn partition_at_index_by<F>(
+ &mut self,
+ index: usize,
+ compare: F,
+ ) -> (&mut [T], &mut T, &mut [T])
+ where
+ F: FnMut(&T, &T) -> Ordering,
+ {
+ self.select_nth_unstable_by(index, compare)
+ }
+
+ /// Reorder the slice with a key extraction function such that the element at `index` is at its
+ /// final sorted position.
+ #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+ #[rustc_deprecated(since = "1.49.0", reason = "use the select_nth_unstable_by_key() instead")]
+ #[inline]
+ pub fn partition_at_index_by_key<K, F>(
+ &mut self,
+ index: usize,
+ f: F,
+ ) -> (&mut [T], &mut T, &mut [T])
+ where
+ F: FnMut(&T) -> K,
+ K: Ord,
+ {
+ self.select_nth_unstable_by_key(index, f)
+ }
+
+ /// Reorder the slice such that the element at `index` is at its final sorted position.
///
/// This reordering has the additional property that any value at position `i < index` will be
/// less than or equal to any value at a position `j > index`. Additionally, this reordering is
@@ -2057,12 +2171,10 @@
/// # Examples
///
/// ```
- /// #![feature(slice_partition_at_index)]
- ///
/// let mut v = [-5i32, 4, 1, -3, 2];
///
/// // Find the median
- /// v.partition_at_index(2);
+ /// v.select_nth_unstable(2);
///
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
/// // about the specified index.
@@ -2071,9 +2183,9 @@
/// v == [-3, -5, 1, 4, 2] ||
/// v == [-5, -3, 1, 4, 2]);
/// ```
- #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+ #[stable(feature = "slice_select_nth_unstable", since = "1.49.0")]
#[inline]
- pub fn partition_at_index(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T])
+ pub fn select_nth_unstable(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T])
where
T: Ord,
{
@@ -2107,12 +2219,10 @@
/// # Examples
///
/// ```
- /// #![feature(slice_partition_at_index)]
- ///
/// let mut v = [-5i32, 4, 1, -3, 2];
///
/// // Find the median as if the slice were sorted in descending order.
- /// v.partition_at_index_by(2, |a, b| b.cmp(a));
+ /// v.select_nth_unstable_by(2, |a, b| b.cmp(a));
///
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
/// // about the specified index.
@@ -2121,9 +2231,9 @@
/// v == [4, 2, 1, -5, -3] ||
/// v == [4, 2, 1, -3, -5]);
/// ```
- #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+ #[stable(feature = "slice_select_nth_unstable", since = "1.49.0")]
#[inline]
- pub fn partition_at_index_by<F>(
+ pub fn select_nth_unstable_by<F>(
&mut self,
index: usize,
mut compare: F,
@@ -2161,12 +2271,10 @@
/// # Examples
///
/// ```
- /// #![feature(slice_partition_at_index)]
- ///
/// let mut v = [-5i32, 4, 1, -3, 2];
///
/// // Return the median as if the array were sorted according to absolute value.
- /// v.partition_at_index_by_key(2, |a| a.abs());
+ /// v.select_nth_unstable_by_key(2, |a| a.abs());
///
/// // We are only guaranteed the slice will be one of the following, based on the way we sort
/// // about the specified index.
@@ -2175,9 +2283,9 @@
/// v == [2, 1, -3, 4, -5] ||
/// v == [2, 1, -3, -5, 4]);
/// ```
- #[unstable(feature = "slice_partition_at_index", issue = "55300")]
+ #[stable(feature = "slice_select_nth_unstable", since = "1.49.0")]
#[inline]
- pub fn partition_at_index_by_key<K, F>(
+ pub fn select_nth_unstable_by_key<K, F>(
&mut self,
index: usize,
mut f: F,
@@ -2675,7 +2783,7 @@
where
T: Copy,
{
- let Range { start: src_start, end: src_end } = check_range(self.len(), src);
+ let Range { start: src_start, end: src_end } = src.assert_len(self.len());
let count = src_end - src_start;
assert!(dest <= self.len() - count, "dest is out of bounds");
// SAFETY: the conditions for `ptr::copy` have all been checked above,
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index 71d2c2c..2a7693d 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -1,7 +1,7 @@
//! Slice sorting
//!
//! This module contains a sorting algorithm based on Orson Peters' pattern-defeating quicksort,
-//! published at: https://github.com/orlp/pdqsort
+//! published at: <https://github.com/orlp/pdqsort>
//!
//! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our
//! stable sorting implementation.
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index de2a93f..952d059 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -157,7 +157,8 @@
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
-#[allow_internal_unstable(const_fn_transmute)]
+#[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+#[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
// SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
// Also relies on `&str` and `&[u8]` having the same layout.
diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs
index 427f720..ccf7b20 100644
--- a/library/core/src/str/error.rs
+++ b/library/core/src/str/error.rs
@@ -72,6 +72,7 @@
/// assert_eq!(1, error.valid_up_to());
/// ```
#[stable(feature = "utf8_error", since = "1.5.0")]
+ #[inline]
pub fn valid_up_to(&self) -> usize {
self.valid_up_to
}
@@ -92,6 +93,7 @@
///
/// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
#[stable(feature = "utf8_error_error_len", since = "1.20.0")]
+ #[inline]
pub fn error_len(&self) -> Option<usize> {
self.error_len.map(|len| len as usize)
}
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 27a67e2..28cd350 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -326,6 +326,7 @@
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl TrustedRandomAccess for Bytes<'_> {
+ #[inline]
fn may_have_side_effect() -> bool {
false
}
@@ -690,6 +691,17 @@
},
}
}
+
+ #[inline]
+ fn as_str(&self) -> &'a str {
+ // `Self::get_end` doesn't change `self.start`
+ if self.finished {
+ return "";
+ }
+
+ // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
+ unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
+ }
}
generate_pattern_iterators! {
@@ -710,6 +722,48 @@
delegate double ended;
}
+impl<'a, P: Pattern<'a>> Split<'a, P> {
+ /// Returns remainder of the splitted string
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(str_split_as_str)]
+ /// let mut split = "Mary had a little lamb".split(' ');
+ /// assert_eq!(split.as_str(), "Mary had a little lamb");
+ /// split.next();
+ /// assert_eq!(split.as_str(), "had a little lamb");
+ /// split.by_ref().for_each(drop);
+ /// assert_eq!(split.as_str(), "");
+ /// ```
+ #[inline]
+ #[unstable(feature = "str_split_as_str", issue = "77998")]
+ pub fn as_str(&self) -> &'a str {
+ self.0.as_str()
+ }
+}
+
+impl<'a, P: Pattern<'a>> RSplit<'a, P> {
+ /// Returns remainder of the splitted string
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(str_split_as_str)]
+ /// let mut split = "Mary had a little lamb".rsplit(' ');
+ /// assert_eq!(split.as_str(), "Mary had a little lamb");
+ /// split.next();
+ /// assert_eq!(split.as_str(), "Mary had a little");
+ /// split.by_ref().for_each(drop);
+ /// assert_eq!(split.as_str(), "");
+ /// ```
+ #[inline]
+ #[unstable(feature = "str_split_as_str", issue = "77998")]
+ pub fn as_str(&self) -> &'a str {
+ self.0.as_str()
+ }
+}
+
generate_pattern_iterators! {
forward:
/// Created with the method [`split_terminator`].
@@ -728,6 +782,48 @@
delegate double ended;
}
+impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
+ /// Returns remainder of the splitted string
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(str_split_as_str)]
+ /// let mut split = "A..B..".split_terminator('.');
+ /// assert_eq!(split.as_str(), "A..B..");
+ /// split.next();
+ /// assert_eq!(split.as_str(), ".B..");
+ /// split.by_ref().for_each(drop);
+ /// assert_eq!(split.as_str(), "");
+ /// ```
+ #[inline]
+ #[unstable(feature = "str_split_as_str", issue = "77998")]
+ pub fn as_str(&self) -> &'a str {
+ self.0.as_str()
+ }
+}
+
+impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
+ /// Returns remainder of the splitted string
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(str_split_as_str)]
+ /// let mut split = "A..B..".rsplit_terminator('.');
+ /// assert_eq!(split.as_str(), "A..B..");
+ /// split.next();
+ /// assert_eq!(split.as_str(), "A..B");
+ /// split.by_ref().for_each(drop);
+ /// assert_eq!(split.as_str(), "");
+ /// ```
+ #[inline]
+ #[unstable(feature = "str_split_as_str", issue = "77998")]
+ pub fn as_str(&self) -> &'a str {
+ self.0.as_str()
+ }
+}
+
derive_pattern_clone! {
clone SplitNInternal
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
@@ -784,6 +880,11 @@
}
}
}
+
+ #[inline]
+ fn as_str(&self) -> &'a str {
+ self.iter.as_str()
+ }
}
generate_pattern_iterators! {
@@ -804,6 +905,48 @@
delegate single ended;
}
+impl<'a, P: Pattern<'a>> SplitN<'a, P> {
+ /// Returns remainder of the splitted string
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(str_split_as_str)]
+ /// let mut split = "Mary had a little lamb".splitn(3, ' ');
+ /// assert_eq!(split.as_str(), "Mary had a little lamb");
+ /// split.next();
+ /// assert_eq!(split.as_str(), "had a little lamb");
+ /// split.by_ref().for_each(drop);
+ /// assert_eq!(split.as_str(), "");
+ /// ```
+ #[inline]
+ #[unstable(feature = "str_split_as_str", issue = "77998")]
+ pub fn as_str(&self) -> &'a str {
+ self.0.as_str()
+ }
+}
+
+impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
+ /// Returns remainder of the splitted string
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(str_split_as_str)]
+ /// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
+ /// assert_eq!(split.as_str(), "Mary had a little lamb");
+ /// split.next();
+ /// assert_eq!(split.as_str(), "Mary had a little");
+ /// split.by_ref().for_each(drop);
+ /// assert_eq!(split.as_str(), "");
+ /// ```
+ #[inline]
+ #[unstable(feature = "str_split_as_str", issue = "77998")]
+ pub fn as_str(&self) -> &'a str {
+ self.0.as_str()
+ }
+}
+
derive_pattern_clone! {
clone MatchIndicesInternal
with |s| MatchIndicesInternal(s.0.clone())
@@ -1134,6 +1277,28 @@
#[unstable(feature = "split_inclusive", issue = "72360")]
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
+impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
+ /// Returns remainder of the splitted string
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(str_split_inclusive_as_str)]
+ /// #![feature(split_inclusive)]
+ /// let mut split = "Mary had a little lamb".split_inclusive(' ');
+ /// assert_eq!(split.as_str(), "Mary had a little lamb");
+ /// split.next();
+ /// assert_eq!(split.as_str(), "had a little lamb");
+ /// split.by_ref().for_each(drop);
+ /// assert_eq!(split.as_str(), "");
+ /// ```
+ #[inline]
+ #[unstable(feature = "str_split_inclusive_as_str", issue = "77998")]
+ pub fn as_str(&self) -> &'a str {
+ self.0.as_str()
+ }
+}
+
/// An iterator of [`u16`] over the string encoded as UTF-16.
///
/// This struct is created by the [`encode_utf16`] method on [`str`].
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 3e18a4e..23d63a4 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -219,7 +219,8 @@
#[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
#[inline(always)]
#[allow(unused_attributes)]
- #[allow_internal_unstable(const_fn_transmute)]
+ #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+ #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
pub const fn as_bytes(&self) -> &[u8] {
// SAFETY: const sound because we transmute two types with the same layout
unsafe { mem::transmute(self) }
@@ -841,7 +842,9 @@
/// Lines are ended with either a newline (`\n`) or a carriage return with
/// a line feed (`\r\n`).
///
- /// The final line ending is optional.
+ /// The final line ending is optional. A string that ends with a final line
+ /// ending will return the same lines as an otherwise identical string
+ /// without a final line ending.
///
/// # Examples
///
@@ -1711,6 +1714,7 @@
///
/// assert_eq!("Hello\tworld", s.trim());
/// ```
+ #[inline]
#[must_use = "this returns the trimmed string as a slice, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1748,6 +1752,7 @@
/// let s = " עברית ";
/// assert!(Some('ע') == s.trim_start().chars().next());
/// ```
+ #[inline]
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[stable(feature = "trim_direction", since = "1.30.0")]
@@ -1785,6 +1790,7 @@
/// let s = " עברית ";
/// assert!(Some('ת') == s.trim_end().chars().rev().next());
/// ```
+ #[inline]
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[stable(feature = "trim_direction", since = "1.30.0")]
@@ -1823,6 +1829,7 @@
/// let s = " עברית";
/// assert!(Some('ע') == s.trim_left().chars().next());
/// ```
+ #[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(
since = "1.33.0",
@@ -1864,6 +1871,7 @@
/// let s = "עברית ";
/// assert!(Some('ת') == s.trim_right().chars().rev().next());
/// ```
+ #[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(
since = "1.33.0",
@@ -1964,11 +1972,10 @@
/// Returns a string slice with the prefix removed.
///
- /// If the string starts with the pattern `prefix`, `Some` is returned with the substring where
- /// the prefix is removed. Unlike `trim_start_matches`, this method removes the prefix exactly
- /// once.
+ /// If the string starts with the pattern `prefix`, returns substring after the prefix, wrapped
+ /// in `Some`. Unlike `trim_start_matches`, this method removes the prefix exactly once.
///
- /// If the string does not start with `prefix`, `None` is returned.
+ /// If the string does not start with `prefix`, returns `None`.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
/// function or closure that determines if a character matches.
@@ -1992,11 +1999,10 @@
/// Returns a string slice with the suffix removed.
///
- /// If the string ends with the pattern `suffix`, `Some` is returned with the substring where
- /// the suffix is removed. Unlike `trim_end_matches`, this method removes the suffix exactly
- /// once.
+ /// If the string ends with the pattern `suffix`, returns the substring before the suffix,
+ /// wrapped in `Some`. Unlike `trim_end_matches`, this method removes the suffix exactly once.
///
- /// If the string does not end with `suffix`, `None` is returned.
+ /// If the string does not end with `suffix`, returns `None`.
///
/// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
/// function or closure that determines if a character matches.
@@ -2261,6 +2267,7 @@
/// assert_eq!("GRüßE, JüRGEN ❤", s);
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+ #[inline]
pub fn make_ascii_uppercase(&mut self) {
// SAFETY: safe because we transmute two types with the same layout.
let me = unsafe { self.as_bytes_mut() };
@@ -2287,6 +2294,7 @@
/// assert_eq!("grÜße, jÜrgen ❤", s);
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+ #[inline]
pub fn make_ascii_lowercase(&mut self) {
// SAFETY: safe because we transmute two types with the same layout.
let me = unsafe { self.as_bytes_mut() };
@@ -2424,6 +2432,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for &str {
/// Creates an empty str
+ #[inline]
fn default() -> Self {
""
}
@@ -2432,6 +2441,7 @@
#[stable(feature = "default_mut_str", since = "1.28.0")]
impl Default for &mut str {
/// Creates an empty mutable str
+ #[inline]
fn default() -> Self {
// SAFETY: The empty string is valid UTF-8.
unsafe { from_utf8_unchecked_mut(&mut []) }
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 4f8aa24..1906fa2 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -9,7 +9,7 @@
/// Implements ordering of strings.
///
-/// Strings are ordered lexicographically by their byte values. This orders Unicode code
+/// Strings are ordered [lexicographically](Ord#lexicographical-comparison) by their byte values. This orders Unicode code
/// points based on their positions in the code charts. This is not necessarily the same as
/// "alphabetical" order, which varies by language and locale. Sorting strings according to
/// culturally-accepted standards requires locale-specific data that is outside the scope of
@@ -39,7 +39,7 @@
/// Implements comparison operations on strings.
///
-/// Strings are compared lexicographically by their byte values. This compares Unicode code
+/// Strings are compared [lexicographically](Ord#lexicographical-comparison) by their byte values. This compares Unicode code
/// points based on their positions in the code charts. This is not necessarily the same as
/// "alphabetical" order, which varies by language and locale. Comparing strings according to
/// culturally-accepted standards requires locale-specific data that is outside the scope of
@@ -89,7 +89,7 @@
/// self`. Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. Unlike
/// other indexing operations, this can never panic.
///
-/// This operation is `O(1)`.
+/// This operation is *O*(1).
///
/// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`.
@@ -130,7 +130,7 @@
/// Returns a slice of the given string from the byte range
/// [`begin`, `end`).
///
-/// This operation is `O(1)`.
+/// This operation is *O*(1).
///
/// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`.
@@ -237,7 +237,7 @@
/// Returns a slice of the given string from the byte range [`0`, `end`).
/// Equivalent to `&self[0 .. end]` or `&mut self[0 .. end]`.
///
-/// This operation is `O(1)`.
+/// This operation is *O*(1).
///
/// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`.
@@ -308,7 +308,7 @@
/// `len`). Equivalent to `&self[begin .. len]` or `&mut self[begin ..
/// len]`.
///
-/// This operation is `O(1)`.
+/// This operation is *O*(1).
///
/// Prior to 1.20.0, these indexing operations were still supported by
/// direct implementation of `Index` and `IndexMut`.
@@ -385,7 +385,7 @@
/// self[begin .. end + 1]`, except if `end` has the maximum value for
/// `usize`.
///
-/// This operation is `O(1)`.
+/// This operation is *O*(1).
///
/// # Panics
///
@@ -398,39 +398,35 @@
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
- if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) }
+ if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
}
#[inline]
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
- if *self.end() == usize::MAX {
- None
- } else {
- (*self.start()..self.end() + 1).get_mut(slice)
- }
+ if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
}
#[inline]
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
// SAFETY: the caller must uphold the safety contract for `get_unchecked`.
- unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
+ unsafe { self.into_slice_range().get_unchecked(slice) }
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
// SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
- unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
+ unsafe { self.into_slice_range().get_unchecked_mut(slice) }
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
if *self.end() == usize::MAX {
str_index_overflow_fail();
}
- (*self.start()..self.end() + 1).index(slice)
+ self.into_slice_range().index(slice)
}
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
if *self.end() == usize::MAX {
str_index_overflow_fail();
}
- (*self.start()..self.end() + 1).index_mut(slice)
+ self.into_slice_range().index_mut(slice)
}
}
@@ -441,7 +437,7 @@
/// Equivalent to `&self [0 .. end + 1]`, except if `end` has the maximum
/// value for `usize`.
///
-/// This operation is `O(1)`.
+/// This operation is *O*(1).
///
/// # Panics
///
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 5c9cfe2..d48c02b 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -115,23 +115,13 @@
/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
///
-/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
-/// power or switching hyper-threads.
-///
-/// This function is different from [`std::thread::yield_now`] which directly yields to the
-/// system's scheduler, whereas `spin_loop_hint` does not interact with the operating system.
-///
-/// A common use case for `spin_loop_hint` is implementing bounded optimistic spinning in a CAS
-/// loop in synchronization primitives. To avoid problems like priority inversion, it is strongly
-/// recommended that the spin loop is terminated after a finite amount of iterations and an
-/// appropriate blocking syscall is made.
+/// This function is expected to be deprecated in favor of
+/// [`hint::spin_loop`].
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
-/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html
-/// [`std::thread::sleep`]: ../../../std/thread/fn.sleep.html
-/// [`std::sync::Mutex`]: ../../../std/sync/struct.Mutex.html
+/// [`hint::spin_loop`]: crate::hint::spin_loop
#[inline]
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
pub fn spin_loop_hint() {
@@ -155,6 +145,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for AtomicBool {
/// Creates an `AtomicBool` initialized to `false`.
+ #[inline]
fn default() -> Self {
Self::new(false)
}
@@ -364,7 +355,8 @@
/// ```
#[inline]
#[stable(feature = "atomic_access", since = "1.15.0")]
- pub fn into_inner(self) -> bool {
+ #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ pub const fn into_inner(self) -> bool {
self.v.into_inner() != 0
}
@@ -800,6 +792,64 @@
pub fn as_mut_ptr(&self) -> *mut bool {
self.v.get() as *mut bool
}
+
+ /// Fetches the value, and applies a function to it that returns an optional
+ /// new value. Returns a `Result` of `Ok(previous_value)` if the function
+ /// returned `Some(_)`, else `Err(previous_value)`.
+ ///
+ /// Note: This may call the function multiple times if the value has been
+ /// changed from other threads in the meantime, as long as the function
+ /// returns `Some(_)`, but the function will have been applied only once to
+ /// the stored value.
+ ///
+ /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
+ /// ordering of this operation. The first describes the required ordering for
+ /// when the operation finally succeeds while the second describes the
+ /// required ordering for loads. These correspond to the success and failure
+ /// orderings of [`AtomicBool::compare_exchange`] respectively.
+ ///
+ /// Using [`Acquire`] as success ordering makes the store part of this
+ /// operation [`Relaxed`], and using [`Release`] makes the final successful
+ /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
+ /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the
+ /// success ordering.
+ ///
+ /// **Note:** This method is only available on platforms that support atomic
+ /// operations on `u8`.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// #![feature(atomic_fetch_update)]
+ /// use std::sync::atomic::{AtomicBool, Ordering};
+ ///
+ /// let x = AtomicBool::new(false);
+ /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false));
+ /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false));
+ /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true));
+ /// assert_eq!(x.load(Ordering::SeqCst), false);
+ /// ```
+ #[inline]
+ #[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")]
+ #[cfg(target_has_atomic = "8")]
+ pub fn fetch_update<F>(
+ &self,
+ set_order: Ordering,
+ fetch_order: Ordering,
+ mut f: F,
+ ) -> Result<bool, bool>
+ where
+ F: FnMut(bool) -> Option<bool>,
+ {
+ let mut prev = self.load(fetch_order);
+ while let Some(next) = f(prev) {
+ match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
+ x @ Ok(_) => return x,
+ Err(next_prev) => prev = next_prev,
+ }
+ }
+ Err(prev)
+ }
}
#[cfg(target_has_atomic_load_store = "ptr")]
@@ -882,7 +932,8 @@
/// ```
#[inline]
#[stable(feature = "atomic_access", since = "1.15.0")]
- pub fn into_inner(self) -> *mut T {
+ #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ pub const fn into_inner(self) -> *mut T {
self.p.into_inner()
}
@@ -1122,6 +1173,73 @@
}
}
}
+
+ /// Fetches the value, and applies a function to it that returns an optional
+ /// new value. Returns a `Result` of `Ok(previous_value)` if the function
+ /// returned `Some(_)`, else `Err(previous_value)`.
+ ///
+ /// Note: This may call the function multiple times if the value has been
+ /// changed from other threads in the meantime, as long as the function
+ /// returns `Some(_)`, but the function will have been applied only once to
+ /// the stored value.
+ ///
+ /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
+ /// ordering of this operation. The first describes the required ordering for
+ /// when the operation finally succeeds while the second describes the
+ /// required ordering for loads. These correspond to the success and failure
+ /// orderings of [`AtomicPtr::compare_exchange`] respectively.
+ ///
+ /// Using [`Acquire`] as success ordering makes the store part of this
+ /// operation [`Relaxed`], and using [`Release`] makes the final successful
+ /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
+ /// [`Acquire`] or [`Relaxed`] and must be equivalent to or weaker than the
+ /// success ordering.
+ ///
+ /// **Note:** This method is only available on platforms that support atomic
+ /// operations on pointers.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// #![feature(atomic_fetch_update)]
+ /// use std::sync::atomic::{AtomicPtr, Ordering};
+ ///
+ /// let ptr: *mut _ = &mut 5;
+ /// let some_ptr = AtomicPtr::new(ptr);
+ ///
+ /// let new: *mut _ = &mut 10;
+ /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr));
+ /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
+ /// if x == ptr {
+ /// Some(new)
+ /// } else {
+ /// None
+ /// }
+ /// });
+ /// assert_eq!(result, Ok(ptr));
+ /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
+ /// ```
+ #[inline]
+ #[unstable(feature = "atomic_fetch_update", reason = "recently added", issue = "78639")]
+ #[cfg(target_has_atomic = "ptr")]
+ pub fn fetch_update<F>(
+ &self,
+ set_order: Ordering,
+ fetch_order: Ordering,
+ mut f: F,
+ ) -> Result<*mut T, *mut T>
+ where
+ F: FnMut(*mut T) -> Option<*mut T>,
+ {
+ let mut prev = self.load(fetch_order);
+ while let Some(next) = f(prev) {
+ match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
+ x @ Ok(_) => return x,
+ Err(next_prev) => prev = next_prev,
+ }
+ }
+ Err(prev)
+ }
}
#[cfg(target_has_atomic_load_store = "8")]
@@ -1212,6 +1330,7 @@
#[$stable]
impl Default for $atomic_type {
+ #[inline]
fn default() -> Self {
Self::new(Default::default())
}
@@ -1335,7 +1454,8 @@
```"),
#[inline]
#[$stable_access]
- pub fn into_inner(self) -> $int_type {
+ #[rustc_const_unstable(feature = "const_cell_into_inner", issue = "78729")]
+ pub const fn into_inner(self) -> $int_type {
self.v.into_inner()
}
}
@@ -2148,64 +2268,56 @@
"AtomicU128::new(0)",
u128 AtomicU128 ATOMIC_U128_INIT
}
-#[cfg(target_has_atomic_load_store = "ptr")]
-#[cfg(target_pointer_width = "16")]
-macro_rules! ptr_width {
- () => {
- 2
- };
+
+macro_rules! atomic_int_ptr_sized {
+ ( $($target_pointer_width:literal $align:literal)* ) => { $(
+ #[cfg(target_has_atomic_load_store = "ptr")]
+ #[cfg(target_pointer_width = $target_pointer_width)]
+ atomic_int! {
+ cfg(target_has_atomic = "ptr"),
+ cfg(target_has_atomic_equal_alignment = "ptr"),
+ stable(feature = "rust1", since = "1.0.0"),
+ stable(feature = "extended_compare_and_swap", since = "1.10.0"),
+ stable(feature = "atomic_debug", since = "1.3.0"),
+ 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"),
+ stable(feature = "rust1", since = "1.0.0"),
+ "isize", "../../../std/primitive.isize.html",
+ "",
+ atomic_min, atomic_max,
+ $align,
+ "AtomicIsize::new(0)",
+ isize AtomicIsize ATOMIC_ISIZE_INIT
+ }
+ #[cfg(target_has_atomic_load_store = "ptr")]
+ #[cfg(target_pointer_width = $target_pointer_width)]
+ atomic_int! {
+ cfg(target_has_atomic = "ptr"),
+ cfg(target_has_atomic_equal_alignment = "ptr"),
+ stable(feature = "rust1", since = "1.0.0"),
+ stable(feature = "extended_compare_and_swap", since = "1.10.0"),
+ stable(feature = "atomic_debug", since = "1.3.0"),
+ 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"),
+ stable(feature = "rust1", since = "1.0.0"),
+ "usize", "../../../std/primitive.usize.html",
+ "",
+ atomic_umin, atomic_umax,
+ $align,
+ "AtomicUsize::new(0)",
+ usize AtomicUsize ATOMIC_USIZE_INIT
+ }
+ )* };
}
-#[cfg(target_has_atomic_load_store = "ptr")]
-#[cfg(target_pointer_width = "32")]
-macro_rules! ptr_width {
- () => {
- 4
- };
-}
-#[cfg(target_has_atomic_load_store = "ptr")]
-#[cfg(target_pointer_width = "64")]
-macro_rules! ptr_width {
- () => {
- 8
- };
-}
-#[cfg(target_has_atomic_load_store = "ptr")]
-atomic_int! {
- cfg(target_has_atomic = "ptr"),
- cfg(target_has_atomic_equal_alignment = "ptr"),
- stable(feature = "rust1", since = "1.0.0"),
- stable(feature = "extended_compare_and_swap", since = "1.10.0"),
- stable(feature = "atomic_debug", since = "1.3.0"),
- 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"),
- stable(feature = "rust1", since = "1.0.0"),
- "isize", "../../../std/primitive.isize.html",
- "",
- atomic_min, atomic_max,
- ptr_width!(),
- "AtomicIsize::new(0)",
- isize AtomicIsize ATOMIC_ISIZE_INIT
-}
-#[cfg(target_has_atomic_load_store = "ptr")]
-atomic_int! {
- cfg(target_has_atomic = "ptr"),
- cfg(target_has_atomic_equal_alignment = "ptr"),
- stable(feature = "rust1", since = "1.0.0"),
- stable(feature = "extended_compare_and_swap", since = "1.10.0"),
- stable(feature = "atomic_debug", since = "1.3.0"),
- 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"),
- stable(feature = "rust1", since = "1.0.0"),
- "usize", "../../../std/primitive.usize.html",
- "",
- atomic_umin, atomic_umax,
- ptr_width!(),
- "AtomicUsize::new(0)",
- usize AtomicUsize ATOMIC_USIZE_INIT
+
+atomic_int_ptr_sized! {
+ "16" 2
+ "32" 4
+ "64" 8
}
#[inline]
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 4e987a5..6851f3f 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -39,15 +39,17 @@
/// Returns `true` if this is `Poll::Ready`
#[inline]
+ #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
#[stable(feature = "futures_api", since = "1.36.0")]
- pub fn is_ready(&self) -> bool {
+ pub const fn is_ready(&self) -> bool {
matches!(*self, Poll::Ready(_))
}
/// Returns `true` if this is `Poll::Pending`
#[inline]
+ #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
#[stable(feature = "futures_api", since = "1.36.0")]
- pub fn is_pending(&self) -> bool {
+ pub const fn is_pending(&self) -> bool {
!self.is_ready()
}
}
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index ba3fb35..d3c0d9b 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -130,8 +130,8 @@
#[rustc_promotable]
#[stable(feature = "futures_api", since = "1.36.0")]
#[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
- #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_fn_ptr_basics))]
- #[cfg_attr(bootstrap, rustc_allow_const_fn_ptr)]
+ #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics))]
+ #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_fn_ptr_basics))]
pub const fn new(
clone: unsafe fn(*const ()) -> RawWaker,
wake: unsafe fn(*const ()),
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 6dc542d..88b4e2a 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -108,18 +108,20 @@
#[unstable(feature = "duration_constants", issue = "57391")]
pub const NANOSECOND: Duration = Duration::from_nanos(1);
- /// The minimum duration.
+ /// A duration of zero time.
///
/// # Examples
///
/// ```
- /// #![feature(duration_constants)]
+ /// #![feature(duration_zero)]
/// use std::time::Duration;
///
- /// assert_eq!(Duration::MIN, Duration::new(0, 0));
+ /// let duration = Duration::ZERO;
+ /// assert!(duration.is_zero());
+ /// assert_eq!(duration.as_nanos(), 0);
/// ```
- #[unstable(feature = "duration_constants", issue = "57391")]
- pub const MIN: Duration = Duration::from_nanos(0);
+ #[unstable(feature = "duration_zero", issue = "73544")]
+ pub const ZERO: Duration = Duration::from_nanos(0);
/// The maximum duration.
///
@@ -166,24 +168,6 @@
Duration { secs, nanos }
}
- /// Creates a new `Duration` that spans no time.
- ///
- /// # 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")]
- #[inline]
- pub const fn zero() -> Duration {
- Duration { secs: 0, nanos: 0 }
- }
-
/// Creates a new `Duration` from the specified number of whole seconds.
///
/// # Examples
@@ -277,7 +261,7 @@
/// #![feature(duration_zero)]
/// use std::time::Duration;
///
- /// assert!(Duration::zero().is_zero());
+ /// assert!(Duration::ZERO.is_zero());
/// assert!(Duration::new(0, 0).is_zero());
/// assert!(Duration::from_nanos(0).is_zero());
/// assert!(Duration::from_secs(0).is_zero());
@@ -536,18 +520,18 @@
}
}
- /// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::MIN`]
+ /// Saturating `Duration` subtraction. Computes `self - other`, returning [`Duration::ZERO`]
/// if the result would be negative or if overflow occurred.
///
/// # Examples
///
/// ```
/// #![feature(duration_saturating_ops)]
- /// #![feature(duration_constants)]
+ /// #![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::MIN);
+ /// assert_eq!(Duration::new(0, 0).saturating_sub(Duration::new(0, 1)), Duration::ZERO);
/// ```
#[unstable(feature = "duration_saturating_ops", issue = "76416")]
#[inline]
@@ -555,7 +539,7 @@
pub const fn saturating_sub(self, rhs: Duration) -> Duration {
match self.checked_sub(rhs) {
Some(res) => res,
- None => Duration::MIN,
+ None => Duration::ZERO,
}
}