summaryrefslogtreecommitdiffstats
path: root/library/core
diff options
context:
space:
mode:
Diffstat (limited to 'library/core')
-rw-r--r--library/core/primitive_docs/box_into_raw.md1
-rw-r--r--library/core/primitive_docs/fs_file.md1
-rw-r--r--library/core/primitive_docs/io_bufread.md1
-rw-r--r--library/core/primitive_docs/io_read.md1
-rw-r--r--library/core/primitive_docs/io_seek.md1
-rw-r--r--library/core/primitive_docs/io_write.md1
-rw-r--r--library/core/primitive_docs/net_tosocketaddrs.md1
-rw-r--r--library/core/primitive_docs/process_exit.md1
-rw-r--r--library/core/primitive_docs/string_string.md1
-rw-r--r--library/core/src/ascii/ascii_char.rs41
-rw-r--r--library/core/src/cell.rs51
-rw-r--r--library/core/src/char/convert.rs38
-rw-r--r--library/core/src/char/methods.rs52
-rw-r--r--library/core/src/cmp.rs118
-rw-r--r--library/core/src/convert/num.rs4
-rw-r--r--library/core/src/error.md2
-rw-r--r--library/core/src/ffi/c_str.rs107
-rw-r--r--library/core/src/fmt/builders.rs8
-rw-r--r--library/core/src/fmt/mod.rs28
-rw-r--r--library/core/src/hash/mod.rs5
-rw-r--r--library/core/src/hint.rs41
-rw-r--r--library/core/src/intrinsics.rs31
-rw-r--r--library/core/src/intrinsics/mir.rs45
-rw-r--r--library/core/src/iter/adapters/take.rs101
-rw-r--r--library/core/src/iter/range.rs130
-rw-r--r--library/core/src/lib.rs31
-rw-r--r--library/core/src/macros/mod.rs93
-rw-r--r--library/core/src/macros/panic.md30
-rw-r--r--library/core/src/marker.rs7
-rw-r--r--library/core/src/mem/mod.rs13
-rw-r--r--library/core/src/net/ip_addr.rs8
-rw-r--r--library/core/src/num/dec2flt/fpu.rs11
-rw-r--r--library/core/src/num/dec2flt/number.rs1
-rw-r--r--library/core/src/num/f32.rs21
-rw-r--r--library/core/src/num/f64.rs21
-rw-r--r--library/core/src/num/int_macros.rs54
-rw-r--r--library/core/src/num/mod.rs3
-rw-r--r--library/core/src/num/nonzero.rs14
-rw-r--r--library/core/src/num/saturating.rs438
-rw-r--r--library/core/src/num/uint_macros.rs64
-rw-r--r--library/core/src/num/wrapping.rs1
-rw-r--r--library/core/src/ops/deref.rs10
-rw-r--r--library/core/src/ops/drop.rs12
-rw-r--r--library/core/src/ops/function.rs6
-rw-r--r--library/core/src/ops/range.rs2
-rw-r--r--library/core/src/option.rs2
-rw-r--r--library/core/src/panic.rs4
-rw-r--r--library/core/src/panic/panic_info.rs15
-rw-r--r--library/core/src/panicking.rs57
-rw-r--r--library/core/src/pin.rs5
-rw-r--r--library/core/src/primitive_docs.rs29
-rw-r--r--library/core/src/ptr/const_ptr.rs23
-rw-r--r--library/core/src/ptr/mod.rs10
-rw-r--r--library/core/src/ptr/mut_ptr.rs41
-rw-r--r--library/core/src/ptr/non_null.rs20
-rw-r--r--library/core/src/slice/ascii.rs2
-rw-r--r--library/core/src/slice/mod.rs4
-rw-r--r--library/core/src/str/mod.rs6
-rw-r--r--library/core/src/sync/atomic.rs3
-rw-r--r--library/core/src/sync/exclusive.rs46
-rw-r--r--library/core/src/time.rs8
-rw-r--r--library/core/src/tuple.rs2
-rw-r--r--library/core/tests/iter/range.rs18
-rw-r--r--library/core/tests/lib.rs5
-rw-r--r--library/core/tests/macros.rs154
-rw-r--r--library/core/tests/num/int_macros.rs32
-rw-r--r--library/core/tests/num/uint_macros.rs29
-rw-r--r--library/core/tests/time.rs1
68 files changed, 1710 insertions, 457 deletions
diff --git a/library/core/primitive_docs/box_into_raw.md b/library/core/primitive_docs/box_into_raw.md
deleted file mode 100644
index 9dd0344c7..000000000
--- a/library/core/primitive_docs/box_into_raw.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/boxed/struct.Box.html#method.into_raw
diff --git a/library/core/primitive_docs/fs_file.md b/library/core/primitive_docs/fs_file.md
deleted file mode 100644
index 4023e340a..000000000
--- a/library/core/primitive_docs/fs_file.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/fs/struct.File.html
diff --git a/library/core/primitive_docs/io_bufread.md b/library/core/primitive_docs/io_bufread.md
deleted file mode 100644
index 7beda2cd3..000000000
--- a/library/core/primitive_docs/io_bufread.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/io/trait.BufRead.html
diff --git a/library/core/primitive_docs/io_read.md b/library/core/primitive_docs/io_read.md
deleted file mode 100644
index b7ecf5e27..000000000
--- a/library/core/primitive_docs/io_read.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/io/trait.Read.html
diff --git a/library/core/primitive_docs/io_seek.md b/library/core/primitive_docs/io_seek.md
deleted file mode 100644
index db0274d29..000000000
--- a/library/core/primitive_docs/io_seek.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/io/trait.Seek.html
diff --git a/library/core/primitive_docs/io_write.md b/library/core/primitive_docs/io_write.md
deleted file mode 100644
index 92a3b88a7..000000000
--- a/library/core/primitive_docs/io_write.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/io/trait.Write.html
diff --git a/library/core/primitive_docs/net_tosocketaddrs.md b/library/core/primitive_docs/net_tosocketaddrs.md
deleted file mode 100644
index 4daa10ddb..000000000
--- a/library/core/primitive_docs/net_tosocketaddrs.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/net/trait.ToSocketAddrs.html
diff --git a/library/core/primitive_docs/process_exit.md b/library/core/primitive_docs/process_exit.md
deleted file mode 100644
index cae34d12d..000000000
--- a/library/core/primitive_docs/process_exit.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/process/fn.exit.html
diff --git a/library/core/primitive_docs/string_string.md b/library/core/primitive_docs/string_string.md
deleted file mode 100644
index 303dc07b1..000000000
--- a/library/core/primitive_docs/string_string.md
+++ /dev/null
@@ -1 +0,0 @@
-../std/string/struct.String.html
diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs
index 5378b210e..cc872a534 100644
--- a/library/core/src/ascii/ascii_char.rs
+++ b/library/core/src/ascii/ascii_char.rs
@@ -3,7 +3,7 @@
//! suggestions from rustc if you get anything slightly wrong in here, and overall
//! helps with clarity as we're also referring to `char` intentionally in here.
-use crate::fmt;
+use crate::fmt::{self, Write};
use crate::mem::transmute;
/// One of the 128 Unicode characters from U+0000 through U+007F,
@@ -54,7 +54,7 @@ use crate::mem::transmute;
/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf
/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf
/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[unstable(feature = "ascii_char", issue = "110998")]
#[repr(u8)]
pub enum AsciiChar {
@@ -563,3 +563,40 @@ impl fmt::Display for AsciiChar {
<str as fmt::Display>::fmt(self.as_str(), f)
}
}
+
+#[unstable(feature = "ascii_char", issue = "110998")]
+impl fmt::Debug for AsciiChar {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ #[inline]
+ fn backslash(a: AsciiChar) -> ([AsciiChar; 4], u8) {
+ ([AsciiChar::ReverseSolidus, a, AsciiChar::Null, AsciiChar::Null], 2)
+ }
+
+ let (buf, len) = match self {
+ AsciiChar::Null => backslash(AsciiChar::Digit0),
+ AsciiChar::CharacterTabulation => backslash(AsciiChar::SmallT),
+ AsciiChar::CarriageReturn => backslash(AsciiChar::SmallR),
+ AsciiChar::LineFeed => backslash(AsciiChar::SmallN),
+ AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus),
+ AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe),
+ _ => {
+ let byte = self.to_u8();
+ if !byte.is_ascii_control() {
+ ([*self, AsciiChar::Null, AsciiChar::Null, AsciiChar::Null], 1)
+ } else {
+ const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap();
+
+ let hi = HEX_DIGITS[usize::from(byte >> 4)];
+ let lo = HEX_DIGITS[usize::from(byte & 0xf)];
+ ([AsciiChar::ReverseSolidus, AsciiChar::SmallX, hi, lo], 4)
+ }
+ }
+ };
+
+ f.write_char('\'')?;
+ for byte in &buf[..len as usize] {
+ f.write_str(byte.as_str())?;
+ }
+ f.write_char('\'')
+ }
+}
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index bf4c682d3..3b4d99221 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -237,6 +237,7 @@
use crate::cmp::Ordering;
use crate::fmt::{self, Debug, Display};
+use crate::intrinsics::is_nonoverlapping;
use crate::marker::{PhantomData, Unsize};
use crate::mem;
use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn};
@@ -415,6 +416,12 @@ impl<T> Cell<T> {
/// Swaps the values of two `Cell`s.
/// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference.
///
+ /// # Panics
+ ///
+ /// This function will panic if `self` and `other` are different `Cell`s that partially overlap.
+ /// (Using just standard library methods, it is impossible to create such partially overlapping `Cell`s.
+ /// However, unsafe code is allowed to e.g. create two `&Cell<[i32; 2]>` that partially overlap.)
+ ///
/// # Examples
///
/// ```
@@ -430,14 +437,20 @@ impl<T> Cell<T> {
#[stable(feature = "move_cell", since = "1.17.0")]
pub fn swap(&self, other: &Self) {
if ptr::eq(self, other) {
+ // Swapping wouldn't change anything.
return;
}
+ if !is_nonoverlapping(self, other, 1) {
+ // See <https://github.com/rust-lang/rust/issues/80778> for why we need to stop here.
+ panic!("`Cell::swap` on overlapping non-identical `Cell`s");
+ }
// SAFETY: This can be risky if called from separate threads, but `Cell`
// is `!Sync` so this won't happen. This also won't invalidate any
// pointers since `Cell` makes sure nothing else will be pointing into
- // either of these `Cell`s.
+ // either of these `Cell`s. We also excluded shenanigans like partially overlapping `Cell`s,
+ // so `swap` will just properly copy two full values of type `T` back and forth.
unsafe {
- ptr::swap(self.value.get(), other.value.get());
+ mem::swap(&mut *self.value.get(), &mut *other.value.get());
}
}
@@ -543,6 +556,7 @@ impl<T: ?Sized> Cell<T> {
#[inline]
#[stable(feature = "cell_as_ptr", since = "1.12.0")]
#[rustc_const_stable(feature = "const_cell_as_ptr", since = "1.32.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn as_ptr(&self) -> *mut T {
self.value.get()
}
@@ -740,6 +754,22 @@ impl Display for BorrowMutError {
}
}
+// This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
+#[inline(never)]
+#[track_caller]
+#[cold]
+fn panic_already_borrowed(err: BorrowMutError) -> ! {
+ panic!("already borrowed: {:?}", err)
+}
+
+// This ensures the panicking code is outlined from `borrow` for `RefCell`.
+#[inline(never)]
+#[track_caller]
+#[cold]
+fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
+ panic!("already mutably borrowed: {:?}", err)
+}
+
// Positive values represent the number of `Ref` active. Negative values
// represent the number of `RefMut` active. Multiple `RefMut`s can only be
// active at a time if they refer to distinct, nonoverlapping components of a
@@ -921,7 +951,10 @@ impl<T: ?Sized> RefCell<T> {
#[inline]
#[track_caller]
pub fn borrow(&self) -> Ref<'_, T> {
- self.try_borrow().expect("already mutably borrowed")
+ match self.try_borrow() {
+ Ok(b) => b,
+ Err(err) => panic_already_mutably_borrowed(err),
+ }
}
/// Immutably borrows the wrapped value, returning an error if the value is currently mutably
@@ -1014,7 +1047,10 @@ impl<T: ?Sized> RefCell<T> {
#[inline]
#[track_caller]
pub fn borrow_mut(&self) -> RefMut<'_, T> {
- self.try_borrow_mut().expect("already borrowed")
+ match self.try_borrow_mut() {
+ Ok(b) => b,
+ Err(err) => panic_already_borrowed(err),
+ }
}
/// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
@@ -1076,6 +1112,7 @@ impl<T: ?Sized> RefCell<T> {
/// ```
#[inline]
#[stable(feature = "cell_as_ptr", since = "1.12.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub fn as_ptr(&self) -> *mut T {
self.value.get()
}
@@ -1893,8 +1930,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
/// on an _exclusive_ `UnsafeCell<T>`. Even though `T` and `UnsafeCell<T>` have the
/// same memory layout, the following is not allowed and undefined behavior:
///
-#[cfg_attr(bootstrap, doc = "```rust,no_run")]
-#[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")]
+/// ```rust,compile_fail
/// # use std::cell::UnsafeCell;
/// unsafe fn not_allowed<T>(ptr: &UnsafeCell<T>) -> &mut T {
/// let t = ptr as *const UnsafeCell<T> as *mut T;
@@ -2071,6 +2107,7 @@ impl<T: ?Sized> UnsafeCell<T> {
#[inline(always)]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn get(&self) -> *mut T {
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
// #[repr(transparent)]. This exploits std's special status, there is
@@ -2131,6 +2168,7 @@ impl<T: ?Sized> UnsafeCell<T> {
#[inline(always)]
#[stable(feature = "unsafe_cell_raw_get", since = "1.56.0")]
#[rustc_const_stable(feature = "unsafe_cell_raw_get", since = "1.56.0")]
+ #[rustc_diagnostic_item = "unsafe_cell_raw_get"]
pub const fn raw_get(this: *const Self) -> *mut T {
// We can just cast the pointer from `UnsafeCell<T>` to `T` because of
// #[repr(transparent)]. This exploits std's special status, there is
@@ -2213,6 +2251,7 @@ impl<T: ?Sized> SyncUnsafeCell<T> {
/// when casting to `&mut T`, and ensure that there are no mutations
/// or mutable aliases going on when casting to `&T`
#[inline]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn get(&self) -> *mut T {
self.value.get()
}
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index b84e4b35b..453de9754 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -87,20 +87,54 @@ impl From<char> for u128 {
}
}
-/// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing
-/// if the code point is greater than U+00FF.
+/// Maps a `char` with code point in U+0000..=U+00FF to a byte in 0x00..=0xFF with same value,
+/// failing if the code point is greater than U+00FF.
///
/// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding.
#[stable(feature = "u8_from_char", since = "1.59.0")]
impl TryFrom<char> for u8 {
type Error = TryFromCharError;
+ /// Tries to convert a [`char`] into a [`u8`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let a = 'ÿ'; // U+00FF
+ /// let b = 'Ā'; // U+0100
+ /// assert_eq!(u8::try_from(a), Ok(0xFF_u8));
+ /// assert!(u8::try_from(b).is_err());
+ /// ```
#[inline]
fn try_from(c: char) -> Result<u8, Self::Error> {
u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
}
}
+/// Maps a `char` with code point in U+0000..=U+FFFF to a `u16` in 0x0000..=0xFFFF with same value,
+/// failing if the code point is greater than U+FFFF.
+///
+/// This corresponds to the UCS-2 encoding, as specified in ISO/IEC 10646:2003.
+#[stable(feature = "u16_from_char", since = "1.74.0")]
+impl TryFrom<char> for u16 {
+ type Error = TryFromCharError;
+
+ /// Tries to convert a [`char`] into a [`u16`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let trans_rights = '⚧'; // U+26A7
+ /// let ninjas = '🥷'; // U+1F977
+ /// assert_eq!(u16::try_from(trans_rights), Ok(0x26A7_u16));
+ /// assert!(u16::try_from(ninjas).is_err());
+ /// ```
+ #[inline]
+ fn try_from(c: char) -> Result<u16, Self::Error> {
+ u16::try_from(u32::from(c)).map_err(|_| TryFromCharError(()))
+ }
+}
+
/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
///
/// Unicode is designed such that this effectively decodes bytes
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 515b8d20e..4ac956e7b 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -9,8 +9,58 @@ use crate::unicode::{self, conversions};
use super::*;
impl char {
+ /// The lowest valid code point a `char` can have, `'\0'`.
+ ///
+ /// Unlike integer types, `char` actually has a gap in the middle,
+ /// meaning that the range of possible `char`s is smaller than you
+ /// might expect. Ranges of `char` will automatically hop this gap
+ /// for you:
+ ///
+ /// ```
+ /// #![feature(char_min)]
+ /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
+ /// let size = (char::MIN..=char::MAX).count() as u32;
+ /// assert!(size < dist);
+ /// ```
+ ///
+ /// Despite this gap, the `MIN` and [`MAX`] values can be used as bounds for
+ /// all `char` values.
+ ///
+ /// [`MAX`]: char::MAX
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(char_min)]
+ /// # fn something_which_returns_char() -> char { 'a' }
+ /// let c: char = something_which_returns_char();
+ /// assert!(char::MIN <= c);
+ ///
+ /// let value_at_min = u32::from(char::MIN);
+ /// assert_eq!(char::from_u32(value_at_min), Some('\0'));
+ /// ```
+ #[unstable(feature = "char_min", issue = "114298")]
+ pub const MIN: char = '\0';
+
/// The highest valid code point a `char` can have, `'\u{10FFFF}'`.
///
+ /// Unlike integer types, `char` actually has a gap in the middle,
+ /// meaning that the range of possible `char`s is smaller than you
+ /// might expect. Ranges of `char` will automatically hop this gap
+ /// for you:
+ ///
+ /// ```
+ /// #![feature(char_min)]
+ /// let dist = u32::from(char::MAX) - u32::from(char::MIN);
+ /// let size = (char::MIN..=char::MAX).count() as u32;
+ /// assert!(size < dist);
+ /// ```
+ ///
+ /// Despite this gap, the [`MIN`] and `MAX` values can be used as bounds for
+ /// all `char` values.
+ ///
+ /// [`MIN`]: char::MIN
+ ///
/// # Examples
///
/// ```
@@ -18,7 +68,7 @@ impl char {
/// let c: char = something_which_returns_char();
/// assert!(c <= char::MAX);
///
- /// let value_at_max = char::MAX as u32;
+ /// let value_at_max = u32::from(char::MAX);
/// assert_eq!(char::from_u32(value_at_max), Some('\u{10FFFF}'));
/// assert_eq!(char::from_u32(value_at_max + 1), None);
/// ```
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 3c127efb3..360806167 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -63,6 +63,11 @@ use self::Ordering::*;
/// (transitive) impls are not forced to exist, but these requirements apply
/// whenever they do exist.
///
+/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
+/// specified, but users of the trait must ensure that such logic errors do *not* result in
+/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
+/// methods.
+///
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d on structs, two
@@ -250,6 +255,11 @@ pub macro PartialEq($item:item) {
/// This property cannot be checked by the compiler, and therefore `Eq` implies
/// [`PartialEq`], and has no extra methods.
///
+/// Violating this property is a logic error. The behavior resulting from a logic error is not
+/// specified, but users of the trait must ensure that such logic errors do *not* result in
+/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
+/// methods.
+///
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has
@@ -281,15 +291,16 @@ pub macro PartialEq($item:item) {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Eq"]
pub trait Eq: PartialEq<Self> {
- // this method is used solely by #[deriving] to assert
- // that every component of a type implements #[deriving]
- // itself, the current deriving infrastructure means doing this
+ // this method is used solely by #[derive(Eq)] to assert
+ // that every component of a type implements `Eq`
+ // itself. The current deriving infrastructure means doing this
// assertion without using a method on this trait is nearly
// impossible.
//
// This should never be implemented by hand.
#[doc(hidden)]
- #[no_coverage] // rust-lang/rust#84605
+ #[cfg_attr(bootstrap, no_coverage)] // rust-lang/rust#84605
+ #[cfg_attr(not(bootstrap), coverage(off))] //
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn assert_receiver_is_total_eq(&self) {}
@@ -298,7 +309,9 @@ pub trait Eq: PartialEq<Self> {
/// Derive macro generating an impl of the trait [`Eq`].
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match, no_coverage)]
+#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
+#[cfg_attr(bootstrap, allow_internal_unstable(no_coverage))]
+#[cfg_attr(not(bootstrap), allow_internal_unstable(coverage_attribute))]
pub macro Eq($item:item) {
/* compiler built-in */
}
@@ -656,6 +669,11 @@ impl<T: Clone> Clone for Reverse<T> {
/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
/// deriving some of the traits and manually implementing others.
///
+/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
+/// specified, but users of the trait must ensure that such logic errors do *not* result in
+/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
+/// methods.
+///
/// ## Corollaries
///
/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
@@ -889,6 +907,11 @@ pub macro Ord($item:item) {
/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
/// PartialOrd<V>`.
///
+/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
+/// specified, but users of the trait must ensure that such logic errors do *not* result in
+/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
+/// methods.
+///
/// ## Corollaries
///
/// The following corollaries follow from the above requirements:
@@ -1266,6 +1289,91 @@ pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
}
+/// Compares and sorts two values, returning minimum and maximum.
+///
+/// Returns `[v1, v2]` if the comparison determines them to be equal.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(cmp_minmax)]
+/// use std::cmp;
+///
+/// assert_eq!(cmp::minmax(1, 2), [1, 2]);
+/// assert_eq!(cmp::minmax(2, 2), [2, 2]);
+///
+/// // You can destructure the result using array patterns
+/// let [min, max] = cmp::minmax(42, 17);
+/// assert_eq!(min, 17);
+/// assert_eq!(max, 42);
+/// ```
+#[inline]
+#[must_use]
+#[unstable(feature = "cmp_minmax", issue = "115939")]
+pub fn minmax<T>(v1: T, v2: T) -> [T; 2]
+where
+ T: Ord,
+{
+ if v1 <= v2 { [v1, v2] } else { [v2, v1] }
+}
+
+/// Returns minimum and maximum values with respect to the specified comparison function.
+///
+/// Returns `[v1, v2]` if the comparison determines them to be equal.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(cmp_minmax)]
+/// use std::cmp;
+///
+/// assert_eq!(cmp::minmax_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [1, -2]);
+/// assert_eq!(cmp::minmax_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), [-2, 2]);
+///
+/// // You can destructure the result using array patterns
+/// let [min, max] = cmp::minmax_by(-42, 17, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
+/// assert_eq!(min, 17);
+/// assert_eq!(max, -42);
+/// ```
+#[inline]
+#[must_use]
+#[unstable(feature = "cmp_minmax", issue = "115939")]
+pub fn minmax_by<T, F>(v1: T, v2: T, compare: F) -> [T; 2]
+where
+ F: FnOnce(&T, &T) -> Ordering,
+{
+ if compare(&v1, &v2).is_le() { [v1, v2] } else { [v2, v1] }
+}
+
+/// Returns minimum and maximum values with respect to the specified key function.
+///
+/// Returns `[v1, v2]` if the comparison determines them to be equal.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(cmp_minmax)]
+/// use std::cmp;
+///
+/// assert_eq!(cmp::minmax_by_key(-2, 1, |x: &i32| x.abs()), [1, -2]);
+/// assert_eq!(cmp::minmax_by_key(-2, 2, |x: &i32| x.abs()), [-2, 2]);
+///
+/// // You can destructure the result using array patterns
+/// let [min, max] = cmp::minmax_by_key(-42, 17, |x: &i32| x.abs());
+/// assert_eq!(min, 17);
+/// assert_eq!(max, -42);
+/// ```
+#[inline]
+#[must_use]
+#[unstable(feature = "cmp_minmax", issue = "115939")]
+pub fn minmax_by_key<T, F, K>(v1: T, v2: T, mut f: F) -> [T; 2]
+where
+ F: FnMut(&T) -> K,
+ K: Ord,
+{
+ minmax_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
+}
+
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
mod impls {
use crate::cmp::Ordering::{self, Equal, Greater, Less};
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index 56ab63be2..b048b5135 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -142,9 +142,9 @@ impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.2
// RISC-V defines the possibility of a 128-bit address space (RV128).
-// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
+// CHERI proposes 128-bit “capabilities”. Unclear if this would be relevant to usize/isize.
// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
-// https://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
+// https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf
// Note: integers can only be represented with full precision in a float if
// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
diff --git a/library/core/src/error.md b/library/core/src/error.md
index 7771b8adc..a5deb71e6 100644
--- a/library/core/src/error.md
+++ b/library/core/src/error.md
@@ -37,7 +37,7 @@ responsibilities they cover:
The panic and error systems are not entirely distinct. Often times errors
that are anticipated runtime failures in an API might instead represent bugs
to a caller. For these situations the standard library provides APIs for
-constructing panics with an `Error` as it's source.
+constructing panics with an `Error` as its source.
* [`Result::unwrap`]
* [`Result::expect`]
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 163a65c90..93a6716d7 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -214,6 +214,8 @@ impl CStr {
/// * The memory referenced by the returned `CStr` must not be mutated for
/// the duration of lifetime `'a`.
///
+ /// * The nul terminator must be within `isize::MAX` from `ptr`
+ ///
/// > **Note**: This operation is intended to be a 0-cost cast but it is
/// > currently implemented with an up-front calculation of the length of
/// > the string. This is not guaranteed to always be the case.
@@ -259,42 +261,16 @@ impl CStr {
#[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")]
pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
// SAFETY: The caller has provided a pointer that points to a valid C
- // string with a NUL terminator of size less than `isize::MAX`, whose
- // content remain valid and doesn't change for the lifetime of the
- // returned `CStr`.
- //
- // Thus computing the length is fine (a NUL byte exists), the call to
- // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning
- // the call to `from_bytes_with_nul_unchecked` is correct.
+ // string with a NUL terminator less than `isize::MAX` from `ptr`.
+ let len = unsafe { const_strlen(ptr) };
+
+ // SAFETY: The caller has provided a valid pointer with length less than
+ // `isize::MAX`, so `from_raw_parts` is safe. The content remains valid
+ // and doesn't change for the lifetime of the returned `CStr`. This
+ // means the call to `from_bytes_with_nul_unchecked` is correct.
//
// The cast from c_char to u8 is ok because a c_char is always one byte.
- unsafe {
- const fn strlen_ct(s: *const c_char) -> usize {
- let mut len = 0;
-
- // SAFETY: Outer caller has provided a pointer to a valid C string.
- while unsafe { *s.add(len) } != 0 {
- len += 1;
- }
-
- len
- }
-
- // `inline` is necessary for codegen to see strlen.
- #[inline]
- fn strlen_rt(s: *const c_char) -> usize {
- extern "C" {
- /// Provided by libc or compiler_builtins.
- fn strlen(s: *const c_char) -> usize;
- }
-
- // SAFETY: Outer caller has provided a pointer to a valid C string.
- unsafe { strlen(s) }
- }
-
- let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt);
- Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1))
- }
+ unsafe { Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) }
}
/// Creates a C string wrapper from a byte slice with any number of nuls.
@@ -511,10 +487,39 @@ impl CStr {
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn as_ptr(&self) -> *const c_char {
self.inner.as_ptr()
}
+ /// Returns the length of `self`. Like C's `strlen`, this does not include the nul terminator.
+ ///
+ /// > **Note**: This method is currently implemented as a constant-time
+ /// > cast, but it is planned to alter its definition in the future to
+ /// > perform the length calculation whenever this method is called.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(cstr_count_bytes)]
+ ///
+ /// use std::ffi::CStr;
+ ///
+ /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap();
+ /// assert_eq!(cstr.count_bytes(), 3);
+ ///
+ /// let cstr = CStr::from_bytes_with_nul(b"\0").unwrap();
+ /// assert_eq!(cstr.count_bytes(), 0);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[doc(alias("len", "strlen"))]
+ #[unstable(feature = "cstr_count_bytes", issue = "114441")]
+ #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")]
+ pub const fn count_bytes(&self) -> usize {
+ self.inner.len() - 1
+ }
+
/// Returns `true` if `self.to_bytes()` has a length of 0.
///
/// # Examples
@@ -681,3 +686,37 @@ impl AsRef<CStr> for CStr {
self
}
}
+
+/// Calculate the length of a nul-terminated string. Defers to C's `strlen` when possible.
+///
+/// # Safety
+///
+/// The pointer must point to a valid buffer that contains a NUL terminator. The NUL must be
+/// located within `isize::MAX` from `ptr`.
+#[inline]
+const unsafe fn const_strlen(ptr: *const c_char) -> usize {
+ const fn strlen_ct(s: *const c_char) -> usize {
+ let mut len = 0;
+
+ // SAFETY: Outer caller has provided a pointer to a valid C string.
+ while unsafe { *s.add(len) } != 0 {
+ len += 1;
+ }
+
+ len
+ }
+
+ #[inline]
+ fn strlen_rt(s: *const c_char) -> usize {
+ extern "C" {
+ /// Provided by libc or compiler_builtins.
+ fn strlen(s: *const c_char) -> usize;
+ }
+
+ // SAFETY: Outer caller has provided a pointer to a valid C string.
+ unsafe { strlen(s) }
+ }
+
+ // SAFETY: the two functions always provide equivalent functionality
+ unsafe { intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt) }
+}
diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs
index d2c9f9800..922724804 100644
--- a/library/core/src/fmt/builders.rs
+++ b/library/core/src/fmt/builders.rs
@@ -40,6 +40,14 @@ impl fmt::Write for PadAdapter<'_, '_> {
Ok(())
}
+
+ fn write_char(&mut self, c: char) -> fmt::Result {
+ if self.state.on_newline {
+ self.buf.write_str(" ")?;
+ }
+ self.state.on_newline = c == '\n';
+ self.buf.write_char(c)
+ }
}
/// A struct to help with [`fmt::Debug`](Debug) implementations.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 9ce6093f1..fc91d1afc 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -112,9 +112,9 @@ pub trait Write {
///
/// # Errors
///
- /// This function will return an instance of [`Error`] on error.
+ /// This function will return an instance of [`std::fmt::Error`][Error] on error.
///
- /// The purpose of std::fmt::Error is to abort the formatting operation when the underlying
+ /// The purpose of that error is to abort the formatting operation when the underlying
/// destination encounters some error preventing it from accepting more text; it should
/// generally be propagated rather than handled, at least when implementing formatting traits.
///
@@ -188,8 +188,28 @@ pub trait Write {
/// assert_eq!(&buf, "world");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> Result {
- write(&mut self, args)
+ fn write_fmt(&mut self, args: Arguments<'_>) -> Result {
+ // We use a specialization for `Sized` types to avoid an indirection
+ // through `&mut self`
+ trait SpecWriteFmt {
+ fn spec_write_fmt(self, args: Arguments<'_>) -> Result;
+ }
+
+ impl<W: Write + ?Sized> SpecWriteFmt for &mut W {
+ #[inline]
+ default fn spec_write_fmt(mut self, args: Arguments<'_>) -> Result {
+ write(&mut self, args)
+ }
+ }
+
+ impl<W: Write> SpecWriteFmt for &mut W {
+ #[inline]
+ fn spec_write_fmt(self, args: Arguments<'_>) -> Result {
+ write(self, args)
+ }
+ }
+
+ self.spec_write_fmt(args)
}
}
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index 794a57f09..35b757dc1 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -153,6 +153,11 @@ mod sip;
/// Thankfully, you won't need to worry about upholding this property when
/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`.
///
+/// Violating this property is a logic error. The behavior resulting from a logic error is not
+/// specified, but users of the trait must ensure that such logic errors do *not* result in
+/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these
+/// methods.
+///
/// ## Prefix collisions
///
/// Implementations of `hash` should ensure that the data they
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 75c104ce2..4bf3da073 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -175,34 +175,27 @@ pub fn spin_loop() {
unsafe { crate::arch::x86_64::_mm_pause() };
}
- // RISC-V platform spin loop hint implementation
+ #[cfg(target_arch = "riscv32")]
{
- // RISC-V RV32 and RV64 share the same PAUSE instruction, but they are located in different
- // modules in `core::arch`.
- // In this case, here we call `pause` function in each core arch module.
- #[cfg(target_arch = "riscv32")]
- {
- crate::arch::riscv32::pause();
- }
- #[cfg(target_arch = "riscv64")]
- {
- crate::arch::riscv64::pause();
- }
+ crate::arch::riscv32::pause();
}
- #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
+ #[cfg(target_arch = "riscv64")]
{
- #[cfg(target_arch = "aarch64")]
- {
- // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
- unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
- }
- #[cfg(target_arch = "arm")]
- {
- // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
- // with support for the v6 feature.
- unsafe { crate::arch::arm::__yield() };
- }
+ crate::arch::riscv64::pause();
+ }
+
+ #[cfg(target_arch = "aarch64")]
+ {
+ // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
+ unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
+ }
+
+ #[cfg(all(target_arch = "arm", target_feature = "v6"))]
+ {
+ // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
+ // with support for the v6 feature.
+ unsafe { crate::arch::arm::__yield() };
}
}
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 676d4f2f3..4c76662ac 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1130,7 +1130,10 @@ extern "rust-intrinsic" {
/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
/// unsafe**. `transmute` should be the absolute last resort.
///
- /// Transmuting pointers to integers in a `const` context is [undefined behavior][ub].
+ /// Transmuting pointers *to* integers in a `const` context is [undefined behavior][ub],
+ /// unless the pointer was originally created *from* an integer.
+ /// (That includes this function specifically, integer-to-pointer casts, and helpers like [`invalid`][crate::ptr::invalid],
+ /// but also semantically-equivalent conversions such as punning through `repr(C)` union fields.)
/// Any attempt to use the resulting value for integer operations will abort const-evaluation.
/// (And even outside `const`, such transmutation is touching on many unspecified aspects of the
/// Rust memory model and should be avoided. See below for alternatives.)
@@ -2399,7 +2402,6 @@ extern "rust-intrinsic" {
/// that differs. That allows optimizations that can read in large chunks.
///
/// [valid]: crate::ptr#safety
- #[cfg(not(bootstrap))]
#[rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none")]
#[rustc_nounwind]
pub fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32;
@@ -2568,7 +2570,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
let size = mem::size_of::<T>()
.checked_mul(count)
.expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize");
- let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
+ let diff = src_usize.abs_diff(dst_usize);
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
// they do not overlap.
diff >= size
@@ -2705,9 +2707,13 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
///
/// Behavior is undefined if any of the following conditions are violated:
///
-/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes, and must remain valid even
+/// when `dst` is written for `count * size_of::<T>()` bytes. (This means if the memory ranges
+/// overlap, the two pointers must not be subject to aliasing restrictions relative to each
+/// other.)
///
-/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes, and must remain valid even
+/// when `src` is read for `count * size_of::<T>()` bytes.
///
/// * Both `src` and `dst` must be properly aligned.
///
@@ -2844,18 +2850,3 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
write_bytes(dst, val, count)
}
}
-
-/// Backfill for bootstrap
-#[cfg(bootstrap)]
-pub unsafe fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32 {
- extern "C" {
- fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> crate::ffi::c_int;
- }
-
- if bytes != 0 {
- // SAFETY: Since bytes is non-zero, the caller has met `memcmp`'s requirements.
- unsafe { memcmp(left, right, bytes).into() }
- } else {
- 0
- }
-}
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index ef0a2fd4e..cab195dad 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -12,9 +12,10 @@
//!
//! Typical usage will look like this:
//!
-//! ```rust
+#![cfg_attr(bootstrap, doc = "```rust,ignore")]
+#![cfg_attr(not(bootstrap), doc = "```rust")]
//! #![feature(core_intrinsics, custom_mir)]
-#![cfg_attr(not(bootstrap), doc = "#![allow(internal_features)]")]
+//! #![allow(internal_features)]
//!
//! use core::intrinsics::mir::*;
//!
@@ -62,9 +63,10 @@
//!
//! # Examples
//!
-//! ```rust
+#![cfg_attr(bootstrap, doc = "```rust,ignore")]
+#![cfg_attr(not(bootstrap), doc = "```rust")]
//! #![feature(core_intrinsics, custom_mir)]
-#![cfg_attr(not(bootstrap), doc = "#![allow(internal_features)]")]
+//! #![allow(internal_features)]
//!
//! use core::intrinsics::mir::*;
//!
@@ -317,8 +319,9 @@ define!(
///
/// # Examples
///
- /// ```rust
- #[cfg_attr(not(bootstrap), doc = "#![allow(internal_features)]")]
+ #[cfg_attr(bootstrap, doc = "```rust,ignore")]
+ #[cfg_attr(not(bootstrap), doc = "```rust")]
+ /// #![allow(internal_features)]
/// #![feature(custom_mir, core_intrinsics)]
///
/// use core::intrinsics::mir::*;
@@ -361,6 +364,11 @@ define!(
#[doc(hidden)]
fn __internal_make_place<T>(place: T) -> *mut T
);
+define!(
+ "mir_debuginfo",
+ #[doc(hidden)]
+ fn __debuginfo<T>(name: &'static str, s: T)
+);
/// Macro for generating custom MIR.
///
@@ -371,6 +379,7 @@ pub macro mir {
(
$(type RET = $ret_ty:ty ;)?
$(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
+ $(debug $dbg_name:ident => $dbg_data:expr ;)*
{
$($entry:tt)*
@@ -394,26 +403,32 @@ pub macro mir {
$(
let $local_decl $(: $local_decl_ty)? ;
)*
-
::core::intrinsics::mir::__internal_extract_let!($($entry)*);
$(
::core::intrinsics::mir::__internal_extract_let!($($block)*);
)*
{
- // Finally, the contents of the basic blocks
- ::core::intrinsics::mir::__internal_remove_let!({
- {}
- { $($entry)* }
- });
+ // Now debuginfo
$(
+ __debuginfo(stringify!($dbg_name), $dbg_data);
+ )*
+
+ {
+ // Finally, the contents of the basic blocks
::core::intrinsics::mir::__internal_remove_let!({
{}
- { $($block)* }
+ { $($entry)* }
});
- )*
+ $(
+ ::core::intrinsics::mir::__internal_remove_let!({
+ {}
+ { $($block)* }
+ });
+ )*
- RET
+ RET
+ }
}
}
}}
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index ce18bffe7..c1d8cc4ff 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -1,5 +1,7 @@
use crate::cmp;
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
+use crate::iter::{
+ adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess,
+};
use crate::num::NonZeroUsize;
use crate::ops::{ControlFlow, Try};
@@ -98,26 +100,18 @@ where
}
}
- impl_fold_via_try_fold! { fold -> try_fold }
-
#[inline]
- fn for_each<F: FnMut(Self::Item)>(mut self, f: F) {
- // The default implementation would use a unit accumulator, so we can
- // avoid a stateful closure by folding over the remaining number
- // of items we wish to return instead.
- fn check<'a, Item>(
- mut action: impl FnMut(Item) + 'a,
- ) -> impl FnMut(usize, Item) -> Option<usize> + 'a {
- move |more, x| {
- action(x);
- more.checked_sub(1)
- }
- }
+ fn fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ Self::spec_fold(self, init, f)
+ }
- let remaining = self.n;
- if remaining > 0 {
- self.iter.try_fold(remaining - 1, check(f));
- }
+ #[inline]
+ fn for_each<F: FnMut(Self::Item)>(self, f: F) {
+ Self::spec_for_each(self, f)
}
#[inline]
@@ -249,3 +243,72 @@ impl<I> FusedIterator for Take<I> where I: FusedIterator {}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
+
+trait SpecTake: Iterator {
+ fn spec_fold<B, F>(self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B;
+
+ fn spec_for_each<F: FnMut(Self::Item)>(self, f: F);
+}
+
+impl<I: Iterator> SpecTake for Take<I> {
+ #[inline]
+ default fn spec_fold<B, F>(mut self, init: B, f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ use crate::ops::NeverShortCircuit;
+ self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
+ }
+
+ #[inline]
+ default fn spec_for_each<F: FnMut(Self::Item)>(mut self, f: F) {
+ // The default implementation would use a unit accumulator, so we can
+ // avoid a stateful closure by folding over the remaining number
+ // of items we wish to return instead.
+ fn check<'a, Item>(
+ mut action: impl FnMut(Item) + 'a,
+ ) -> impl FnMut(usize, Item) -> Option<usize> + 'a {
+ move |more, x| {
+ action(x);
+ more.checked_sub(1)
+ }
+ }
+
+ let remaining = self.n;
+ if remaining > 0 {
+ self.iter.try_fold(remaining - 1, check(f));
+ }
+ }
+}
+
+impl<I: Iterator + TrustedRandomAccess> SpecTake for Take<I> {
+ #[inline]
+ fn spec_fold<B, F>(mut self, init: B, mut f: F) -> B
+ where
+ Self: Sized,
+ F: FnMut(B, Self::Item) -> B,
+ {
+ let mut acc = init;
+ let end = self.n.min(self.iter.size());
+ for i in 0..end {
+ // SAFETY: i < end <= self.iter.size() and we discard the iterator at the end
+ let val = unsafe { self.iter.__iterator_get_unchecked(i) };
+ acc = f(acc, val);
+ }
+ acc
+ }
+
+ #[inline]
+ fn spec_for_each<F: FnMut(Self::Item)>(mut self, mut f: F) {
+ let end = self.n.min(self.iter.size());
+ for i in 0..end {
+ // SAFETY: i < end <= self.iter.size() and we discard the iterator at the end
+ let val = unsafe { self.iter.__iterator_get_unchecked(i) };
+ f(val);
+ }
+ }
+}
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 462f7170a..0e03d0c2d 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,5 +1,7 @@
+use crate::ascii::Char as AsciiChar;
use crate::convert::TryFrom;
use crate::mem;
+use crate::net::{Ipv4Addr, Ipv6Addr};
use crate::num::NonZeroUsize;
use crate::ops::{self, Try};
@@ -14,7 +16,7 @@ macro_rules! unsafe_impl_trusted_step {
unsafe impl TrustedStep for $type {}
)*};
}
-unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
+unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize Ipv4Addr Ipv6Addr];
/// Objects that have a notion of *successor* and *predecessor* operations.
///
@@ -484,6 +486,112 @@ impl Step for char {
}
}
+#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
+impl Step for AsciiChar {
+ #[inline]
+ fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> Option<usize> {
+ Step::steps_between(&start.to_u8(), &end.to_u8())
+ }
+
+ #[inline]
+ fn forward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
+ let end = Step::forward_checked(start.to_u8(), count)?;
+ AsciiChar::from_u8(end)
+ }
+
+ #[inline]
+ fn backward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
+ let end = Step::backward_checked(start.to_u8(), count)?;
+
+ // SAFETY: Values below that of a valid ASCII character are also valid ASCII
+ Some(unsafe { AsciiChar::from_u8_unchecked(end) })
+ }
+
+ #[inline]
+ unsafe fn forward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
+ // SAFETY: Caller asserts that result is a valid ASCII character,
+ // and therefore it is a valid u8.
+ let end = unsafe { Step::forward_unchecked(start.to_u8(), count) };
+
+ // SAFETY: Caller asserts that result is a valid ASCII character.
+ unsafe { AsciiChar::from_u8_unchecked(end) }
+ }
+
+ #[inline]
+ unsafe fn backward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
+ // SAFETY: Caller asserts that result is a valid ASCII character,
+ // and therefore it is a valid u8.
+ let end = unsafe { Step::backward_unchecked(start.to_u8(), count) };
+
+ // SAFETY: Caller asserts that result is a valid ASCII character.
+ unsafe { AsciiChar::from_u8_unchecked(end) }
+ }
+}
+
+#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
+impl Step for Ipv4Addr {
+ #[inline]
+ fn steps_between(&start: &Ipv4Addr, &end: &Ipv4Addr) -> Option<usize> {
+ u32::steps_between(&start.to_bits(), &end.to_bits())
+ }
+
+ #[inline]
+ fn forward_checked(start: Ipv4Addr, count: usize) -> Option<Ipv4Addr> {
+ u32::forward_checked(start.to_bits(), count).map(Ipv4Addr::from_bits)
+ }
+
+ #[inline]
+ fn backward_checked(start: Ipv4Addr, count: usize) -> Option<Ipv4Addr> {
+ u32::backward_checked(start.to_bits(), count).map(Ipv4Addr::from_bits)
+ }
+
+ #[inline]
+ unsafe fn forward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr {
+ // SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
+ // this is as safe as the u32 version.
+ Ipv4Addr::from_bits(unsafe { u32::forward_unchecked(start.to_bits(), count) })
+ }
+
+ #[inline]
+ unsafe fn backward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr {
+ // SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
+ // this is as safe as the u32 version.
+ Ipv4Addr::from_bits(unsafe { u32::backward_unchecked(start.to_bits(), count) })
+ }
+}
+
+#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
+impl Step for Ipv6Addr {
+ #[inline]
+ fn steps_between(&start: &Ipv6Addr, &end: &Ipv6Addr) -> Option<usize> {
+ u128::steps_between(&start.to_bits(), &end.to_bits())
+ }
+
+ #[inline]
+ fn forward_checked(start: Ipv6Addr, count: usize) -> Option<Ipv6Addr> {
+ u128::forward_checked(start.to_bits(), count).map(Ipv6Addr::from_bits)
+ }
+
+ #[inline]
+ fn backward_checked(start: Ipv6Addr, count: usize) -> Option<Ipv6Addr> {
+ u128::backward_checked(start.to_bits(), count).map(Ipv6Addr::from_bits)
+ }
+
+ #[inline]
+ unsafe fn forward_unchecked(start: Ipv6Addr, count: usize) -> Ipv6Addr {
+ // SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
+ // this is as safe as the u128 version.
+ Ipv6Addr::from_bits(unsafe { u128::forward_unchecked(start.to_bits(), count) })
+ }
+
+ #[inline]
+ unsafe fn backward_unchecked(start: Ipv6Addr, count: usize) -> Ipv6Addr {
+ // SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
+ // this is as safe as the u128 version.
+ Ipv6Addr::from_bits(unsafe { u128::backward_unchecked(start.to_bits(), count) })
+ }
+}
+
macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
@@ -723,6 +831,15 @@ impl<A: Step> Iterator for ops::Range<A> {
}
#[inline]
+ fn count(self) -> usize {
+ if self.start < self.end {
+ Step::steps_between(&self.start, &self.end).expect("count overflowed usize")
+ } else {
+ 0
+ }
+ }
+
+ #[inline]
fn nth(&mut self, n: usize) -> Option<A> {
self.spec_nth(n)
}
@@ -1120,6 +1237,17 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
}
#[inline]
+ fn count(self) -> usize {
+ if self.is_empty() {
+ return 0;
+ }
+
+ Step::steps_between(&self.start, &self.end)
+ .and_then(|steps| steps.checked_add(1))
+ .expect("count overflowed usize")
+ }
+
+ #[inline]
fn nth(&mut self, n: usize) -> Option<A> {
if self.is_empty() {
return None;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index a2729b374..8b15e8269 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -20,11 +20,19 @@
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
-//! * `memcpy`, `memcmp`, `memset`, `strlen` - These are core memory routines which are
-//! often generated by LLVM. Additionally, this library can make explicit
-//! calls to these functions. Their signatures are the same as found in C.
-//! These functions are often provided by the system libc, but can also be
-//! provided by the [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
+//! * `memcpy`, `memmove`, `memset`, `memcmp`, `bcmp`, `strlen` - These are core memory routines
+//! which are generated by Rust codegen backends. Additionally, this library can make explicit
+//! calls to `strlen`. Their signatures are the same as found in C, but there are extra
+//! assumptions about their semantics: For `memcpy`, `memmove`, `memset`, `memcmp`, and `bcmp`, if
+//! the `n` parameter is 0, the function is assumed to not be UB. Furthermore, for `memcpy`, if
+//! source and target pointer are equal, the function is assumed to not be UB.
+//! (Note that these are [standard assumptions](https://reviews.llvm.org/D86993) among compilers.)
+//! These functions are often provided by the system libc, but can also be provided by the
+//! [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
+//! Note that the library does not guarantee that it will always make these assumptions, so Rust
+//! user code directly calling the C functions should follow the C specification! The advice for
+//! Rust user code is to call the functions provided by this library instead (such as
+//! `ptr::copy`).
//!
//! * `rust_begin_panic` - This function takes four arguments, a
//! `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
@@ -96,12 +104,14 @@
#![allow(explicit_outlives_requirements)]
#![allow(incomplete_features)]
#![warn(multiple_supertrait_upcastable)]
-#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![allow(internal_features)]
// Do not check link redundancy on bootstraping phase
-#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
+#![allow(rustdoc::redundant_explicit_links)]
//
// Library features:
// tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(no_coverage))] // rust-lang/rust#84605
+#![cfg_attr(not(bootstrap), feature(coverage_attribute))] // rust-lang/rust#84605
#![feature(char_indices_offset)]
#![feature(const_align_of_val)]
#![feature(const_align_of_val_raw)]
@@ -152,12 +162,10 @@
#![feature(const_slice_from_raw_parts_mut)]
#![feature(const_slice_from_ref)]
#![feature(const_slice_index)]
-#![feature(const_slice_is_ascii)]
#![feature(const_slice_ptr_len)]
#![feature(const_slice_split_at_mut)]
#![feature(const_str_from_utf8_unchecked_mut)]
#![feature(const_swap)]
-#![feature(const_transmute_copy)]
#![feature(const_try)]
#![feature(const_type_id)]
#![feature(const_type_name)]
@@ -170,6 +178,7 @@
#![feature(ip)]
#![feature(ip_bits)]
#![feature(is_ascii_octdigit)]
+#![feature(isqrt)]
#![feature(maybe_uninit_uninit_array)]
#![feature(ptr_alignment_type)]
#![feature(ptr_metadata)]
@@ -228,7 +237,6 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(no_core)]
-#![feature(no_coverage)] // rust-lang/rust#84605
#![feature(platform_intrinsics)]
#![feature(prelude_import)]
#![feature(repr_simd)]
@@ -282,6 +290,9 @@ pub mod assert_matches {
pub use crate::macros::{assert_matches, debug_assert_matches};
}
+#[unstable(feature = "cfg_match", issue = "115585")]
+pub use crate::macros::cfg_match;
+
#[macro_use]
mod internal_macros;
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 14cc523b0..123661b35 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -168,6 +168,94 @@ pub macro assert_matches {
},
}
+/// A macro for defining `#[cfg]` match-like statements.
+///
+/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
+/// `#[cfg]` cases, emitting the implementation which matches first.
+///
+/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
+/// without having to rewrite each clause multiple times.
+///
+/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
+/// all previous declarations do not evaluate to true.
+///
+/// # Example
+///
+/// ```
+/// #![feature(cfg_match)]
+///
+/// cfg_match! {
+/// cfg(unix) => {
+/// fn foo() { /* unix specific functionality */ }
+/// }
+/// cfg(target_pointer_width = "32") => {
+/// fn foo() { /* non-unix, 32-bit functionality */ }
+/// }
+/// _ => {
+/// fn foo() { /* fallback implementation */ }
+/// }
+/// }
+/// ```
+#[unstable(feature = "cfg_match", issue = "115585")]
+#[rustc_diagnostic_item = "cfg_match"]
+pub macro cfg_match {
+ // with a final wildcard
+ (
+ $(cfg($initial_meta:meta) => { $($initial_tokens:item)* })+
+ _ => { $($extra_tokens:item)* }
+ ) => {
+ cfg_match! {
+ @__items ();
+ $((($initial_meta) ($($initial_tokens)*)),)+
+ (() ($($extra_tokens)*)),
+ }
+ },
+
+ // without a final wildcard
+ (
+ $(cfg($extra_meta:meta) => { $($extra_tokens:item)* })*
+ ) => {
+ cfg_match! {
+ @__items ();
+ $((($extra_meta) ($($extra_tokens)*)),)*
+ }
+ },
+
+ // Internal and recursive macro to emit all the items
+ //
+ // Collects all the previous cfgs in a list at the beginning, so they can be
+ // negated. After the semicolon is all the remaining items.
+ (@__items ($($_:meta,)*);) => {},
+ (
+ @__items ($($no:meta,)*);
+ (($($yes:meta)?) ($($tokens:item)*)),
+ $($rest:tt,)*
+ ) => {
+ // Emit all items within one block, applying an appropriate #[cfg]. The
+ // #[cfg] will require all `$yes` matchers specified and must also negate
+ // all previous matchers.
+ #[cfg(all(
+ $($yes,)?
+ not(any($($no),*))
+ ))]
+ cfg_match! { @__identity $($tokens)* }
+
+ // Recurse to emit all other items in `$rest`, and when we do so add all
+ // our `$yes` matchers to the list of `$no` matchers as future emissions
+ // will have to negate everything we just matched as well.
+ cfg_match! {
+ @__items ($($no,)* $($yes,)?);
+ $($rest,)*
+ }
+ },
+
+ // Internal macro to make __apply work out right for different match types,
+ // because of how macros match/expand stuff.
+ (@__identity $($tokens:item)*) => {
+ $($tokens)*
+ }
+}
+
/// Asserts that a boolean expression is `true` at runtime.
///
/// This will invoke the [`panic!`] macro if the provided expression cannot be
@@ -849,7 +937,8 @@ pub(crate) mod builtin {
/// assert_eq!(display, debug);
/// ```
///
- /// For more information, see the documentation in [`std::fmt`].
+ /// See [the formatting documentation in `std::fmt`](../std/fmt/index.html)
+ /// for details of the macro argument syntax, and further information.
///
/// [`Display`]: crate::fmt::Display
/// [`Debug`]: crate::fmt::Debug
@@ -1043,7 +1132,7 @@ pub(crate) mod builtin {
/// expression of type `&'static str` which represents all of the literals
/// concatenated left-to-right.
///
- /// Integer and floating point literals are stringified in order to be
+ /// Integer and floating point literals are [stringified](core::stringify) in order to be
/// concatenated.
///
/// # Examples
diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md
index 8b549e187..60100c265 100644
--- a/library/core/src/macros/panic.md
+++ b/library/core/src/macros/panic.md
@@ -8,8 +8,8 @@ tests. `panic!` is closely tied with the `unwrap` method of both
[`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call
`panic!` when they are set to [`None`] or [`Err`] variants.
-When using `panic!()` you can specify a string payload, that is built using
-the [`format!`] syntax. That payload is used when injecting the panic into
+When using `panic!()` you can specify a string payload that is built using
+[formatting syntax]. That payload is used when injecting the panic into
the calling Rust thread, causing the thread to panic entirely.
The behavior of the default `std` hook, i.e. the code that runs directly
@@ -18,6 +18,7 @@ after the panic is invoked, is to print the message payload to
call. You can override the panic hook using [`std::panic::set_hook()`].
Inside the hook a panic can be accessed as a `&dyn Any + Send`,
which contains either a `&str` or `String` for regular `panic!()` invocations.
+(Whether a particular invocation contains the payload at type `&str` or `String` is unspecified and can change.)
To panic with a value of another other type, [`panic_any`] can be used.
See also the macro [`compile_error!`], for raising errors during compilation.
@@ -55,7 +56,7 @@ For more detailed information about error handling check out the [book] or the
[`panic_any`]: ../std/panic/fn.panic_any.html
[`Box`]: ../std/boxed/struct.Box.html
[`Any`]: crate::any::Any
-[`format!`]: ../std/macro.format.html
+[`format!` syntax]: ../std/fmt/index.html
[book]: ../book/ch09-00-error-handling.html
[`std::result`]: ../std/result/index.html
@@ -64,6 +65,29 @@ For more detailed information about error handling check out the [book] or the
If the main thread panics it will terminate all your threads and end your
program with code `101`.
+# Editions
+
+Behavior of the panic macros changed over editions.
+
+## 2021 and later
+
+In Rust 2021 and later, `panic!` always requires a format string and
+the applicable format arguments, and is the same in `core` and `std`.
+Use [`std::panic::panic_any(x)`](../std/panic/fn.panic_any.html) to
+panic with an arbitrary payload.
+
+## 2018 and 2015
+
+In Rust Editions prior to 2021, `std::panic!(x)` with a single
+argument directly uses that argument as a payload.
+This is true even if the argument is a string literal.
+For example, `panic!("problem: {reason}")` panics with a
+payload of literally `"problem: {reason}"` (a `&'static str`).
+
+`core::panic!(x)` with a single argument requires that `x` be `&str`,
+but otherwise behaves like `std::panic!`. In particular, the string
+need not be a literal, and is not interpreted as a format string.
+
# Examples
```should_panic
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 5ec751e51..5ed82e26a 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -986,11 +986,16 @@ pub trait Tuple {}
pub trait PointerLike {}
/// A marker for types which can be used as types of `const` generic parameters.
+///
+/// These types must have a proper equivalence relation (`Eq`) and it must be automatically
+/// derived (`StructuralPartialEq`). There's a hard-coded check in the compiler ensuring
+/// that all fields are also `ConstParamTy`, which implies that recursively, all fields
+/// are `StructuralPartialEq`.
#[lang = "const_param_ty"]
#[unstable(feature = "adt_const_params", issue = "95174")]
#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
#[allow(multiple_supertrait_upcastable)]
-pub trait ConstParamTy: StructuralEq + StructuralPartialEq {}
+pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {}
/// Derive macro generating an impl of the trait `ConstParamTy`.
#[rustc_builtin_macro]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 2fff3f0ef..e478b217f 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -413,7 +413,7 @@ pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(note = "use `align_of` instead", since = "1.2.0")]
+#[deprecated(note = "use `align_of` instead", since = "1.2.0", suggestion = "align_of")]
pub fn min_align_of<T>() -> usize {
intrinsics::min_align_of::<T>()
}
@@ -436,7 +436,7 @@ pub fn min_align_of<T>() -> usize {
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(note = "use `align_of_val` instead", since = "1.2.0")]
+#[deprecated(note = "use `align_of_val` instead", since = "1.2.0", suggestion = "align_of_val")]
pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
// SAFETY: val is a reference, so it's a valid raw pointer
unsafe { intrinsics::min_align_of_val(val) }
@@ -1051,7 +1051,7 @@ pub const fn copy<T: Copy>(x: &T) -> T {
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
+#[rustc_const_stable(feature = "const_transmute_copy", since = "1.74.0")]
pub const unsafe fn transmute_copy<Src, Dst>(src: &Src) -> Dst {
assert!(
size_of::<Src>() >= size_of::<Dst>(),
@@ -1126,6 +1126,13 @@ impl<T> fmt::Debug for Discriminant<T> {
///
/// [Reference]: ../../reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations
///
+/// The value of a [`Discriminant<T>`] is independent of any *free lifetimes* in `T`. As such,
+/// reading or writing a `Discriminant<Foo<'a>>` as a `Discriminant<Foo<'b>>` (whether via
+/// [`transmute`] or otherwise) is always sound. Note that this is **not** true for other kinds
+/// of generic parameters and for higher-ranked lifetimes; `Discriminant<Foo<A>>` and
+/// `Discriminant<Foo<B>>` as well as `Discriminant<Bar<dyn for<'a> Trait<'a>>>` and
+/// `Discriminant<Bar<dyn Trait<'static>>>` may be incompatible.
+///
/// # Examples
///
/// This can be used to compare enums that carry data, while disregarding
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index 56460c75e..6a36dfec0 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1856,13 +1856,7 @@ impl fmt::Display for Ipv6Addr {
if f.precision().is_none() && f.width().is_none() {
let segments = self.segments();
- // Special case for :: and ::1; otherwise they get written with the
- // IPv4 formatter
- if self.is_unspecified() {
- f.write_str("::")
- } else if self.is_loopback() {
- f.write_str("::1")
- } else if let Some(ipv4) = self.to_ipv4_mapped() {
+ if let Some(ipv4) = self.to_ipv4_mapped() {
write!(f, "::ffff:{}", ipv4)
} else {
#[derive(Copy, Clone, Default)]
diff --git a/library/core/src/num/dec2flt/fpu.rs b/library/core/src/num/dec2flt/fpu.rs
index 3806977f7..8d62684f8 100644
--- a/library/core/src/num/dec2flt/fpu.rs
+++ b/library/core/src/num/dec2flt/fpu.rs
@@ -8,6 +8,17 @@ pub use fpu_precision::set_precision;
// round to 80 bits causing double rounding to happen when values are eventually represented as
// 32/64 bit float values. To overcome this, the FPU control word can be set so that the
// computations are performed in the desired precision.
+//
+// Note that normally, it is Undefined Behavior to alter the FPU control word while Rust code runs.
+// The compiler assumes that the control word is always in its default state. However, in this
+// particular case the semantics with the altered control word are actually *more faithful*
+// to Rust semantics than the default -- arguably it is all the code that runs *outside* of the scope
+// of a `set_precision` guard that is wrong.
+// In other words, we are only using this to work around <https://github.com/rust-lang/rust/issues/114479>.
+// Sometimes killing UB with UB actually works...
+// (If this is used to set 32bit precision, there is still a risk that the compiler moves some 64bit
+// operation into the scope of the `set_precision` guard. So it's not like this is totally sound.
+// But it's not really any less sound than the default state of 80bit precision...)
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
mod fpu_precision {
use core::arch::asm;
diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs
index 8589e2bbd..253899156 100644
--- a/library/core/src/num/dec2flt/number.rs
+++ b/library/core/src/num/dec2flt/number.rs
@@ -51,6 +51,7 @@ impl Number {
/// There is an exception: disguised fast-path cases, where we can shift
/// powers-of-10 from the exponent to the significant digits.
pub fn try_fast_path<F: RawFloat>(&self) -> Option<F> {
+ // Here we need to work around <https://github.com/rust-lang/rust/issues/114479>.
// The fast path crucially depends on arithmetic being rounded to the correct number of bits
// without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
// of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit.
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index d050d21c8..290f649f9 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -277,6 +277,14 @@ pub mod consts {
#[stable(feature = "tau_constant", since = "1.47.0")]
pub const TAU: f32 = 6.28318530717958647692528676655900577_f32;
+ /// The golden ratio (φ)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const PHI: f32 = 1.618033988749894848204586834365638118_f32;
+
+ /// The Euler-Mascheroni constant (γ)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const EGAMMA: f32 = 0.577215664901532860606512090082402431_f32;
+
/// π/2
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
@@ -301,6 +309,10 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
+ /// 1/sqrt(π)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const FRAC_1_SQRT_PI: f32 = 0.564189583547756286948079451560772586_f32;
+
/// 2/π
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
@@ -317,6 +329,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32;
+ /// sqrt(3)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const SQRT_3: f32 = 1.732050807568877293527446341505872367_f32;
+
+ /// 1/sqrt(3)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const FRAC_1_SQRT_3: f32 = 0.577350269189625764509148780501957456_f32;
+
/// Euler's number (e)
#[stable(feature = "rust1", since = "1.0.0")]
pub const E: f32 = 2.71828182845904523536028747135266250_f32;
@@ -937,6 +957,7 @@ impl f32 {
} else if self == other {
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
} else {
+ // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
self + other
}
}
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index d9a738191..7569d2cd6 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -277,6 +277,14 @@ pub mod consts {
#[stable(feature = "tau_constant", since = "1.47.0")]
pub const TAU: f64 = 6.28318530717958647692528676655900577_f64;
+ /// The golden ratio (φ)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const PHI: f64 = 1.618033988749894848204586834365638118_f64;
+
+ /// The Euler-Mascheroni constant (γ)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const EGAMMA: f64 = 0.577215664901532860606512090082402431_f64;
+
/// π/2
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64;
@@ -301,6 +309,10 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64;
+ /// 1/sqrt(π)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const FRAC_1_SQRT_PI: f64 = 0.564189583547756286948079451560772586_f64;
+
/// 2/π
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64;
@@ -317,6 +329,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64;
+ /// sqrt(3)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const SQRT_3: f64 = 1.732050807568877293527446341505872367_f64;
+
+ /// 1/sqrt(3)
+ #[unstable(feature = "more_float_constants", issue = "103883")]
+ pub const FRAC_1_SQRT_3: f64 = 0.577350269189625764509148780501957456_f64;
+
/// Euler's number (e)
#[stable(feature = "rust1", since = "1.0.0")]
pub const E: f64 = 2.71828182845904523536028747135266250_f64;
@@ -948,6 +968,7 @@ impl f64 {
} else if self == other {
if self.is_sign_negative() && other.is_sign_positive() { self } else { other }
} else {
+ // At least one input is NaN. Use `+` to perform NaN propagation and quieting.
self + other
}
}
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 1f43520e1..3cbb55af3 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -898,6 +898,30 @@ macro_rules! int_impl {
acc.checked_mul(base)
}
+ /// Returns the square root of the number, rounded down.
+ ///
+ /// Returns `None` if `self` is negative.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ /// ```
+ /// #![feature(isqrt)]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_isqrt(), Some(3));")]
+ /// ```
+ #[unstable(feature = "isqrt", issue = "116226")]
+ #[rustc_const_unstable(feature = "isqrt", issue = "116226")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn checked_isqrt(self) -> Option<Self> {
+ if self < 0 {
+ None
+ } else {
+ Some((self as $UnsignedT).isqrt() as Self)
+ }
+ }
+
/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
/// bounds instead of overflowing.
///
@@ -2061,6 +2085,36 @@ macro_rules! int_impl {
acc * base
}
+ /// Returns the square root of the number, rounded down.
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if `self` is negative.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ /// ```
+ /// #![feature(isqrt)]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")]
+ /// ```
+ #[unstable(feature = "isqrt", issue = "116226")]
+ #[rustc_const_unstable(feature = "isqrt", issue = "116226")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn isqrt(self) -> Self {
+ // I would like to implement it as
+ // ```
+ // self.checked_isqrt().expect("argument of integer square root must be non-negative")
+ // ```
+ // but `expect` is not yet stable as a `const fn`.
+ match self.checked_isqrt() {
+ Some(sqrt) => sqrt,
+ None => panic!("argument of integer square root must be non-negative"),
+ }
+ }
+
/// Calculates the quotient of Euclidean division of `self` by `rhs`.
///
/// This computes the integer `q` such that `self = q * rhs + r`, with
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 95dcaf5dd..8b127132c 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -44,11 +44,10 @@ mod uint_macros; // import uint_impl!
mod error;
mod int_log10;
mod nonzero;
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
mod saturating;
mod wrapping;
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub use saturating::Saturating;
#[stable(feature = "rust1", since = "1.0.0")]
pub use wrapping::Wrapping;
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 5939dedbd..7f8d673c1 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -41,6 +41,20 @@ macro_rules! nonzero_integers {
/// with the exception that `0` is not a valid instance.
#[doc = concat!("`Option<", stringify!($Ty), ">` is guaranteed to be compatible with `", stringify!($Int), "`,")]
/// including in FFI.
+ ///
+ /// Thanks to the [null pointer optimization],
+ #[doc = concat!("`", stringify!($Ty), "` and `Option<", stringify!($Ty), ">`")]
+ /// are guaranteed to have the same size and alignment:
+ ///
+ /// ```
+ /// # use std::mem::{size_of, align_of};
+ #[doc = concat!("use std::num::", stringify!($Ty), ";")]
+ ///
+ #[doc = concat!("assert_eq!(size_of::<", stringify!($Ty), ">(), size_of::<Option<", stringify!($Ty), ">>());")]
+ #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::<Option<", stringify!($Ty), ">>());")]
+ /// ```
+ ///
+ /// [null pointer optimization]: crate::option#representation
#[$stability]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs
index 8982473b2..d9ccc73c4 100644
--- a/library/core/src/num/saturating.rs
+++ b/library/core/src/num/saturating.rs
@@ -4,7 +4,7 @@ use crate::fmt;
use crate::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign};
use crate::ops::{BitXor, BitXorAssign, Div, DivAssign};
use crate::ops::{Mul, MulAssign, Neg, Not, Rem, RemAssign};
-use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
+use crate::ops::{Sub, SubAssign};
/// Provides intentionally-saturating arithmetic on `T`.
///
@@ -24,7 +24,6 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
/// # Examples
///
/// ```
-/// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
/// let max = Saturating(u32::MAX);
@@ -32,180 +31,186 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
///
/// assert_eq!(u32::MAX, (max + one).0);
/// ```
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
#[repr(transparent)]
-pub struct Saturating<T>(#[unstable(feature = "saturating_int_impl", issue = "87920")] pub T);
+#[rustc_diagnostic_item = "Saturating"]
+pub struct Saturating<T>(
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] pub T,
+);
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl<T: fmt::Debug> fmt::Debug for Saturating<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl<T: fmt::Display> fmt::Display for Saturating<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl<T: fmt::Binary> fmt::Binary for Saturating<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl<T: fmt::Octal> fmt::Octal for Saturating<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl<T: fmt::LowerHex> fmt::LowerHex for Saturating<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
-#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl<T: fmt::UpperHex> fmt::UpperHex for Saturating<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
-#[allow(unused_macros)]
-macro_rules! sh_impl_signed {
- ($t:ident, $f:ident) => {
- // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065
- //
- // #[unstable(feature = "saturating_int_impl", issue = "87920")]
- // impl Shl<$f> for Saturating<$t> {
- // type Output = Saturating<$t>;
- //
- // #[inline]
- // fn shl(self, other: $f) -> Saturating<$t> {
- // if other < 0 {
- // Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32))
- // } else {
- // Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32))
- // }
- // }
- // }
- // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
- // #[unstable(feature = "saturating_int_impl", issue = "87920")] }
- //
- // #[unstable(feature = "saturating_int_impl", issue = "87920")]
- // impl ShlAssign<$f> for Saturating<$t> {
- // #[inline]
- // fn shl_assign(&mut self, other: $f) {
- // *self = *self << other;
- // }
- // }
- // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
-
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- impl Shr<$f> for Saturating<$t> {
- type Output = Saturating<$t>;
-
- #[inline]
- fn shr(self, other: $f) -> Saturating<$t> {
- if other < 0 {
- Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32))
- } else {
- Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32))
- }
- }
- }
- forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
-
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- impl ShrAssign<$f> for Saturating<$t> {
- #[inline]
- fn shr_assign(&mut self, other: $f) {
- *self = *self >> other;
- }
- }
- forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
- };
-}
-
-macro_rules! sh_impl_unsigned {
- ($t:ident, $f:ident) => {
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- impl Shl<$f> for Saturating<$t> {
- type Output = Saturating<$t>;
-
- #[inline]
- fn shl(self, other: $f) -> Saturating<$t> {
- Saturating(self.0.wrapping_shl(other as u32))
- }
- }
- forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
-
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- impl ShlAssign<$f> for Saturating<$t> {
- #[inline]
- fn shl_assign(&mut self, other: $f) {
- *self = *self << other;
- }
- }
- forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
-
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- impl Shr<$f> for Saturating<$t> {
- type Output = Saturating<$t>;
-
- #[inline]
- fn shr(self, other: $f) -> Saturating<$t> {
- Saturating(self.0.wrapping_shr(other as u32))
- }
- }
- forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- impl ShrAssign<$f> for Saturating<$t> {
- #[inline]
- fn shr_assign(&mut self, other: $f) {
- *self = *self >> other;
- }
- }
- forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
- };
-}
-
-// FIXME (#23545): uncomment the remaining impls
-macro_rules! sh_impl_all {
- ($($t:ident)*) => ($(
- //sh_impl_unsigned! { $t, u8 }
- //sh_impl_unsigned! { $t, u16 }
- //sh_impl_unsigned! { $t, u32 }
- //sh_impl_unsigned! { $t, u64 }
- //sh_impl_unsigned! { $t, u128 }
- sh_impl_unsigned! { $t, usize }
-
- //sh_impl_signed! { $t, i8 }
- //sh_impl_signed! { $t, i16 }
- //sh_impl_signed! { $t, i32 }
- //sh_impl_signed! { $t, i64 }
- //sh_impl_signed! { $t, i128 }
- //sh_impl_signed! { $t, isize }
- )*)
-}
-
-sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
+// FIXME the correct implementation is not clear. Waiting for a real world use case at https://github.com/rust-lang/libs-team/issues/230
+//
+// #[allow(unused_macros)]
+// macro_rules! sh_impl_signed {
+// ($t:ident, $f:ident) => {
+// // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065
+// //
+// // #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// // impl Shl<$f> for Saturating<$t> {
+// // type Output = Saturating<$t>;
+// //
+// // #[inline]
+// // fn shl(self, other: $f) -> Saturating<$t> {
+// // if other < 0 {
+// // Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32))
+// // } else {
+// // Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32))
+// // }
+// // }
+// // }
+// // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
+// // #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+// //
+// // #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// // impl ShlAssign<$f> for Saturating<$t> {
+// // #[inline]
+// // fn shl_assign(&mut self, other: $f) {
+// // *self = *self << other;
+// // }
+// // }
+// // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
+//
+// #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// impl Shr<$f> for Saturating<$t> {
+// type Output = Saturating<$t>;
+//
+// #[inline]
+// fn shr(self, other: $f) -> Saturating<$t> {
+// if other < 0 {
+// Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32))
+// } else {
+// Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32))
+// }
+// }
+// }
+// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
+// #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+//
+// #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// impl ShrAssign<$f> for Saturating<$t> {
+// #[inline]
+// fn shr_assign(&mut self, other: $f) {
+// *self = *self >> other;
+// }
+// }
+// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
+// };
+// }
+//
+// macro_rules! sh_impl_unsigned {
+// ($t:ident, $f:ident) => {
+// #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// impl Shl<$f> for Saturating<$t> {
+// type Output = Saturating<$t>;
+//
+// #[inline]
+// fn shl(self, other: $f) -> Saturating<$t> {
+// Saturating(self.0.wrapping_shl(other as u32))
+// }
+// }
+// forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
+// #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+//
+// #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// impl ShlAssign<$f> for Saturating<$t> {
+// #[inline]
+// fn shl_assign(&mut self, other: $f) {
+// *self = *self << other;
+// }
+// }
+// forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
+//
+// #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// impl Shr<$f> for Saturating<$t> {
+// type Output = Saturating<$t>;
+//
+// #[inline]
+// fn shr(self, other: $f) -> Saturating<$t> {
+// Saturating(self.0.wrapping_shr(other as u32))
+// }
+// }
+// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
+// #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+//
+// #[unstable(feature = "saturating_int_impl", issue = "87920")]
+// impl ShrAssign<$f> for Saturating<$t> {
+// #[inline]
+// fn shr_assign(&mut self, other: $f) {
+// *self = *self >> other;
+// }
+// }
+// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
+// };
+// }
+//
+// // FIXME (#23545): uncomment the remaining impls
+// macro_rules! sh_impl_all {
+// ($($t:ident)*) => ($(
+// //sh_impl_unsigned! { $t, u8 }
+// //sh_impl_unsigned! { $t, u16 }
+// //sh_impl_unsigned! { $t, u32 }
+// //sh_impl_unsigned! { $t, u64 }
+// //sh_impl_unsigned! { $t, u128 }
+// sh_impl_unsigned! { $t, usize }
+//
+// //sh_impl_signed! { $t, i8 }
+// //sh_impl_signed! { $t, i16 }
+// //sh_impl_signed! { $t, i32 }
+// //sh_impl_signed! { $t, i64 }
+// //sh_impl_signed! { $t, i128 }
+// //sh_impl_signed! { $t, isize }
+// )*)
+// }
+//
+// sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
// FIXME(30524): impl Op<T> for Saturating<T>, impl OpAssign<T> for Saturating<T>
macro_rules! saturating_impl {
($($t:ty)*) => ($(
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl Add for Saturating<$t> {
type Output = Saturating<$t>;
@@ -215,9 +220,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl AddAssign for Saturating<$t> {
#[inline]
fn add_assign(&mut self, other: Saturating<$t>) {
@@ -226,7 +231,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl AddAssign<$t> for Saturating<$t> {
#[inline]
fn add_assign(&mut self, other: $t) {
@@ -235,7 +240,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl Sub for Saturating<$t> {
type Output = Saturating<$t>;
@@ -245,9 +250,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl SubAssign for Saturating<$t> {
#[inline]
fn sub_assign(&mut self, other: Saturating<$t>) {
@@ -256,7 +261,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl SubAssign<$t> for Saturating<$t> {
#[inline]
fn sub_assign(&mut self, other: $t) {
@@ -265,7 +270,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl Mul for Saturating<$t> {
type Output = Saturating<$t>;
@@ -275,9 +280,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl MulAssign for Saturating<$t> {
#[inline]
fn mul_assign(&mut self, other: Saturating<$t>) {
@@ -286,7 +291,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl MulAssign<$t> for Saturating<$t> {
#[inline]
fn mul_assign(&mut self, other: $t) {
@@ -300,7 +305,6 @@ macro_rules! saturating_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / Saturating(2));")]
@@ -309,12 +313,11 @@ macro_rules! saturating_impl {
/// ```
///
/// ```should_panic
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")]
/// ```
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl Div for Saturating<$t> {
type Output = Saturating<$t>;
@@ -324,10 +327,10 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl DivAssign for Saturating<$t> {
#[inline]
fn div_assign(&mut self, other: Saturating<$t>) {
@@ -336,7 +339,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl DivAssign<$t> for Saturating<$t> {
#[inline]
fn div_assign(&mut self, other: $t) {
@@ -345,7 +348,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl Rem for Saturating<$t> {
type Output = Saturating<$t>;
@@ -355,9 +358,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl RemAssign for Saturating<$t> {
#[inline]
fn rem_assign(&mut self, other: Saturating<$t>) {
@@ -366,7 +369,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl RemAssign<$t> for Saturating<$t> {
#[inline]
fn rem_assign(&mut self, other: $t) {
@@ -375,7 +378,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl Not for Saturating<$t> {
type Output = Saturating<$t>;
@@ -385,9 +388,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_unop! { impl Not, not for Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl BitXor for Saturating<$t> {
type Output = Saturating<$t>;
@@ -397,9 +400,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl BitXorAssign for Saturating<$t> {
#[inline]
fn bitxor_assign(&mut self, other: Saturating<$t>) {
@@ -408,7 +411,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl BitXorAssign<$t> for Saturating<$t> {
#[inline]
fn bitxor_assign(&mut self, other: $t) {
@@ -417,7 +420,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl BitOr for Saturating<$t> {
type Output = Saturating<$t>;
@@ -427,9 +430,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl BitOrAssign for Saturating<$t> {
#[inline]
fn bitor_assign(&mut self, other: Saturating<$t>) {
@@ -438,7 +441,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl BitOrAssign<$t> for Saturating<$t> {
#[inline]
fn bitor_assign(&mut self, other: $t) {
@@ -447,7 +450,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl BitAnd for Saturating<$t> {
type Output = Saturating<$t>;
@@ -457,9 +460,9 @@ macro_rules! saturating_impl {
}
}
forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl BitAndAssign for Saturating<$t> {
#[inline]
fn bitand_assign(&mut self, other: Saturating<$t>) {
@@ -468,7 +471,7 @@ macro_rules! saturating_impl {
}
forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t> }
- #[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
+ #[stable(feature = "saturating_int_assign_impl", since = "1.74.0")]
impl BitAndAssign<$t> for Saturating<$t> {
#[inline]
fn bitand_assign(&mut self, other: $t) {
@@ -492,12 +495,11 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MIN, Saturating(", stringify!($t), "::MIN));")]
/// ```
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const MIN: Self = Self(<$t>::MIN);
/// Returns the largest value that can be represented by this integer type.
@@ -507,12 +509,11 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MAX, Saturating(", stringify!($t), "::MAX));")]
/// ```
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const MAX: Self = Self(<$t>::MAX);
/// Returns the size of this integer type in bits.
@@ -522,12 +523,11 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::BITS, ", stringify!($t), "::BITS);")]
/// ```
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const BITS: u32 = <$t>::BITS;
/// Returns the number of ones in the binary representation of `self`.
@@ -537,7 +537,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(0b01001100", stringify!($t), ");")]
@@ -549,7 +548,8 @@ macro_rules! saturating_int_impl {
#[doc(alias = "popcnt")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn count_ones(self) -> u32 {
self.0.count_ones()
}
@@ -561,7 +561,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(Saturating(!0", stringify!($t), ").count_zeros(), 0);")]
@@ -569,7 +568,8 @@ macro_rules! saturating_int_impl {
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn count_zeros(self) -> u32 {
self.0.count_zeros()
}
@@ -581,7 +581,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(0b0101000", stringify!($t), ");")]
@@ -591,7 +590,8 @@ macro_rules! saturating_int_impl {
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn trailing_zeros(self) -> u32 {
self.0.trailing_zeros()
}
@@ -608,7 +608,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
/// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
@@ -619,7 +618,8 @@ macro_rules! saturating_int_impl {
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn rotate_left(self, n: u32) -> Self {
Saturating(self.0.rotate_left(n))
}
@@ -636,7 +636,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
/// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
@@ -647,7 +646,8 @@ macro_rules! saturating_int_impl {
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn rotate_right(self, n: u32) -> Self {
Saturating(self.0.rotate_right(n))
}
@@ -659,7 +659,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
/// let n: Saturating<i16> = Saturating(0b0000000_01010101);
@@ -673,7 +672,8 @@ macro_rules! saturating_int_impl {
#[inline]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn swap_bytes(self) -> Self {
Saturating(self.0.swap_bytes())
}
@@ -688,7 +688,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
/// let n = Saturating(0b0000000_01010101i16);
@@ -700,8 +699,8 @@ macro_rules! saturating_int_impl {
/// assert_eq!(m, Saturating(-22016));
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- #[rustc_const_unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn reverse_bits(self) -> Self {
@@ -718,7 +717,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
@@ -731,7 +729,8 @@ macro_rules! saturating_int_impl {
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn from_be(x: Self) -> Self {
Saturating(<$t>::from_be(x.0))
}
@@ -746,7 +745,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
@@ -759,7 +757,8 @@ macro_rules! saturating_int_impl {
/// ```
#[inline]
#[must_use]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn from_le(x: Self) -> Self {
Saturating(<$t>::from_le(x.0))
}
@@ -774,7 +773,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
@@ -786,7 +784,8 @@ macro_rules! saturating_int_impl {
/// }
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn to_be(self) -> Self {
@@ -803,7 +802,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
@@ -815,7 +813,8 @@ macro_rules! saturating_int_impl {
/// }
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn to_le(self) -> Self {
@@ -829,7 +828,6 @@ macro_rules! saturating_int_impl {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(Saturating(3", stringify!($t), ").pow(4), Saturating(81));")]
@@ -838,17 +836,17 @@ macro_rules! saturating_int_impl {
/// Results that are too large are saturated:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
/// assert_eq!(Saturating(3i8).pow(5), Saturating(127));
/// assert_eq!(Saturating(3i8).pow(6), Saturating(127));
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- pub fn pow(self, exp: u32) -> Self {
+ pub const fn pow(self, exp: u32) -> Self {
Saturating(self.0.saturating_pow(exp))
}
}
@@ -867,7 +865,6 @@ macro_rules! saturating_int_impl_signed {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
@@ -875,7 +872,8 @@ macro_rules! saturating_int_impl_signed {
/// assert_eq!(n.leading_zeros(), 3);
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn leading_zeros(self) -> u32 {
@@ -890,7 +888,6 @@ macro_rules! saturating_int_impl_signed {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(Saturating(100", stringify!($t), ").abs(), Saturating(100));")]
@@ -900,10 +897,11 @@ macro_rules! saturating_int_impl_signed {
#[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MAX));")]
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- pub fn abs(self) -> Saturating<$t> {
+ pub const fn abs(self) -> Saturating<$t> {
Saturating(self.0.saturating_abs())
}
@@ -918,7 +916,6 @@ macro_rules! saturating_int_impl_signed {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert_eq!(Saturating(10", stringify!($t), ").signum(), Saturating(1));")]
@@ -926,10 +923,11 @@ macro_rules! saturating_int_impl_signed {
#[doc = concat!("assert_eq!(Saturating(-10", stringify!($t), ").signum(), Saturating(-1));")]
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
- pub fn signum(self) -> Saturating<$t> {
+ pub const fn signum(self) -> Saturating<$t> {
Saturating(self.0.signum())
}
@@ -941,7 +939,6 @@ macro_rules! saturating_int_impl_signed {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert!(Saturating(10", stringify!($t), ").is_positive());")]
@@ -949,7 +946,8 @@ macro_rules! saturating_int_impl_signed {
/// ```
#[must_use]
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn is_positive(self) -> bool {
self.0.is_positive()
}
@@ -962,7 +960,6 @@ macro_rules! saturating_int_impl_signed {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert!(Saturating(-10", stringify!($t), ").is_negative());")]
@@ -970,13 +967,14 @@ macro_rules! saturating_int_impl_signed {
/// ```
#[must_use]
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
pub const fn is_negative(self) -> bool {
self.0.is_negative()
}
}
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
impl Neg for Saturating<$t> {
type Output = Self;
#[inline]
@@ -985,7 +983,7 @@ macro_rules! saturating_int_impl_signed {
}
}
forward_ref_unop! { impl Neg, neg for Saturating<$t>,
- #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")] }
)*)
}
@@ -1001,7 +999,6 @@ macro_rules! saturating_int_impl_unsigned {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
@@ -1009,7 +1006,8 @@ macro_rules! saturating_int_impl_unsigned {
/// assert_eq!(n.leading_zeros(), 2);
/// ```
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
pub const fn leading_zeros(self) -> u32 {
@@ -1023,7 +1021,6 @@ macro_rules! saturating_int_impl_unsigned {
/// Basic usage:
///
/// ```
- /// #![feature(saturating_int_impl)]
/// use std::num::Saturating;
///
#[doc = concat!("assert!(Saturating(16", stringify!($t), ").is_power_of_two());")]
@@ -1031,8 +1028,9 @@ macro_rules! saturating_int_impl_unsigned {
/// ```
#[must_use]
#[inline]
- #[unstable(feature = "saturating_int_impl", issue = "87920")]
- pub fn is_power_of_two(self) -> bool {
+ #[rustc_const_stable(feature = "saturating_int_impl", since = "1.74.0")]
+ #[stable(feature = "saturating_int_impl", since = "1.74.0")]
+ pub const fn is_power_of_two(self) -> bool {
self.0.is_power_of_two()
}
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 23ca37817..a9c5312a1 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1259,6 +1259,10 @@ macro_rules! uint_impl {
/// This function exists, so that all operations
/// are accounted for in the wrapping operations.
///
+ /// # Panics
+ ///
+ /// This function will panic if `rhs` is 0.
+ ///
/// # Examples
///
/// Basic usage:
@@ -1284,6 +1288,10 @@ macro_rules! uint_impl {
/// definitions of division are equal, this
/// is exactly equal to `self.wrapping_div(rhs)`.
///
+ /// # Panics
+ ///
+ /// This function will panic if `rhs` is 0.
+ ///
/// # Examples
///
/// Basic usage:
@@ -1307,6 +1315,10 @@ macro_rules! uint_impl {
/// This function exists, so that all operations
/// are accounted for in the wrapping operations.
///
+ /// # Panics
+ ///
+ /// This function will panic if `rhs` is 0.
+ ///
/// # Examples
///
/// Basic usage:
@@ -1333,6 +1345,10 @@ macro_rules! uint_impl {
/// definitions of division are equal, this
/// is exactly equal to `self.wrapping_rem(rhs)`.
///
+ /// # Panics
+ ///
+ /// This function will panic if `rhs` is 0.
+ ///
/// # Examples
///
/// Basic usage:
@@ -1979,6 +1995,54 @@ macro_rules! uint_impl {
acc * base
}
+ /// Returns the square root of the number, rounded down.
+ ///
+ /// # Examples
+ ///
+ /// Basic usage:
+ /// ```
+ /// #![feature(isqrt)]
+ #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".isqrt(), 3);")]
+ /// ```
+ #[unstable(feature = "isqrt", issue = "116226")]
+ #[rustc_const_unstable(feature = "isqrt", issue = "116226")]
+ #[must_use = "this returns the result of the operation, \
+ without modifying the original"]
+ #[inline]
+ pub const fn isqrt(self) -> Self {
+ if self < 2 {
+ return self;
+ }
+
+ // The algorithm is based on the one presented in
+ // <https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_(base_2)>
+ // which cites as source the following C code:
+ // <https://web.archive.org/web/20120306040058/http://medialab.freaknet.org/martin/src/sqrt/sqrt.c>.
+
+ let mut op = self;
+ let mut res = 0;
+ let mut one = 1 << (self.ilog2() & !1);
+
+ while one != 0 {
+ if op >= res + one {
+ op -= res + one;
+ res = (res >> 1) + one;
+ } else {
+ res >>= 1;
+ }
+ one >>= 2;
+ }
+
+ // SAFETY: the result is positive and fits in an integer with half as many bits.
+ // Inform the optimizer about it.
+ unsafe {
+ intrinsics::assume(0 < res);
+ intrinsics::assume(res < 1 << (Self::BITS / 2));
+ }
+
+ res
+ }
+
/// Performs Euclidean division.
///
/// Since, for the positive integers, all common
diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs
index ed354a2e5..16f0b6d91 100644
--- a/library/core/src/num/wrapping.rs
+++ b/library/core/src/num/wrapping.rs
@@ -39,6 +39,7 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
#[repr(transparent)]
+#[rustc_diagnostic_item = "Wrapping"]
pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 08c35b6da..911761c6e 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -14,6 +14,11 @@
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
+/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
+/// specified, but users of the trait must ensure that such logic errors do *not* result in
+/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
+/// method.
+///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
@@ -114,6 +119,11 @@ impl<T: ?Sized> Deref for &mut T {
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
+/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
+/// specified, but users of the trait must ensure that such logic errors do *not* result in
+/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
+/// method.
+///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index 9ebf426be..34dfa9e4c 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -202,7 +202,7 @@
/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle
#[lang = "drop"]
#[stable(feature = "rust1", since = "1.0.0")]
-#[const_trait]
+// FIXME(effects) #[const_trait]
pub trait Drop {
/// Executes the destructor for this type.
///
@@ -217,8 +217,13 @@ pub trait Drop {
///
/// # Panics
///
- /// Given that a [`panic!`] will call `drop` as it unwinds, any [`panic!`]
- /// in a `drop` implementation will likely abort.
+ /// Implementations should generally avoid [`panic!`]ing, because `drop()` may itself be called
+ /// during unwinding due to a panic, and if the `drop()` panics in that situation (a “double
+ /// panic”), this will likely abort the program. It is possible to check [`panicking()`] first,
+ /// which may be desirable for a `Drop` implementation that is reporting a bug of the kind
+ /// “you didn't finish using this before it was dropped”; but most types should simply clean up
+ /// their owned allocations or other resources and return normally from `drop()`, regardless of
+ /// what state they are in.
///
/// Note that even if this panics, the value is considered to be dropped;
/// you must not cause `drop` to be called again. This is normally automatically
@@ -227,6 +232,7 @@ pub trait Drop {
///
/// [E0040]: ../../error_codes/E0040.html
/// [`panic!`]: crate::panic!
+ /// [`panicking()`]: ../../std/thread/fn.panicking.html
/// [`mem::drop`]: drop
/// [`ptr::drop_in_place`]: crate::ptr::drop_in_place
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index 67c8245f0..20f0bba4c 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -72,7 +72,7 @@ use crate::marker::Tuple;
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
-#[const_trait]
+// FIXME(effects) #[const_trait]
pub trait Fn<Args: Tuple>: FnMut<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -159,7 +159,7 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
-#[const_trait]
+// FIXME(effects) #[const_trait]
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -238,7 +238,7 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
-#[const_trait]
+// FIXME(effects) #[const_trait]
pub trait FnOnce<Args: Tuple> {
/// The returned type after the call operator is used.
#[lang = "fn_once_output"]
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index ba5e6ddc7..cc596293c 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -11,7 +11,7 @@ use crate::hash::Hash;
/// The `..` syntax is a `RangeFull`:
///
/// ```
-/// assert_eq!((..), std::ops::RangeFull);
+/// assert_eq!(.., std::ops::RangeFull);
/// ```
///
/// It does not have an [`IntoIterator`] implementation, so you can't use it in
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index becb63309..f2909a81d 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -119,7 +119,7 @@
//! # Representation
//!
//! Rust guarantees to optimize the following types `T` such that
-//! [`Option<T>`] has the same size as `T`:
+//! [`Option<T>`] has the same size and alignment as `T`:
//!
//! * [`Box<U>`]
//! * `&U`
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 20be60d35..386f5fcbd 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -99,7 +99,7 @@ pub macro unreachable_2021 {
/// use.
#[unstable(feature = "std_internals", issue = "none")]
#[doc(hidden)]
-pub unsafe trait BoxMeUp {
+pub unsafe trait PanicPayload {
/// Take full ownership of the contents.
/// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core.
///
@@ -107,7 +107,7 @@ pub unsafe trait BoxMeUp {
/// Calling this method twice, or calling `get` after calling this method, is an error.
///
/// The argument is borrowed because the panic runtime (`__rust_start_panic`) only
- /// gets a borrowed `dyn BoxMeUp`.
+ /// gets a borrowed `dyn PanicPayload`.
fn take_box(&mut self) -> *mut (dyn Any + Send);
/// Just borrow the contents.
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index c7f04f11e..c77e9675a 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -28,6 +28,7 @@ pub struct PanicInfo<'a> {
message: Option<&'a fmt::Arguments<'a>>,
location: &'a Location<'a>,
can_unwind: bool,
+ force_no_backtrace: bool,
}
impl<'a> PanicInfo<'a> {
@@ -42,9 +43,10 @@ impl<'a> PanicInfo<'a> {
message: Option<&'a fmt::Arguments<'a>>,
location: &'a Location<'a>,
can_unwind: bool,
+ force_no_backtrace: bool,
) -> Self {
struct NoPayload;
- PanicInfo { location, message, payload: &NoPayload, can_unwind }
+ PanicInfo { location, message, payload: &NoPayload, can_unwind, force_no_backtrace }
}
#[unstable(
@@ -141,6 +143,17 @@ impl<'a> PanicInfo<'a> {
pub fn can_unwind(&self) -> bool {
self.can_unwind
}
+
+ #[unstable(
+ feature = "panic_internals",
+ reason = "internal details of the implementation of the `panic!` and related macros",
+ issue = "none"
+ )]
+ #[doc(hidden)]
+ #[inline]
+ pub fn force_no_backtrace(&self) -> bool {
+ self.force_no_backtrace
+ }
}
#[stable(feature = "panic_hook_display", since = "1.26.0")]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 7b6249207..e6cdffd96 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -61,7 +61,12 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
fn panic_impl(pi: &PanicInfo<'_>) -> !;
}
- let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
+ let pi = PanicInfo::internal_constructor(
+ Some(&fmt),
+ Location::caller(),
+ /* can_unwind */ true,
+ /* force_no_backtrace */ false,
+ );
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
unsafe { panic_impl(&pi) }
@@ -77,7 +82,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
// which causes a "panic in a function that cannot unwind".
#[rustc_nounwind]
-pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
+pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
if cfg!(feature = "panic_immediate_abort") {
super::intrinsics::abort()
}
@@ -90,7 +95,12 @@ pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! {
}
// PanicInfo with the `can_unwind` flag set to false forces an abort.
- let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
+ let pi = PanicInfo::internal_constructor(
+ Some(&fmt),
+ Location::caller(),
+ /* can_unwind */ false,
+ force_no_backtrace,
+ );
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
unsafe { panic_impl(&pi) }
@@ -123,7 +133,15 @@ pub const fn panic(expr: &'static str) -> ! {
#[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
#[rustc_nounwind]
pub fn panic_nounwind(expr: &'static str) -> ! {
- panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]));
+ panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ false);
+}
+
+/// Like `panic_nounwind`, but also inhibits showing a backtrace.
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[rustc_nounwind]
+pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! {
+ panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true);
}
#[inline]
@@ -172,13 +190,18 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
super::intrinsics::abort()
}
- panic_nounwind_fmt(format_args!(
- "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}"
- ))
+ panic_nounwind_fmt(
+ format_args!(
+ "misaligned pointer dereference: address must be a multiple of {required:#x} but is {found:#x}"
+ ),
+ /* force_no_backtrace */ false,
+ )
}
/// Panic because we cannot unwind out of a function.
///
+/// This is a separate function to avoid the codesize impact of each crate containing the string to
+/// pass to `panic_nounwind`.
/// This function is called directly by the codegen backend, and must not have
/// any extra arguments (including those synthesized by track_caller).
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
@@ -186,15 +209,33 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
#[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function
#[rustc_nounwind]
fn panic_cannot_unwind() -> ! {
+ // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`.
panic_nounwind("panic in a function that cannot unwind")
}
+/// Panic because we are unwinding out of a destructor during cleanup.
+///
+/// This is a separate function to avoid the codesize impact of each crate containing the string to
+/// pass to `panic_nounwind`.
+/// This function is called directly by the codegen backend, and must not have
+/// any extra arguments (including those synthesized by track_caller).
+#[cfg(not(bootstrap))]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function
+#[rustc_nounwind]
+fn panic_in_cleanup() -> ! {
+ // Keep the text in sync with `UnwindTerminateReason::as_str` in `rustc_middle`.
+ panic_nounwind_nobacktrace("panic in a destructor during cleanup")
+}
+
/// This function is used instead of panic_fmt in const eval.
#[lang = "const_panic_fmt"]
#[rustc_const_unstable(feature = "core_panic", issue = "none")]
pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
if let Some(msg) = fmt.as_str() {
- panic_str(msg);
+ // The panic_display function is hooked by const eval.
+ panic_display(&msg);
} else {
// SAFETY: This is only evaluated at compile time, which reliably
// handles this UB (in case this branch turns out to be reachable
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 6b319b435..94c682b61 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -572,7 +572,10 @@ impl<P: Deref> Pin<P> {
/// // though we have previously pinned it! We have violated the pinning API contract.
/// }
/// ```
- /// A value, once pinned, must remain pinned forever (unless its type implements `Unpin`).
+ /// A value, once pinned, must remain pinned until it is dropped (unless its type implements
+ /// `Unpin`). Because `Pin<&mut T>` does not own the value, dropping the `Pin` will not drop
+ /// the value and will not end the pinning contract. So moving the value after dropping the
+ /// `Pin<&mut T>` is still a violation of the API contract.
///
/// Similarly, calling `Pin::new_unchecked` on an `Rc<T>` is unsafe because there could be
/// aliases to the same data that are not subject to the pinning restrictions:
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 80289ca08..fd5fe5a04 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1,6 +1,3 @@
-// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
-// These are different files so that relative links work properly without
-// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
#[rustc_doc_primitive = "bool"]
#[doc(alias = "true")]
#[doc(alias = "false")]
@@ -106,7 +103,7 @@ mod prim_bool {}
/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
///
/// [`u32`]: prim@u32
-#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
+/// [`exit`]: ../std/process/fn.exit.html
///
/// # `!` and generics
///
@@ -191,7 +188,7 @@ mod prim_bool {}
/// because `!` coerces to `Result<!, ConnectionError>` automatically.
///
/// [`String::from_str`]: str::FromStr::from_str
-#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+/// [`String`]: ../std/string/struct.String.html
/// [`FromStr`]: str::FromStr
///
/// # `!` and traits
@@ -267,7 +264,7 @@ mod prim_bool {}
/// `impl` for this which simply panics, but the same is true for any type (we could `impl
/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
///
-#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
+/// [`File`]: ../std/fs/struct.File.html
/// [`Debug`]: fmt::Debug
/// [`default()`]: Default::default
///
@@ -355,7 +352,7 @@ mod prim_never {}
/// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
/// ```
///
-#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+/// [`String`]: ../std/string/struct.String.html
///
/// As always, remember that a human intuition for 'character' might not map to
/// Unicode's definitions. For example, despite looking similar, the 'é'
@@ -572,7 +569,7 @@ impl Copy for () {
/// [`null_mut`]: ptr::null_mut
/// [`is_null`]: pointer::is_null
/// [`offset`]: pointer::offset
-#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
+/// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
/// [`write`]: ptr::write
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_pointer {}
@@ -612,7 +609,7 @@ mod prim_pointer {}
/// statically generated up to size 32.
///
/// Arrays of sizes from 1 to 12 (inclusive) implement [`From<Tuple>`], where `Tuple`
-/// is a homogenous [prim@tuple] of appropriate length.
+/// is a homogeneous [prim@tuple] of appropriate length.
///
/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
/// an array. Indeed, this provides most of the API for working with arrays.
@@ -676,7 +673,7 @@ mod prim_pointer {}
/// move_away(roa);
/// ```
///
-/// Arrays can be created from homogenous tuples of appropriate length:
+/// Arrays can be created from homogeneous tuples of appropriate length:
///
/// ```
/// let tuple: (u32, u32, u32) = (1, 2, 3);
@@ -1065,7 +1062,7 @@ mod prim_str {}
/// assert_eq!(y, 5);
/// ```
///
-/// Homogenous tuples can be created from arrays of appropriate length:
+/// Homogeneous tuples can be created from arrays of appropriate length:
///
/// ```
/// let array: [u32; 3] = [1, 2, 3];
@@ -1361,7 +1358,7 @@ mod prim_usize {}
///
/// [`std::fmt`]: fmt
/// [`Hash`]: hash::Hash
-#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
+/// [`ToSocketAddrs`]: ../std/net/trait.ToSocketAddrs.html
///
/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
/// implements that trait:
@@ -1381,10 +1378,10 @@ mod prim_usize {}
///
/// [`FusedIterator`]: iter::FusedIterator
/// [`TrustedLen`]: iter::TrustedLen
-#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
-#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
-#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
-#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
+/// [`Seek`]: ../std/io/trait.Seek.html
+/// [`BufRead`]: ../std/io/trait.BufRead.html
+/// [`Read`]: ../std/io/trait.Read.html
+/// [`io::Write`]: ../std/io/trait.Write.html
///
/// Note that due to method call deref coercion, simply calling a trait method will act like they
/// work on references as well as they do on owned values! The implementations described here are
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index ee69d89a4..9af8f1228 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -607,7 +607,16 @@ impl<T: ?Sized> *const T {
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes divided by `mem::size_of::<T>()`.
///
- /// This function is the inverse of [`offset`].
+ /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::<T>() as isize)`,
+ /// except that it has a lot more opportunities for UB, in exchange for the compiler
+ /// better understanding what you are doing.
+ ///
+ /// The primary motivation of this method is for computing the `len` of an array/slice
+ /// of `T` that you are currently representing as a "start" and "end" pointer
+ /// (and "end" is "one past the end" of the array).
+ /// In that case, `end.offset_from(start)` gets you the length of the array.
+ ///
+ /// All of the following safety requirements are trivially satisfied for this usecase.
///
/// [`offset`]: #method.offset
///
@@ -616,7 +625,7 @@ impl<T: ?Sized> *const T {
/// If any of the following conditions are violated, the result is Undefined
/// Behavior:
///
- /// * Both the starting and other pointer must be either in bounds or one
+ /// * Both `self` and `origin` must be either in bounds or one
/// byte past the end of the same [allocated object].
///
/// * Both pointers must be *derived from* a pointer to the same object.
@@ -646,6 +655,14 @@ impl<T: ?Sized> *const T {
/// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on
/// such large allocations either.)
///
+ /// The requirement for pointers to be derived from the same allocated object is primarily
+ /// needed for `const`-compatibility: the distance between pointers into *different* allocated
+ /// objects is not known at compile-time. However, the requirement also exists at
+ /// runtime and may be exploited by optimizations. If you wish to compute the difference between
+ /// pointers that are not guaranteed to be from the same allocation, use `(self as isize -
+ /// origin as isize) / mem::size_of::<T>()`.
+ // FIXME: recommend `addr()` instead of `as usize` once that is stable.
+ ///
/// [`add`]: #method.add
/// [allocated object]: crate::ptr#allocated-object
///
@@ -703,7 +720,7 @@ impl<T: ?Sized> *const T {
/// units of **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
- /// using [offset_from][pointer::offset_from] on it. See that method for
+ /// using [`offset_from`][pointer::offset_from] on it. See that method for
/// documentation and safety requirements.
///
/// For non-`Sized` pointees this operation considers only the data pointers,
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 5f094ac4e..d1286a1de 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -698,6 +698,7 @@ where
#[inline(always)]
#[must_use]
#[unstable(feature = "ptr_from_ref", issue = "106116")]
+#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[rustc_diagnostic_item = "ptr_from_ref"]
pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
r
@@ -710,7 +711,7 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
#[inline(always)]
#[must_use]
#[unstable(feature = "ptr_from_ref", issue = "106116")]
-#[rustc_diagnostic_item = "ptr_from_mut"]
+#[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn from_mut<T: ?Sized>(r: &mut T) -> *mut T {
r
}
@@ -795,7 +796,9 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
///
/// Behavior is undefined if any of the following conditions are violated:
///
-/// * Both `x` and `y` must be [valid] for both reads and writes.
+/// * Both `x` and `y` must be [valid] for both reads and writes. They must remain valid even when the
+/// other pointer is written. (This means if the memory ranges overlap, the two pointers must not
+/// be subject to aliasing restrictions relative to each other.)
///
/// * Both `x` and `y` must be properly aligned.
///
@@ -1357,6 +1360,7 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+#[rustc_diagnostic_item = "ptr_write"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn write<T>(dst: *mut T, src: T) {
// Semantically, it would be fine for this to be implemented as a
@@ -1459,6 +1463,7 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
#[inline]
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+#[rustc_diagnostic_item = "ptr_write_unaligned"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
// SAFETY: the caller must guarantee that `dst` is valid for writes.
@@ -1607,6 +1612,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
/// ```
#[inline]
#[stable(feature = "volatile", since = "1.9.0")]
+#[rustc_diagnostic_item = "ptr_write_volatile"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
// SAFETY: the caller must uphold the safety contract for `volatile_store`.
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 9dbb3f9d3..109c28692 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -109,7 +109,7 @@ impl<T: ?Sized> *mut T {
/// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit
/// coercion.
///
- /// [`cast_mut`]: #method.cast_mut
+ /// [`cast_mut`]: pointer::cast_mut
#[stable(feature = "ptr_const_cast", since = "1.65.0")]
#[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
#[rustc_diagnostic_item = "ptr_cast_const"]
@@ -121,7 +121,7 @@ impl<T: ?Sized> *mut T {
/// Casts a pointer to its raw bits.
///
/// This is equivalent to `as usize`, but is more specific to enhance readability.
- /// The inverse method is [`from_bits`](#method.from_bits-1).
+ /// The inverse method is [`from_bits`](pointer#method.from_bits-1).
///
/// In particular, `*p as usize` and `p as usize` will both compile for
/// pointers to numeric types but do very different things, so using this
@@ -157,7 +157,7 @@ impl<T: ?Sized> *mut T {
/// Creates a pointer from its raw bits.
///
/// This is equivalent to `as *mut T`, but is more specific to enhance readability.
- /// The inverse method is [`to_bits`](#method.to_bits-1).
+ /// The inverse method is [`to_bits`](pointer#method.to_bits-1).
///
/// # Examples
///
@@ -307,7 +307,7 @@ impl<T: ?Sized> *mut T {
///
/// For the mutable counterpart see [`as_mut`].
///
- /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+ /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
/// [`as_mut`]: #method.as_mut
///
/// # Safety
@@ -373,7 +373,7 @@ impl<T: ?Sized> *mut T {
///
/// For the mutable counterpart see [`as_uninit_mut`].
///
- /// [`as_ref`]: #method.as_ref-1
+ /// [`as_ref`]: pointer#method.as_ref-1
/// [`as_uninit_mut`]: #method.as_uninit_mut
///
/// # Safety
@@ -628,7 +628,7 @@ impl<T: ?Sized> *mut T {
/// For the shared counterpart see [`as_ref`].
///
/// [`as_uninit_mut`]: #method.as_uninit_mut
- /// [`as_ref`]: #method.as_ref-1
+ /// [`as_ref`]: pointer#method.as_ref-1
///
/// # Safety
///
@@ -693,7 +693,7 @@ impl<T: ?Sized> *mut T {
/// For the shared counterpart see [`as_uninit_ref`].
///
/// [`as_mut`]: #method.as_mut
- /// [`as_uninit_ref`]: #method.as_uninit_ref-1
+ /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1
///
/// # Safety
///
@@ -781,16 +781,25 @@ impl<T: ?Sized> *mut T {
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes divided by `mem::size_of::<T>()`.
///
- /// This function is the inverse of [`offset`].
+ /// This is equivalent to `(self as isize - origin as isize) / (mem::size_of::<T>() as isize)`,
+ /// except that it has a lot more opportunities for UB, in exchange for the compiler
+ /// better understanding what you are doing.
///
- /// [`offset`]: #method.offset-1
+ /// The primary motivation of this method is for computing the `len` of an array/slice
+ /// of `T` that you are currently representing as a "start" and "end" pointer
+ /// (and "end" is "one past the end" of the array).
+ /// In that case, `end.offset_from(start)` gets you the length of the array.
+ ///
+ /// All of the following safety requirements are trivially satisfied for this usecase.
+ ///
+ /// [`offset`]: pointer#method.offset-1
///
/// # Safety
///
/// If any of the following conditions are violated, the result is Undefined
/// Behavior:
///
- /// * Both the starting and other pointer must be either in bounds or one
+ /// * Both `self` and `origin` must be either in bounds or one
/// byte past the end of the same [allocated object].
///
/// * Both pointers must be *derived from* a pointer to the same object.
@@ -820,6 +829,14 @@ impl<T: ?Sized> *mut T {
/// (Note that [`offset`] and [`add`] also have a similar limitation and hence cannot be used on
/// such large allocations either.)
///
+ /// The requirement for pointers to be derived from the same allocated object is primarily
+ /// needed for `const`-compatibility: the distance between pointers into *different* allocated
+ /// objects is not known at compile-time. However, the requirement also exists at
+ /// runtime and may be exploited by optimizations. If you wish to compute the difference between
+ /// pointers that are not guaranteed to be from the same allocation, use `(self as isize -
+ /// origin as isize) / mem::size_of::<T>()`.
+ // FIXME: recommend `addr()` instead of `as usize` once that is stable.
+ ///
/// [`add`]: #method.add
/// [allocated object]: crate::ptr#allocated-object
///
@@ -875,7 +892,7 @@ impl<T: ?Sized> *mut T {
/// units of **bytes**.
///
/// This is purely a convenience for casting to a `u8` pointer and
- /// using [offset_from][pointer::offset_from] on it. See that method for
+ /// using [`offset_from`][pointer::offset_from] on it. See that method for
/// documentation and safety requirements.
///
/// For non-`Sized` pointees this operation considers only the data pointers,
@@ -2064,7 +2081,7 @@ impl<T> *mut [T] {
///
/// For the mutable counterpart see [`as_uninit_slice_mut`].
///
- /// [`as_ref`]: #method.as_ref-1
+ /// [`as_ref`]: pointer#method.as_ref-1
/// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut
///
/// # Safety
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index e0fd347a0..d5bd54fd5 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -43,9 +43,27 @@ use crate::slice::{self, SliceIndex};
/// it is your responsibility to ensure that `as_mut` is never called, and `as_ptr`
/// is never used for mutation.
///
+/// # Representation
+///
+/// Thanks to the [null pointer optimization],
+/// `NonNull<T>` and `Option<NonNull<T>>`
+/// are guaranteed to have the same size and alignment:
+///
+/// ```
+/// # use std::mem::{size_of, align_of};
+/// use std::ptr::NonNull;
+///
+/// assert_eq!(size_of::<NonNull<i16>>(), size_of::<Option<NonNull<i16>>>());
+/// assert_eq!(align_of::<NonNull<i16>>(), align_of::<Option<NonNull<i16>>>());
+///
+/// assert_eq!(size_of::<NonNull<str>>(), size_of::<Option<NonNull<str>>>());
+/// assert_eq!(align_of::<NonNull<str>>(), align_of::<Option<NonNull<str>>>());
+/// ```
+///
/// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
/// [`PhantomData`]: crate::marker::PhantomData
/// [`UnsafeCell<T>`]: crate::cell::UnsafeCell
+/// [null pointer optimization]: crate::option#representation
#[stable(feature = "nonnull", since = "1.25.0")]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
@@ -320,6 +338,7 @@ impl<T: ?Sized> NonNull<T> {
/// ```
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[must_use]
#[inline(always)]
pub const fn as_ptr(self) -> *mut T {
@@ -579,6 +598,7 @@ impl<T> NonNull<[T]> {
#[must_use]
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn as_mut_ptr(self) -> *mut T {
self.as_non_null_ptr().as_ptr()
}
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index f3311f76a..4cfccd2e3 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -10,7 +10,7 @@ use crate::ops;
impl [u8] {
/// Checks if all bytes in this slice are within the ASCII range.
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
- #[rustc_const_unstable(feature = "const_slice_is_ascii", issue = "111090")]
+ #[rustc_const_stable(feature = "const_slice_is_ascii", since = "1.74.0")]
#[must_use]
#[inline]
pub const fn is_ascii(&self) -> bool {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index d95662afd..a19fcf93c 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -730,6 +730,7 @@ impl<T> [T] {
/// [`as_mut_ptr`]: slice::as_mut_ptr
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[inline(always)]
#[must_use]
pub const fn as_ptr(&self) -> *const T {
@@ -760,6 +761,7 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
#[rustc_allow_const_fn_unstable(const_mut_refs)]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[inline(always)]
#[must_use]
pub const fn as_mut_ptr(&mut self) -> *mut T {
@@ -3408,7 +3410,7 @@ impl<T> [T] {
/// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
/// ```
///
- /// Rotate a subslice:
+ /// Rotating a subslice:
///
/// ```
/// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index e5f34952c..dfa2d4fd5 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -386,6 +386,7 @@ impl str {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[must_use]
#[inline(always)]
pub const fn as_ptr(&self) -> *const u8 {
@@ -401,6 +402,7 @@ impl str {
/// It is your responsibility to make sure that the string slice only gets
/// modified in a way that it remains valid UTF-8.
#[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
#[must_use]
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut u8 {
@@ -997,7 +999,7 @@ impl str {
/// An iterator over the lines of a string.
#[stable(feature = "rust1", since = "1.0.0")]
- #[deprecated(since = "1.4.0", note = "use lines() instead now")]
+ #[deprecated(since = "1.4.0", note = "use lines() instead now", suggestion = "lines")]
#[inline]
#[allow(deprecated)]
pub fn lines_any(&self) -> LinesAny<'_> {
@@ -2322,7 +2324,7 @@ impl str {
/// assert!(!non_ascii.is_ascii());
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
- #[rustc_const_unstable(feature = "const_slice_is_ascii", issue = "111090")]
+ #[rustc_const_stable(feature = "const_slice_is_ascii", since = "1.74.0")]
#[must_use]
#[inline]
pub const fn is_ascii(&self) -> bool {
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 22a1c0978..cf1fbe2d3 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1018,6 +1018,7 @@ impl AtomicBool {
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn as_ptr(&self) -> *mut bool {
self.v.get().cast()
}
@@ -1953,6 +1954,7 @@ impl<T> AtomicPtr<T> {
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn as_ptr(&self) -> *mut *mut T {
self.p.get()
}
@@ -2891,6 +2893,7 @@ macro_rules! atomic_int {
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
+ #[cfg_attr(not(bootstrap), rustc_never_returns_null_ptr)]
pub const fn as_ptr(&self) -> *mut $int_type {
self.v.get()
}
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index 3f3e19c55..ff538d55c 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -2,6 +2,8 @@
use core::fmt;
use core::future::Future;
+use core::marker::Tuple;
+use core::ops::{Generator, GeneratorState};
use core::pin::Pin;
use core::task::{Context, Poll};
@@ -168,10 +170,52 @@ impl<T> From<T> for Exclusive<T> {
}
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
-impl<T: Future + ?Sized> Future for Exclusive<T> {
+impl<F, Args> FnOnce<Args> for Exclusive<F>
+where
+ F: FnOnce<Args>,
+ Args: Tuple,
+{
+ type Output = F::Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
+ self.into_inner().call_once(args)
+ }
+}
+
+#[unstable(feature = "exclusive_wrapper", issue = "98407")]
+impl<F, Args> FnMut<Args> for Exclusive<F>
+where
+ F: FnMut<Args>,
+ Args: Tuple,
+{
+ extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
+ self.get_mut().call_mut(args)
+ }
+}
+
+#[unstable(feature = "exclusive_wrapper", issue = "98407")]
+impl<T> Future for Exclusive<T>
+where
+ T: Future + ?Sized,
+{
type Output = T::Output;
+
#[inline]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.get_pin_mut().poll(cx)
}
}
+
+#[unstable(feature = "generator_trait", issue = "43122")] // also #98407
+impl<R, G> Generator<R> for Exclusive<G>
+where
+ G: Generator<R> + ?Sized,
+{
+ type Yield = G::Yield;
+ type Return = G::Return;
+
+ #[inline]
+ fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+ G::resume(self.get_pin_mut(), arg)
+ }
+}
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index b08d5782a..1e8d28979 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -656,10 +656,10 @@ impl Duration {
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
pub const fn checked_div(self, rhs: u32) -> Option<Duration> {
if rhs != 0 {
- let secs = self.secs / (rhs as u64);
- let carry = self.secs - secs * (rhs as u64);
- let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
- let nanos = self.nanos.0 / rhs + (extra_nanos as u32);
+ let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64));
+ let (mut nanos, extra_nanos) = (self.nanos.0 / rhs, self.nanos.0 % rhs);
+ nanos +=
+ ((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32;
debug_assert!(nanos < NANOS_PER_SEC);
Some(Duration::new(secs, nanos))
} else {
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 7782ace69..ff292ff2d 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -1,4 +1,4 @@
-// See src/libstd/primitive_docs.rs for documentation.
+// See core/src/primitive_docs.rs for documentation.
use crate::cmp::Ordering::{self, *};
use crate::marker::ConstParamTy;
diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs
index 0a77ecddb..5b87d6c1f 100644
--- a/library/core/tests/iter/range.rs
+++ b/library/core/tests/iter/range.rs
@@ -1,5 +1,6 @@
-use core::num::NonZeroUsize;
use super::*;
+use core::ascii::Char as AsciiChar;
+use core::num::NonZeroUsize;
#[test]
fn test_range() {
@@ -40,6 +41,21 @@ fn test_char_range() {
}
#[test]
+fn test_ascii_char_range() {
+ let from = AsciiChar::Null;
+ let to = AsciiChar::Delete;
+ assert!((from..=to).eq((from as u8..=to as u8).filter_map(AsciiChar::from_u8)));
+ assert!((from..=to).rev().eq((from as u8..=to as u8).filter_map(AsciiChar::from_u8).rev()));
+
+ assert_eq!((AsciiChar::CapitalA..=AsciiChar::CapitalZ).count(), 26);
+ assert_eq!((AsciiChar::CapitalA..=AsciiChar::CapitalZ).size_hint(), (26, Some(26)));
+ assert_eq!((AsciiChar::SmallA..=AsciiChar::SmallZ).count(), 26);
+ assert_eq!((AsciiChar::SmallA..=AsciiChar::SmallZ).size_hint(), (26, Some(26)));
+ assert_eq!((AsciiChar::Digit0..=AsciiChar::Digit9).count(), 10);
+ assert_eq!((AsciiChar::Digit0..=AsciiChar::Digit9).size_hint(), (10, Some(10)));
+}
+
+#[test]
fn test_range_exhaustion() {
let mut r = 10..10;
assert!(r.is_empty());
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 7a6def37a..e4003a208 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -2,6 +2,8 @@
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_windows)]
+#![feature(ascii_char)]
+#![feature(ascii_char_variants)]
#![feature(bigint_helper_methods)]
#![feature(cell_update)]
#![feature(const_align_offset)]
@@ -54,6 +56,7 @@
#![feature(min_specialization)]
#![feature(numfmt)]
#![feature(num_midpoint)]
+#![feature(isqrt)]
#![feature(step_trait)]
#![feature(str_internals)]
#![feature(std_internals)]
@@ -94,6 +97,7 @@
#![feature(const_option_ext)]
#![feature(const_result)]
#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
+#![cfg_attr(test, feature(cfg_match))]
#![feature(int_roundings)]
#![feature(slice_group_by)]
#![feature(split_array)]
@@ -137,6 +141,7 @@ mod hash;
mod intrinsics;
mod iter;
mod lazy;
+#[cfg(test)]
mod macros;
mod manually_drop;
mod mem;
diff --git a/library/core/tests/macros.rs b/library/core/tests/macros.rs
index ff3632e35..eb886def1 100644
--- a/library/core/tests/macros.rs
+++ b/library/core/tests/macros.rs
@@ -1,3 +1,25 @@
+trait Trait {
+ fn blah(&self);
+}
+
+#[allow(dead_code)]
+struct Struct;
+
+impl Trait for Struct {
+ cfg_match! {
+ cfg(feature = "blah") => {
+ fn blah(&self) {
+ unimplemented!();
+ }
+ }
+ _ => {
+ fn blah(&self) {
+ unimplemented!();
+ }
+ }
+ }
+}
+
#[test]
fn assert_eq_trailing_comma() {
assert_eq!(1, 1,);
@@ -18,3 +40,135 @@ fn assert_ne_trailing_comma() {
fn matches_leading_pipe() {
matches!(1, | 1 | 2 | 3);
}
+
+#[test]
+fn cfg_match_basic() {
+ cfg_match! {
+ cfg(target_pointer_width = "64") => { fn f0_() -> bool { true }}
+ }
+
+ cfg_match! {
+ cfg(unix) => { fn f1_() -> bool { true }}
+ cfg(any(target_os = "macos", target_os = "linux")) => { fn f1_() -> bool { false }}
+ }
+
+ cfg_match! {
+ cfg(target_pointer_width = "32") => { fn f2_() -> bool { false }}
+ cfg(target_pointer_width = "64") => { fn f2_() -> bool { true }}
+ }
+
+ cfg_match! {
+ cfg(target_pointer_width = "16") => { fn f3_() -> i32 { 1 }}
+ _ => { fn f3_() -> i32 { 2 }}
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ assert!(f0_());
+
+ #[cfg(unix)]
+ assert!(f1_());
+
+ #[cfg(target_pointer_width = "32")]
+ assert!(!f2_());
+ #[cfg(target_pointer_width = "64")]
+ assert!(f2_());
+
+ #[cfg(not(target_pointer_width = "16"))]
+ assert_eq!(f3_(), 2);
+}
+
+#[test]
+fn cfg_match_debug_assertions() {
+ cfg_match! {
+ cfg(debug_assertions) => {
+ assert!(cfg!(debug_assertions));
+ assert_eq!(4, 2+2);
+ }
+ _ => {
+ assert!(cfg!(not(debug_assertions)));
+ assert_eq!(10, 5+5);
+ }
+ }
+}
+
+#[cfg(target_pointer_width = "64")]
+#[test]
+fn cfg_match_no_duplication_on_64() {
+ cfg_match! {
+ cfg(windows) => {
+ fn foo() {}
+ }
+ cfg(unix) => {
+ fn foo() {}
+ }
+ cfg(target_pointer_width = "64") => {
+ fn foo() {}
+ }
+ }
+ foo();
+}
+
+#[test]
+fn cfg_match_options() {
+ cfg_match! {
+ cfg(test) => {
+ use core::option::Option as Option2;
+ fn works1() -> Option2<u32> { Some(1) }
+ }
+ _ => { fn works1() -> Option<u32> { None } }
+ }
+
+ cfg_match! {
+ cfg(feature = "foo") => { fn works2() -> bool { false } }
+ cfg(test) => { fn works2() -> bool { true } }
+ _ => { fn works2() -> bool { false } }
+ }
+
+ cfg_match! {
+ cfg(feature = "foo") => { fn works3() -> bool { false } }
+ _ => { fn works3() -> bool { true } }
+ }
+
+ cfg_match! {
+ cfg(test) => {
+ use core::option::Option as Option3;
+ fn works4() -> Option3<u32> { Some(1) }
+ }
+ }
+
+ cfg_match! {
+ cfg(feature = "foo") => { fn works5() -> bool { false } }
+ cfg(test) => { fn works5() -> bool { true } }
+ }
+
+ assert!(works1().is_some());
+ assert!(works2());
+ assert!(works3());
+ assert!(works4().is_some());
+ assert!(works5());
+}
+
+#[test]
+fn cfg_match_two_functions() {
+ cfg_match! {
+ cfg(target_pointer_width = "64") => {
+ fn foo1() {}
+ fn bar1() {}
+ }
+ _ => {
+ fn foo2() {}
+ fn bar2() {}
+ }
+ }
+
+ #[cfg(target_pointer_width = "64")]
+ {
+ foo1();
+ bar1();
+ }
+ #[cfg(not(target_pointer_width = "64"))]
+ {
+ foo2();
+ bar2();
+ }
+}
diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs
index 439bbe669..165d9a296 100644
--- a/library/core/tests/num/int_macros.rs
+++ b/library/core/tests/num/int_macros.rs
@@ -291,6 +291,38 @@ macro_rules! int_module {
}
#[test]
+ fn test_isqrt() {
+ assert_eq!($T::MIN.checked_isqrt(), None);
+ assert_eq!((-1 as $T).checked_isqrt(), None);
+ assert_eq!((0 as $T).isqrt(), 0 as $T);
+ assert_eq!((1 as $T).isqrt(), 1 as $T);
+ assert_eq!((2 as $T).isqrt(), 1 as $T);
+ assert_eq!((99 as $T).isqrt(), 9 as $T);
+ assert_eq!((100 as $T).isqrt(), 10 as $T);
+ }
+
+ #[cfg(not(miri))] // Miri is too slow
+ #[test]
+ fn test_lots_of_isqrt() {
+ let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T;
+ for n in 0..=n_max {
+ let isqrt: $T = n.isqrt();
+
+ assert!(isqrt.pow(2) <= n);
+ let (square, overflow) = (isqrt + 1).overflowing_pow(2);
+ assert!(overflow || square > n);
+ }
+
+ for n in ($T::MAX - 127)..=$T::MAX {
+ let isqrt: $T = n.isqrt();
+
+ assert!(isqrt.pow(2) <= n);
+ let (square, overflow) = (isqrt + 1).overflowing_pow(2);
+ assert!(overflow || square > n);
+ }
+ }
+
+ #[test]
fn test_div_floor() {
let a: $T = 8;
let b = 3;
diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs
index 7d6203db0..955440647 100644
--- a/library/core/tests/num/uint_macros.rs
+++ b/library/core/tests/num/uint_macros.rs
@@ -207,6 +207,35 @@ macro_rules! uint_module {
}
#[test]
+ fn test_isqrt() {
+ assert_eq!((0 as $T).isqrt(), 0 as $T);
+ assert_eq!((1 as $T).isqrt(), 1 as $T);
+ assert_eq!((2 as $T).isqrt(), 1 as $T);
+ assert_eq!((99 as $T).isqrt(), 9 as $T);
+ assert_eq!((100 as $T).isqrt(), 10 as $T);
+ assert_eq!($T::MAX.isqrt(), (1 << ($T::BITS / 2)) - 1);
+ }
+
+ #[cfg(not(miri))] // Miri is too slow
+ #[test]
+ fn test_lots_of_isqrt() {
+ let n_max: $T = (1024 * 1024).min($T::MAX as u128) as $T;
+ for n in 0..=n_max {
+ let isqrt: $T = n.isqrt();
+
+ assert!(isqrt.pow(2) <= n);
+ assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n);
+ }
+
+ for n in ($T::MAX - 255)..=$T::MAX {
+ let isqrt: $T = n.isqrt();
+
+ assert!(isqrt.pow(2) <= n);
+ assert!(isqrt + 1 == (1 as $T) << ($T::BITS / 2) || (isqrt + 1).pow(2) > n);
+ }
+ }
+
+ #[test]
fn test_div_floor() {
assert_eq!((8 as $T).div_floor(3), 2);
}
diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs
index 872611937..bd6e63edb 100644
--- a/library/core/tests/time.rs
+++ b/library/core/tests/time.rs
@@ -170,6 +170,7 @@ fn saturating_mul() {
fn div() {
assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
+ assert_eq!(Duration::new(1, 1) / 7, Duration::new(0, 142_857_143));
assert_eq!(Duration::new(99, 999_999_000) / 100, Duration::new(0, 999_999_990));
}