55) ]
66
77use crate :: cmp:: Ordering ;
8- use crate :: fmt;
98use crate :: hash:: { Hash , Hasher } ;
109use crate :: marker:: StructuralPartialEq ;
10+ use crate :: { fmt, pattern_type} ;
1111
1212macro_rules! define_valid_range_type {
1313 ( $(
1414 $( #[ $m: meta] ) *
15- $vis: vis struct $name: ident( $int: ident as $uint : ident in $low : literal..=$high : literal ) ;
15+ $vis: vis struct $name: ident( $int: ident is $pat : pat ) ;
1616 ) +) => { $(
17- #[ derive( Clone , Copy , Eq ) ]
17+ #[ derive( Clone , Copy ) ]
1818 #[ repr( transparent) ]
19- #[ rustc_layout_scalar_valid_range_start( $low) ]
20- #[ rustc_layout_scalar_valid_range_end( $high) ]
2119 $( #[ $m] ) *
22- $vis struct $name( $int) ;
23-
24- const _: ( ) = {
25- // With the `valid_range` attributes, it's always specified as unsigned
26- assert!( <$uint>:: MIN == 0 ) ;
27- let ulow: $uint = $low;
28- let uhigh: $uint = $high;
29- assert!( ulow <= uhigh) ;
30-
31- assert!( size_of:: <$int>( ) == size_of:: <$uint>( ) ) ;
32- } ;
33-
20+ $vis struct $name( pattern_type!( $int is $pat) ) ;
3421 impl $name {
3522 #[ inline]
3623 pub const fn new( val: $int) -> Option <Self > {
37- if ( val as $uint) >= ( $low as $uint) && ( val as $uint) <= ( $high as $uint) {
24+ #[ allow( non_contiguous_range_endpoints) ]
25+ if let $pat = val {
3826 // SAFETY: just checked the inclusive range
39- Some ( unsafe { $name( val) } )
27+ Some ( unsafe { $name( crate :: mem :: transmute ( val) ) } )
4028 } else {
4129 None
4230 }
4331 }
4432
4533 /// Constructs an instance of this type from the underlying integer
46- /// primitive without checking whether its zero .
34+ /// primitive without checking whether its valid .
4735 ///
4836 /// # Safety
49- /// Immediate language UB if `val == 0`, as it violates the validity
37+ /// Immediate language UB if `val` is not in the range of the pattern type,
38+ /// as it violates the validity
5039 /// invariant of this type.
5140 #[ inline]
5241 pub const unsafe fn new_unchecked( val: $int) -> Self {
53- // SAFETY: Caller promised that `val` is non-zero .
54- unsafe { $name( val) }
42+ // SAFETY: Caller promised that `val` is in the valid range .
43+ unsafe { $name( crate :: mem :: transmute ( val) ) }
5544 }
5645
5746 #[ inline]
5847 pub const fn as_inner( self ) -> $int {
59- // SAFETY: This is a transparent wrapper, so unwrapping it is sound
60- // (Not using `.0` due to MCP#807.)
61- unsafe { crate :: mem:: transmute( self ) }
48+ // SAFETY: pattern types are always legal values of their base type
49+ unsafe { crate :: mem:: transmute( self . 0 ) }
6250 }
6351 }
6452
@@ -67,6 +55,8 @@ macro_rules! define_valid_range_type {
6755 // by <https://github.com/rust-lang/compiler-team/issues/807>.
6856 impl StructuralPartialEq for $name { }
6957
58+ impl Eq for $name { }
59+
7060 impl PartialEq for $name {
7161 #[ inline]
7262 fn eq( & self , other: & Self ) -> bool {
@@ -104,7 +94,7 @@ macro_rules! define_valid_range_type {
10494}
10595
10696define_valid_range_type ! {
107- pub struct Nanoseconds ( u32 as u32 in 0 ..=999_999_999 ) ;
97+ pub struct Nanoseconds ( u32 is 0 ..=999_999_999 ) ;
10898}
10999
110100impl Nanoseconds {
@@ -119,45 +109,30 @@ impl Default for Nanoseconds {
119109 }
120110}
121111
122- define_valid_range_type ! {
123- pub struct NonZeroU8Inner ( u8 as u8 in 1 ..=0xff ) ;
124- pub struct NonZeroU16Inner ( u16 as u16 in 1 ..=0xff_ff ) ;
125- pub struct NonZeroU32Inner ( u32 as u32 in 1 ..=0xffff_ffff ) ;
126- pub struct NonZeroU64Inner ( u64 as u64 in 1 ..=0xffffffff_ffffffff ) ;
127- pub struct NonZeroU128Inner ( u128 as u128 in 1 ..=0xffffffffffffffff_ffffffffffffffff ) ;
128-
129- pub struct NonZeroI8Inner ( i8 as u8 in 1 ..=0xff ) ;
130- pub struct NonZeroI16Inner ( i16 as u16 in 1 ..=0xff_ff ) ;
131- pub struct NonZeroI32Inner ( i32 as u32 in 1 ..=0xffff_ffff ) ;
132- pub struct NonZeroI64Inner ( i64 as u64 in 1 ..=0xffffffff_ffffffff ) ;
133- pub struct NonZeroI128Inner ( i128 as u128 in 1 ..=0xffffffffffffffff_ffffffffffffffff ) ;
134- }
135-
136- #[ cfg( target_pointer_width = "16" ) ]
137- define_valid_range_type ! {
138- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff ) ;
139- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff ) ;
140- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff ) ;
141- }
142- #[ cfg( target_pointer_width = "32" ) ]
143- define_valid_range_type ! {
144- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff_ffff ) ;
145- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff_ffff ) ;
146- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff_ffff ) ;
147- }
148- #[ cfg( target_pointer_width = "64" ) ]
149- define_valid_range_type ! {
150- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff_ffff_ffff_ffff ) ;
151- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff_ffff_ffff_ffff ) ;
152- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff_ffff_ffff_ffff ) ;
153- }
112+ const HALF_USIZE : usize = usize:: MAX >> 1 ;
154113
155114define_valid_range_type ! {
156- pub struct U32NotAllOnes ( u32 as u32 in 0 ..=0xffff_fffe ) ;
157- pub struct I32NotAllOnes ( i32 as u32 in 0 ..=0xffff_fffe ) ;
158-
159- pub struct U64NotAllOnes ( u64 as u64 in 0 ..=0xffff_ffff_ffff_fffe ) ;
160- pub struct I64NotAllOnes ( i64 as u64 in 0 ..=0xffff_ffff_ffff_fffe ) ;
115+ pub struct NonZeroU8Inner ( u8 is 1 ..) ;
116+ pub struct NonZeroU16Inner ( u16 is 1 ..) ;
117+ pub struct NonZeroU32Inner ( u32 is 1 ..) ;
118+ pub struct NonZeroU64Inner ( u64 is 1 ..) ;
119+ pub struct NonZeroU128Inner ( u128 is 1 ..) ;
120+
121+ pub struct NonZeroI8Inner ( i8 is ..0 | 1 ..) ;
122+ pub struct NonZeroI16Inner ( i16 is ..0 | 1 ..) ;
123+ pub struct NonZeroI32Inner ( i32 is ..0 | 1 ..) ;
124+ pub struct NonZeroI64Inner ( i64 is ..0 | 1 ..) ;
125+ pub struct NonZeroI128Inner ( i128 is ..0 | 1 ..) ;
126+
127+ pub struct UsizeNoHighBit ( usize is 0 ..=HALF_USIZE ) ;
128+ pub struct NonZeroUsizeInner ( usize is 1 ..) ;
129+ pub struct NonZeroIsizeInner ( isize is ..0 | 1 ..) ;
130+
131+ pub struct U32NotAllOnes ( u32 is 0 ..u32 :: MAX ) ;
132+ pub struct I32NotAllOnes ( i32 is ..-1 | 0 ..) ;
133+
134+ pub struct U64NotAllOnes ( u64 is 0 ..u64 :: MAX ) ;
135+ pub struct I64NotAllOnes ( i64 is ..-1 | 0 ..) ;
161136}
162137
163138pub trait NotAllOnesHelper {
0 commit comments