Auto merge of #121454 - reitermarkus:generic-nonzero-library, r=dtolnay

Use generic `NonZero` everywhere in `library`.

Tracking issue: https://github.com/rust-lang/rust/issues/120257

Use generic `NonZero` everywhere (except stable examples).

r? `@dtolnay`
This commit is contained in:
bors 2024-02-23 14:27:33 +00:00
commit b6a23b8537
18 changed files with 128 additions and 142 deletions

View file

@ -11,7 +11,7 @@ use core::borrow::Borrow;
use core::ffi::{c_char, CStr}; use core::ffi::{c_char, CStr};
use core::fmt; use core::fmt;
use core::mem; use core::mem;
use core::num::NonZeroU8; use core::num::NonZero;
use core::ops; use core::ops;
use core::ptr; use core::ptr;
use core::slice; use core::slice;
@ -795,22 +795,22 @@ impl From<Box<CStr>> for CString {
} }
#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")] #[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")]
impl From<Vec<NonZeroU8>> for CString { impl From<Vec<NonZero<u8>>> for CString {
/// Converts a <code>[Vec]<[NonZeroU8]></code> into a [`CString`] without /// Converts a <code>[Vec]<[NonZero]<[u8]>></code> into a [`CString`] without
/// copying nor checking for inner nul bytes. /// copying nor checking for inner nul bytes.
#[inline] #[inline]
fn from(v: Vec<NonZeroU8>) -> CString { fn from(v: Vec<NonZero<u8>>) -> CString {
unsafe { unsafe {
// Transmute `Vec<NonZeroU8>` to `Vec<u8>`. // Transmute `Vec<NonZero<u8>>` to `Vec<u8>`.
let v: Vec<u8> = { let v: Vec<u8> = {
// SAFETY: // SAFETY:
// - transmuting between `NonZeroU8` and `u8` is sound; // - transmuting between `NonZero<u8>` and `u8` is sound;
// - `alloc::Layout<NonZeroU8> == alloc::Layout<u8>`. // - `alloc::Layout<NonZero<u8>> == alloc::Layout<u8>`.
let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v); let (ptr, len, cap): (*mut NonZero<u8>, _, _) = Vec::into_raw_parts(v);
Vec::from_raw_parts(ptr.cast::<u8>(), len, cap) Vec::from_raw_parts(ptr.cast::<u8>(), len, cap)
}; };
// SAFETY: `v` cannot contain nul bytes, given the type-level // SAFETY: `v` cannot contain nul bytes, given the type-level
// invariant of `NonZeroU8`. // invariant of `NonZero<u8>`.
Self::_from_vec_unchecked(v) Self::_from_vec_unchecked(v)
} }
} }

View file

@ -1,4 +1,4 @@
use core::num::{Saturating, Wrapping}; use core::num::{NonZero, Saturating, Wrapping};
use crate::boxed::Box; use crate::boxed::Box;
@ -69,7 +69,7 @@ unsafe impl<T: IsZero, const N: usize> IsZero for [T; N] {
} }
// This is recursive macro. // This is recursive macro.
macro_rules! impl_for_tuples { macro_rules! impl_is_zero_tuples {
// Stopper // Stopper
() => { () => {
// No use for implementing for empty tuple because it is ZST. // 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<Box<T>>` are guaranteed to represent `None` as null. // `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null.
// For fat pointers, the bytes that would be the pointer metadata in the `Some` // For fat pointers, the bytes that would be the pointer metadata in the `Some`
@ -115,16 +115,15 @@ unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
} }
} }
// `Option<num::NonZeroU32>` and similar have a representation guarantee that // `Option<NonZero<u32>>` and similar have a representation guarantee that
// they're the same size as the corresponding `u32` type, as well as a guarantee // they're the same size as the corresponding `u32` type, as well as a guarantee
// that transmuting between `NonZeroU32` and `Option<num::NonZeroU32>` works. // that transmuting between `NonZero<u32>` and `Option<NonZero<u32>>` works.
// While the documentation officially makes it UB to transmute from `None`, // 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 // 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. // the only niche available to represent `None` is the one that's all zeros.
macro_rules! impl_is_zero_option_of_nonzero_int {
macro_rules! impl_is_zero_option_of_nonzero { ($($t:ty),+ $(,)?) => {$(
($($t:ident,)+) => {$( unsafe impl IsZero for Option<NonZero<$t>> {
unsafe impl IsZero for Option<core::num::$t> {
#[inline] #[inline]
fn is_zero(&self) -> bool { fn is_zero(&self) -> bool {
self.is_none() self.is_none()
@ -133,23 +132,10 @@ macro_rules! impl_is_zero_option_of_nonzero {
)+}; )+};
} }
impl_is_zero_option_of_nonzero!( impl_is_zero_option_of_nonzero_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
NonZeroU8,
NonZeroU16,
NonZeroU32,
NonZeroU64,
NonZeroU128,
NonZeroI8,
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroI128,
NonZeroUsize,
NonZeroIsize,
);
macro_rules! impl_is_zero_option_of_num { macro_rules! impl_is_zero_option_of_int {
($($t:ty,)+) => {$( ($($t:ty),+ $(,)?) => {$(
unsafe impl IsZero for Option<$t> { unsafe impl IsZero for Option<$t> {
#[inline] #[inline]
fn is_zero(&self) -> bool { 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<T: IsZero> IsZero for Wrapping<T> { unsafe impl<T: IsZero> IsZero for Wrapping<T> {
#[inline] #[inline]
@ -179,8 +165,8 @@ unsafe impl<T: IsZero> IsZero for Saturating<T> {
} }
} }
macro_rules! impl_for_optional_bool { macro_rules! impl_is_zero_option_of_bool {
($($t:ty,)+) => {$( ($($t:ty),+ $(,)?) => {$(
unsafe impl IsZero for $t { unsafe impl IsZero for $t {
#[inline] #[inline]
fn is_zero(&self) -> bool { 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<bool>, Option<bool>,
Option<Option<bool>>, Option<Option<bool>>,
Option<Option<Option<bool>>>, Option<Option<Option<bool>>>,
// Could go further, but not worth the metadata overhead // Could go further, but not worth the metadata overhead.
} }

View file

@ -511,7 +511,7 @@ impl<T, const N: usize> [T; N] {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(array_try_map)] /// #![feature(array_try_map, generic_nonzero)]
/// let a = ["1", "2", "3"]; /// let a = ["1", "2", "3"];
/// let b = a.try_map(|v| v.parse::<u32>()).unwrap().map(|v| v + 1); /// let b = a.try_map(|v| v.parse::<u32>()).unwrap().map(|v| v + 1);
/// assert_eq!(b, [2, 3, 4]); /// assert_eq!(b, [2, 3, 4]);
@ -520,12 +520,12 @@ impl<T, const N: usize> [T; N] {
/// let b = a.try_map(|v| v.parse::<u32>()); /// let b = a.try_map(|v| v.parse::<u32>());
/// assert!(b.is_err()); /// assert!(b.is_err());
/// ///
/// use std::num::NonZeroU32; /// use std::num::NonZero;
/// let z = [1, 2, 0, 3, 4]; /// 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 a = [1, 2, 3];
/// let b = a.try_map(NonZeroU32::new); /// let b = a.try_map(NonZero::new);
/// let c = b.map(|x| x.map(NonZeroU32::get)); /// let c = b.map(|x| x.map(NonZero::get));
/// assert_eq!(c, Some(a)); /// assert_eq!(c, Some(a));
/// ``` /// ```
#[unstable(feature = "array_try_map", issue = "79711")] #[unstable(feature = "array_try_map", issue = "79711")]

View file

@ -1,5 +1,4 @@
use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; use crate::num::NonZero;
use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
/// Types where `==` & `!=` are equivalent to comparing their underlying bytes. /// 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, // SAFETY: Similarly, the `NonZero` type has a niche, but no undef and no pointers,
// and they compare like their underlying numeric type. // and they compare like their underlying numeric type.
is_bytewise_comparable!( is_bytewise_comparable!(
NonZeroU8, NonZero<u8>,
NonZeroU16, NonZero<u16>,
NonZeroU32, NonZero<u32>,
NonZeroU64, NonZero<u64>,
NonZeroU128, NonZero<u128>,
NonZeroUsize, NonZero<usize>,
NonZeroI8, NonZero<i8>,
NonZeroI16, NonZero<i16>,
NonZeroI32, NonZero<i32>,
NonZeroI64, NonZero<i64>,
NonZeroI128, NonZero<i128>,
NonZeroIsize, NonZero<isize>,
); );
// SAFETY: The `NonZero` type has the "null" optimization guaranteed, and thus // 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 // 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. // for `<` or `>` on the signed types, but since we only do `==` it's fine.
is_bytewise_comparable!( is_bytewise_comparable!(
Option<NonZeroU8>, Option<NonZero<u8>>,
Option<NonZeroU16>, Option<NonZero<u16>>,
Option<NonZeroU32>, Option<NonZero<u32>>,
Option<NonZeroU64>, Option<NonZero<u64>>,
Option<NonZeroU128>, Option<NonZero<u128>>,
Option<NonZeroUsize>, Option<NonZero<usize>>,
Option<NonZeroI8>, Option<NonZero<i8>>,
Option<NonZeroI16>, Option<NonZero<i16>>,
Option<NonZeroI32>, Option<NonZero<i32>>,
Option<NonZeroI64>, Option<NonZero<i64>>,
Option<NonZeroI128>, Option<NonZero<i128>>,
Option<NonZeroIsize>, Option<NonZero<isize>>,
); );
macro_rules! is_bytewise_comparable_array_length { macro_rules! is_bytewise_comparable_array_length {

View file

@ -100,7 +100,7 @@ pub trait DoubleEndedIterator: Iterator {
/// to `n` times until [`None`] is encountered. /// to `n` times until [`None`] is encountered.
/// ///
/// `advance_back_by(n)` will return `Ok(())` if the iterator successfully advances by /// `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<usize>)` with value `k` if [`None`] is encountered, where `k`
/// is remaining number of steps that could not be advanced because the iterator ran out. /// 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)`. /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`.
/// Otherwise, `k` is always less than `n`. /// Otherwise, `k` is always less than `n`.
@ -118,8 +118,8 @@ pub trait DoubleEndedIterator: Iterator {
/// Basic usage: /// Basic usage:
/// ///
/// ``` /// ```
/// #![feature(iter_advance_by)] /// #![feature(generic_nonzero, iter_advance_by)]
/// use std::num::NonZeroUsize; /// use std::num::NonZero;
/// ///
/// let a = [3, 4, 5, 6]; /// let a = [3, 4, 5, 6];
/// let mut iter = a.iter(); /// let mut iter = a.iter();
@ -127,7 +127,7 @@ pub trait DoubleEndedIterator: Iterator {
/// assert_eq!(iter.advance_back_by(2), Ok(())); /// assert_eq!(iter.advance_back_by(2), Ok(()));
/// assert_eq!(iter.next_back(), Some(&4)); /// assert_eq!(iter.next_back(), Some(&4));
/// assert_eq!(iter.advance_back_by(0), Ok(())); /// 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 /// [`Ok(())`]: Ok

View file

@ -304,7 +304,7 @@ pub trait Iterator {
/// times until [`None`] is encountered. /// times until [`None`] is encountered.
/// ///
/// `advance_by(n)` will return `Ok(())` if the iterator successfully advances by /// `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<usize>)` with value `k` if [`None`] is encountered,
/// where `k` is remaining number of steps that could not be advanced because the iterator ran out. /// 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)`. /// If `self` is empty and `n` is non-zero, then this returns `Err(n)`.
/// Otherwise, `k` is always less than `n`. /// Otherwise, `k` is always less than `n`.
@ -319,8 +319,8 @@ pub trait Iterator {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(iter_advance_by)] /// #![feature(generic_nonzero, iter_advance_by)]
/// use std::num::NonZeroUsize; /// use std::num::NonZero;
/// ///
/// let a = [1, 2, 3, 4]; /// let a = [1, 2, 3, 4];
/// let mut iter = a.iter(); /// let mut iter = a.iter();
@ -328,7 +328,7 @@ pub trait Iterator {
/// assert_eq!(iter.advance_by(2), Ok(())); /// assert_eq!(iter.advance_by(2), Ok(()));
/// assert_eq!(iter.next(), Some(&3)); /// assert_eq!(iter.next(), Some(&3));
/// assert_eq!(iter.advance_by(0), Ok(())); /// 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] #[inline]
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
@ -2967,17 +2967,18 @@ pub trait Iterator {
/// assert!(result.is_err()); /// 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(try_find)]
/// ///
/// use std::num::NonZeroU32; /// ```
/// let a = [3, 5, 7, 4, 9, 0, 11]; /// #![feature(generic_nonzero, try_find)]
/// let result = a.iter().try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two())); /// use std::num::NonZero;
///
/// 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))); /// 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)); /// 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); /// assert_eq!(result, None);
/// ``` /// ```
#[inline] #[inline]

View file

@ -23,7 +23,7 @@ mod private {
/// A marker trait for primitive types which can be zero. /// A marker trait for primitive types which can be zero.
/// ///
/// This is an implementation detail for [`NonZero<T>`](NonZero) which may disappear or be replaced at any time. /// This is an implementation detail for <code>[NonZero]\<T></code> which may disappear or be replaced at any time.
#[unstable( #[unstable(
feature = "nonzero_internals", feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time", reason = "implementation detail which may disappear or be replaced at any time",
@ -507,18 +507,16 @@ macro_rules! nonzero_integer {
/// Basic usage: /// Basic usage:
/// ///
/// ``` /// ```
/// #![feature(non_zero_count_ones)] /// #![feature(generic_nonzero, non_zero_count_ones)]
/// # fn main() { test().unwrap(); } /// # fn main() { test().unwrap(); }
/// # fn test() -> Option<()> { /// # fn test() -> Option<()> {
/// # use std::num::*; /// # use std::num::*;
/// # /// #
/// let one = NonZeroU32::new(1)?; #[doc = concat!("let a = NonZero::<", stringify!($Int), ">::new(0b100_0000)?;")]
/// let three = NonZeroU32::new(3)?; #[doc = concat!("let b = NonZero::<", stringify!($Int), ">::new(0b100_0011)?;")]
#[doc = concat!("let a = ", stringify!($Ty), "::new(0b100_0000)?;")]
#[doc = concat!("let b = ", stringify!($Ty), "::new(0b100_0011)?;")]
/// ///
/// assert_eq!(a.count_ones(), one); /// assert_eq!(a.count_ones(), NonZero::new(1)?);
/// assert_eq!(b.count_ones(), three); /// assert_eq!(b.count_ones(), NonZero::new(3)?);
/// # Some(()) /// # Some(())
/// # } /// # }
/// ``` /// ```
@ -530,7 +528,7 @@ macro_rules! nonzero_integer {
#[must_use = "this returns the result of the operation, \ #[must_use = "this returns the result of the operation, \
without modifying the original"] without modifying the original"]
#[inline(always)] #[inline(always)]
pub const fn count_ones(self) -> NonZeroU32 { pub const fn count_ones(self) -> NonZero<u32> {
// SAFETY: // SAFETY:
// `self` is non-zero, which means it has at least one bit set, which means // `self` is non-zero, which means it has at least one bit set, which means
// that the result of `count_ones` is non-zero. // that the result of `count_ones` is non-zero.

View file

@ -558,6 +558,7 @@ use crate::panicking::{panic, panic_str};
use crate::pin::Pin; use crate::pin::Pin;
use crate::{ use crate::{
cmp, convert, hint, mem, cmp, convert, hint, mem,
num::NonZero,
ops::{self, ControlFlow, Deref, DerefMut}, ops::{self, ControlFlow, Deref, DerefMut},
slice, slice,
}; };
@ -2194,18 +2195,18 @@ macro_rules! non_zero_option {
} }
non_zero_option! { non_zero_option! {
#[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU8; #[stable(feature = "nonzero", since = "1.28.0")] NonZero<u8>;
#[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU16; #[stable(feature = "nonzero", since = "1.28.0")] NonZero<u16>;
#[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU32; #[stable(feature = "nonzero", since = "1.28.0")] NonZero<u32>;
#[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU64; #[stable(feature = "nonzero", since = "1.28.0")] NonZero<u64>;
#[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroU128; #[stable(feature = "nonzero", since = "1.28.0")] NonZero<u128>;
#[stable(feature = "nonzero", since = "1.28.0")] crate::num::NonZeroUsize; #[stable(feature = "nonzero", since = "1.28.0")] NonZero<usize>;
#[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI8; #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero<i8>;
#[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI16; #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero<i16>;
#[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI32; #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero<i32>;
#[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI64; #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero<i64>;
#[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroI128; #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero<i128>;
#[stable(feature = "signed_nonzero", since = "1.34.0")] crate::num::NonZeroIsize; #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZero<isize>;
} }
#[stable(feature = "nonnull", since = "1.25.0")] #[stable(feature = "nonnull", since = "1.25.0")]

View file

@ -1577,8 +1577,7 @@ mod prim_ref {}
/// - Any two types with size 0 and alignment 1 are ABI-compatible. /// - 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 /// - 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). /// 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 /// - `i32` is ABI-compatible with `NonZero<i32>`, and similar for all other integer types.
/// matching `NonZero*` type.
/// - If `T` is guaranteed to be subject to the [null pointer /// - If `T` is guaranteed to be subject to the [null pointer
/// optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible. /// optimization](option/index.html#representation), then `T` and `Option<T>` 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 /// 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 /// [`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 /// 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 /// function expects a `NonZero<i32>` and the function pointer uses the ABI-compatible type
/// `Option<NonZeroI32>`, and the value used for the argument is `None`, then this call is Undefined /// `Option<NonZero<i32>>`, and the value used for the argument is `None`, then this call is Undefined
/// Behavior since transmuting `None::<NonZeroI32>` to `NonZeroI32` violates the non-zero /// Behavior since transmuting `None::<NonZero<i32>>` to `NonZero<i32>` violates the non-zero
/// requirement. /// requirement.
/// ///
/// #### Requirements concerning target features /// #### Requirements concerning target features

View file

@ -1,5 +1,5 @@
use crate::convert::{TryFrom, TryInto}; use crate::convert::{TryFrom, TryInto};
use crate::num::{NonZero, NonZeroUsize}; use crate::num::NonZero;
use crate::{cmp, fmt, hash, mem, num}; use crate::{cmp, fmt, hash, mem, num};
/// A type storing a `usize` which is a power of two, and thus /// A type storing a `usize` which is a power of two, and thus
@ -87,7 +87,7 @@ impl Alignment {
unsafe { mem::transmute::<usize, Alignment>(align) } unsafe { mem::transmute::<usize, Alignment>(align) }
} }
/// Returns the alignment as a [`usize`] /// Returns the alignment as a [`usize`].
#[unstable(feature = "ptr_alignment_type", issue = "102070")] #[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline] #[inline]
@ -95,11 +95,11 @@ impl Alignment {
self.0 as usize self.0 as usize
} }
/// Returns the alignment as a [`NonZeroUsize`] /// Returns the alignment as a <code>[NonZero]<[usize]></code>.
#[unstable(feature = "ptr_alignment_type", issue = "102070")] #[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")] #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline] #[inline]
pub const fn as_nonzero(self) -> NonZeroUsize { pub const fn as_nonzero(self) -> NonZero<usize> {
// SAFETY: All the discriminants are non-zero. // SAFETY: All the discriminants are non-zero.
unsafe { NonZero::new_unchecked(self.as_usize()) } unsafe { NonZero::new_unchecked(self.as_usize()) }
} }
@ -164,11 +164,11 @@ impl fmt::Debug for Alignment {
} }
#[unstable(feature = "ptr_alignment_type", issue = "102070")] #[unstable(feature = "ptr_alignment_type", issue = "102070")]
impl TryFrom<NonZeroUsize> for Alignment { impl TryFrom<NonZero<usize>> for Alignment {
type Error = num::TryFromIntError; type Error = num::TryFromIntError;
#[inline] #[inline]
fn try_from(align: NonZeroUsize) -> Result<Alignment, Self::Error> { fn try_from(align: NonZero<usize>) -> Result<Alignment, Self::Error> {
align.get().try_into() align.get().try_into()
} }
} }
@ -184,9 +184,9 @@ impl TryFrom<usize> for Alignment {
} }
#[unstable(feature = "ptr_alignment_type", issue = "102070")] #[unstable(feature = "ptr_alignment_type", issue = "102070")]
impl From<Alignment> for NonZeroUsize { impl From<Alignment> for NonZero<usize> {
#[inline] #[inline]
fn from(align: Alignment) -> NonZeroUsize { fn from(align: Alignment) -> NonZero<usize> {
align.as_nonzero() align.as_nonzero()
} }
} }

View file

@ -5,7 +5,7 @@ use crate::intrinsics;
use crate::intrinsics::assert_unsafe_precondition; use crate::intrinsics::assert_unsafe_precondition;
use crate::marker::Unsize; use crate::marker::Unsize;
use crate::mem::{MaybeUninit, SizedTypeProperties}; use crate::mem::{MaybeUninit, SizedTypeProperties};
use crate::num::{NonZero, NonZeroUsize}; use crate::num::NonZero;
use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::ops::{CoerceUnsized, DispatchFromDyn};
use crate::ptr; use crate::ptr;
use crate::ptr::Unique; use crate::ptr::Unique;
@ -291,7 +291,7 @@ impl<T: ?Sized> NonNull<T> {
#[must_use] #[must_use]
#[inline] #[inline]
#[unstable(feature = "strict_provenance", issue = "95228")] #[unstable(feature = "strict_provenance", issue = "95228")]
pub fn addr(self) -> NonZeroUsize { pub fn addr(self) -> NonZero<usize> {
// SAFETY: The pointer is guaranteed by the type to be non-null, // SAFETY: The pointer is guaranteed by the type to be non-null,
// meaning that the address will be non-zero. // meaning that the address will be non-zero.
unsafe { NonZero::new_unchecked(self.pointer.addr()) } unsafe { NonZero::new_unchecked(self.pointer.addr()) }
@ -306,7 +306,7 @@ impl<T: ?Sized> NonNull<T> {
#[must_use] #[must_use]
#[inline] #[inline]
#[unstable(feature = "strict_provenance", issue = "95228")] #[unstable(feature = "strict_provenance", issue = "95228")]
pub fn with_addr(self, addr: NonZeroUsize) -> Self { pub fn with_addr(self, addr: NonZero<usize>) -> Self {
// SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. // 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 _) } unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) }
} }
@ -320,7 +320,7 @@ impl<T: ?Sized> NonNull<T> {
#[must_use] #[must_use]
#[inline] #[inline]
#[unstable(feature = "strict_provenance", issue = "95228")] #[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<usize>) -> NonZero<usize>) -> Self {
self.with_addr(f(self.addr())) self.with_addr(f(self.addr()))
} }

View file

@ -5,10 +5,10 @@ use crate::fmt::{self, Write};
use crate::iter::{Chain, FlatMap, Flatten}; use crate::iter::{Chain, FlatMap, Flatten};
use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen}; use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen};
use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::num::NonZero;
use crate::ops::Try; use crate::ops::Try;
use crate::option; use crate::option;
use crate::slice::{self, Split as SliceSplit}; use crate::slice::{self, Split as SliceSplit};
use core::num::{NonZero, NonZeroUsize};
use super::from_utf8_unchecked; use super::from_utf8_unchecked;
use super::pattern::Pattern; use super::pattern::Pattern;
@ -51,7 +51,7 @@ impl<'a> Iterator for Chars<'a> {
} }
#[inline] #[inline]
fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZeroUsize> { fn advance_by(&mut self, mut remainder: usize) -> Result<(), NonZero<usize>> {
const CHUNK_SIZE: usize = 32; const CHUNK_SIZE: usize = 32;
if remainder >= CHUNK_SIZE { if remainder >= CHUNK_SIZE {

View file

@ -136,7 +136,7 @@ thread_local! {
arena: arena::Arena::new(), arena: arena::Arena::new(),
names: fxhash::FxHashMap::default(), names: fxhash::FxHashMap::default(),
strings: Vec::new(), 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<u32>` works.
sym_base: NonZero::new(1).unwrap(), sym_base: NonZero::new(1).unwrap(),
}); });
} }

View file

@ -73,7 +73,7 @@
//! union Repr { //! union Repr {
//! // holds integer (Simple/Os) variants, and //! // holds integer (Simple/Os) variants, and
//! // provides access to the tag bits. //! // provides access to the tag bits.
//! bits: NonZeroU64, //! bits: NonZero<u64>,
//! // Tag is 0, so this is stored untagged. //! // Tag is 0, so this is stored untagged.
//! msg: &'static SimpleMessage, //! msg: &'static SimpleMessage,
//! // Tagged (offset) `Box<Custom>` pointer. //! // Tagged (offset) `Box<Custom>` pointer.
@ -93,7 +93,7 @@
//! `io::Result<()>` and `io::Result<usize>` larger, which defeats part of //! `io::Result<()>` and `io::Result<usize>` larger, which defeats part of
//! the motivation of this bitpacking. //! the motivation of this bitpacking.
//! //!
//! Storing everything in a `NonZeroUsize` (or some other integer) would be a //! Storing everything in a `NonZero<usize>` (or some other integer) would be a
//! bit more traditional for pointer tagging, but it would lose provenance //! bit more traditional for pointer tagging, but it would lose provenance
//! information, couldn't be constructed from a `const fn`, and would probably //! information, couldn't be constructed from a `const fn`, and would probably
//! run into other issues as well. //! run into other issues as well.

View file

@ -111,7 +111,7 @@ use crate::ffi::OsStr;
use crate::fmt; use crate::fmt;
use crate::fs; use crate::fs;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::num::NonZeroI32; use crate::num::NonZero;
use crate::path::Path; use crate::path::Path;
use crate::str; use crate::str;
use crate::sys::pipe::{read2, AnonPipe}; use crate::sys::pipe::{read2, AnonPipe};
@ -1775,9 +1775,9 @@ impl ExitStatusError {
self.code_nonzero().map(Into::into) 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 <code>[NonZero]<[i32]></code>.
/// ///
/// Plain `code`, returning a plain integer, is provided because it is often more convenient. /// 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 /// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want
@ -1786,17 +1786,17 @@ impl ExitStatusError {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(exit_status_error)] /// #![feature(exit_status_error, generic_nonzero)]
/// # if cfg!(unix) { /// # if cfg!(unix) {
/// use std::num::NonZeroI32; /// use std::num::NonZero;
/// use std::process::Command; /// use std::process::Command;
/// ///
/// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err(); /// 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) /// # } // cfg!(unix)
/// ``` /// ```
#[must_use] #[must_use]
pub fn code_nonzero(&self) -> Option<NonZeroI32> { pub fn code_nonzero(&self) -> Option<NonZero<i32>> {
self.0.code() self.0.code()
} }

View file

@ -165,7 +165,7 @@ use crate::fmt;
use crate::io; use crate::io;
use crate::marker::PhantomData; use crate::marker::PhantomData;
use crate::mem::{self, forget}; use crate::mem::{self, forget};
use crate::num::{NonZero, NonZeroU64, NonZeroUsize}; use crate::num::NonZero;
use crate::panic; use crate::panic;
use crate::panicking; use crate::panicking;
use crate::pin::Pin; use crate::pin::Pin;
@ -1222,7 +1222,7 @@ impl ThreadId {
/// change across Rust versions. /// change across Rust versions.
#[must_use] #[must_use]
#[unstable(feature = "thread_id_value", issue = "67939")] #[unstable(feature = "thread_id_value", issue = "67939")]
pub fn as_u64(&self) -> NonZeroU64 { pub fn as_u64(&self) -> NonZero<u64> {
self.0 self.0
} }
} }
@ -1784,6 +1784,6 @@ fn _assert_sync_and_send() {
#[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. #[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. #[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality.
#[stable(feature = "available_parallelism", since = "1.59.0")] #[stable(feature = "available_parallelism", since = "1.59.0")]
pub fn available_parallelism() -> io::Result<NonZeroUsize> { pub fn available_parallelism() -> io::Result<NonZero<usize>> {
imp::available_parallelism() imp::available_parallelism()
} }

View file

@ -1,10 +1,10 @@
//! Helper module which helps to determine amount of threads to be used //! Helper module which helps to determine amount of threads to be used
//! during tests execution. //! during tests execution.
use std::{env, num::NonZeroUsize, thread}; use std::{env, num::NonZero, thread};
pub fn get_concurrency() -> usize { pub fn get_concurrency() -> usize {
if let Ok(value) = env::var("RUST_TEST_THREADS") { if let Ok(value) = env::var("RUST_TEST_THREADS") {
match value.parse::<NonZeroUsize>().ok() { match value.parse::<NonZero<usize>>().ok() {
Some(n) => n.get(), Some(n) => n.get(),
_ => panic!("RUST_TEST_THREADS is `{value}`, should be a positive integer."), _ => panic!("RUST_TEST_THREADS is `{value}`, should be a positive integer."),
} }

View file

@ -17,6 +17,7 @@
#![unstable(feature = "test", issue = "50297")] #![unstable(feature = "test", issue = "50297")]
#![doc(test(attr(deny(warnings))))] #![doc(test(attr(deny(warnings))))]
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(generic_nonzero)]
#![feature(rustdoc_internals)] #![feature(rustdoc_internals)]
#![feature(internal_output_capture)] #![feature(internal_output_capture)]
#![feature(staged_api)] #![feature(staged_api)]