5
5
) ]
6
6
7
7
use crate :: cmp:: Ordering ;
8
- use crate :: fmt;
9
8
use crate :: hash:: { Hash , Hasher } ;
10
9
use crate :: marker:: StructuralPartialEq ;
10
+ use crate :: { fmt, pattern_type} ;
11
11
12
12
macro_rules! define_valid_range_type {
13
13
( $(
14
14
$( #[ $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 ) ;
16
16
) +) => { $(
17
- #[ derive( Clone , Copy , Eq ) ]
17
+ #[ derive( Clone , Copy ) ]
18
18
#[ repr( transparent) ]
19
- #[ rustc_layout_scalar_valid_range_start( $low) ]
20
- #[ rustc_layout_scalar_valid_range_end( $high) ]
21
19
$( #[ $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) ) ;
34
21
impl $name {
35
22
#[ inline]
36
23
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) ) } )
40
28
} else {
41
29
None
42
30
}
43
31
}
44
32
45
33
/// Constructs an instance of this type from the underlying integer
46
- /// primitive without checking whether its zero .
34
+ /// primitive without checking whether its valid .
47
35
///
48
36
/// # Safety
49
37
/// Immediate language UB if `val` is not within the valid range for this
50
38
/// type, as it violates the validity invariant.
51
39
#[ inline]
52
40
pub const unsafe fn new_unchecked( val: $int) -> Self {
53
41
// SAFETY: Caller promised that `val` is within the valid range.
54
- unsafe { $name( val) }
42
+ unsafe { $name( crate :: mem :: transmute ( val) ) }
55
43
}
56
44
57
45
#[ inline]
58
46
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 ) }
62
49
}
63
50
}
64
51
@@ -67,6 +54,8 @@ macro_rules! define_valid_range_type {
67
54
// by <https://github.com/rust-lang/compiler-team/issues/807>.
68
55
impl StructuralPartialEq for $name { }
69
56
57
+ impl Eq for $name { }
58
+
70
59
impl PartialEq for $name {
71
60
#[ inline]
72
61
fn eq( & self , other: & Self ) -> bool {
@@ -104,7 +93,7 @@ macro_rules! define_valid_range_type {
104
93
}
105
94
106
95
define_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 ) ;
108
97
}
109
98
110
99
impl Nanoseconds {
@@ -119,47 +108,32 @@ impl Default for Nanoseconds {
119
108
}
120
109
}
121
110
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
- pub struct NonZeroCharInner ( char as u32 in 1 ..=0x10ffff ) ;
136
- }
111
+ const HALF_USIZE : usize = usize:: MAX >> 1 ;
137
112
138
- #[ cfg( target_pointer_width = "16" ) ]
139
- define_valid_range_type ! {
140
- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff ) ;
141
- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff ) ;
142
- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff ) ;
143
- }
144
- #[ cfg( target_pointer_width = "32" ) ]
145
113
define_valid_range_type ! {
146
- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff_ffff ) ;
147
- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff_ffff ) ;
148
- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff_ffff ) ;
149
- }
150
- #[ cfg( target_pointer_width = "64" ) ]
151
- define_valid_range_type ! {
152
- pub struct UsizeNoHighBit ( usize as usize in 0 ..=0x7fff_ffff_ffff_ffff ) ;
153
- pub struct NonZeroUsizeInner ( usize as usize in 1 ..=0xffff_ffff_ffff_ffff ) ;
154
- pub struct NonZeroIsizeInner ( isize as usize in 1 ..=0xffff_ffff_ffff_ffff ) ;
155
- }
114
+ pub struct NonZeroU8Inner ( u8 is 1 ..) ;
115
+ pub struct NonZeroU16Inner ( u16 is 1 ..) ;
116
+ pub struct NonZeroU32Inner ( u32 is 1 ..) ;
117
+ pub struct NonZeroU64Inner ( u64 is 1 ..) ;
118
+ pub struct NonZeroU128Inner ( u128 is 1 ..) ;
156
119
157
- define_valid_range_type ! {
158
- pub struct U32NotAllOnes ( u32 as u32 in 0 ..=0xffff_fffe ) ;
159
- pub struct I32NotAllOnes ( i32 as u32 in 0 ..=0xffff_fffe ) ;
120
+ pub struct NonZeroI8Inner ( i8 is ..0 | 1 ..) ;
121
+ pub struct NonZeroI16Inner ( i16 is ..0 | 1 ..) ;
122
+ pub struct NonZeroI32Inner ( i32 is ..0 | 1 ..) ;
123
+ pub struct NonZeroI64Inner ( i64 is ..0 | 1 ..) ;
124
+ pub struct NonZeroI128Inner ( i128 is ..0 | 1 ..) ;
125
+
126
+ pub struct UsizeNoHighBit ( usize is 0 ..=HALF_USIZE ) ;
127
+ pub struct NonZeroUsizeInner ( usize is 1 ..) ;
128
+ pub struct NonZeroIsizeInner ( isize is ..0 | 1 ..) ;
129
+
130
+ pub struct U32NotAllOnes ( u32 is 0 ..u32 :: MAX ) ;
131
+ pub struct I32NotAllOnes ( i32 is ..-1 | 0 ..) ;
132
+
133
+ pub struct U64NotAllOnes ( u64 is 0 ..u64 :: MAX ) ;
134
+ pub struct I64NotAllOnes ( i64 is ..-1 | 0 ..) ;
160
135
161
- pub struct U64NotAllOnes ( u64 as u64 in 0 ..=0xffff_ffff_ffff_fffe ) ;
162
- pub struct I64NotAllOnes ( i64 as u64 in 0 ..=0xffff_ffff_ffff_fffe ) ;
136
+ pub struct NonZeroCharInner ( char is '\u{1}' ..= '\u{10ffff}' ) ;
163
137
}
164
138
165
139
pub trait NotAllOnesHelper {
@@ -180,7 +154,7 @@ impl NotAllOnesHelper for i64 {
180
154
}
181
155
182
156
define_valid_range_type ! {
183
- pub struct CodePointInner ( u32 as u32 in 0 ..=0x10ffff ) ;
157
+ pub struct CodePointInner ( u32 is 0 ..=0x10ffff ) ;
184
158
}
185
159
186
160
impl CodePointInner {
0 commit comments