Skip to content

Commit 69f2909

Browse files
committed
Move generic NonZero rustc_layout_scalar_valid_range_start attribute to inner type.
1 parent e53abfc commit 69f2909

File tree

1 file changed

+76
-51
lines changed

1 file changed

+76
-51
lines changed

core/src/num/nonzero.rs

Lines changed: 76 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,12 @@ use crate::hash::{Hash, Hasher};
66
use crate::intrinsics;
77
use crate::marker::StructuralPartialEq;
88
use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem};
9+
use crate::ptr;
910
use crate::str::FromStr;
1011

1112
use super::from_str_radix;
1213
use super::{IntErrorKind, ParseIntError};
1314

14-
mod private {
15-
#[unstable(
16-
feature = "nonzero_internals",
17-
reason = "implementation detail which may disappear or be replaced at any time",
18-
issue = "none"
19-
)]
20-
#[const_trait]
21-
pub trait Sealed {}
22-
}
23-
2415
/// A marker trait for primitive types which can be zero.
2516
///
2617
/// This is an implementation detail for <code>[NonZero]\<T></code> which may disappear or be replaced at any time.
@@ -34,38 +25,70 @@ mod private {
3425
issue = "none"
3526
)]
3627
#[const_trait]
37-
pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed {}
28+
pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed {
29+
#[doc(hidden)]
30+
type NonZeroInner: Sized + Copy;
31+
}
3832

3933
macro_rules! impl_zeroable_primitive {
40-
($primitive:ty) => {
41-
#[unstable(
42-
feature = "nonzero_internals",
43-
reason = "implementation detail which may disappear or be replaced at any time",
44-
issue = "none"
45-
)]
46-
impl const private::Sealed for $primitive {}
47-
48-
#[unstable(
49-
feature = "nonzero_internals",
50-
reason = "implementation detail which may disappear or be replaced at any time",
51-
issue = "none"
52-
)]
53-
unsafe impl const ZeroablePrimitive for $primitive {}
34+
($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => {
35+
mod private {
36+
#[unstable(
37+
feature = "nonzero_internals",
38+
reason = "implementation detail which may disappear or be replaced at any time",
39+
issue = "none"
40+
)]
41+
#[const_trait]
42+
pub trait Sealed {}
43+
44+
$(
45+
#[derive(Debug, Clone, Copy, PartialEq)]
46+
#[repr(transparent)]
47+
#[rustc_layout_scalar_valid_range_start(1)]
48+
#[rustc_nonnull_optimization_guaranteed]
49+
#[unstable(
50+
feature = "nonzero_internals",
51+
reason = "implementation detail which may disappear or be replaced at any time",
52+
issue = "none"
53+
)]
54+
pub struct $NonZeroInner($primitive);
55+
)+
56+
}
57+
58+
$(
59+
#[unstable(
60+
feature = "nonzero_internals",
61+
reason = "implementation detail which may disappear or be replaced at any time",
62+
issue = "none"
63+
)]
64+
impl const private::Sealed for $primitive {}
65+
66+
#[unstable(
67+
feature = "nonzero_internals",
68+
reason = "implementation detail which may disappear or be replaced at any time",
69+
issue = "none"
70+
)]
71+
unsafe impl const ZeroablePrimitive for $primitive {
72+
type NonZeroInner = private::$NonZeroInner;
73+
}
74+
)+
5475
};
5576
}
5677

57-
impl_zeroable_primitive!(u8);
58-
impl_zeroable_primitive!(u16);
59-
impl_zeroable_primitive!(u32);
60-
impl_zeroable_primitive!(u64);
61-
impl_zeroable_primitive!(u128);
62-
impl_zeroable_primitive!(usize);
63-
impl_zeroable_primitive!(i8);
64-
impl_zeroable_primitive!(i16);
65-
impl_zeroable_primitive!(i32);
66-
impl_zeroable_primitive!(i64);
67-
impl_zeroable_primitive!(i128);
68-
impl_zeroable_primitive!(isize);
78+
impl_zeroable_primitive!(
79+
NonZeroU8Inner(u8),
80+
NonZeroU16Inner(u16),
81+
NonZeroU32Inner(u32),
82+
NonZeroU64Inner(u64),
83+
NonZeroU128Inner(u128),
84+
NonZeroUsizeInner(usize),
85+
NonZeroI8Inner(i8),
86+
NonZeroI16Inner(i16),
87+
NonZeroI32Inner(i32),
88+
NonZeroI64Inner(i64),
89+
NonZeroI128Inner(i128),
90+
NonZeroIsizeInner(isize),
91+
);
6992

7093
/// A value that is known not to equal zero.
7194
///
@@ -80,10 +103,8 @@ impl_zeroable_primitive!(isize);
80103
/// ```
81104
#[unstable(feature = "generic_nonzero", issue = "120257")]
82105
#[repr(transparent)]
83-
#[rustc_layout_scalar_valid_range_start(1)]
84-
#[rustc_nonnull_optimization_guaranteed]
85106
#[rustc_diagnostic_item = "NonZero"]
86-
pub struct NonZero<T: ZeroablePrimitive>(T);
107+
pub struct NonZero<T: ZeroablePrimitive>(T::NonZeroInner);
87108

88109
macro_rules! impl_nonzero_fmt {
89110
($Trait:ident) => {
@@ -114,8 +135,7 @@ where
114135
{
115136
#[inline]
116137
fn clone(&self) -> Self {
117-
// SAFETY: The contained value is non-zero.
118-
unsafe { Self(self.0) }
138+
Self(self.0)
119139
}
120140
}
121141

@@ -188,19 +208,19 @@ where
188208
#[inline]
189209
fn max(self, other: Self) -> Self {
190210
// SAFETY: The maximum of two non-zero values is still non-zero.
191-
unsafe { Self(self.get().max(other.get())) }
211+
unsafe { Self::new_unchecked(self.get().max(other.get())) }
192212
}
193213

194214
#[inline]
195215
fn min(self, other: Self) -> Self {
196216
// SAFETY: The minimum of two non-zero values is still non-zero.
197-
unsafe { Self(self.get().min(other.get())) }
217+
unsafe { Self::new_unchecked(self.get().min(other.get())) }
198218
}
199219

200220
#[inline]
201221
fn clamp(self, min: Self, max: Self) -> Self {
202222
// SAFETY: A non-zero value clamped between two non-zero values is still non-zero.
203-
unsafe { Self(self.get().clamp(min.get(), max.get())) }
223+
unsafe { Self::new_unchecked(self.get().clamp(min.get(), max.get())) }
204224
}
205225
}
206226

@@ -240,7 +260,7 @@ where
240260
#[inline]
241261
fn bitor(self, rhs: Self) -> Self::Output {
242262
// SAFETY: Bitwise OR of two non-zero values is still non-zero.
243-
unsafe { Self(self.get() | rhs.get()) }
263+
unsafe { Self::new_unchecked(self.get() | rhs.get()) }
244264
}
245265
}
246266

@@ -254,7 +274,7 @@ where
254274
#[inline]
255275
fn bitor(self, rhs: T) -> Self::Output {
256276
// SAFETY: Bitwise OR of a non-zero value with anything is still non-zero.
257-
unsafe { Self(self.get() | rhs) }
277+
unsafe { Self::new_unchecked(self.get() | rhs) }
258278
}
259279
}
260280

@@ -268,7 +288,7 @@ where
268288
#[inline]
269289
fn bitor(self, rhs: NonZero<T>) -> Self::Output {
270290
// SAFETY: Bitwise OR of anything with a non-zero value is still non-zero.
271-
unsafe { NonZero(self | rhs.get()) }
291+
unsafe { NonZero::new_unchecked(self | rhs.get()) }
272292
}
273293
}
274294

@@ -346,7 +366,7 @@ where
346366
pub fn from_mut(n: &mut T) -> Option<&mut Self> {
347367
// SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
348368
// the same layout and size as `T`, with `0` representing `None`.
349-
let opt_n = unsafe { &mut *(n as *mut T as *mut Option<Self>) };
369+
let opt_n = unsafe { &mut *(ptr::from_mut(n).cast::<Option<Self>>()) };
350370

351371
opt_n.as_mut()
352372
}
@@ -390,12 +410,17 @@ where
390410
// memory somewhere. If the value of `self` was from by-value argument
391411
// of some not-inlined function, LLVM don't have range metadata
392412
// to understand that the value cannot be zero.
393-
match Self::new(self.0) {
394-
Some(Self(n)) => n,
413+
//
414+
// SAFETY: `Self` is guaranteed to have the same layout as `Option<Self>`.
415+
match unsafe { intrinsics::transmute_unchecked(self) } {
395416
None => {
396417
// SAFETY: `NonZero` is guaranteed to only contain non-zero values, so this is unreachable.
397418
unsafe { intrinsics::unreachable() }
398419
}
420+
Some(Self(inner)) => {
421+
// SAFETY: `T::NonZeroInner` is guaranteed to have the same layout as `T`.
422+
unsafe { intrinsics::transmute_unchecked(inner) }
423+
}
399424
}
400425
}
401426
}

0 commit comments

Comments
 (0)