From 14ed426eec6939737ea320e50bb28d239c7aee93 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 18 Feb 2024 21:29:24 +0100 Subject: [PATCH 1/5] Use generic `NonZero` everywhere in `core`. --- library/core/src/array/mod.rs | 10 ++-- library/core/src/cmp/bytewise.rs | 51 ++++++++++---------- library/core/src/iter/traits/double_ended.rs | 8 +-- library/core/src/iter/traits/iterator.rs | 18 +++---- library/core/src/num/nonzero.rs | 16 +++--- library/core/src/option.rs | 25 +++++----- library/core/src/primitive_docs.rs | 9 ++-- library/core/src/ptr/alignment.rs | 16 +++--- library/core/src/ptr/non_null.rs | 8 +-- library/core/src/str/iter.rs | 4 +- 10 files changed, 81 insertions(+), 84 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 743f07644e354..42663ff2b53f0 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -511,7 +511,7 @@ impl [T; N] { /// # Examples /// /// ``` - /// #![feature(array_try_map)] + /// #![feature(array_try_map, generic_nonzero)] /// let a = ["1", "2", "3"]; /// let b = a.try_map(|v| v.parse::()).unwrap().map(|v| v + 1); /// assert_eq!(b, [2, 3, 4]); @@ -520,12 +520,12 @@ impl [T; N] { /// let b = a.try_map(|v| v.parse::()); /// assert!(b.is_err()); /// - /// use std::num::NonZeroU32; + /// use std::num::NonZero; /// let z = [1, 2, 0, 3, 4]; - /// assert_eq!(z.try_map(NonZeroU32::new), None); + /// assert_eq!(z.try_map(NonZero::new), None); /// let a = [1, 2, 3]; - /// let b = a.try_map(NonZeroU32::new); - /// let c = b.map(|x| x.map(NonZeroU32::get)); + /// let b = a.try_map(NonZero::new); + /// let c = b.map(|x| x.map(NonZero::get)); /// assert_eq!(c, Some(a)); /// ``` #[unstable(feature = "array_try_map", issue = "79711")] diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs index b19eef8e25587..a06a5227fe285 100644 --- a/library/core/src/cmp/bytewise.rs +++ b/library/core/src/cmp/bytewise.rs @@ -1,5 +1,4 @@ -use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; -use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; +use crate::num::NonZero; /// Types where `==` & `!=` are equivalent to comparing their underlying bytes. /// @@ -36,18 +35,18 @@ is_bytewise_comparable!(bool, char, super::Ordering); // SAFETY: Similarly, the `NonZero` type has a niche, but no undef and no pointers, // and they compare like their underlying numeric type. is_bytewise_comparable!( - NonZeroU8, - NonZeroU16, - NonZeroU32, - NonZeroU64, - NonZeroU128, - NonZeroUsize, - NonZeroI8, - NonZeroI16, - NonZeroI32, - NonZeroI64, - NonZeroI128, - NonZeroIsize, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, + NonZero, ); // SAFETY: The `NonZero` type has the "null" optimization guaranteed, and thus @@ -55,18 +54,18 @@ is_bytewise_comparable!( // The way `PartialOrd` is defined for `Option` means that this wouldn't work // for `<` or `>` on the signed types, but since we only do `==` it's fine. is_bytewise_comparable!( - Option, - Option, - Option, - Option, - Option, - Option, - Option, - Option, - Option, - Option, - Option, - Option, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, + Option>, ); macro_rules! is_bytewise_comparable_array_length { diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 48aae73d928a0..35092ec51cdd9 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -100,7 +100,7 @@ pub trait DoubleEndedIterator: Iterator { /// to `n` times until [`None`] is encountered. /// /// `advance_back_by(n)` will return `Ok(())` if the iterator successfully advances by - /// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered, where `k` + /// `n` elements, or a `Err(NonZero)` with value `k` if [`None`] is encountered, where `k` /// is remaining number of steps that could not be advanced because the iterator ran out. /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. /// Otherwise, `k` is always less than `n`. @@ -118,8 +118,8 @@ pub trait DoubleEndedIterator: Iterator { /// Basic usage: /// /// ``` - /// #![feature(iter_advance_by)] - /// use std::num::NonZeroUsize; + /// #![feature(generic_nonzero, iter_advance_by)] + /// use std::num::NonZero; /// /// let a = [3, 4, 5, 6]; /// let mut iter = a.iter(); @@ -127,7 +127,7 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(iter.advance_back_by(2), Ok(())); /// assert_eq!(iter.next_back(), Some(&4)); /// assert_eq!(iter.advance_back_by(0), Ok(())); - /// assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&3` was skipped + /// assert_eq!(iter.advance_back_by(100), Err(NonZero::new(99).unwrap())); // only `&3` was skipped /// ``` /// /// [`Ok(())`]: Ok diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 522e75a5683b2..9dd724a7166f0 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -304,7 +304,7 @@ pub trait Iterator { /// times until [`None`] is encountered. /// /// `advance_by(n)` will return `Ok(())` if the iterator successfully advances by - /// `n` elements, or a `Err(NonZeroUsize)` with value `k` if [`None`] is encountered, + /// `n` elements, or a `Err(NonZero)` with value `k` if [`None`] is encountered, /// where `k` is remaining number of steps that could not be advanced because the iterator ran out. /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`. /// Otherwise, `k` is always less than `n`. @@ -319,8 +319,8 @@ pub trait Iterator { /// # Examples /// /// ``` - /// #![feature(iter_advance_by)] - /// use std::num::NonZeroUsize; + /// #![feature(generic_nonzero, iter_advance_by)] + /// use std::num::NonZero; /// /// let a = [1, 2, 3, 4]; /// let mut iter = a.iter(); @@ -328,7 +328,7 @@ pub trait Iterator { /// assert_eq!(iter.advance_by(2), Ok(())); /// assert_eq!(iter.next(), Some(&3)); /// assert_eq!(iter.advance_by(0), Ok(())); - /// assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(99).unwrap())); // only `&4` was skipped + /// assert_eq!(iter.advance_by(100), Err(NonZero::new(99).unwrap())); // only `&4` was skipped /// ``` #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] @@ -2969,15 +2969,15 @@ pub trait Iterator { /// /// This also supports other types which implement `Try`, not just `Result`. /// ``` - /// #![feature(try_find)] + /// #![feature(generic_nonzero, try_find)] /// - /// use std::num::NonZeroU32; + /// use std::num::NonZero; /// let a = [3, 5, 7, 4, 9, 0, 11]; - /// let result = a.iter().try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two())); + /// let result = a.iter().try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); /// assert_eq!(result, Some(Some(&4))); - /// let result = a.iter().take(3).try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two())); + /// let result = a.iter().take(3).try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); /// assert_eq!(result, Some(None)); - /// let result = a.iter().rev().try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two())); + /// let result = a.iter().rev().try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); /// assert_eq!(result, None); /// ``` #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8943e2f0e2ab5..295b88361cfbb 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -23,7 +23,7 @@ mod private { /// A marker trait for primitive types which can be zero. /// -/// This is an implementation detail for [`NonZero`](NonZero) which may disappear or be replaced at any time. +/// This is an implementation detail for [NonZero]\ which may disappear or be replaced at any time. #[unstable( feature = "nonzero_internals", reason = "implementation detail which may disappear or be replaced at any time", @@ -507,18 +507,16 @@ macro_rules! nonzero_integer { /// Basic usage: /// /// ``` - /// #![feature(non_zero_count_ones)] + /// #![feature(generic_nonzero, non_zero_count_ones)] /// # fn main() { test().unwrap(); } /// # fn test() -> Option<()> { /// # use std::num::*; /// # - /// let one = NonZeroU32::new(1)?; - /// let three = NonZeroU32::new(3)?; - #[doc = concat!("let a = ", stringify!($Ty), "::new(0b100_0000)?;")] - #[doc = concat!("let b = ", stringify!($Ty), "::new(0b100_0011)?;")] + #[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b100_0000)?;")] + #[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b100_0011)?;")] /// - /// assert_eq!(a.count_ones(), one); - /// assert_eq!(b.count_ones(), three); + /// assert_eq!(a.count_ones(), NonZero::new(1)?); + /// assert_eq!(b.count_ones(), NonZero::new(3)?); /// # Some(()) /// # } /// ``` @@ -530,7 +528,7 @@ macro_rules! nonzero_integer { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] - pub const fn count_ones(self) -> NonZeroU32 { + pub const fn count_ones(self) -> NonZero { // SAFETY: // `self` is non-zero, which means it has at least one bit set, which means // that the result of `count_ones` is non-zero. diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 0e5eb03239ce6..2821f622700a6 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -558,6 +558,7 @@ use crate::panicking::{panic, panic_str}; use crate::pin::Pin; use crate::{ cmp, convert, hint, mem, + num::NonZero, ops::{self, ControlFlow, Deref, DerefMut}, slice, }; @@ -2193,18 +2194,18 @@ macro_rules! non_zero_option { } non_zero_option! { - #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU8; - #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU16; - #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU32; - #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU64; - #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU128; - #[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroUsize; - #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI8; - #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI16; - #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI32; - #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI64; - #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI128; - #[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroIsize; + #[stable(feature = "nonzero", since = "1.28.0")] NonZero; + #[stable(feature = "nonzero", since = "1.28.0")] NonZero; + #[stable(feature = "nonzero", since = "1.28.0")] NonZero; + #[stable(feature = "nonzero", since = "1.28.0")] NonZero; + #[stable(feature = "nonzero", since = "1.28.0")] NonZero; + #[stable(feature = "nonzero", since = "1.28.0")] NonZero; + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero; + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero; + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero; + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero; + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero; + #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero; } #[stable(feature = "nonnull", since = "1.25.0")] diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index eb3f93a6e9657..15da4171bda21 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1577,8 +1577,7 @@ mod prim_ref {} /// - Any two types with size 0 and alignment 1 are ABI-compatible. /// - A `repr(transparent)` type `T` is ABI-compatible with its unique non-trivial field, i.e., the /// unique field that doesn't have size 0 and alignment 1 (if there is such a field). -/// - `i32` is ABI-compatible with `NonZeroI32`, and similar for all other integer types with their -/// matching `NonZero*` type. +/// - `i32` is ABI-compatible with `NonZero`, and similar for all other integer types. /// - If `T` is guaranteed to be subject to the [null pointer /// optimization](option/index.html#representation), then `T` and `Option` are ABI-compatible. /// @@ -1613,9 +1612,9 @@ mod prim_ref {} /// type in the function pointer to the type at the function declaration, and the return value is /// [`transmute`d][mem::transmute] from the type in the declaration to the type in the /// pointer. All the usual caveats and concerns around transmutation apply; for instance, if the -/// function expects a `NonZeroI32` and the function pointer uses the ABI-compatible type -/// `Option`, and the value used for the argument is `None`, then this call is Undefined -/// Behavior since transmuting `None::` to `NonZeroI32` violates the non-zero +/// function expects a `NonZero` and the function pointer uses the ABI-compatible type +/// `Option>`, and the value used for the argument is `None`, then this call is Undefined +/// Behavior since transmuting `None::>` to `NonZero` violates the non-zero /// requirement. /// /// #### Requirements concerning target features diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 6dfecb5a826af..bd58c167c2e06 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -1,5 +1,5 @@ use crate::convert::{TryFrom, TryInto}; -use crate::num::{NonZero, NonZeroUsize}; +use crate::num::NonZero; use crate::{cmp, fmt, hash, mem, num}; /// A type storing a `usize` which is a power of two, and thus @@ -87,7 +87,7 @@ impl Alignment { unsafe { mem::transmute::(align) } } - /// Returns the alignment as a [`usize`] + /// Returns the alignment as a [`usize`]. #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] @@ -95,11 +95,11 @@ impl Alignment { self.0 as usize } - /// Returns the alignment as a [`NonZeroUsize`] + /// Returns the alignment as a [NonZero]<[usize]>. #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[inline] - pub const fn as_nonzero(self) -> NonZeroUsize { + pub const fn as_nonzero(self) -> NonZero { // SAFETY: All the discriminants are non-zero. unsafe { NonZero::new_unchecked(self.as_usize()) } } @@ -164,11 +164,11 @@ impl fmt::Debug for Alignment { } #[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl TryFrom for Alignment { +impl TryFrom> for Alignment { type Error = num::TryFromIntError; #[inline] - fn try_from(align: NonZeroUsize) -> Result { + fn try_from(align: NonZero) -> Result { align.get().try_into() } } @@ -184,9 +184,9 @@ impl TryFrom for Alignment { } #[unstable(feature = "ptr_alignment_type", issue = "102070")] -impl From for NonZeroUsize { +impl From for NonZero { #[inline] - fn from(align: Alignment) -> NonZeroUsize { + fn from(align: Alignment) -> NonZero { align.as_nonzero() } } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 098ec23385567..acb8c552a6338 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -5,7 +5,7 @@ use crate::intrinsics; use crate::intrinsics::assert_unsafe_precondition; use crate::marker::Unsize; use crate::mem::{MaybeUninit, SizedTypeProperties}; -use crate::num::{NonZero, NonZeroUsize}; +use crate::num::NonZero; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::ptr; use crate::ptr::Unique; @@ -291,7 +291,7 @@ impl NonNull { #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] - pub fn addr(self) -> NonZeroUsize { + pub fn addr(self) -> NonZero { // SAFETY: The pointer is guaranteed by the type to be non-null, // meaning that the address will be non-zero. unsafe { NonZero::new_unchecked(self.pointer.addr()) } @@ -306,7 +306,7 @@ impl NonNull { #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] - pub fn with_addr(self, addr: NonZeroUsize) -> Self { + pub fn with_addr(self, addr: NonZero) -> Self { // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) } } @@ -320,7 +320,7 @@ impl NonNull { #[must_use] #[inline] #[unstable(feature = "strict_provenance", issue = "95228")] - pub fn map_addr(self, f: impl FnOnce(NonZeroUsize) -> NonZeroUsize) -> Self { + pub fn map_addr(self, f: impl FnOnce(NonZero) -> NonZero) -> Self { self.with_addr(f(self.addr())) } diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 00b4405faaefb..19627f28e64f8 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -5,10 +5,10 @@ use crate::fmt::{self, Write}; use crate::iter::{Chain, FlatMap, Flatten}; use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen}; use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use crate::num::NonZero; use crate::ops::Try; use crate::option; use crate::slice::{self, Split as SliceSplit}; -use core::num::{NonZero, NonZeroUsize}; use super::from_utf8_unchecked; use super::pattern::Pattern; @@ -51,7 +51,7 @@ impl<'a> Iterator for Chars<'a> { } #[inline] - fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZeroUsize> { + fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZero> { const CHUNK_SIZE: usize = 32; if remainder >= CHUNK_SIZE { From e0732e42d829cd8aa8480811d0c860387437e6ca Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 19 Feb 2024 06:02:17 +0100 Subject: [PATCH 2/5] Use generic `NonZero` everywhere in `std`. --- library/std/src/io/error/repr_bitpacked.rs | 4 ++-- library/std/src/process.rs | 14 +++++++------- library/std/src/thread/mod.rs | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index c053e047b1a63..6f8d5e3777568 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -73,7 +73,7 @@ //! union Repr { //! // holds integer (Simple/Os) variants, and //! // provides access to the tag bits. -//! bits: NonZeroU64, +//! bits: NonZero, //! // Tag is 0, so this is stored untagged. //! msg: &'static SimpleMessage, //! // Tagged (offset) `Box` pointer. @@ -93,7 +93,7 @@ //! `io::Result<()>` and `io::Result` larger, which defeats part of //! the motivation of this bitpacking. //! -//! Storing everything in a `NonZeroUsize` (or some other integer) would be a +//! Storing everything in a `NonZero` (or some other integer) would be a //! bit more traditional for pointer tagging, but it would lose provenance //! information, couldn't be constructed from a `const fn`, and would probably //! run into other issues as well. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 669affa266a4d..b84d5f11954de 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -111,7 +111,7 @@ use crate::ffi::OsStr; use crate::fmt; use crate::fs; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; -use crate::num::NonZeroI32; +use crate::num::NonZero; use crate::path::Path; use crate::str; use crate::sys::pipe::{read2, AnonPipe}; @@ -1775,9 +1775,9 @@ impl ExitStatusError { self.code_nonzero().map(Into::into) } - /// Reports the exit code, if applicable, from an `ExitStatusError`, as a `NonZero` + /// Reports the exit code, if applicable, from an `ExitStatusError`, as a [`NonZero`]. /// - /// This is exactly like [`code()`](Self::code), except that it returns a `NonZeroI32`. + /// This is exactly like [`code()`](Self::code), except that it returns a [NonZero]<[i32]>. /// /// Plain `code`, returning a plain integer, is provided because it is often more convenient. /// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want @@ -1786,17 +1786,17 @@ impl ExitStatusError { /// # Examples /// /// ``` - /// #![feature(exit_status_error)] + /// #![feature(exit_status_error, generic_nonzero)] /// # if cfg!(unix) { - /// use std::num::NonZeroI32; + /// use std::num::NonZero; /// use std::process::Command; /// /// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err(); - /// assert_eq!(bad.code_nonzero().unwrap(), NonZeroI32::try_from(1).unwrap()); + /// assert_eq!(bad.code_nonzero().unwrap(), NonZero::new(1).unwrap()); /// # } // cfg!(unix) /// ``` #[must_use] - pub fn code_nonzero(&self) -> Option { + pub fn code_nonzero(&self) -> Option> { self.0.code() } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 4f0f010984ab9..76af7fec92648 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -165,7 +165,7 @@ use crate::fmt; use crate::io; use crate::marker::PhantomData; use crate::mem::{self, forget}; -use crate::num::{NonZero, NonZeroU64, NonZeroUsize}; +use crate::num::NonZero; use crate::panic; use crate::panicking; use crate::pin::Pin; @@ -1222,7 +1222,7 @@ impl ThreadId { /// change across Rust versions. #[must_use] #[unstable(feature = "thread_id_value", issue = "67939")] - pub fn as_u64(&self) -> NonZeroU64 { + pub fn as_u64(&self) -> NonZero { self.0 } } @@ -1784,6 +1784,6 @@ fn _assert_sync_and_send() { #[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. #[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. #[stable(feature = "available_parallelism", since = "1.59.0")] -pub fn available_parallelism() -> io::Result { +pub fn available_parallelism() -> io::Result> { imp::available_parallelism() } From 36d194f5612852a6d4fcf9d5fae8e0fba942adfa Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 19 Feb 2024 05:51:10 +0100 Subject: [PATCH 3/5] Use generic `NonZero` everywhere in `alloc`. --- library/alloc/src/ffi/c_str.rs | 18 +++++------ library/alloc/src/vec/is_zero.rs | 51 ++++++++++++-------------------- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 9419b0cfb24fa..61ec04a4849d0 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -11,7 +11,7 @@ use core::borrow::Borrow; use core::ffi::{c_char, CStr}; use core::fmt; use core::mem; -use core::num::NonZeroU8; +use core::num::NonZero; use core::ops; use core::ptr; use core::slice; @@ -795,22 +795,22 @@ impl From> for CString { } #[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")] -impl From> for CString { - /// Converts a [Vec]<[NonZeroU8]> into a [`CString`] without +impl From>> for CString { + /// Converts a [Vec]<[NonZero]<[u8]>> into a [`CString`] without /// copying nor checking for inner nul bytes. #[inline] - fn from(v: Vec) -> CString { + fn from(v: Vec>) -> CString { unsafe { - // Transmute `Vec` to `Vec`. + // Transmute `Vec>` to `Vec`. let v: Vec = { // SAFETY: - // - transmuting between `NonZeroU8` and `u8` is sound; - // - `alloc::Layout == alloc::Layout`. - let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v); + // - transmuting between `NonZero` and `u8` is sound; + // - `alloc::Layout> == alloc::Layout`. + let (ptr, len, cap): (*mut NonZero, _, _) = Vec::into_raw_parts(v); Vec::from_raw_parts(ptr.cast::(), len, cap) }; // SAFETY: `v` cannot contain nul bytes, given the type-level - // invariant of `NonZeroU8`. + // invariant of `NonZero`. Self::_from_vec_unchecked(v) } } diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index cb9adf05c25b0..bcc5bf4d65bb4 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -1,4 +1,4 @@ -use core::num::{Saturating, Wrapping}; +use core::num::{NonZero, Saturating, Wrapping}; use crate::boxed::Box; @@ -69,7 +69,7 @@ unsafe impl IsZero for [T; N] { } // This is recursive macro. -macro_rules! impl_for_tuples { +macro_rules! impl_is_zero_tuples { // Stopper () => { // No use for implementing for empty tuple because it is ZST. @@ -88,11 +88,11 @@ macro_rules! impl_for_tuples { } } - impl_for_tuples!($($rest),*); + impl_is_zero_tuples!($($rest),*); } } -impl_for_tuples!(A, B, C, D, E, F, G, H); +impl_is_zero_tuples!(A, B, C, D, E, F, G, H); // `Option<&T>` and `Option>` are guaranteed to represent `None` as null. // For fat pointers, the bytes that would be the pointer metadata in the `Some` @@ -115,16 +115,15 @@ unsafe impl IsZero for Option> { } } -// `Option` and similar have a representation guarantee that +// `Option>` and similar have a representation guarantee that // they're the same size as the corresponding `u32` type, as well as a guarantee -// that transmuting between `NonZeroU32` and `Option` works. +// that transmuting between `NonZero` and `Option>` works. // While the documentation officially makes it UB to transmute from `None`, // we're the standard library so we can make extra inferences, and we know that // the only niche available to represent `None` is the one that's all zeros. - -macro_rules! impl_is_zero_option_of_nonzero { - ($($t:ident,)+) => {$( - unsafe impl IsZero for Option { +macro_rules! impl_is_zero_option_of_nonzero_int { + ($($t:ty),+ $(,)?) => {$( + unsafe impl IsZero for Option> { #[inline] fn is_zero(&self) -> bool { self.is_none() @@ -133,23 +132,10 @@ macro_rules! impl_is_zero_option_of_nonzero { )+}; } -impl_is_zero_option_of_nonzero!( - NonZeroU8, - NonZeroU16, - NonZeroU32, - NonZeroU64, - NonZeroU128, - NonZeroI8, - NonZeroI16, - NonZeroI32, - NonZeroI64, - NonZeroI128, - NonZeroUsize, - NonZeroIsize, -); - -macro_rules! impl_is_zero_option_of_num { - ($($t:ty,)+) => {$( +impl_is_zero_option_of_nonzero_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +macro_rules! impl_is_zero_option_of_int { + ($($t:ty),+ $(,)?) => {$( unsafe impl IsZero for Option<$t> { #[inline] fn is_zero(&self) -> bool { @@ -163,7 +149,7 @@ macro_rules! impl_is_zero_option_of_num { )+}; } -impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,); +impl_is_zero_option_of_int!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize); unsafe impl IsZero for Wrapping { #[inline] @@ -179,8 +165,8 @@ unsafe impl IsZero for Saturating { } } -macro_rules! impl_for_optional_bool { - ($($t:ty,)+) => {$( +macro_rules! impl_is_zero_option_of_bool { + ($($t:ty),+ $(,)?) => {$( unsafe impl IsZero for $t { #[inline] fn is_zero(&self) -> bool { @@ -194,9 +180,10 @@ macro_rules! impl_for_optional_bool { } )+}; } -impl_for_optional_bool! { + +impl_is_zero_option_of_bool! { Option, Option>, Option>>, - // Could go further, but not worth the metadata overhead + // Could go further, but not worth the metadata overhead. } From 0c474acdfaba7aea63d0ed28526c670b298b96ba Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 19 Feb 2024 05:57:05 +0100 Subject: [PATCH 4/5] Use generic `NonZero` everywhere else. --- library/proc_macro/src/bridge/symbol.rs | 2 +- library/test/src/helpers/concurrency.rs | 4 ++-- library/test/src/lib.rs | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/library/proc_macro/src/bridge/symbol.rs b/library/proc_macro/src/bridge/symbol.rs index 712f6b4545828..02225d20b26e1 100644 --- a/library/proc_macro/src/bridge/symbol.rs +++ b/library/proc_macro/src/bridge/symbol.rs @@ -136,7 +136,7 @@ thread_local! { arena: arena::Arena::new(), names: fxhash::FxHashMap::default(), strings: Vec::new(), - // Start with a base of 1 to make sure that `NonZeroU32` works. + // Start with a base of 1 to make sure that `NonZero` works. sym_base: NonZero::new(1).unwrap(), }); } diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs index eb211157371b5..b395adcf885ce 100644 --- a/library/test/src/helpers/concurrency.rs +++ b/library/test/src/helpers/concurrency.rs @@ -1,10 +1,10 @@ //! Helper module which helps to determine amount of threads to be used //! during tests execution. -use std::{env, num::NonZeroUsize, thread}; +use std::{env, num::NonZero, thread}; pub fn get_concurrency() -> usize { if let Ok(value) = env::var("RUST_TEST_THREADS") { - match value.parse::().ok() { + match value.parse::>().ok() { Some(n) => n.get(), _ => panic!("RUST_TEST_THREADS is `{value}`, should be a positive integer."), } diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index da110f9924861..728c73d8c502a 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -17,6 +17,7 @@ #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] #![doc(rust_logo)] +#![feature(generic_nonzero)] #![feature(rustdoc_internals)] #![feature(internal_output_capture)] #![feature(staged_api)] From b74d8db9d258bbfbfb9d993dce6fbdd8f09dfa31 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 22 Feb 2024 16:47:33 +0100 Subject: [PATCH 5/5] Fix example. --- library/core/src/iter/traits/iterator.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 9dd724a7166f0..3267cea38b743 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2967,12 +2967,13 @@ pub trait Iterator { /// assert!(result.is_err()); /// ``` /// - /// This also supports other types which implement `Try`, not just `Result`. + /// This also supports other types which implement [`Try`], not just [`Result`]. + /// /// ``` /// #![feature(generic_nonzero, try_find)] - /// /// use std::num::NonZero; - /// let a = [3, 5, 7, 4, 9, 0, 11]; + /// + /// let a = [3, 5, 7, 4, 9, 0, 11u32]; /// let result = a.iter().try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two())); /// assert_eq!(result, Some(Some(&4))); /// let result = a.iter().take(3).try_find(|&&x| NonZero::new(x).map(|y| y.is_power_of_two()));