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) {
38- // SAFETY: just checked the inclusive range
39- Some ( unsafe { $name( val) } )
24+ #[ allow( non_contiguous_range_endpoints) ]
25+ if let $pat = val {
26+ // SAFETY: just checked that the value matches the pattern
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
4937 /// Immediate language UB if `val` is not within the valid range for this
5038 /// type, as it violates the validity invariant.
5139 #[ inline]
5240 pub const unsafe fn new_unchecked( val: $int) -> Self {
5341 // SAFETY: Caller promised that `val` is within the valid range.
54- unsafe { $name( val) }
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 ) ;
10897}
10998
11099impl Nanoseconds {
@@ -120,47 +109,32 @@ impl const Default for Nanoseconds {
120109 }
121110}
122111
123- define_valid_range_type ! {
124- pub struct NonZeroU8Inner ( u8 as u8 in 1 ..=0xff ) ;
125- pub struct NonZeroU16Inner ( u16 as u16 in 1 ..=0xff_ff ) ;
126- pub struct NonZeroU32Inner ( u32 as u32 in 1 ..=0xffff_ffff ) ;
127- pub struct NonZeroU64Inner ( u64 as u64 in 1 ..=0xffffffff_ffffffff ) ;
128- pub struct NonZeroU128Inner ( u128 as u128 in 1 ..=0xffffffffffffffff_ffffffffffffffff ) ;
129-
130- pub struct NonZeroI8Inner ( i8 as u8 in 1 ..=0xff ) ;
131- pub struct NonZeroI16Inner ( i16 as u16 in 1 ..=0xff_ff ) ;
132- pub struct NonZeroI32Inner ( i32 as u32 in 1 ..=0xffff_ffff ) ;
133- pub struct NonZeroI64Inner ( i64 as u64 in 1 ..=0xffffffff_ffffffff ) ;
134- pub struct NonZeroI128Inner ( i128 as u128 in 1 ..=0xffffffffffffffff_ffffffffffffffff ) ;
135-
136- pub struct NonZeroCharInner ( char as u32 in 1 ..=0x10ffff ) ;
137- }
112+ const HALF_USIZE : usize = usize:: MAX >> 1 ;
138113
139- #[ cfg( target_pointer_width = "16" ) ]
140- define_valid_range_type ! {
141- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff ) ;
142- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff ) ;
143- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff ) ;
144- }
145- #[ cfg( target_pointer_width = "32" ) ]
146114define_valid_range_type ! {
147- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff_ffff ) ;
148- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff_ffff ) ;
149- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff_ffff ) ;
150- }
151- #[ cfg( target_pointer_width = "64" ) ]
152- define_valid_range_type ! {
153- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff_ffff_ffff_ffff ) ;
154- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff_ffff_ffff_ffff ) ;
155- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff_ffff_ffff_ffff ) ;
156- }
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 ..) ;
157120
158- define_valid_range_type ! {
159- pub struct U32NotAllOnes ( u32 as u32 in 0 ..=0xffff_fffe ) ;
160- pub struct I32NotAllOnes ( i32 as u32 in 0 ..=0xffff_fffe ) ;
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
162- pub struct U64NotAllOnes ( u64 as u64 in 0 ..=0xffff_ffff_ffff_fffe ) ;
163- pub struct I64NotAllOnes ( i64 as u64 in 0 ..=0xffff_ffff_ffff_fffe ) ;
137+ pub struct NonZeroCharInner ( char is '\u{1}' ..= '\u{10ffff}' ) ;
164138}
165139
166140pub trait NotAllOnesHelper {
@@ -181,7 +155,7 @@ impl NotAllOnesHelper for i64 {
181155}
182156
183157define_valid_range_type ! {
184- pub struct CodePointInner ( u32 as u32 in 0 ..=0x10ffff ) ;
158+ pub struct CodePointInner ( u32 is 0 ..=0x10ffff ) ;
185159}
186160
187161impl CodePointInner {
0 commit comments