@@ -104,7 +104,7 @@ macro_rules! newtype_index {
104104 impl $type {
105105 $v const MAX_AS_U32 : u32 = $max;
106106
107- $v const MAX : $type = unsafe { $type:: from_u32_unchecked ( $max) } ;
107+ $v const MAX : $type = $type:: from_u32_const ( $max) ;
108108
109109 #[ inline]
110110 $v fn from_usize( value: usize ) -> Self {
@@ -122,6 +122,24 @@ macro_rules! newtype_index {
122122 }
123123 }
124124
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+
125143 #[ inline]
126144 $v const unsafe fn from_u32_unchecked( value: u32 ) -> Self {
127145 $type { private: :: std:: num:: NonZeroU32 :: new_unchecked( value + 1 ) }
@@ -424,7 +442,7 @@ macro_rules! newtype_index {
424442 const $name: ident = $constant: expr,
425443 $( $tokens: tt) * ) => (
426444 $( #[ doc = $doc] ) *
427- pub const $name: $type = unsafe { $type:: from_u32_unchecked ( $constant) } ;
445+ pub const $name: $type = $type:: from_u32_const ( $constant) ;
428446 newtype_index!(
429447 @derives [ $( $derives, ) * ]
430448 @type [ $type]
0 commit comments