From 17edbe7cad199e04345db5e810970576e8dc6f40 Mon Sep 17 00:00:00 2001 From: David Thomas Date: Sun, 10 Dec 2023 11:36:56 +0000 Subject: [PATCH 01/31] Use AtomicU8 instead of AtomicUsize in backtrace.rs --- library/std/src/backtrace.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 7fcf2ee358c46..34ac095305025 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -93,7 +93,7 @@ use crate::env; use crate::ffi::c_void; use crate::fmt; use crate::panic::UnwindSafe; -use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; +use crate::sync::atomic::{AtomicU8, Ordering::Relaxed}; use crate::sync::LazyLock; use crate::sys_common::backtrace::{lock, output_filename, set_image_base}; use crate::vec::Vec; @@ -255,7 +255,7 @@ impl Backtrace { // Cache the result of reading the environment variables to make // backtrace captures speedy, because otherwise reading environment // variables every time can be somewhat slow. - static ENABLED: AtomicUsize = AtomicUsize::new(0); + static ENABLED: AtomicU8 = AtomicU8::new(0); match ENABLED.load(Relaxed) { 0 => {} 1 => return false, @@ -268,7 +268,7 @@ impl Backtrace { Err(_) => false, }, }; - ENABLED.store(enabled as usize + 1, Relaxed); + ENABLED.store(enabled as u8 + 1, Relaxed); enabled } From 1c5b2ce67cb8d698350b93143b8de342805145cc Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Tue, 19 Dec 2023 22:08:48 +0100 Subject: [PATCH 02/31] Docs: Use non-SeqCst in module example of atomics I done this for this reasons: 1. The example now shows that there is more Orderings than just SeqCst. 2. People who would copy from example would now have more suitable orderings for the job. 3. SeqCst is both much harder to reason about and not needed in most situations. IMHO, we should encourage people to think and use memory orderings that is suitable to task instead of blindly defaulting to SeqCst. --- library/core/src/sync/atomic.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 5f1f41e68658c..ad8c70c6a3ca3 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -138,7 +138,7 @@ //! //! In general, *all* atomic accesses on read-only memory are Undefined Behavior. For instance, attempting //! to do a `compare_exchange` that will definitely fail (making it conceptually a read-only -//! operation) can still cause a page fault if the underlying memory page is mapped read-only. Since +//! operation) can still cause a segmentation fault if the underlying memory page is mapped read-only. Since //! atomic `load`s might be implemented using compare-exchange operations, even a `load` can fault //! on read-only memory. //! @@ -181,12 +181,13 @@ //! let spinlock = Arc::new(AtomicUsize::new(1)); //! //! let spinlock_clone = Arc::clone(&spinlock); +//! //! let thread = thread::spawn(move|| { -//! spinlock_clone.store(0, Ordering::SeqCst); +//! spinlock_clone.store(0, Ordering::Release); //! }); //! //! // Wait for the other thread to release the lock -//! while spinlock.load(Ordering::SeqCst) != 0 { +//! while spinlock.load(Ordering::Acquire) != 0 { //! hint::spin_loop(); //! } //! @@ -203,7 +204,11 @@ //! //! static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0); //! -//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst); +//! // Note that Relaxed ordering doesn't synchronize anything +//! // except the global thread counter itself. +//! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::Relaxed); +//! // Note that this number may not be true at the moment of printing +//! // because some other thread may have changed static value already. //! println!("live threads: {}", old_thread_count + 1); //! ``` From 46ad13136c96acfa05c2249796913b3280ae0fc3 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:09:38 +0000 Subject: [PATCH 03/31] update fn pointer trait impl docs --- library/core/src/primitive_docs.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bd2851a26fb8c..5025b77d6982c 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1634,9 +1634,8 @@ mod prim_ref {} /// function pointers of varying length. Note that this is a convenience notation to avoid /// repetitive documentation, not valid Rust syntax. /// -/// Due to a temporary restriction in Rust's type system, these traits are only implemented on -/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this -/// may change: +/// The following traits are implemented for function pointers with any number of arguments and +/// any ABI. /// /// * [`PartialEq`] /// * [`Eq`] @@ -1645,11 +1644,6 @@ mod prim_ref {} /// * [`Hash`] /// * [`Pointer`] /// * [`Debug`] -/// -/// The following traits are implemented for function pointers with any number of arguments and -/// any ABI. These traits have implementations that are automatically generated by the compiler, -/// so are not limited by missing language features: -/// /// * [`Clone`] /// * [`Copy`] /// * [`Send`] From 56df3bb70d808d535e46f1c017bafeccbbf1cb6d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:47:10 -0800 Subject: [PATCH 04/31] Move nonzero_integers macro call to bottom of module This way all the other macros defined in this module, such as nonzero_leading_trailing_zeros, are available to call within the expansion of nonzero_integers. (Macros defined by macro_rules cannot be called from the same module above the location of the macro_rules.) In this commit the ability to call things like nonzero_leading_trailing_zeros is not immediately used, but later commits in this stack will be consolidating the entire API of NonZeroT to be generated through nonzero_integers, and will need to make use of some of the other macros to do that. --- library/core/src/num/nonzero.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 2df38ab5848af..1de9226f47f2c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -190,21 +190,6 @@ macro_rules! nonzero_integers { } } -nonzero_integers! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); -} - macro_rules! from_str_radix_nzint_impl { ($($t:ty)*) => {$( #[stable(feature = "nonzero_parse", since = "1.35.0")] @@ -1396,3 +1381,18 @@ nonzero_bits! { NonZeroUsize(usize); NonZeroIsize(isize); } + +nonzero_integers! { + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); + #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); + #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); +} From 54cb822563dc7ffd4838c23d04f7c1ad6c3e90cd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:21:50 -0800 Subject: [PATCH 05/31] Define only a single NonZero type per macro call Later in this stack, as the nonzero_integers macro is going to be responsible for producing a larger fraction of the API for the NonZero integer types, it will need to receive a number of additional arguments beyond the ones currently seen here. Additional arguments, especially named arguments across multiple lines, will turn out clearer if everything in one macro call is for the same NonZero type. This commit adopts a similar arrangement to what we do for generating the API of the integer primitives (`impl u8` etc), which also generate a single type's API per top-level macro call, rather than generating all 12 impl blocks for the 12 types from one macro call. --- library/core/src/num/nonzero.rs | 45 ++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1de9226f47f2c..6b113d57f25fe 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -22,9 +22,10 @@ macro_rules! impl_nonzero_fmt { } } -macro_rules! nonzero_integers { - ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => { - $( +macro_rules! nonzero_integer { + ( + #[$stability:meta] #[$const_new_unchecked_stability:meta] $Ty:ident($Int:ty); + ) => { /// An integer that is known not to equal zero. /// /// This enables some memory layout optimization. @@ -186,8 +187,7 @@ macro_rules! nonzero_integers { impl_nonzero_fmt! { #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } - )+ - } + }; } macro_rules! from_str_radix_nzint_impl { @@ -1382,17 +1382,50 @@ nonzero_bits! { NonZeroIsize(isize); } -nonzero_integers! { +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); +} + +nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); +} + +nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); } From 9196d2a552c28144252730bcf8a8e58878f625d4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:44:02 -0800 Subject: [PATCH 06/31] Unindent nonzero_integer macro body --- library/core/src/num/nonzero.rs | 278 ++++++++++++++++---------------- 1 file changed, 139 insertions(+), 139 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6b113d57f25fe..f7098bcf6e9c9 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -26,167 +26,167 @@ macro_rules! nonzero_integer { ( #[$stability:meta] #[$const_new_unchecked_stability:meta] $Ty:ident($Int:ty); ) => { - /// An integer that is known not to equal zero. + /// An integer that is known not to equal zero. + /// + /// This enables some memory layout optimization. + #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// + /// ```rust + /// use std::mem::size_of; + #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] + /// ``` + /// + /// # Layout + /// + #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] + /// 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::>());")] + #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] + /// ``` + /// + /// [null pointer optimization]: crate::option#representation + #[$stability] + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + #[repr(transparent)] + #[rustc_layout_scalar_valid_range_start(1)] + #[rustc_nonnull_optimization_guaranteed] + #[rustc_diagnostic_item = stringify!($Ty)] + pub struct $Ty($Int); + + impl $Ty { + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behaviour if the value is zero. /// - /// This enables some memory layout optimization. - #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] + /// # Safety /// - /// ```rust - /// use std::mem::size_of; - #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] - /// ``` - /// - /// # Layout - /// - #[doc = concat!("`", stringify!($Ty), "` is guaranteed to have the same layout and bit validity as `", stringify!($Int), "`")] - /// 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::>());")] - #[doc = concat!("assert_eq!(align_of::<", stringify!($Ty), ">(), align_of::>());")] - /// ``` - /// - /// [null pointer optimization]: crate::option#representation + /// The value must not be zero. #[$stability] - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] - #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start(1)] - #[rustc_nonnull_optimization_guaranteed] - #[rustc_diagnostic_item = stringify!($Ty)] - pub struct $Ty($Int); - - impl $Ty { - /// Creates a non-zero without checking whether the value is non-zero. - /// This results in undefined behaviour if the value is zero. - /// - /// # Safety - /// - /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] - #[must_use] - #[inline] - pub const unsafe fn new_unchecked(n: $Int) -> Self { - crate::panic::debug_assert_nounwind!( - n != 0, - concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") - ); - // SAFETY: this is guaranteed to be safe by the caller. - unsafe { - Self(n) - } - } - - /// Creates a non-zero if the given value is not zero. - #[$stability] - #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] - #[must_use] - #[inline] - pub const fn new(n: $Int) -> Option { - if n != 0 { - // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) - } else { - None - } + #[$const_new_unchecked_stability] + #[must_use] + #[inline] + pub const unsafe fn new_unchecked(n: $Int) -> Self { + crate::panic::debug_assert_nounwind!( + n != 0, + concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") + ); + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { + Self(n) } + } - /// Returns the value as a primitive type. - #[$stability] - #[inline] - #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] - pub const fn get(self) -> $Int { - // FIXME: Remove this after LLVM supports `!range` metadata for function - // arguments https://github.com/llvm/llvm-project/issues/76628 - // - // Rustc can set range metadata only if it loads `self` from - // memory somewhere. If the value of `self` was from by-value argument - // of some not-inlined function, LLVM don't have range metadata - // to understand that the value cannot be zero. - - // SAFETY: It is an invariant of this type. - unsafe { - intrinsics::assume(self.0 != 0); - } - self.0 + /// Creates a non-zero if the given value is not zero. + #[$stability] + #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[must_use] + #[inline] + pub const fn new(n: $Int) -> Option { + if n != 0 { + // SAFETY: we just checked that there's no `0` + Some(unsafe { Self(n) }) + } else { + None } - } - #[stable(feature = "from_nonzero", since = "1.31.0")] - impl From<$Ty> for $Int { - #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] - #[inline] - fn from(nonzero: $Ty) -> Self { - // Call nonzero to keep information range information - // from get method. - nonzero.get() + /// Returns the value as a primitive type. + #[$stability] + #[inline] + #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] + pub const fn get(self) -> $Int { + // FIXME: Remove this after LLVM supports `!range` metadata for function + // arguments https://github.com/llvm/llvm-project/issues/76628 + // + // Rustc can set range metadata only if it loads `self` from + // memory somewhere. If the value of `self` was from by-value argument + // of some not-inlined function, LLVM don't have range metadata + // to understand that the value cannot be zero. + + // SAFETY: It is an invariant of this type. + unsafe { + intrinsics::assume(self.0 != 0); } + self.0 } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr for $Ty { - type Output = Self; - #[inline] - fn bitor(self, rhs: Self) -> Self::Output { - // SAFETY: since `self` and `rhs` are both nonzero, the - // result of the bitwise-or will be nonzero. - unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } - } + } + + #[stable(feature = "from_nonzero", since = "1.31.0")] + impl From<$Ty> for $Int { + #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] + #[inline] + fn from(nonzero: $Ty) -> Self { + // Call nonzero to keep information range information + // from get method. + nonzero.get() } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Int> for $Ty { - type Output = Self; - #[inline] - fn bitor(self, rhs: $Int) -> Self::Output { - // SAFETY: since `self` is nonzero, the result of the - // bitwise-or will be nonzero regardless of the value of - // `rhs`. - unsafe { $Ty::new_unchecked(self.get() | rhs) } - } + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr for $Ty { + type Output = Self; + #[inline] + fn bitor(self, rhs: Self) -> Self::Output { + // SAFETY: since `self` and `rhs` are both nonzero, the + // result of the bitwise-or will be nonzero. + unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOr<$Ty> for $Int { - type Output = $Ty; - #[inline] - fn bitor(self, rhs: $Ty) -> Self::Output { - // SAFETY: since `rhs` is nonzero, the result of the - // bitwise-or will be nonzero regardless of the value of - // `self`. - unsafe { $Ty::new_unchecked(self | rhs.get()) } - } + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr<$Int> for $Ty { + type Output = Self; + #[inline] + fn bitor(self, rhs: $Int) -> Self::Output { + // SAFETY: since `self` is nonzero, the result of the + // bitwise-or will be nonzero regardless of the value of + // `rhs`. + unsafe { $Ty::new_unchecked(self.get() | rhs) } } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: Self) { - *self = *self | rhs; - } + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOr<$Ty> for $Int { + type Output = $Ty; + #[inline] + fn bitor(self, rhs: $Ty) -> Self::Output { + // SAFETY: since `rhs` is nonzero, the result of the + // bitwise-or will be nonzero regardless of the value of + // `self`. + unsafe { $Ty::new_unchecked(self | rhs.get()) } } + } - #[stable(feature = "nonzero_bitor", since = "1.45.0")] - impl BitOrAssign<$Int> for $Ty { - #[inline] - fn bitor_assign(&mut self, rhs: $Int) { - *self = *self | rhs; - } + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOrAssign for $Ty { + #[inline] + fn bitor_assign(&mut self, rhs: Self) { + *self = *self | rhs; } + } - impl_nonzero_fmt! { - #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[stable(feature = "nonzero_bitor", since = "1.45.0")] + impl BitOrAssign<$Int> for $Ty { + #[inline] + fn bitor_assign(&mut self, rhs: $Int) { + *self = *self | rhs; } + } + + impl_nonzero_fmt! { + #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + } }; } From a6152cdd9a6c287411212209a18904ca5d68d484 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:24:16 -0800 Subject: [PATCH 07/31] Format nonzero_integer macro calls same way we do the primitive int impls The `key = $value` style will be beneficial as we introduce some more macro arguments here in later commits. --- library/core/src/num/nonzero.rs | 79 ++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index f7098bcf6e9c9..f6ccefa261415 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -24,7 +24,10 @@ macro_rules! impl_nonzero_fmt { macro_rules! nonzero_integer { ( - #[$stability:meta] #[$const_new_unchecked_stability:meta] $Ty:ident($Int:ty); + Self = $Ty:ident, + Primitive = $signedness:ident $Int:ident, + feature = $feature:literal, + original_stabilization = $since:literal, ) => { /// An integer that is known not to equal zero. /// @@ -56,7 +59,7 @@ macro_rules! nonzero_integer { /// ``` /// /// [null pointer optimization]: crate::option#representation - #[$stability] + #[stable(feature = $feature, since = $since)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -71,8 +74,8 @@ macro_rules! nonzero_integer { /// # Safety /// /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] + #[stable(feature = $feature, since = $since)] + #[rustc_const_stable(feature = $feature, since = $since)] #[must_use] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { @@ -87,7 +90,7 @@ macro_rules! nonzero_integer { } /// Creates a non-zero if the given value is not zero. - #[$stability] + #[stable(feature = $feature, since = $since)] #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] #[must_use] #[inline] @@ -101,7 +104,7 @@ macro_rules! nonzero_integer { } /// Returns the value as a primitive type. - #[$stability] + #[stable(feature = $feature, since = $since)] #[inline] #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] pub const fn get(self) -> $Int { @@ -119,7 +122,6 @@ macro_rules! nonzero_integer { } self.0 } - } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -185,7 +187,8 @@ macro_rules! nonzero_integer { } impl_nonzero_fmt! { - #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[stable(feature = $feature, since = $since)] + (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } }; } @@ -1383,49 +1386,85 @@ nonzero_bits! { } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); + Self = NonZeroU8, + Primitive = unsigned u8, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); + Self = NonZeroU16, + Primitive = unsigned u16, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); + Self = NonZeroU32, + Primitive = unsigned u32, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); + Self = NonZeroU64, + Primitive = unsigned u64, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); + Self = NonZeroU128, + Primitive = unsigned u128, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); + Self = NonZeroUsize, + Primitive = unsigned usize, + feature = "nonzero", + original_stabilization = "1.28.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); + Self = NonZeroI8, + Primitive = signed i8, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); + Self = NonZeroI16, + Primitive = signed i16, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); + Self = NonZeroI32, + Primitive = signed i32, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); + Self = NonZeroI64, + Primitive = signed i64, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); + Self = NonZeroI128, + Primitive = signed i128, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } nonzero_integer! { - #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); + Self = NonZeroIsize, + Primitive = signed isize, + feature = "signed_nonzero", + original_stabilization = "1.34.0", } From 3de0af1a4da54885dd312e5e6f39641f5da06410 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:28:52 -0800 Subject: [PATCH 08/31] Move 'impl FromStr for NonZero' into nonzero_integer macro --- library/core/src/num/nonzero.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index f6ccefa261415..0f5d421235e1a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -190,13 +190,9 @@ macro_rules! nonzero_integer { #[stable(feature = $feature, since = $since)] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } - }; -} -macro_rules! from_str_radix_nzint_impl { - ($($t:ty)*) => {$( #[stable(feature = "nonzero_parse", since = "1.35.0")] - impl FromStr for $t { + impl FromStr for $Ty { type Err = ParseIntError; fn from_str(src: &str) -> Result { Self::new(from_str_radix(src, 10)?) @@ -205,12 +201,9 @@ macro_rules! from_str_radix_nzint_impl { }) } } - )*} + }; } -from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize -NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } - macro_rules! nonzero_leading_trailing_zeros { ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { $( From 81e1a7c6b5bb5bea9fbbd0f5db0c118dbea867fb Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 18:41:24 -0800 Subject: [PATCH 09/31] Move impl Div and Rem into nonzero_integer macro --- library/core/src/num/nonzero.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0f5d421235e1a..79cca27647999 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -201,6 +201,8 @@ macro_rules! nonzero_integer { }) } } + + nonzero_integer_impl_div_rem!($Ty $signedness $Int); }; } @@ -275,9 +277,12 @@ nonzero_leading_trailing_zeros! { NonZeroIsize(usize), -1isize; } -macro_rules! nonzero_integers_div { - ( $( $Ty: ident($Int: ty); )+ ) => { - $( +macro_rules! nonzero_integer_impl_div_rem { + ($Ty:ident signed $Int:ty) => { + // nothing for signed ints + }; + + ($Ty:ident unsigned $Int:ty) => { #[stable(feature = "nonzero_div", since = "1.51.0")] impl Div<$Ty> for $Int { type Output = $Int; @@ -302,17 +307,7 @@ macro_rules! nonzero_integers_div { unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } } } - )+ - } -} - -nonzero_integers_div! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); + }; } // A bunch of methods for unsigned nonzero types only. From a78d9a6de1848358b3835d3ac8ce6b20a24c061f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:07:42 -0800 Subject: [PATCH 10/31] Unindent nonzero_integer_impl_div_rem macro body --- library/core/src/num/nonzero.rs | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 79cca27647999..75429d9059a69 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -283,30 +283,30 @@ macro_rules! nonzero_integer_impl_div_rem { }; ($Ty:ident unsigned $Int:ty) => { - #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Div<$Ty> for $Int { - type Output = $Int; - /// This operation rounds towards zero, - /// truncating any fractional part of the exact result, and cannot panic. - #[inline] - fn div(self, other: $Ty) -> $Int { - // SAFETY: div by zero is checked because `other` is a nonzero, - // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_div(self, other.get()) } - } + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Div<$Ty> for $Int { + type Output = $Int; + /// This operation rounds towards zero, + /// truncating any fractional part of the exact result, and cannot panic. + #[inline] + fn div(self, other: $Ty) -> $Int { + // SAFETY: div by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_div(self, other.get()) } } + } - #[stable(feature = "nonzero_div", since = "1.51.0")] - impl Rem<$Ty> for $Int { - type Output = $Int; - /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. - #[inline] - fn rem(self, other: $Ty) -> $Int { - // SAFETY: rem by zero is checked because `other` is a nonzero, - // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } - } + #[stable(feature = "nonzero_div", since = "1.51.0")] + impl Rem<$Ty> for $Int { + type Output = $Int; + /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. + #[inline] + fn rem(self, other: $Ty) -> $Int { + // SAFETY: rem by zero is checked because `other` is a nonzero, + // and MIN/-1 is checked because `self` is an unsigned int. + unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } } + } }; } From f846ed53e41a18fbb900e794467351fda5ffbb80 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:37:28 -0800 Subject: [PATCH 11/31] Move leading_zeros and trailing_zeros methods into nonzero_integer macro --- library/core/src/num/nonzero.rs | 146 ++++++++++++++++---------------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 75429d9059a69..9c396710fd488 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -26,8 +26,12 @@ macro_rules! nonzero_integer { ( Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, + UnsignedPrimitive = $UnsignedPrimitive:ty, feature = $feature:literal, original_stabilization = $since:literal, + + // Used in doc comments. + leading_zeros_test = $leading_zeros_test:expr, ) => { /// An integer that is known not to equal zero. /// @@ -122,6 +126,53 @@ macro_rules! nonzero_integer { } self.0 } + + /// Returns the number of leading zeros in the binary representation of `self`. + /// + /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($leading_zeros_test), ").unwrap();")] + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn leading_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. + unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] + /// + /// assert_eq!(n.trailing_zeros(), 3); + /// ``` + #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn trailing_zeros(self) -> u32 { + // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. + unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 } + } } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -206,77 +257,6 @@ macro_rules! nonzero_integer { }; } -macro_rules! nonzero_leading_trailing_zeros { - ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { - $( - impl $Ty { - /// Returns the number of leading zeros in the binary representation of `self`. - /// - /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")] - /// - /// assert_eq!(n.leading_zeros(), 0); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn leading_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. - unsafe { intrinsics::ctlz_nonzero(self.get() as $Uint) as u32 } - } - - /// Returns the number of trailing zeros in the binary representation - /// of `self`. - /// - /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] - /// - /// assert_eq!(n.trailing_zeros(), 3); - /// ``` - #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn trailing_zeros(self) -> u32 { - // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. - unsafe { intrinsics::cttz_nonzero(self.get() as $Uint) as u32 } - } - - } - )+ - } -} - -nonzero_leading_trailing_zeros! { - NonZeroU8(u8), u8::MAX; - NonZeroU16(u16), u16::MAX; - NonZeroU32(u32), u32::MAX; - NonZeroU64(u64), u64::MAX; - NonZeroU128(u128), u128::MAX; - NonZeroUsize(usize), usize::MAX; - NonZeroI8(u8), -1i8; - NonZeroI16(u16), -1i16; - NonZeroI32(u32), -1i32; - NonZeroI64(u64), -1i64; - NonZeroI128(u128), -1i128; - NonZeroIsize(usize), -1isize; -} - macro_rules! nonzero_integer_impl_div_rem { ($Ty:ident signed $Int:ty) => { // nothing for signed ints @@ -1376,83 +1356,107 @@ nonzero_bits! { nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, + UnsignedPrimitive = u8, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u8::MAX, } nonzero_integer! { Self = NonZeroU16, Primitive = unsigned u16, + UnsignedPrimitive = u16, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u16::MAX, } nonzero_integer! { Self = NonZeroU32, Primitive = unsigned u32, + UnsignedPrimitive = u32, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u32::MAX, } nonzero_integer! { Self = NonZeroU64, Primitive = unsigned u64, + UnsignedPrimitive = u64, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u64::MAX, } nonzero_integer! { Self = NonZeroU128, Primitive = unsigned u128, + UnsignedPrimitive = u128, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = u128::MAX, } nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, + UnsignedPrimitive = usize, feature = "nonzero", original_stabilization = "1.28.0", + leading_zeros_test = usize::MAX, } nonzero_integer! { Self = NonZeroI8, Primitive = signed i8, + UnsignedPrimitive = u8, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i8, } nonzero_integer! { Self = NonZeroI16, Primitive = signed i16, + UnsignedPrimitive = u16, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i16, } nonzero_integer! { Self = NonZeroI32, Primitive = signed i32, + UnsignedPrimitive = u32, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i32, } nonzero_integer! { Self = NonZeroI64, Primitive = signed i64, + UnsignedPrimitive = u64, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i64, } nonzero_integer! { Self = NonZeroI128, Primitive = signed i128, + UnsignedPrimitive = u128, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1i128, } nonzero_integer! { Self = NonZeroIsize, Primitive = signed isize, + UnsignedPrimitive = usize, feature = "signed_nonzero", original_stabilization = "1.34.0", + leading_zeros_test = -1isize, } From 757ed2566701feba8fc67cae3d21a7423254efba Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 21:50:14 -0800 Subject: [PATCH 12/31] Move Neg impl into the macro that generates Div and Rem --- library/core/src/num/nonzero.rs | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 9c396710fd488..b1dd766de315c 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -253,15 +253,12 @@ macro_rules! nonzero_integer { } } - nonzero_integer_impl_div_rem!($Ty $signedness $Int); + nonzero_integer_signedness_dependent_impls!($Ty $signedness $Int); }; } -macro_rules! nonzero_integer_impl_div_rem { - ($Ty:ident signed $Int:ty) => { - // nothing for signed ints - }; - +macro_rules! nonzero_integer_signedness_dependent_impls { + // Impls for unsigned nonzero types only. ($Ty:ident unsigned $Int:ty) => { #[stable(feature = "nonzero_div", since = "1.51.0")] impl Div<$Ty> for $Int { @@ -288,6 +285,23 @@ macro_rules! nonzero_integer_impl_div_rem { } } }; + + // Impls for signed nonzero types only. + ($Ty:ident signed $Int:ty) => { + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] + impl Neg for $Ty { + type Output = $Ty; + + #[inline] + fn neg(self) -> $Ty { + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().neg()) } + } + } + + forward_ref_unop! { impl Neg, neg for $Ty, + #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } + }; } // A bunch of methods for unsigned nonzero types only. @@ -921,20 +935,6 @@ macro_rules! nonzero_signed_operations { unsafe { $Ty::new_unchecked(result) } } } - - #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] - impl Neg for $Ty { - type Output = $Ty; - - #[inline] - fn neg(self) -> $Ty { - // SAFETY: negation of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().neg()) } - } - } - - forward_ref_unop! { impl Neg, neg for $Ty, - #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] } )+ } } From 4291b3ff62e4aad3dae4c573bde5f203d3baec79 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:03:55 -0800 Subject: [PATCH 13/31] Move signedness dependent methods into the omnibus impl block --- library/core/src/num/nonzero.rs | 65 +++++++++++++++------------------ 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index b1dd766de315c..1b8920f94774f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -26,6 +26,7 @@ macro_rules! nonzero_integer { ( Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, + $(UnsignedNonZero = $UnsignedNonZero:ident,)? UnsignedPrimitive = $UnsignedPrimitive:ty, feature = $feature:literal, original_stabilization = $since:literal, @@ -173,6 +174,13 @@ macro_rules! nonzero_integer { // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 } } + + nonzero_integer_signedness_dependent_methods! { + Self = $Ty, + Primitive = $signedness $Int, + $(UnsignedNonZero = $UnsignedNonZero,)? + UnsignedPrimitive = $UnsignedPrimitive, + } } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -304,11 +312,13 @@ macro_rules! nonzero_integer_signedness_dependent_impls { }; } -// A bunch of methods for unsigned nonzero types only. -macro_rules! nonzero_unsigned_operations { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { +macro_rules! nonzero_integer_signedness_dependent_methods { + // Methods for unsigned nonzero types only. + ( + Self = $Ty:ident, + Primitive = unsigned $Int:ident, + UnsignedPrimitive = $Uint:ty, + ) => { /// Adds an unsigned integer to a non-zero value. /// Checks for overflow and returns [`None`] on overflow. /// As a consequence, the result cannot wrap to zero. @@ -538,25 +548,15 @@ macro_rules! nonzero_unsigned_operations { // never being 0. unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } } - } - )+ - } -} - -nonzero_unsigned_operations! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); -} + }; -// A bunch of methods for signed nonzero types only. -macro_rules! nonzero_signed_operations { - ( $( $Ty: ident($Int: ty) -> $Uty: ident($Uint: ty); )+ ) => { - $( - impl $Ty { + // Methods for signed nonzero types only. + ( + Self = $Ty:ident, + Primitive = signed $Int:ident, + UnsignedNonZero = $Uty:ident, + UnsignedPrimitive = $Uint:ty, + ) => { /// Computes the absolute value of self. #[doc = concat!("See [`", stringify!($Int), "::abs`]")] /// for documentation on overflow behaviour. @@ -934,18 +934,7 @@ macro_rules! nonzero_signed_operations { // SAFETY: negation of nonzero cannot yield zero values. unsafe { $Ty::new_unchecked(result) } } - } - )+ - } -} - -nonzero_signed_operations! { - NonZeroI8(i8) -> NonZeroU8(u8); - NonZeroI16(i16) -> NonZeroU16(u16); - NonZeroI32(i32) -> NonZeroU32(u32); - NonZeroI64(i64) -> NonZeroU64(u64); - NonZeroI128(i128) -> NonZeroU128(u128); - NonZeroIsize(isize) -> NonZeroUsize(usize); + }; } // A bunch of methods for both signed and unsigned nonzero types. @@ -1410,6 +1399,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI8, Primitive = signed i8, + UnsignedNonZero = NonZeroU8, UnsignedPrimitive = u8, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1419,6 +1409,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI16, Primitive = signed i16, + UnsignedNonZero = NonZeroU16, UnsignedPrimitive = u16, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1428,6 +1419,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI32, Primitive = signed i32, + UnsignedNonZero = NonZeroU32, UnsignedPrimitive = u32, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1437,6 +1429,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI64, Primitive = signed i64, + UnsignedNonZero = NonZeroU64, UnsignedPrimitive = u64, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1446,6 +1439,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroI128, Primitive = signed i128, + UnsignedNonZero = NonZeroU128, UnsignedPrimitive = u128, feature = "signed_nonzero", original_stabilization = "1.34.0", @@ -1455,6 +1449,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroIsize, Primitive = signed isize, + UnsignedNonZero = NonZeroUsize, UnsignedPrimitive = usize, feature = "signed_nonzero", original_stabilization = "1.34.0", From b21b9cc901c3f021c7b7475c406662cd9c0d76e1 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:06:40 -0800 Subject: [PATCH 14/31] Unindent nonzero_integer_signedness_dependent_methods macro body --- library/core/src/num/nonzero.rs | 1178 +++++++++++++++---------------- 1 file changed, 589 insertions(+), 589 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1b8920f94774f..8550a7b4c7b68 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -319,235 +319,235 @@ macro_rules! nonzero_integer_signedness_dependent_methods { Primitive = unsigned $Int:ident, UnsignedPrimitive = $Uint:ty, ) => { - /// Adds an unsigned integer to a non-zero value. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(two), one.checked_add(1)); - /// assert_eq!(None, max.checked_add(1)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_add(self, other: $Int) -> Option<$Ty> { - if let Some(result) = self.get().checked_add(other) { - // SAFETY: - // - `checked_add` returns `None` on overflow - // - `self` is non-zero - // - the only way to get zero from an addition without overflow is for both - // sides to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } + /// Adds an unsigned integer to a non-zero value. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), one.checked_add(1)); + /// assert_eq!(None, max.checked_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add(self, other: $Int) -> Option<$Ty> { + if let Some(result) = self.get().checked_add(other) { + // SAFETY: + // - `checked_add` returns `None` on overflow + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } - /// Adds an unsigned integer to a non-zero value. - #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(two, one.saturating_add(1)); - /// assert_eq!(max, max.saturating_add(1)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_add(self, other: $Int) -> $Ty { - // SAFETY: - // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero - // - `self` is non-zero - // - the only way to get zero from an addition without overflow is for both - // sides to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } - } + /// Adds an unsigned integer to a non-zero value. + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(two, one.saturating_add(1)); + /// assert_eq!(max, max.saturating_add(1)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add(self, other: $Int) -> $Ty { + // SAFETY: + // - `saturating_add` returns `u*::MAX` on overflow, which is non-zero + // - `self` is non-zero + // - the only way to get zero from an addition without overflow is for both + // sides to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } + } - /// Adds an unsigned integer to a non-zero value, - /// assuming overflow cannot occur. - /// Overflow is unchecked, and it is undefined behaviour to overflow - /// *even if the result would wrap to a non-zero value*. - /// The behaviour is undefined as soon as - #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] - /// - /// # Examples - /// - /// ``` - /// #![feature(nonzero_ops)] - /// - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - /// - /// assert_eq!(two, unsafe { one.unchecked_add(1) }); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "nonzero_ops", issue = "84186")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { - // SAFETY: The caller ensures there is no overflow. - unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } - } + /// Adds an unsigned integer to a non-zero value, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + /// + /// assert_eq!(two, unsafe { one.unchecked_add(1) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } + } - /// Returns the smallest power of two greater than or equal to n. - /// Checks for overflow and returns [`None`] - /// if the next power of two is greater than the type’s maximum value. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(two), two.checked_next_power_of_two() ); - /// assert_eq!(Some(four), three.checked_next_power_of_two() ); - /// assert_eq!(None, max.checked_next_power_of_two() ); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_next_power_of_two(self) -> Option<$Ty> { - if let Some(nz) = self.get().checked_next_power_of_two() { - // SAFETY: The next power of two is positive - // and overflow is checked. - Some(unsafe { $Ty::new_unchecked(nz) }) - } else { - None - } - } + /// Returns the smallest power of two greater than or equal to n. + /// Checks for overflow and returns [`None`] + /// if the next power of two is greater than the type’s maximum value. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(two), two.checked_next_power_of_two() ); + /// assert_eq!(Some(four), three.checked_next_power_of_two() ); + /// assert_eq!(None, max.checked_next_power_of_two() ); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_next_power_of_two(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_next_power_of_two() { + // SAFETY: The next power of two is positive + // and overflow is checked. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None + } + } - /// Returns the base 2 logarithm of the number, rounded down. - /// - /// This is the same operation as - #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] - /// except that it has no failure cases to worry about - /// since this value can never be zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] - /// ``` - #[stable(feature = "int_log", since = "1.67.0")] - #[rustc_const_stable(feature = "int_log", since = "1.67.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn ilog2(self) -> u32 { - Self::BITS - 1 - self.leading_zeros() - } + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog2(self) -> u32 { + Self::BITS - 1 - self.leading_zeros() + } - /// Returns the base 10 logarithm of the number, rounded down. - /// - /// This is the same operation as - #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] - /// except that it has no failure cases to worry about - /// since this value can never be zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] - /// ``` - #[stable(feature = "int_log", since = "1.67.0")] - #[rustc_const_stable(feature = "int_log", since = "1.67.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn ilog10(self) -> u32 { - super::int_log10::$Int(self.get()) - } + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] + /// ``` + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn ilog10(self) -> u32 { + super::int_log10::$Int(self.get()) + } - /// Calculates the middle point of `self` and `rhs`. - /// - /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a - /// sufficiently-large signed integral type. This implies that the result is - /// always rounded towards negative infinity and that no overflow will ever occur. - /// - /// # Examples - /// - /// ``` - /// #![feature(num_midpoint)] - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - /// - /// assert_eq!(one.midpoint(four), two); - /// assert_eq!(four.midpoint(one), two); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "num_midpoint", issue = "110840")] - #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] - #[rustc_allow_const_fn_unstable(const_num_midpoint)] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn midpoint(self, rhs: Self) -> Self { - // SAFETY: The only way to get `0` with midpoint is to have two opposite or - // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because - // of the unsignedness of this number and also because $Ty is guaranteed to - // never being 0. - unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } - } + /// Calculates the middle point of `self` and `rhs`. + /// + /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a + /// sufficiently-large signed integral type. This implies that the result is + /// always rounded towards negative infinity and that no overflow will ever occur. + /// + /// # Examples + /// + /// ``` + /// #![feature(num_midpoint)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(one.midpoint(four), two); + /// assert_eq!(four.midpoint(one), two); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "num_midpoint", issue = "110840")] + #[rustc_const_unstable(feature = "const_num_midpoint", issue = "110840")] + #[rustc_allow_const_fn_unstable(const_num_midpoint)] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn midpoint(self, rhs: Self) -> Self { + // SAFETY: The only way to get `0` with midpoint is to have two opposite or + // near opposite numbers: (-5, 5), (0, 1), (0, 0) which is impossible because + // of the unsignedness of this number and also because $Ty is guaranteed to + // never being 0. + unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } + } }; // Methods for signed nonzero types only. @@ -557,383 +557,383 @@ macro_rules! nonzero_integer_signedness_dependent_methods { UnsignedNonZero = $Uty:ident, UnsignedPrimitive = $Uint:ty, ) => { - /// Computes the absolute value of self. - #[doc = concat!("See [`", stringify!($Int), "::abs`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - /// - /// assert_eq!(pos, pos.abs()); - /// assert_eq!(pos, neg.abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn abs(self) -> $Ty { - // SAFETY: This cannot overflow to zero. - unsafe { $Ty::new_unchecked(self.get().abs()) } - } + /// Computes the absolute value of self. + #[doc = concat!("See [`", stringify!($Int), "::abs`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + /// + /// assert_eq!(pos, pos.abs()); + /// assert_eq!(pos, neg.abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn abs(self) -> $Ty { + // SAFETY: This cannot overflow to zero. + unsafe { $Ty::new_unchecked(self.get().abs()) } + } - /// Checked absolute value. - /// Checks for overflow and returns [`None`] if - #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")] - /// The result cannot be zero. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(Some(pos), neg.checked_abs()); - /// assert_eq!(None, min.checked_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_abs(self) -> Option<$Ty> { - if let Some(nz) = self.get().checked_abs() { - // SAFETY: absolute value of nonzero cannot yield zero values. - Some(unsafe { $Ty::new_unchecked(nz) }) - } else { - None - } - } + /// Checked absolute value. + /// Checks for overflow and returns [`None`] if + #[doc = concat!("`self == ", stringify!($Ty), "::MIN`.")] + /// The result cannot be zero. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(Some(pos), neg.checked_abs()); + /// assert_eq!(None, min.checked_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_abs(self) -> Option<$Ty> { + if let Some(nz) = self.get().checked_abs() { + // SAFETY: absolute value of nonzero cannot yield zero values. + Some(unsafe { $Ty::new_unchecked(nz) }) + } else { + None + } + } - /// Computes the absolute value of self, - /// with overflow information, see - #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!((pos, false), pos.overflowing_abs()); - /// assert_eq!((pos, false), neg.overflowing_abs()); - /// assert_eq!((min, true), min.overflowing_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn overflowing_abs(self) -> ($Ty, bool) { - let (nz, flag) = self.get().overflowing_abs(); - ( - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(nz) }, - flag, - ) - } + /// Computes the absolute value of self, + /// with overflow information, see + #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!((pos, false), pos.overflowing_abs()); + /// assert_eq!((pos, false), neg.overflowing_abs()); + /// assert_eq!((min, true), min.overflowing_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_abs(self) -> ($Ty, bool) { + let (nz, flag) = self.get().overflowing_abs(); + ( + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(nz) }, + flag, + ) + } - /// Saturating absolute value, see - #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN + 1)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos, pos.saturating_abs()); - /// assert_eq!(pos, neg.saturating_abs()); - /// assert_eq!(max, min.saturating_abs()); - /// assert_eq!(max, min_plus.saturating_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_abs(self) -> $Ty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } - } + /// Saturating absolute value, see + #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.saturating_abs()); + /// assert_eq!(pos, neg.saturating_abs()); + /// assert_eq!(max, min.saturating_abs()); + /// assert_eq!(max, min_plus.saturating_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } + } - /// Wrapping absolute value, see - #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("# let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos, pos.wrapping_abs()); - /// assert_eq!(pos, neg.wrapping_abs()); - /// assert_eq!(min, min.wrapping_abs()); - /// assert_eq!(max, (-max).wrapping_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn wrapping_abs(self) -> $Ty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } - } + /// Wrapping absolute value, see + #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("# let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos, pos.wrapping_abs()); + /// assert_eq!(pos, neg.wrapping_abs()); + /// assert_eq!(min, min.wrapping_abs()); + /// assert_eq!(max, (-max).wrapping_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_abs(self) -> $Ty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } + } - /// Computes the absolute value of self - /// without any wrapping or panicking. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("# use std::num::", stringify!($Uty), ";")] - /// - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] - #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] - #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] - #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", - stringify!($Uint), "::MAX / 2 + 1)?;")] - /// - /// assert_eq!(u_pos, i_pos.unsigned_abs()); - /// assert_eq!(u_pos, i_neg.unsigned_abs()); - /// assert_eq!(u_max, i_min.unsigned_abs()); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn unsigned_abs(self) -> $Uty { - // SAFETY: absolute value of nonzero cannot yield zero values. - unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } - } + /// Computes the absolute value of self + /// without any wrapping or panicking. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("# use std::num::", stringify!($Uty), ";")] + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] + #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] + #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] + #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", + stringify!($Uint), "::MAX / 2 + 1)?;")] + /// + /// assert_eq!(u_pos, i_pos.unsigned_abs()); + /// assert_eq!(u_pos, i_neg.unsigned_abs()); + /// assert_eq!(u_max, i_min.unsigned_abs()); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn unsigned_abs(self) -> $Uty { + // SAFETY: absolute value of nonzero cannot yield zero values. + unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } + } - /// Returns `true` if `self` is positive and `false` if the - /// number is negative. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - /// - /// assert!(pos_five.is_positive()); - /// assert!(!neg_five.is_positive()); - /// # Some(()) - /// # } - /// ``` - #[must_use] - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn is_positive(self) -> bool { - self.get().is_positive() - } + /// Returns `true` if `self` is positive and `false` if the + /// number is negative. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(pos_five.is_positive()); + /// assert!(!neg_five.is_positive()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_positive(self) -> bool { + self.get().is_positive() + } - /// Returns `true` if `self` is negative and `false` if the - /// number is positive. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - /// - /// assert!(neg_five.is_negative()); - /// assert!(!pos_five.is_negative()); - /// # Some(()) - /// # } - /// ``` - #[must_use] - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn is_negative(self) -> bool { - self.get().is_negative() - } + /// Returns `true` if `self` is negative and `false` if the + /// number is positive. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + /// + /// assert!(neg_five.is_negative()); + /// assert!(!pos_five.is_negative()); + /// # Some(()) + /// # } + /// ``` + #[must_use] + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn is_negative(self) -> bool { + self.get().is_negative() + } - /// Checked negation. Computes `-self`, - #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")] - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); - /// assert_eq!(min.checked_neg(), None); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn checked_neg(self) -> Option<$Ty> { - if let Some(result) = self.get().checked_neg() { - // SAFETY: negation of nonzero cannot yield zero values. - return Some(unsafe { $Ty::new_unchecked(result) }); - } - None - } + /// Checked negation. Computes `-self`, + #[doc = concat!("returning `None` if `self == ", stringify!($Ty), "::MIN`.")] + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); + /// assert_eq!(min.checked_neg(), None); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn checked_neg(self) -> Option<$Ty> { + if let Some(result) = self.get().checked_neg() { + // SAFETY: negation of nonzero cannot yield zero values. + return Some(unsafe { $Ty::new_unchecked(result) }); + } + None + } - /// Negates self, overflowing if this is equal to the minimum value. - /// - #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); - /// assert_eq!(min.overflowing_neg(), (min, true)); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn overflowing_neg(self) -> ($Ty, bool) { - let (result, overflow) = self.get().overflowing_neg(); - // SAFETY: negation of nonzero cannot yield zero values. - ((unsafe { $Ty::new_unchecked(result) }), overflow) - } + /// Negates self, overflowing if this is equal to the minimum value. + /// + #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); + /// assert_eq!(min.overflowing_neg(), (min, true)); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn overflowing_neg(self) -> ($Ty, bool) { + let (result, overflow) = self.get().overflowing_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + ((unsafe { $Ty::new_unchecked(result) }), overflow) + } - /// Saturating negation. Computes `-self`, - #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")] - #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")] - /// instead of overflowing. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN + 1)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(pos_five.saturating_neg(), neg_five); - /// assert_eq!(min.saturating_neg(), max); - /// assert_eq!(max.saturating_neg(), min_plus_one); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn saturating_neg(self) -> $Ty { - if let Some(result) = self.checked_neg() { - return result; - } - $Ty::MAX - } + /// Saturating negation. Computes `-self`, + #[doc = concat!("returning [`", stringify!($Ty), "::MAX`]")] + #[doc = concat!("if `self == ", stringify!($Ty), "::MIN`")] + /// instead of overflowing. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN + 1)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(pos_five.saturating_neg(), neg_five); + /// assert_eq!(min.saturating_neg(), max); + /// assert_eq!(max.saturating_neg(), min_plus_one); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn saturating_neg(self) -> $Ty { + if let Some(result) = self.checked_neg() { + return result; + } + $Ty::MAX + } - /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary - /// of the type. - /// - #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] - /// for documentation on overflow behaviour. - /// - /// # Example - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] - #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] - #[doc = concat!("let min = ", stringify!($Ty), "::new(", - stringify!($Int), "::MIN)?;")] - /// - /// assert_eq!(pos_five.wrapping_neg(), neg_five); - /// assert_eq!(min.wrapping_neg(), min); - /// # Some(()) - /// # } - /// ``` - #[inline] - #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] - #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] - pub const fn wrapping_neg(self) -> $Ty { - let result = self.get().wrapping_neg(); - // SAFETY: negation of nonzero cannot yield zero values. - unsafe { $Ty::new_unchecked(result) } - } + /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary + /// of the type. + /// + #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] + /// for documentation on overflow behaviour. + /// + /// # Example + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] + #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] + #[doc = concat!("let min = ", stringify!($Ty), "::new(", + stringify!($Int), "::MIN)?;")] + /// + /// assert_eq!(pos_five.wrapping_neg(), neg_five); + /// assert_eq!(min.wrapping_neg(), min); + /// # Some(()) + /// # } + /// ``` + #[inline] + #[stable(feature = "nonzero_negation_ops", since = "1.71.0")] + #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")] + pub const fn wrapping_neg(self) -> $Ty { + let result = self.get().wrapping_neg(); + // SAFETY: negation of nonzero cannot yield zero values. + unsafe { $Ty::new_unchecked(result) } + } }; } From c6d776ef4ba4f133b5f370f144b99cd3f39388fa Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:38:38 -0800 Subject: [PATCH 15/31] Work around rustfmt doc attribute indentation bug --- library/core/src/num/nonzero.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8550a7b4c7b68..6b28f8100e78a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -312,6 +312,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { }; } +#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5974 macro_rules! nonzero_integer_signedness_dependent_methods { // Methods for unsigned nonzero types only. ( From 63256af236f4620701d7d8771f874c4ef57e6ff2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:46:18 -0800 Subject: [PATCH 16/31] Move nonzero_unsigned_signed_operations methods into the omnibus impl block --- library/core/src/num/nonzero.rs | 426 +++++++++++++++----------------- 1 file changed, 201 insertions(+), 225 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6b28f8100e78a..c9693a22e8761 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -181,6 +181,207 @@ macro_rules! nonzero_integer { $(UnsignedNonZero = $UnsignedNonZero,)? UnsignedPrimitive = $UnsignedPrimitive, } + + /// Multiplies two non-zero integers together. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(Some(four), two.checked_mul(two)); + /// assert_eq!(None, max.checked_mul(two)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { + if let Some(result) = self.get().checked_mul(other.get()) { + // SAFETY: + // - `checked_mul` returns `None` on overflow + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } + + /// Multiplies two non-zero integers together. + #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(four, two.saturating_mul(two)); + /// assert_eq!(max, four.saturating_mul(max)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_mul(self, other: $Ty) -> $Ty { + // SAFETY: + // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` and `other` are non-zero + // - the only way to get zero from a multiplication without overflow is for one + // of the sides to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } + } + + /// Multiplies two non-zero integers together, + /// assuming overflow cannot occur. + /// Overflow is unchecked, and it is undefined behaviour to overflow + /// *even if the result would wrap to a non-zero value*. + /// The behaviour is undefined as soon as + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", + "or `self * rhs < ", stringify!($Int), "::MIN`.") + } + if unsigned { + concat!("`self * rhs > ", stringify!($Int), "::MAX`.") + } + }] + /// + /// # Examples + /// + /// ``` + /// #![feature(nonzero_ops)] + /// + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] + #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] + /// + /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); + /// # Some(()) + /// # } + /// ``` + #[unstable(feature = "nonzero_ops", issue = "84186")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { + // SAFETY: The caller ensures there is no overflow. + unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } + } + + /// Raises non-zero value to an integer power. + /// Checks for overflow and returns [`None`] on overflow. + /// As a consequence, the result cannot wrap to zero. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX / 2)?;")] + /// + /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); + /// assert_eq!(None, half_max.checked_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_pow(self, other: u32) -> Option<$Ty> { + if let Some(result) = self.get().checked_pow(other) { + // SAFETY: + // - `checked_pow` returns `None` on overflow/underflow + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + Some(unsafe { $Ty::new_unchecked(result) }) + } else { + None + } + } + + /// Raise non-zero value to an integer power. + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + concat!("Return [`", stringify!($Ty), "::MIN`] ", + "or [`", stringify!($Ty), "::MAX`] on overflow.") + } + if unsigned { + concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.") + } + }] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// # fn main() { test().unwrap(); } + /// # fn test() -> Option<()> { + #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] + #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] + #[doc = concat!("let max = ", stringify!($Ty), "::new(", + stringify!($Int), "::MAX)?;")] + /// + /// assert_eq!(twenty_seven, three.saturating_pow(3)); + /// assert_eq!(max, max.saturating_pow(3)); + /// # Some(()) + /// # } + /// ``` + #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] + #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_pow(self, other: u32) -> $Ty { + // SAFETY: + // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, + // all of which are non-zero + // - `self` is non-zero + // - the only way to get zero from an exponentiation without overflow is + // for base to be zero + // + // So the result cannot be zero. + unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } + } } #[stable(feature = "from_nonzero", since = "1.31.0")] @@ -938,216 +1139,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods { }; } -// A bunch of methods for both signed and unsigned nonzero types. -macro_rules! nonzero_unsigned_signed_operations { - ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => { - $( - impl $Ty { - /// Multiplies two non-zero integers together. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(Some(four), two.checked_mul(two)); - /// assert_eq!(None, max.checked_mul(two)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { - if let Some(result) = self.get().checked_mul(other.get()) { - // SAFETY: - // - `checked_mul` returns `None` on overflow - // - `self` and `other` are non-zero - // - the only way to get zero from a multiplication without overflow is for one - // of the sides to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } - - /// Multiplies two non-zero integers together. - #[doc = concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(four, two.saturating_mul(two)); - /// assert_eq!(max, four.saturating_mul(max)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_mul(self, other: $Ty) -> $Ty { - // SAFETY: - // - `saturating_mul` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, - // all of which are non-zero - // - `self` and `other` are non-zero - // - the only way to get zero from a multiplication without overflow is for one - // of the sides to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } - } - - /// Multiplies two non-zero integers together, - /// assuming overflow cannot occur. - /// Overflow is unchecked, and it is undefined behaviour to overflow - /// *even if the result would wrap to a non-zero value*. - /// The behaviour is undefined as soon as - #[doc = sign_dependent_expr!{ - $signedness ? - if signed { - concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", - "or `self * rhs < ", stringify!($Int), "::MIN`.") - } - if unsigned { - concat!("`self * rhs > ", stringify!($Int), "::MAX`.") - } - }] - /// - /// # Examples - /// - /// ``` - /// #![feature(nonzero_ops)] - /// - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] - #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] - /// - /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); - /// # Some(()) - /// # } - /// ``` - #[unstable(feature = "nonzero_ops", issue = "84186")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { - // SAFETY: The caller ensures there is no overflow. - unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } - } - - /// Raises non-zero value to an integer power. - /// Checks for overflow and returns [`None`] on overflow. - /// As a consequence, the result cannot wrap to zero. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] - #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX / 2)?;")] - /// - /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); - /// assert_eq!(None, half_max.checked_pow(3)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn checked_pow(self, other: u32) -> Option<$Ty> { - if let Some(result) = self.get().checked_pow(other) { - // SAFETY: - // - `checked_pow` returns `None` on overflow/underflow - // - `self` is non-zero - // - the only way to get zero from an exponentiation without overflow is - // for base to be zero - // - // So the result cannot be zero. - Some(unsafe { $Ty::new_unchecked(result) }) - } else { - None - } - } - - /// Raise non-zero value to an integer power. - #[doc = sign_dependent_expr!{ - $signedness ? - if signed { - concat!("Return [`", stringify!($Ty), "::MIN`] ", - "or [`", stringify!($Ty), "::MAX`] on overflow.") - } - if unsigned { - concat!("Return [`", stringify!($Ty), "::MAX`] on overflow.") - } - }] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// # fn main() { test().unwrap(); } - /// # fn test() -> Option<()> { - #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] - #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] - #[doc = concat!("let max = ", stringify!($Ty), "::new(", - stringify!($Int), "::MAX)?;")] - /// - /// assert_eq!(twenty_seven, three.saturating_pow(3)); - /// assert_eq!(max, max.saturating_pow(3)); - /// # Some(()) - /// # } - /// ``` - #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] - #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn saturating_pow(self, other: u32) -> $Ty { - // SAFETY: - // - `saturating_pow` returns `u*::MAX`/`i*::MAX`/`i*::MIN` on overflow/underflow, - // all of which are non-zero - // - `self` is non-zero - // - the only way to get zero from an exponentiation without overflow is - // for base to be zero - // - // So the result cannot be zero. - unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } - } - } - )+ - } -} - // Use this when the generated code should differ between signed and unsigned types. macro_rules! sign_dependent_expr { (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { @@ -1158,21 +1149,6 @@ macro_rules! sign_dependent_expr { }; } -nonzero_unsigned_signed_operations! { - unsigned NonZeroU8(u8); - unsigned NonZeroU16(u16); - unsigned NonZeroU32(u32); - unsigned NonZeroU64(u64); - unsigned NonZeroU128(u128); - unsigned NonZeroUsize(usize); - signed NonZeroI8(i8); - signed NonZeroI16(i16); - signed NonZeroI32(i32); - signed NonZeroI64(i64); - signed NonZeroI128(i128); - signed NonZeroIsize(isize); -} - macro_rules! nonzero_unsigned_is_power_of_two { ( $( $Ty: ident )+ ) => { $( From 441913626d33919b743e167c5c9e951487291fdd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:47:53 -0800 Subject: [PATCH 17/31] Move is_power_of_two into unsigned part of signedness_dependent_methods --- library/core/src/num/nonzero.rs | 68 ++++++++++++++------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index c9693a22e8761..0c34012ab5c61 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -750,6 +750,34 @@ macro_rules! nonzero_integer_signedness_dependent_methods { // never being 0. unsafe { $Ty::new_unchecked(self.get().midpoint(rhs.get())) } } + + /// Returns `true` if and only if `self == (1 << k)` for some `k`. + /// + /// On many architectures, this function can perform better than `is_power_of_two()` + /// on the underlying integer type, as special handling of zero can be avoided. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] + /// assert!(eight.is_power_of_two()); + #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] + /// assert!(!ten.is_power_of_two()); + /// ``` + #[must_use] + #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[inline] + pub const fn is_power_of_two(self) -> bool { + // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. + // On the basic x86-64 target, this saves 3 instructions for the zero check. + // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction + // compared to the `POPCNT` implementation on the underlying integer type. + + intrinsics::ctpop(self.get()) < 2 + } }; // Methods for signed nonzero types only. @@ -1149,46 +1177,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_unsigned_is_power_of_two { - ( $( $Ty: ident )+ ) => { - $( - impl $Ty { - - /// Returns `true` if and only if `self == (1 << k)` for some `k`. - /// - /// On many architectures, this function can perform better than `is_power_of_two()` - /// on the underlying integer type, as special handling of zero can be avoided. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] - /// assert!(eight.is_power_of_two()); - #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] - /// assert!(!ten.is_power_of_two()); - /// ``` - #[must_use] - #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] - #[inline] - pub const fn is_power_of_two(self) -> bool { - // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. - // On the basic x86-64 target, this saves 3 instructions for the zero check. - // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction - // compared to the `POPCNT` implementation on the underlying integer type. - - intrinsics::ctpop(self.get()) < 2 - } - - } - )+ - } -} - -nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize } - macro_rules! nonzero_min_max_unsigned { ( $( $Ty: ident($Int: ident); )+ ) => { $( From 7f7c5af097678da556cd57936a8d8b6c02858502 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:49:44 -0800 Subject: [PATCH 18/31] Move unsigned MIN and MAX into signedness_dependent_methods --- library/core/src/num/nonzero.rs | 69 +++++++++++++-------------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0c34012ab5c61..0ab89aa0d6c24 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -515,12 +515,37 @@ macro_rules! nonzero_integer_signedness_dependent_impls { #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5974 macro_rules! nonzero_integer_signedness_dependent_methods { - // Methods for unsigned nonzero types only. + // Associated items for unsigned nonzero types only. ( Self = $Ty:ident, Primitive = unsigned $Int:ident, UnsignedPrimitive = $Uint:ty, ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, 1. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(1).unwrap(); + + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); + /// Adds an unsigned integer to a non-zero value. /// Checks for overflow and returns [`None`] on overflow. /// As a consequence, the result cannot wrap to zero. @@ -1177,39 +1202,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_min_max_unsigned { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { - /// The smallest value that can be represented by this non-zero - /// integer type, 1. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MIN: Self = Self::new(1).unwrap(); - - /// The largest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); - } - )+ - } -} - macro_rules! nonzero_min_max_signed { ( $( $Ty: ident($Int: ident); )+ ) => { $( @@ -1252,15 +1244,6 @@ macro_rules! nonzero_min_max_signed { } } -nonzero_min_max_unsigned! { - NonZeroU8(u8); - NonZeroU16(u16); - NonZeroU32(u32); - NonZeroU64(u64); - NonZeroU128(u128); - NonZeroUsize(usize); -} - nonzero_min_max_signed! { NonZeroI8(i8); NonZeroI16(i16); From 66cda3b75fb35655076b1fa555bf4f95fdd9b54e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:50:31 -0800 Subject: [PATCH 19/31] Move signed MIN and MAX into signedness_dependent_methods --- library/core/src/num/nonzero.rs | 87 +++++++++++++-------------------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0ab89aa0d6c24..9c48a5b0dbddd 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -805,13 +805,47 @@ macro_rules! nonzero_integer_signedness_dependent_methods { } }; - // Methods for signed nonzero types only. + // Associated items for signed nonzero types only. ( Self = $Ty:ident, Primitive = signed $Int:ident, UnsignedNonZero = $Uty:ident, UnsignedPrimitive = $Uint:ty, ) => { + /// The smallest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); + + /// The largest value that can be represented by this non-zero + /// integer type, + #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] + /// + /// Note: While most integer types are defined for every whole + /// number between `MIN` and `MAX`, signed non-zero integers are + /// a special case. They have a "gap" at 0. + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] + /// ``` + #[stable(feature = "nonzero_min_max", since = "1.70.0")] + pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); + /// Computes the absolute value of self. #[doc = concat!("See [`", stringify!($Int), "::abs`]")] /// for documentation on overflow behaviour. @@ -1202,57 +1236,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_min_max_signed { - ( $( $Ty: ident($Int: ident); )+ ) => { - $( - impl $Ty { - /// The smallest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] - /// - /// Note: While most integer types are defined for every whole - /// number between `MIN` and `MAX`, signed non-zero integers are - /// a special case. They have a "gap" at 0. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); - - /// The largest value that can be represented by this non-zero - /// integer type, - #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] - /// - /// Note: While most integer types are defined for every whole - /// number between `MIN` and `MAX`, signed non-zero integers are - /// a special case. They have a "gap" at 0. - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] - /// ``` - #[stable(feature = "nonzero_min_max", since = "1.70.0")] - pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); - } - )+ - } -} - -nonzero_min_max_signed! { - NonZeroI8(i8); - NonZeroI16(i16); - NonZeroI32(i32); - NonZeroI64(i64); - NonZeroI128(i128); - NonZeroIsize(isize); -} - macro_rules! nonzero_bits { ( $( $Ty: ident($Int: ty); )+ ) => { $( From c53713274cc6c04cad7b903c597ff54e4cdc8d27 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Tue, 5 Dec 2023 22:52:20 -0800 Subject: [PATCH 20/31] Move BITS into omnibus impl block --- library/core/src/num/nonzero.rs | 51 +++++++++------------------------ 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 9c48a5b0dbddd..0b42b628675ad 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -128,6 +128,20 @@ macro_rules! nonzero_integer { self.0 } + /// The size of this non-zero integer type in bits. + /// + #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] + /// + /// # Examples + /// + /// ``` + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] + /// ``` + #[stable(feature = "nonzero_bits", since = "1.67.0")] + pub const BITS: u32 = <$Int>::BITS; + /// Returns the number of leading zeros in the binary representation of `self`. /// /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. @@ -1236,43 +1250,6 @@ macro_rules! sign_dependent_expr { }; } -macro_rules! nonzero_bits { - ( $( $Ty: ident($Int: ty); )+ ) => { - $( - impl $Ty { - /// The size of this non-zero integer type in bits. - /// - #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("# use std::num::", stringify!($Ty), ";")] - /// - #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] - /// ``` - #[stable(feature = "nonzero_bits", since = "1.67.0")] - pub const BITS: u32 = <$Int>::BITS; - } - )+ - } -} - -nonzero_bits! { - NonZeroU8(u8); - NonZeroI8(i8); - NonZeroU16(u16); - NonZeroI16(i16); - NonZeroU32(u32); - NonZeroI32(i32); - NonZeroU64(u64); - NonZeroI64(i64); - NonZeroU128(u128); - NonZeroI128(i128); - NonZeroUsize(usize); - NonZeroIsize(isize); -} - nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, From cdee1feb49989f13e5091c591fbba90ef9278add Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Wed, 6 Dec 2023 00:41:18 -0800 Subject: [PATCH 21/31] Unbreak tidy's feature parser tidy error: /git/rust/library/core/src/num/nonzero.rs:67: malformed stability attribute: missing `feature` key tidy error: /git/rust/library/core/src/num/nonzero.rs:82: malformed stability attribute: missing `feature` key tidy error: /git/rust/library/core/src/num/nonzero.rs:98: malformed stability attribute: missing the `since` key tidy error: /git/rust/library/core/src/num/nonzero.rs:112: malformed stability attribute: missing `feature` key tidy error: /git/rust/library/core/src/num/nonzero.rs:450: malformed stability attribute: missing `feature` key some tidy checks failed --- library/core/src/num/nonzero.rs | 83 ++++++++++++--------------------- 1 file changed, 31 insertions(+), 52 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0b42b628675ad..174fa200737c0 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -24,12 +24,12 @@ macro_rules! impl_nonzero_fmt { macro_rules! nonzero_integer { ( + #[$stability:meta] + #[$const_new_unchecked_stability:meta] Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, $(UnsignedNonZero = $UnsignedNonZero:ident,)? UnsignedPrimitive = $UnsignedPrimitive:ty, - feature = $feature:literal, - original_stabilization = $since:literal, // Used in doc comments. leading_zeros_test = $leading_zeros_test:expr, @@ -64,7 +64,7 @@ macro_rules! nonzero_integer { /// ``` /// /// [null pointer optimization]: crate::option#representation - #[stable(feature = $feature, since = $since)] + #[$stability] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] @@ -79,8 +79,8 @@ macro_rules! nonzero_integer { /// # Safety /// /// The value must not be zero. - #[stable(feature = $feature, since = $since)] - #[rustc_const_stable(feature = $feature, since = $since)] + #[$stability] + #[$const_new_unchecked_stability] #[must_use] #[inline] pub const unsafe fn new_unchecked(n: $Int) -> Self { @@ -95,7 +95,7 @@ macro_rules! nonzero_integer { } /// Creates a non-zero if the given value is not zero. - #[stable(feature = $feature, since = $since)] + #[$stability] #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] #[must_use] #[inline] @@ -109,7 +109,7 @@ macro_rules! nonzero_integer { } /// Returns the value as a primitive type. - #[stable(feature = $feature, since = $since)] + #[$stability] #[inline] #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] pub const fn get(self) -> $Int { @@ -151,7 +151,7 @@ macro_rules! nonzero_integer { /// Basic usage: /// /// ``` - #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($leading_zeros_test), ").unwrap();")] + #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", $leading_zeros_test, ").unwrap();")] /// /// assert_eq!(n.leading_zeros(), 0); /// ``` @@ -461,8 +461,7 @@ macro_rules! nonzero_integer { } impl_nonzero_fmt! { - #[stable(feature = $feature, since = $since)] - (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty + #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty } #[stable(feature = "nonzero_parse", since = "1.35.0")] @@ -478,6 +477,28 @@ macro_rules! nonzero_integer { nonzero_integer_signedness_dependent_impls!($Ty $signedness $Int); }; + + (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => { + nonzero_integer! { + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] + Self = $Ty, + Primitive = unsigned $Int, + UnsignedPrimitive = $Int, + leading_zeros_test = concat!(stringify!($Int), "::MAX"), + } + }; + + (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => { + nonzero_integer! { + #[stable(feature = "signed_nonzero", since = "1.34.0")] + #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] + Self = $Ty, + Primitive = signed $Int, + $($rest)* + leading_zeros_test = concat!("-1", stringify!($Int)), + } + }; } macro_rules! nonzero_integer_signedness_dependent_impls { @@ -1253,55 +1274,31 @@ macro_rules! sign_dependent_expr { nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, - UnsignedPrimitive = u8, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u8::MAX, } nonzero_integer! { Self = NonZeroU16, Primitive = unsigned u16, - UnsignedPrimitive = u16, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u16::MAX, } nonzero_integer! { Self = NonZeroU32, Primitive = unsigned u32, - UnsignedPrimitive = u32, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u32::MAX, } nonzero_integer! { Self = NonZeroU64, Primitive = unsigned u64, - UnsignedPrimitive = u64, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u64::MAX, } nonzero_integer! { Self = NonZeroU128, Primitive = unsigned u128, - UnsignedPrimitive = u128, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = u128::MAX, } nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, - UnsignedPrimitive = usize, - feature = "nonzero", - original_stabilization = "1.28.0", - leading_zeros_test = usize::MAX, } nonzero_integer! { @@ -1309,9 +1306,6 @@ nonzero_integer! { Primitive = signed i8, UnsignedNonZero = NonZeroU8, UnsignedPrimitive = u8, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i8, } nonzero_integer! { @@ -1319,9 +1313,6 @@ nonzero_integer! { Primitive = signed i16, UnsignedNonZero = NonZeroU16, UnsignedPrimitive = u16, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i16, } nonzero_integer! { @@ -1329,9 +1320,6 @@ nonzero_integer! { Primitive = signed i32, UnsignedNonZero = NonZeroU32, UnsignedPrimitive = u32, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i32, } nonzero_integer! { @@ -1339,9 +1327,6 @@ nonzero_integer! { Primitive = signed i64, UnsignedNonZero = NonZeroU64, UnsignedPrimitive = u64, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i64, } nonzero_integer! { @@ -1349,9 +1334,6 @@ nonzero_integer! { Primitive = signed i128, UnsignedNonZero = NonZeroU128, UnsignedPrimitive = u128, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1i128, } nonzero_integer! { @@ -1359,7 +1341,4 @@ nonzero_integer! { Primitive = signed isize, UnsignedNonZero = NonZeroUsize, UnsignedPrimitive = usize, - feature = "signed_nonzero", - original_stabilization = "1.34.0", - leading_zeros_test = -1isize, } From c1c7707238bd58242588d75a350def4ceb59c581 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 02:11:55 +0000 Subject: [PATCH 22/31] Deny braced macro invocations in let-else --- compiler/rustc_ast/src/util/classify.rs | 10 +++++-- tests/ui/parser/bad-let-else-statement.rs | 25 +++++++++++++++++ tests/ui/parser/bad-let-else-statement.stderr | 28 ++++++++++++++++++- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index 65036bcdc36fd..098b8f2d6d038 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -2,7 +2,7 @@ // Predicates on exprs and stmts that the pretty-printer and parser use -use crate::ast; +use crate::{ast, token::Delimiter}; /// Does this expression require a semicolon to be treated /// as a statement? The negation of this: 'can this expression @@ -59,8 +59,12 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> { | While(..) | ConstBlock(_) => break Some(expr), - // FIXME: These can end in `}`, but changing these would break stable code. - InlineAsm(_) | OffsetOf(_, _) | MacCall(_) | IncludedBytes(_) | FormatArgs(_) => { + MacCall(mac) => { + break (mac.args.delim == Delimiter::Brace).then_some(expr); + } + + InlineAsm(_) | OffsetOf(_, _) | IncludedBytes(_) | FormatArgs(_) => { + // These should have been denied pre-expansion. break None; } diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index 7b927c89ba074..a42e8c41c2efd 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -161,4 +161,29 @@ fn q() { }; } +fn r() { + let ok = format_args!("") else { return; }; + + let bad = format_args! {""} else { return; }; + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed +} + +fn s() { + macro_rules! a { + () => { {} } + } + + macro_rules! b { + (1) => { + let x = a!() else { return; }; + }; + (2) => { + let x = a! {} else { return; }; + //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + }; + } + + b!(1); b!(2); +} + fn main() {} diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 7cbda25e417f3..4ea924ddcb806 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -228,5 +228,31 @@ LL | x LL ~ }) else { | -error: aborting due to 17 previous errors +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/bad-let-else-statement.rs:167:31 + | +LL | let bad = format_args! {""} else { return; }; + | ^ + | +help: wrap the expression in parentheses + | +LL | let bad = (format_args! {""}) else { return; }; + | + + + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/bad-let-else-statement.rs:181:25 + | +LL | let x = a! {} else { return; }; + | ^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) +help: wrap the expression in parentheses + | +LL | let x = (a! {}) else { return; }; + | + + + +error: aborting due to 19 previous errors From ec263df5e440598159f19a42c104c3b5f13888a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 18 Dec 2023 03:01:05 +0000 Subject: [PATCH 23/31] Suggest wrapping mac args in parens rather than the whole expression --- compiler/rustc_parse/messages.ftl | 2 + compiler/rustc_parse/src/errors.rs | 37 +++++++++++++------ compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 15 ++++++-- tests/ui/parser/bad-let-else-statement.stderr | 12 +++--- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index d515e86a18296..e3ecd24b6a5f0 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -722,6 +722,8 @@ parse_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifeti parse_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses +parse_sugg_wrap_macro_in_parentheses = use parentheses instead of braces for this macro + parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses parse_switch_mut_let_order = diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 34b34a1bad6c9..8f57b2eb5aa97 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -722,19 +722,32 @@ pub(crate) struct LabeledLoopInBreak { #[primary_span] pub span: Span, #[subdiagnostic] - pub sub: WrapExpressionInParentheses, + pub sub: WrapInParentheses, } #[derive(Subdiagnostic)] -#[multipart_suggestion( - parse_sugg_wrap_expression_in_parentheses, - applicability = "machine-applicable" -)] -pub(crate) struct WrapExpressionInParentheses { - #[suggestion_part(code = "(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, + +pub(crate) enum WrapInParentheses { + #[multipart_suggestion( + parse_sugg_wrap_expression_in_parentheses, + applicability = "machine-applicable" + )] + Expression { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, + #[multipart_suggestion( + parse_sugg_wrap_macro_in_parentheses, + applicability = "machine-applicable" + )] + MacroArgs { + #[suggestion_part(code = "(")] + left: Span, + #[suggestion_part(code = ")")] + right: Span, + }, } #[derive(Diagnostic)] @@ -936,7 +949,7 @@ pub(crate) struct InvalidExpressionInLetElse { pub span: Span, pub operator: &'static str, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] @@ -945,7 +958,7 @@ pub(crate) struct InvalidCurlyInLetElse { #[primary_span] pub span: Span, #[subdiagnostic] - pub sugg: WrapExpressionInParentheses, + pub sugg: WrapInParentheses, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8ca02452342b2..f858706805dbc 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1844,7 +1844,7 @@ impl<'a> Parser<'a> { let lexpr = self.parse_expr_labeled(label, true)?; self.dcx().emit_err(errors::LabeledLoopInBreak { span: lexpr.span, - sub: errors::WrapExpressionInParentheses { + sub: errors::WrapInParentheses::Expression { left: lexpr.span.shrink_to_lo(), right: lexpr.span.shrink_to_hi(), }, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1a8bbf0a15722..1bae5b3224035 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -389,7 +389,7 @@ impl<'a> Parser<'a> { self.dcx().emit_err(errors::InvalidExpressionInLetElse { span: init.span, operator: op.node.as_str(), - sugg: errors::WrapExpressionInParentheses { + sugg: errors::WrapInParentheses::Expression { left: init.span.shrink_to_lo(), right: init.span.shrink_to_hi(), }, @@ -400,12 +400,19 @@ impl<'a> Parser<'a> { fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) { if let Some(trailing) = classify::expr_trailing_brace(init) { - self.dcx().emit_err(errors::InvalidCurlyInLetElse { - span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), - sugg: errors::WrapExpressionInParentheses { + let sugg = match &trailing.kind { + ExprKind::MacCall(mac) => errors::WrapInParentheses::MacroArgs { + left: mac.args.dspan.open, + right: mac.args.dspan.close, + }, + _ => errors::WrapInParentheses::Expression { left: trailing.span.shrink_to_lo(), right: trailing.span.shrink_to_hi(), }, + }; + self.dcx().emit_err(errors::InvalidCurlyInLetElse { + span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)), + sugg, }); } } diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 4ea924ddcb806..887455913d84a 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -234,10 +234,10 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow LL | let bad = format_args! {""} else { return; }; | ^ | -help: wrap the expression in parentheses +help: use parentheses instead of braces for this macro | -LL | let bad = (format_args! {""}) else { return; }; - | + + +LL | let bad = format_args! ("") else { return; }; + | ~ ~ error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:181:25 @@ -249,10 +249,10 @@ LL | b!(1); b!(2); | ----- in this macro invocation | = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) -help: wrap the expression in parentheses +help: use parentheses instead of braces for this macro | -LL | let x = (a! {}) else { return; }; - | + + +LL | let x = a! () else { return; }; + | ~~ error: aborting due to 19 previous errors From 0373ce6876864a2f31b0ab885c7ba80e1f69eb15 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 18 Jan 2024 14:36:17 +1100 Subject: [PATCH 24/31] Warn when no profiler runtime means coverage tests won't be run/blessed --- src/tools/compiletest/src/main.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 34d48559c378d..42c751bb6bedd 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -15,6 +15,15 @@ fn main() { eprintln!("warning: `tidy` is not installed; diffs will not be generated"); } + if !config.profiler_support && config.mode == Mode::CoverageRun { + let actioned = if config.bless { "blessed" } else { "checked" }; + eprintln!( + r#" +WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned} +help: try setting `profiler = true` in the `[build]` section of `config.toml`"# + ); + } + log_config(&config); run_tests(config); } From d95d6ceecb372c66ed18a4e7a0bbb79e74ee8fed Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 12:54:01 -0500 Subject: [PATCH 25/31] `dead_code` treats `#[repr(transparent)]` the same as `#[repr(C)]` Fixes #119659 --- compiler/rustc_passes/src/dead.rs | 18 ++++++++++-------- tests/ui/lint/dead-code/type-in-transparent.rs | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 tests/ui/lint/dead-code/type-in-transparent.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9422a5944881a..d7f17ac4547ab 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -57,7 +57,7 @@ struct MarkSymbolVisitor<'tcx> { tcx: TyCtxt<'tcx>, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, live_symbols: LocalDefIdSet, - repr_has_repr_c: bool, + repr_unconditionally_treats_fields_as_live: bool, repr_has_repr_simd: bool, in_pat: bool, ignore_variant_stack: Vec, @@ -365,15 +365,17 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return; } - let had_repr_c = self.repr_has_repr_c; + let unconditionally_treated_fields_as_live = + self.repr_unconditionally_treats_fields_as_live; let had_repr_simd = self.repr_has_repr_simd; - self.repr_has_repr_c = false; + self.repr_unconditionally_treats_fields_as_live = false; self.repr_has_repr_simd = false; match node { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def = self.tcx.adt_def(item.owner_id); - self.repr_has_repr_c = def.repr().c(); + self.repr_unconditionally_treats_fields_as_live = + def.repr().c() || def.repr().transparent(); self.repr_has_repr_simd = def.repr().simd(); intravisit::walk_item(self, item) @@ -411,7 +413,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { _ => {} } self.repr_has_repr_simd = had_repr_simd; - self.repr_has_repr_c = had_repr_c; + self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live; } fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) { @@ -435,11 +437,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) { let tcx = self.tcx; - let has_repr_c = self.repr_has_repr_c; + let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live; let has_repr_simd = self.repr_has_repr_simd; let live_fields = def.fields().iter().filter_map(|f| { let def_id = f.def_id; - if has_repr_c || (f.is_positional() && has_repr_simd) { + if unconditionally_treat_fields_as_live || (f.is_positional() && has_repr_simd) { return Some(def_id); } if !tcx.visibility(f.hir_id.owner.def_id).is_public() { @@ -741,7 +743,7 @@ fn live_symbols_and_ignored_derived_traits( tcx, maybe_typeck_results: None, live_symbols: Default::default(), - repr_has_repr_c: false, + repr_unconditionally_treats_fields_as_live: false, repr_has_repr_simd: false, in_pat: false, ignore_variant_stack: vec![], diff --git a/tests/ui/lint/dead-code/type-in-transparent.rs b/tests/ui/lint/dead-code/type-in-transparent.rs new file mode 100644 index 0000000000000..5dd6f93fd0318 --- /dev/null +++ b/tests/ui/lint/dead-code/type-in-transparent.rs @@ -0,0 +1,14 @@ +// Verify that we do not warn on fields that are part of transparent types. +// check-pass +#![deny(dead_code)] + +#[repr(transparent)] +struct NamedStruct { field: u8 } + +#[repr(transparent)] +struct TupleStruct(u8); + +fn main() { + let _ = NamedStruct { field: 1 }; + let _ = TupleStruct(1); +} From fb7762b1c51d67a56324b92fd79c85b33d5d1d3b Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:14 -0500 Subject: [PATCH 26/31] Remove no-longer-needed `allow(dead_code)` from the standard library `repr(transparent)` now silences the lint. --- library/alloc/src/boxed/thin.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 9463b73b574f9..f83c8f83cc989 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -171,7 +171,6 @@ struct WithHeader(NonNull, PhantomData); /// An opaque representation of `WithHeader` to avoid the /// projection invariance of `::Metadata`. #[repr(transparent)] -#[allow(dead_code)] // Field only used through `WithHeader` type above. struct WithOpaqueHeader(NonNull); impl WithOpaqueHeader { From 92cc57bafcea1380e2a8f7a6a732302b04c28c5f Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:35 -0500 Subject: [PATCH 27/31] Remove no-longer-needed `allow(dead_code)` from the tests `repr(transparent)` now silences the lint. --- tests/ui/consts/transmute-const.rs | 2 +- tests/ui/layout/unsafe-cell-hides-niche.rs | 2 +- tests/ui/packed/packed-struct-drop-aligned.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/consts/transmute-const.rs b/tests/ui/consts/transmute-const.rs index 65e5700d083f6..5044d99ec5183 100644 --- a/tests/ui/consts/transmute-const.rs +++ b/tests/ui/consts/transmute-const.rs @@ -3,7 +3,7 @@ use std::mem; #[repr(transparent)] -struct Foo(#[allow(dead_code)] u32); +struct Foo(u32); const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) }; diff --git a/tests/ui/layout/unsafe-cell-hides-niche.rs b/tests/ui/layout/unsafe-cell-hides-niche.rs index 8d6cea1093363..e87c402f8f964 100644 --- a/tests/ui/layout/unsafe-cell-hides-niche.rs +++ b/tests/ui/layout/unsafe-cell-hides-niche.rs @@ -17,7 +17,7 @@ use std::sync::{Mutex, RwLock}; struct Wrapper(#[allow(dead_code)] T); #[repr(transparent)] -struct Transparent(#[allow(dead_code)] T); +struct Transparent(T); struct NoNiche(UnsafeCell); diff --git a/tests/ui/packed/packed-struct-drop-aligned.rs b/tests/ui/packed/packed-struct-drop-aligned.rs index 6c2907c86e913..ddfc86f74d3c7 100644 --- a/tests/ui/packed/packed-struct-drop-aligned.rs +++ b/tests/ui/packed/packed-struct-drop-aligned.rs @@ -24,7 +24,7 @@ impl<'a> Drop for Aligned<'a> { } #[repr(transparent)] -struct NotCopy(#[allow(dead_code)] u8); +struct NotCopy(u8); #[repr(packed)] struct Packed<'a>(NotCopy, Aligned<'a>); From aeeaed9ce137d489f7157202548d2ce3d65c60ae Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 18 Jan 2024 13:14:24 -0500 Subject: [PATCH 28/31] Remove no-longer-needed `allow(dead_code)` from Miri tests `repr(transparent)` now silences the lint. --- src/tools/miri/tests/fail/issue-miri-1112.rs | 2 +- src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/fail/issue-miri-1112.rs b/src/tools/miri/tests/fail/issue-miri-1112.rs index 9542673b0d9e1..387253a3f9872 100644 --- a/src/tools/miri/tests/fail/issue-miri-1112.rs +++ b/src/tools/miri/tests/fail/issue-miri-1112.rs @@ -1,7 +1,7 @@ trait Empty {} #[repr(transparent)] -pub struct FunnyPointer(#[allow(dead_code)] dyn Empty); +pub struct FunnyPointer(dyn Empty); #[repr(C)] pub struct Meta { diff --git a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs index 2283231eb010c..d71d5954a40c7 100644 --- a/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs +++ b/src/tools/miri/tests/fail/unaligned_pointers/drop_in_place.rs @@ -1,7 +1,7 @@ //@compile-flags: -Cdebug-assertions=no #[repr(transparent)] -struct HasDrop(#[allow(dead_code)] u8); +struct HasDrop(u8); impl Drop for HasDrop { fn drop(&mut self) {} From 7fead95cec9a4a0c05de6d1d22a6fbe0b8594dd8 Mon Sep 17 00:00:00 2001 From: Waffle Maybe Date: Thu, 18 Jan 2024 21:04:31 +0100 Subject: [PATCH 29/31] Remove myself from review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index bd14640e280e4..b3f3051e177f2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -644,7 +644,6 @@ compiler-team = [ ] compiler-team-contributors = [ "@TaKO8Ki", - "@WaffleLapkin", "@b-naber", ] compiler = [ From 35a9fc3472b232b924b843c468399ca44320a55d Mon Sep 17 00:00:00 2001 From: invpt <57822954+invpt@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:40:56 -0500 Subject: [PATCH 30/31] Clarify docs for Vec::into_boxed_slice, Vec::shrink_to_fit --- library/alloc/src/vec/mod.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8aa0c6e7ed62c..35ea97bfe609c 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -358,7 +358,7 @@ mod spec_extend; /// /// `vec![x; n]`, `vec![a, b, c, d]`, and /// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec` -/// with exactly the requested capacity. If [len] == [capacity], +/// with at least the requested capacity. If [len] == [capacity], /// (as is the case for the [`vec!`] macro), then a `Vec` can be converted to /// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements. /// @@ -1023,8 +1023,11 @@ impl Vec { /// Shrinks the capacity of the vector as much as possible. /// - /// It will drop down as close as possible to the length but the allocator - /// may still inform the vector that there is space for a few more elements. + /// The behavior of this method depends on the allocator, which may either shrink the vector + /// in-place or reallocate. The resulting vector might still have some excess capacity, just as + /// is the case for [`with_capacity`]. See [`Allocator::shrink`] for more details. + /// + /// [`with_capacity`]: Vec::with_capacity /// /// # Examples /// @@ -1074,10 +1077,10 @@ impl Vec { /// Converts the vector into [`Box<[T]>`][owned slice]. /// - /// If the vector has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. + /// Before doing the conversion, this method discards excess capacity like [`shrink_to_fit`]. /// /// [owned slice]: Box + /// [`shrink_to_fit`]: Vec::shrink_to_fit /// /// # Examples /// @@ -3290,8 +3293,10 @@ impl From> for Vec { impl From> for Box<[T], A> { /// Convert a vector into a boxed slice. /// - /// If `v` has excess capacity, its items will be moved into a - /// newly-allocated buffer with exactly the right capacity. + /// Before doing the conversion, this method discards excess capacity like [`Vec::shrink_to_fit`]. + /// + /// [owned slice]: Box + /// [`Vec::shrink_to_fit`]: Vec::shrink_to_fit /// /// # Examples /// From 1a343424f3ba3ce230b2b9ceeff9cc7449f354d3 Mon Sep 17 00:00:00 2001 From: kapilsinha Date: Thu, 18 Jan 2024 17:49:06 -0800 Subject: [PATCH 31/31] Fix typo in documentation in base.rs --- compiler/rustc_expand/src/base.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 0a1c44303970a..054ab2d126a47 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -664,8 +664,8 @@ pub enum SyntaxExtensionKind { /// A token-based attribute macro. Attr( /// An expander with signature (TokenStream, TokenStream) -> TokenStream. - /// The first TokenSteam is the attribute itself, the second is the annotated item. - /// The produced TokenSteam replaces the input TokenSteam. + /// The first TokenStream is the attribute itself, the second is the annotated item. + /// The produced TokenStream replaces the input TokenStream. Box, ), @@ -685,7 +685,7 @@ pub enum SyntaxExtensionKind { /// A token-based derive macro. Derive( /// An expander with signature TokenStream -> TokenStream. - /// The produced TokenSteam is appended to the input TokenSteam. + /// The produced TokenStream is appended to the input TokenStream. /// /// FIXME: The text above describes how this should work. Currently it /// is handled identically to `LegacyDerive`. It should be migrated to