@@ -104,7 +104,7 @@ macro_rules! newtype_index {
104
104
impl $type {
105
105
$v const MAX_AS_U32 : u32 = $max;
106
106
107
- $v const MAX : $type = unsafe { $type:: from_u32_unchecked ( $max) } ;
107
+ $v const MAX : $type = $type:: from_u32_const ( $max) ;
108
108
109
109
#[ inline]
110
110
$v fn from_usize( value: usize ) -> Self {
@@ -122,6 +122,24 @@ macro_rules! newtype_index {
122
122
}
123
123
}
124
124
125
+ /// Hacky variant of `from_u32` for use in constants.
126
+ /// This version checks the "max" constraint by using an
127
+ /// invalid array dereference.
128
+ #[ inline]
129
+ $v const fn from_u32_const( value: u32 ) -> Self {
130
+ // This will fail at const eval time unless `value <=
131
+ // max` is true (in which case we get the index 0).
132
+ // It will also fail at runtime, of course, but in a
133
+ // kind of wacky way.
134
+ let _ = [ "out of range value used" ] [
135
+ !( value <= $max) as usize
136
+ ] ;
137
+
138
+ unsafe {
139
+ $type:: from_u32_unchecked( value)
140
+ }
141
+ }
142
+
125
143
#[ inline]
126
144
$v const unsafe fn from_u32_unchecked( value: u32 ) -> Self {
127
145
$type { private: :: std:: num:: NonZeroU32 :: new_unchecked( value + 1 ) }
@@ -424,7 +442,7 @@ macro_rules! newtype_index {
424
442
const $name: ident = $constant: expr,
425
443
$( $tokens: tt) * ) => (
426
444
$( #[ doc = $doc] ) *
427
- pub const $name: $type = unsafe { $type:: from_u32_unchecked ( $constant) } ;
445
+ pub const $name: $type = $type:: from_u32_const ( $constant) ;
428
446
newtype_index!(
429
447
@derives [ $( $derives, ) * ]
430
448
@type [ $type]
0 commit comments