diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 9e1937c4765e4..0cbc0544e2fe1 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -71,9 +71,13 @@ fn equate_intrinsic_type<'tcx>( /// Returns the unsafety of the given intrinsic. pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Unsafety { - let has_safe_attr = match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { - true => hir::Unsafety::Normal, - false => hir::Unsafety::Unsafe, + let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) { + tcx.fn_sig(intrinsic_id).skip_binder().unsafety() + } else { + match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) { + true => hir::Unsafety::Normal, + false => hir::Unsafety::Unsafe, + } }; let is_in_list = match tcx.item_name(intrinsic_id.into()) { // When adding a new intrinsic to this list, @@ -117,6 +121,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::forget | sym::black_box | sym::variant_count + | sym::is_val_statically_known | sym::ptr_mask => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, }; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index a11c43337cc04..5f6b43f0f5d91 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2513,9 +2513,7 @@ extern "rust-intrinsic" { /// use std::hint::unreachable_unchecked; /// use std::intrinsics::is_val_statically_known; /// -/// unsafe { -/// if !is_val_statically_known(0) { unreachable_unchecked(); } -/// } +/// if !is_val_statically_known(0) { unsafe { unreachable_unchecked(); } } /// ``` /// /// This also means that the following code's behavior is unspecified; it @@ -2526,9 +2524,7 @@ extern "rust-intrinsic" { /// # #![allow(internal_features)] /// use std::intrinsics::is_val_statically_known; /// -/// unsafe { -/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0)); -/// } +/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0)); /// ``` /// /// Unsafe code may not rely on `is_val_statically_known` returning any @@ -2543,7 +2539,7 @@ extern "rust-intrinsic" { #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")] #[cfg_attr(not(bootstrap), rustc_intrinsic)] -pub const unsafe fn is_val_statically_known(_arg: T) -> bool { +pub const fn is_val_statically_known(_arg: T) -> bool { false } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index bb35b6128ea5a..a7147bf4e6c9a 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1377,8 +1377,7 @@ macro_rules! int_impl { #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.unsigned_abs().is_power_of_two() { if self == 1 { // Avoid divide by zero @@ -2094,8 +2093,7 @@ macro_rules! int_impl { #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.unsigned_abs().is_power_of_two() { if self == 1 { // Avoid divide by zero @@ -2628,8 +2626,7 @@ macro_rules! int_impl { #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.unsigned_abs().is_power_of_two() { if self == 1 { // Avoid divide by zero @@ -2709,8 +2706,7 @@ macro_rules! int_impl { #[rustc_inherit_overflow_checks] #[track_caller] // Hides the hackish overflow check for powers of two. pub const fn pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.unsigned_abs().is_power_of_two() { if self == 1 { // Avoid divide by zero diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d450c68a5b230..b048afe77ecb9 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1367,8 +1367,7 @@ macro_rules! uint_impl { #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.is_power_of_two() { if self == 1 { // Avoid divide by zero @@ -1911,8 +1910,7 @@ macro_rules! uint_impl { #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.is_power_of_two() { if self == 1 { // Avoid divide by zero @@ -2386,8 +2384,7 @@ macro_rules! uint_impl { #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.is_power_of_two() { if self == 1 { // Avoid divide by zero @@ -2466,8 +2463,7 @@ macro_rules! uint_impl { // get the power of a power of two and the exponent through a `shl` // instruction, but we must add a couple more checks for parity with // our own `pow`. - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } + if intrinsics::is_val_statically_known(self) && self.is_power_of_two() { if self == 1 { // Avoid divide by zero diff --git a/src/tools/miri/tests/pass/intrinsics.rs b/src/tools/miri/tests/pass/intrinsics.rs index 8e46bd7ad48fb..0dda5aadce20a 100644 --- a/src/tools/miri/tests/pass/intrinsics.rs +++ b/src/tools/miri/tests/pass/intrinsics.rs @@ -37,7 +37,7 @@ fn main() { let mut saw_false = false; for _ in 0..50 { - if unsafe { intrinsics::is_val_statically_known(0) } { + if intrinsics::is_val_statically_known(0) { saw_true = true; } else { saw_false = true; diff --git a/tests/codegen/is_val_statically_known.rs b/tests/codegen/is_val_statically_known.rs index 44187d4f667dd..88cdbe45f0bbf 100644 --- a/tests/codegen/is_val_statically_known.rs +++ b/tests/codegen/is_val_statically_known.rs @@ -11,7 +11,7 @@ pub enum B { #[inline] pub fn _u32(a: u32) -> i32 { - if unsafe { is_val_statically_known(a) } { 1 } else { 0 } + if is_val_statically_known(a) { 1 } else { 0 } } // CHECK-LABEL: @_u32_true( @@ -30,7 +30,7 @@ pub fn _u32_false(a: u32) -> i32 { #[inline] pub fn _bool(b: bool) -> i32 { - if unsafe { is_val_statically_known(b) } { 3 } else { 2 } + if is_val_statically_known(b) { 3 } else { 2 } } // CHECK-LABEL: @_bool_true( diff --git a/tests/ui/consts/is_val_statically_known.rs b/tests/ui/consts/is_val_statically_known.rs index c3d28ad9b475b..f59ecaa068f77 100644 --- a/tests/ui/consts/is_val_statically_known.rs +++ b/tests/ui/consts/is_val_statically_known.rs @@ -4,7 +4,7 @@ use std::intrinsics::is_val_statically_known; -const CONST_TEST: bool = unsafe { is_val_statically_known(0) }; +const CONST_TEST: bool = is_val_statically_known(0); fn main() { if CONST_TEST {