diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index acd35e1aa95..b5ec1ad36ab 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1274,9 +1274,7 @@ impl DebruijnIndex { /// you would need to shift the index for `'a` into 1 new binder. #[must_use] pub fn shifted_in(self, amount: u32) -> DebruijnIndex { - unsafe { - DebruijnIndex::from_u32_unchecked(self.as_u32() + amount) - } + DebruijnIndex::from_u32(self.as_u32() + amount) } /// Update this index in place by shifting it "in" through @@ -1289,9 +1287,7 @@ impl DebruijnIndex { /// `amount` number of new binders. #[must_use] pub fn shifted_out(self, amount: u32) -> DebruijnIndex { - unsafe { - DebruijnIndex::from_u32_unchecked(self.as_u32() - amount) - } + DebruijnIndex::from_u32(self.as_u32() - amount) } /// Update in place by shifting out from `amount` binders. diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index f068fc77d32..9240eaec3b4 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -104,7 +104,7 @@ macro_rules! newtype_index { impl $type { $v const MAX_AS_U32: u32 = $max; - $v const MAX: $type = unsafe { $type::from_u32_unchecked($max) }; + $v const MAX: $type = $type::from_u32_const($max); #[inline] $v fn from_usize(value: usize) -> Self { @@ -122,6 +122,24 @@ macro_rules! newtype_index { } } + /// Hacky variant of `from_u32` for use in constants. + /// This version checks the "max" constraint by using an + /// invalid array dereference. + #[inline] + $v const fn from_u32_const(value: u32) -> Self { + // This will fail at const eval time unless `value <= + // max` is true (in which case we get the index 0). + // It will also fail at runtime, of course, but in a + // kind of wacky way. + let _ = ["out of range value used"][ + !(value <= $max) as usize + ]; + + unsafe { + $type::from_u32_unchecked(value) + } + } + #[inline] $v const unsafe fn from_u32_unchecked(value: u32) -> Self { $type { private: ::std::num::NonZeroU32::new_unchecked(value + 1) } @@ -424,7 +442,7 @@ macro_rules! newtype_index { const $name:ident = $constant:expr, $($tokens:tt)*) => ( $(#[doc = $doc])* - pub const $name: $type = unsafe { $type::from_u32_unchecked($constant) }; + pub const $name: $type = $type::from_u32_const($constant); newtype_index!( @derives [$($derives,)*] @type [$type]