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) {
24
+ #[ allow( non_contiguous_range_endpoints) ]
25
+ if let $pat = val {
38
26
// SAFETY: just checked the inclusive range
39
- Some ( unsafe { $name( val) } )
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
- /// 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
50
39
/// invariant of this type.
51
40
#[ inline]
52
41
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) ) }
55
44
}
56
45
57
46
#[ inline]
58
47
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 ) }
62
50
}
63
51
}
64
52
@@ -67,6 +55,8 @@ macro_rules! define_valid_range_type {
67
55
// by <https://github.com/rust-lang/compiler-team/issues/807>.
68
56
impl StructuralPartialEq for $name { }
69
57
58
+ impl Eq for $name { }
59
+
70
60
impl PartialEq for $name {
71
61
#[ inline]
72
62
fn eq( & self , other: & Self ) -> bool {
@@ -104,7 +94,7 @@ macro_rules! define_valid_range_type {
104
94
}
105
95
106
96
define_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 ) ;
108
98
}
109
99
110
100
impl Nanoseconds {
@@ -119,45 +109,30 @@ impl Default for Nanoseconds {
119
109
}
120
110
}
121
111
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 ;
154
113
155
114
define_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 ..) ;
161
136
}
162
137
163
138
pub trait NotAllOnesHelper {
0 commit comments