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 , $op : tt $val : expr ) ;
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+ if val $op $ val {
3825 // SAFETY: just checked the inclusive range
39- Some ( unsafe { $name( val) } )
26+ Some ( unsafe { $name( crate :: mem :: transmute ( val) ) } )
4027 } else {
4128 None
4229 }
4330 }
4431
4532 /// Constructs an instance of this type from the underlying integer
46- /// primitive without checking whether its zero .
33+ /// primitive without checking whether its valid .
4734 ///
4835 /// # Safety
49- /// Immediate language UB if `val == 0`, as it violates the validity
36+ /// Immediate language UB if `val` is not in the range of the pattern type,
37+ /// as it violates the validity
5038 /// invariant of this type.
5139 #[ inline]
5240 pub const unsafe fn new_unchecked( val: $int) -> Self {
53- // SAFETY: Caller promised that `val` is non-zero .
54- unsafe { $name( val) }
41+ // SAFETY: Caller promised that `val` is in the valid range .
42+ unsafe { $name( crate :: mem :: transmute ( val) ) }
5543 }
5644
5745 #[ inline]
5846 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 ) }
47+ // SAFETY: pattern types are always legal values of their base type
48+ unsafe { crate :: mem:: transmute( self . 0 ) }
6249 }
6350 }
6451
@@ -67,6 +54,8 @@ macro_rules! define_valid_range_type {
6754 // by <https://github.com/rust-lang/compiler-team/issues/807>.
6855 impl StructuralPartialEq for $name { }
6956
57+ impl Eq for $name { }
58+
7059 impl PartialEq for $name {
7160 #[ inline]
7261 fn eq( & self , other: & Self ) -> bool {
@@ -104,7 +93,7 @@ macro_rules! define_valid_range_type {
10493}
10594
10695define_valid_range_type ! {
107- pub struct Nanoseconds ( u32 as u32 in 0 ..=999_999_999 ) ;
96+ pub struct Nanoseconds ( u32 is 0 ..=999_999_999 , <= 999_999_999 ) ;
10897}
10998
11099impl Nanoseconds {
@@ -119,45 +108,32 @@ impl Default for Nanoseconds {
119108 }
120109}
121110
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- }
111+ const MAX_32_MINUS_1 : u32 = u32:: MAX - 1 ;
112+ const MAX_64_MINUS_1 : u64 = u64:: MAX - 1 ;
113+ const HALF_USIZE : usize = usize:: MAX >> 1 ;
154114
155115define_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 ) ;
116+ pub struct NonZeroU8Inner ( u8 is 1 .., != 0 ) ;
117+ pub struct NonZeroU16Inner ( u16 is 1 .., != 0 ) ;
118+ pub struct NonZeroU32Inner ( u32 is 1 .., != 0 ) ;
119+ pub struct NonZeroU64Inner ( u64 is 1 .., != 0 ) ;
120+ pub struct NonZeroU128Inner ( u128 is 1 .., != 0 ) ;
121+
122+ pub struct NonZeroI8Inner ( i8 is ..0 | 1 .., != 0 ) ;
123+ pub struct NonZeroI16Inner ( i16 is ..0 | 1 .., != 0 ) ;
124+ pub struct NonZeroI32Inner ( i32 is ..0 | 1 .., != 0 ) ;
125+ pub struct NonZeroI64Inner ( i64 is ..0 | 1 .., != 0 ) ;
126+ pub struct NonZeroI128Inner ( i128 is ..0 | 1 .., != 0 ) ;
127+
128+ pub struct UsizeNoHighBit ( usize is 0 ..=HALF_USIZE , <= HALF_USIZE ) ;
129+ pub struct NonZeroUsizeInner ( usize is 1 .., != 0 ) ;
130+ pub struct NonZeroIsizeInner ( isize is ..0 | 1 .., != 0 ) ;
131+
132+ pub struct U32NotAllOnes ( u32 is 0 ..=MAX_32_MINUS_1 , <= MAX_32_MINUS_1 ) ;
133+ pub struct I32NotAllOnes ( i32 is ..-1 | 0 .., != -1 ) ;
134+
135+ pub struct U64NotAllOnes ( u64 is 0 ..=MAX_64_MINUS_1 , <= MAX_64_MINUS_1 ) ;
136+ pub struct I64NotAllOnes ( i64 is ..-1 | 0 .., != -1 ) ;
161137}
162138
163139pub trait NotAllOnesHelper {
0 commit comments