Auto merge of #148537 - oli-obk:push-yxuttqrqqyvu, r=dianqk
Start using pattern types in libcore (NonZero and friends) part of rust-lang/rust#136006 This PR only changes the internal representation of `NonZero`, `NonMax`, ... and other integral range types in libcore. This subsequently affects other types made up of it, but nothing really changes except that the field of `NonZero` is now accessible safely in contrast to the `rustc_layout_scalar_range_start` attribute, which has all kinds of obscure rules on how to properly access its field.
This commit is contained in:
commit
bb8b30a5fc
10 changed files with 65 additions and 75 deletions
|
|
@ -5,45 +5,33 @@
|
|||
)]
|
||||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::marker::StructuralPartialEq;
|
||||
use crate::{fmt, pattern_type};
|
||||
|
||||
macro_rules! define_valid_range_type {
|
||||
($(
|
||||
$(#[$m:meta])*
|
||||
$vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal);
|
||||
$vis:vis struct $name:ident($int:ident is $pat:pat);
|
||||
)+) => {$(
|
||||
#[derive(Clone, Copy, Eq)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start($low)]
|
||||
#[rustc_layout_scalar_valid_range_end($high)]
|
||||
$(#[$m])*
|
||||
$vis struct $name($int);
|
||||
|
||||
const _: () = {
|
||||
// With the `valid_range` attributes, it's always specified as unsigned
|
||||
assert!(<$uint>::MIN == 0);
|
||||
let ulow: $uint = $low;
|
||||
let uhigh: $uint = $high;
|
||||
assert!(ulow <= uhigh);
|
||||
|
||||
assert!(size_of::<$int>() == size_of::<$uint>());
|
||||
};
|
||||
|
||||
$vis struct $name(pattern_type!($int is $pat));
|
||||
impl $name {
|
||||
#[inline]
|
||||
pub const fn new(val: $int) -> Option<Self> {
|
||||
if (val as $uint) >= ($low as $uint) && (val as $uint) <= ($high as $uint) {
|
||||
// SAFETY: just checked the inclusive range
|
||||
Some(unsafe { $name(val) })
|
||||
#[allow(non_contiguous_range_endpoints)]
|
||||
if let $pat = val {
|
||||
// SAFETY: just checked that the value matches the pattern
|
||||
Some(unsafe { $name(crate::mem::transmute(val)) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an instance of this type from the underlying integer
|
||||
/// primitive without checking whether its zero.
|
||||
/// primitive without checking whether its valid.
|
||||
///
|
||||
/// # Safety
|
||||
/// Immediate language UB if `val` is not within the valid range for this
|
||||
|
|
@ -51,13 +39,13 @@ macro_rules! define_valid_range_type {
|
|||
#[inline]
|
||||
pub const unsafe fn new_unchecked(val: $int) -> Self {
|
||||
// SAFETY: Caller promised that `val` is within the valid range.
|
||||
unsafe { $name(val) }
|
||||
unsafe { crate::mem::transmute(val) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn as_inner(self) -> $int {
|
||||
// SAFETY: This is a transparent wrapper, so unwrapping it is sound
|
||||
// (Not using `.0` due to MCP#807.)
|
||||
// SAFETY: pattern types are always legal values of their base type
|
||||
// (Not using `.0` because that has perf regressions.)
|
||||
unsafe { crate::mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
|
@ -67,6 +55,8 @@ macro_rules! define_valid_range_type {
|
|||
// by <https://github.com/rust-lang/compiler-team/issues/807>.
|
||||
impl StructuralPartialEq for $name {}
|
||||
|
||||
impl Eq for $name {}
|
||||
|
||||
impl PartialEq for $name {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
|
|
@ -104,7 +94,7 @@ macro_rules! define_valid_range_type {
|
|||
}
|
||||
|
||||
define_valid_range_type! {
|
||||
pub struct Nanoseconds(u32 as u32 in 0..=999_999_999);
|
||||
pub struct Nanoseconds(u32 is 0..=999_999_999);
|
||||
}
|
||||
|
||||
impl Nanoseconds {
|
||||
|
|
@ -120,47 +110,32 @@ impl const Default for Nanoseconds {
|
|||
}
|
||||
}
|
||||
|
||||
define_valid_range_type! {
|
||||
pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff);
|
||||
pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff);
|
||||
pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff);
|
||||
pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff);
|
||||
pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);
|
||||
|
||||
pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff);
|
||||
pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff);
|
||||
pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff);
|
||||
pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff);
|
||||
pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);
|
||||
|
||||
pub struct NonZeroCharInner(char as u32 in 1..=0x10ffff);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
define_valid_range_type! {
|
||||
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff);
|
||||
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff);
|
||||
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff);
|
||||
}
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
define_valid_range_type! {
|
||||
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff);
|
||||
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff);
|
||||
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff);
|
||||
}
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
define_valid_range_type! {
|
||||
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff);
|
||||
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff);
|
||||
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff);
|
||||
}
|
||||
const HALF_USIZE: usize = usize::MAX >> 1;
|
||||
|
||||
define_valid_range_type! {
|
||||
pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe);
|
||||
pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe);
|
||||
pub struct NonZeroU8Inner(u8 is 1..);
|
||||
pub struct NonZeroU16Inner(u16 is 1..);
|
||||
pub struct NonZeroU32Inner(u32 is 1..);
|
||||
pub struct NonZeroU64Inner(u64 is 1..);
|
||||
pub struct NonZeroU128Inner(u128 is 1..);
|
||||
|
||||
pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe);
|
||||
pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe);
|
||||
pub struct NonZeroI8Inner(i8 is ..0 | 1..);
|
||||
pub struct NonZeroI16Inner(i16 is ..0 | 1..);
|
||||
pub struct NonZeroI32Inner(i32 is ..0 | 1..);
|
||||
pub struct NonZeroI64Inner(i64 is ..0 | 1..);
|
||||
pub struct NonZeroI128Inner(i128 is ..0 | 1..);
|
||||
|
||||
pub struct UsizeNoHighBit(usize is 0..=HALF_USIZE);
|
||||
pub struct NonZeroUsizeInner(usize is 1..);
|
||||
pub struct NonZeroIsizeInner(isize is ..0 | 1..);
|
||||
|
||||
pub struct U32NotAllOnes(u32 is 0..u32::MAX);
|
||||
pub struct I32NotAllOnes(i32 is ..-1 | 0..);
|
||||
|
||||
pub struct U64NotAllOnes(u64 is 0..u64::MAX);
|
||||
pub struct I64NotAllOnes(i64 is ..-1 | 0..);
|
||||
|
||||
pub struct NonZeroCharInner(char is '\u{1}' ..= '\u{10ffff}');
|
||||
}
|
||||
|
||||
pub trait NotAllOnesHelper {
|
||||
|
|
@ -181,7 +156,7 @@ impl NotAllOnesHelper for i64 {
|
|||
}
|
||||
|
||||
define_valid_range_type! {
|
||||
pub struct CodePointInner(u32 as u32 in 0..=0x10ffff);
|
||||
pub struct CodePointInner(u32 is 0..=0x10ffff);
|
||||
}
|
||||
|
||||
impl CodePointInner {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue