Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core::num::NonZero<N> type alias #88990

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ pub use dec2flt::ParseFloatError;
#[stable(feature = "rust1", since = "1.0.0")]
pub use error::ParseIntError;

#[unstable(feature = "nonzero_generic_type_alias", issue = "82363")]
pub use nonzero::NonZero;

#[stable(feature = "nonzero", since = "1.28.0")]
pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};

Expand Down
54 changes: 54 additions & 0 deletions library/core/src/num/nonzero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,55 @@ use super::from_str_radix;
use super::{IntErrorKind, ParseIntError};
use crate::intrinsics;

/// Generic type alias for the non-zero type that corresponds to each integer
/// primitive.
///
/// This type alias simply provides an alternative spelling of the various
/// `NonZero` structs found in [`core::num`]. For example `NonZero<u16>` refers
/// to the struct [`core::num::NonZeroU16`].
///
/// **Note:** this is *not* intended for writing code that is generic over
/// multiple types of non-zero integers. The relevant trait bound you would need
/// for that is not exposed. The only thing this is, is an alternative spelling.
///
/// # Example
///
/// Where this comes in handy is if the primitive types themselves are being
/// used via a type alias, such as [`std::os::raw::c_char`][c_char]. The
/// `c_char` type refers to either `i8` or `u8` depending on whether the
/// platform's C character type is signed or unsigned, and without `NonZero<N>`
/// there is not a straightforward way to name either `NonZeroI8` or `NonZeroU8`
/// depending on which one a non-zero `c_char` corresponds to.
///
/// [c_char]: ../../std/os/raw/type.c_char.html
///
/// ```
/// #![feature(nonzero_generic_type_alias)]
///
/// use std::num::NonZero;
/// use std::os::raw::c_char;
///
/// // A separator that we're planning to use with nul-terminated C strings,
/// // where \0 would be nonsensical.
/// pub struct Separator {
/// ch: NonZero<c_char>,
/// }
///
/// impl Separator {
/// pub fn new(ch: c_char) -> Option<Self> {
/// NonZero::<c_char>::new(ch).map(|ch| Separator { ch })
/// }
/// }
/// ```
#[unstable(feature = "nonzero_generic_type_alias", issue = "82363")]
pub type NonZero<N> = <N as IntegerPrimitive>::NonZero;

// Not exposed at any publicly accessible path, only via NonZero<N>.
#[unstable(feature = "nonzero_implementation_detail", issue = "none")]
pub trait IntegerPrimitive {
type NonZero;
}

macro_rules! impl_nonzero_fmt {
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
$(
Expand Down Expand Up @@ -41,6 +90,11 @@ macro_rules! nonzero_integers {
#[rustc_nonnull_optimization_guaranteed]
pub struct $Ty($Int);

#[unstable(feature = "nonzero_implementation_detail", issue = "none")]
impl IntegerPrimitive for $Int {
type NonZero = $Ty;
}

impl $Ty {
/// Creates a non-zero without checking whether the value is non-zero.
/// This results in undefined behaviour if the value is zero.
Expand Down
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@
#![feature(new_uninit)]
#![feature(nll)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(nonzero_generic_type_alias)]
#![feature(once_cell)]
#![feature(panic_info_message)]
#![feature(panic_internals)]
Expand Down
2 changes: 2 additions & 0 deletions library/std/src/num.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub use core::num::Wrapping;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError};

#[unstable(feature = "nonzero_generic_type_alias", issue = "82363")]
pub use core::num::NonZero;
#[stable(feature = "signed_nonzero", since = "1.34.0")]
pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
#[stable(feature = "nonzero", since = "1.28.0")]
Expand Down
56 changes: 17 additions & 39 deletions library/std/src/os/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
#[cfg(test)]
mod tests;

use core::num::*;

macro_rules! type_alias_no_nz {
macro_rules! type_alias {
{
$Docfile:tt, $Alias:ident = $Real:ty;
$( $Cfg:tt )*
Expand All @@ -25,27 +23,7 @@ macro_rules! type_alias_no_nz {
}
}

// To verify that the NonZero types in this file's macro invocations correspond
//
// perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
//
// NB this does not check that the main c_* types are right.

macro_rules! type_alias {
{
$Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
$( $Cfg:tt )*
} => {
type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }

#[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
#[unstable(feature = "raw_os_nonzero", issue = "82363")]
$( $Cfg )*
pub type $NZAlias = $NZReal;
}
}

type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
type_alias! { "char.md", c_char = u8;
#[cfg(any(
all(
target_os = "linux",
Expand Down Expand Up @@ -87,7 +65,7 @@ type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
),
all(target_os = "fuchsia", target_arch = "aarch64")
))]}
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
type_alias! { "char.md", c_char = i8;
#[cfg(not(any(
all(
target_os = "linux",
Expand Down Expand Up @@ -129,24 +107,24 @@ type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
),
all(target_os = "fuchsia", target_arch = "aarch64")
)))]}
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
type_alias! { "schar.md", c_schar = i8; }
type_alias! { "uchar.md", c_uchar = u8; }
type_alias! { "short.md", c_short = i16; }
type_alias! { "ushort.md", c_ushort = u16; }
type_alias! { "int.md", c_int = i32; }
type_alias! { "uint.md", c_uint = u32; }
type_alias! { "long.md", c_long = i32;
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
type_alias! { "ulong.md", c_ulong = u32;
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
type_alias! { "long.md", c_long = i64;
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
type_alias! { "ulong.md", c_ulong = u64;
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
type_alias_no_nz! { "float.md", c_float = f32; }
type_alias_no_nz! { "double.md", c_double = f64; }
type_alias! { "longlong.md", c_longlong = i64; }
type_alias! { "ulonglong.md", c_ulonglong = u64; }
type_alias! { "float.md", c_float = f32; }
type_alias! { "double.md", c_double = f64; }

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
Expand Down
7 changes: 3 additions & 4 deletions library/std/src/sys/unix/process/process_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use crate::convert::{TryFrom, TryInto};
use crate::fmt;
use crate::io::{self, Error, ErrorKind};
use crate::mem;
use crate::num::NonZeroI32;
use crate::os::raw::NonZero_c_int;
use crate::num::{NonZero, NonZeroI32};
use crate::ptr;
use crate::sys;
use crate::sys::cvt;
Expand Down Expand Up @@ -625,7 +624,7 @@ impl ExitStatus {
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html . If it is not
// true for a platform pretending to be Unix, the tests (our doctests, and also
// procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
match NonZero_c_int::try_from(self.0) {
match NonZero::<c_int>::try_from(self.0) {
/* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)),
/* was zero, couldn't convert */ Err(_) => Ok(()),
}
Expand Down Expand Up @@ -684,7 +683,7 @@ impl fmt::Display for ExitStatus {
}

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ExitStatusError(NonZero_c_int);
pub struct ExitStatusError(NonZero<c_int>);

impl Into<ExitStatus> for ExitStatusError {
fn into(self) -> ExitStatus {
Expand Down
5 changes: 2 additions & 3 deletions library/std/src/sys/unix/process/process_unsupported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use crate::convert::{TryFrom, TryInto};
use crate::fmt;
use crate::io;
use crate::io::ErrorKind;
use crate::num::NonZeroI32;
use crate::os::raw::NonZero_c_int;
use crate::num::{NonZero, NonZeroI32};
use crate::sys;
use crate::sys::cvt;
use crate::sys::pipe::AnonPipe;
Expand Down Expand Up @@ -107,7 +106,7 @@ impl fmt::Display for ExitStatus {
}

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ExitStatusError(NonZero_c_int);
pub struct ExitStatusError(NonZero<c_int>);

impl Into<ExitStatus> for ExitStatusError {
fn into(self) -> ExitStatus {
Expand Down
7 changes: 3 additions & 4 deletions library/std/src/sys/unix/process/process_vxworks.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::convert::{TryFrom, TryInto};
use crate::fmt;
use crate::io::{self, Error, ErrorKind};
use crate::num::NonZeroI32;
use crate::os::raw::NonZero_c_int;
use crate::num::{NonZero, NonZeroI32};
use crate::sys;
use crate::sys::cvt;
use crate::sys::process::process_common::*;
Expand Down Expand Up @@ -196,7 +195,7 @@ impl ExitStatus {
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html . If it is not
// true for a platform pretending to be Unix, the tests (our doctests, and also
// procsss_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too.
match NonZero_c_int::try_from(self.0) {
match NonZero::<c_int>::try_from(self.0) {
Ok(failure) => Err(ExitStatusError(failure)),
Err(_) => Ok(()),
}
Expand Down Expand Up @@ -248,7 +247,7 @@ impl fmt::Display for ExitStatus {
}

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ExitStatusError(NonZero_c_int);
pub struct ExitStatusError(NonZero<c_int>);

impl Into<ExitStatus> for ExitStatusError {
fn into(self) -> ExitStatus {
Expand Down
4 changes: 2 additions & 2 deletions library/std/src/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#![cfg_attr(test, allow(dead_code))]
#![unstable(issue = "none", feature = "windows_c")]

use crate::os::raw::NonZero_c_ulong;
use crate::num::NonZero;
use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
use crate::ptr;

Expand All @@ -19,7 +19,7 @@ pub use self::FILE_INFO_BY_HANDLE_CLASS::*;

pub type DWORD_PTR = ULONG_PTR;
pub type DWORD = c_ulong;
pub type NonZeroDWORD = NonZero_c_ulong;
pub type NonZeroDWORD = NonZero<DWORD>;
pub type HANDLE = LPVOID;
pub type HINSTANCE = HANDLE;
pub type HMODULE = HINSTANCE;
Expand Down