Skip to content

Commit

Permalink
Support safe intrinsics with fallback bodies
Browse files Browse the repository at this point in the history
Turn `is_val_statically_known` into such an intrinsic to demonstrate. It is perfectly safe to call after all.
  • Loading branch information
oli-obk committed Feb 2, 2024
1 parent 5d445d1 commit 585e76a
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 30 deletions.
11 changes: 8 additions & 3 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
Expand Down
10 changes: 3 additions & 7 deletions library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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<T: Copy>(_arg: T) -> bool {
pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
false
}

Expand Down
12 changes: 4 additions & 8 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
12 changes: 4 additions & 8 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/tests/pass/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions tests/codegen/is_val_statically_known.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/consts/is_val_statically_known.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 585e76a

Please sign in to comment.