Skip to content

Commit 585e76a

Browse files
committed
Support safe intrinsics with fallback bodies
Turn `is_val_statically_known` into such an intrinsic to demonstrate. It is perfectly safe to call after all.
1 parent 5d445d1 commit 585e76a

File tree

7 files changed

+23
-30
lines changed

7 files changed

+23
-30
lines changed

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,13 @@ fn equate_intrinsic_type<'tcx>(
7171

7272
/// Returns the unsafety of the given intrinsic.
7373
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Unsafety {
74-
let has_safe_attr = match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
75-
true => hir::Unsafety::Normal,
76-
false => hir::Unsafety::Unsafe,
74+
let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
75+
tcx.fn_sig(intrinsic_id).skip_binder().unsafety()
76+
} else {
77+
match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
78+
true => hir::Unsafety::Normal,
79+
false => hir::Unsafety::Unsafe,
80+
}
7781
};
7882
let is_in_list = match tcx.item_name(intrinsic_id.into()) {
7983
// When adding a new intrinsic to this list,
@@ -117,6 +121,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
117121
| sym::forget
118122
| sym::black_box
119123
| sym::variant_count
124+
| sym::is_val_statically_known
120125
| sym::ptr_mask => hir::Unsafety::Normal,
121126
_ => hir::Unsafety::Unsafe,
122127
};

library/core/src/intrinsics.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -2513,9 +2513,7 @@ extern "rust-intrinsic" {
25132513
/// use std::hint::unreachable_unchecked;
25142514
/// use std::intrinsics::is_val_statically_known;
25152515
///
2516-
/// unsafe {
2517-
/// if !is_val_statically_known(0) { unreachable_unchecked(); }
2518-
/// }
2516+
/// if !is_val_statically_known(0) { unsafe { unreachable_unchecked(); } }
25192517
/// ```
25202518
///
25212519
/// This also means that the following code's behavior is unspecified; it
@@ -2526,9 +2524,7 @@ extern "rust-intrinsic" {
25262524
/// # #![allow(internal_features)]
25272525
/// use std::intrinsics::is_val_statically_known;
25282526
///
2529-
/// unsafe {
2530-
/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0));
2531-
/// }
2527+
/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0));
25322528
/// ```
25332529
///
25342530
/// Unsafe code may not rely on `is_val_statically_known` returning any
@@ -2543,7 +2539,7 @@ extern "rust-intrinsic" {
25432539
#[unstable(feature = "core_intrinsics", issue = "none")]
25442540
#[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")]
25452541
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
2546-
pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2542+
pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
25472543
false
25482544
}
25492545

library/core/src/num/int_macros.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -1377,8 +1377,7 @@ macro_rules! int_impl {
13771377
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
13781378
#[inline]
13791379
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
1380-
// SAFETY: This path has the same behavior as the other.
1381-
if unsafe { intrinsics::is_val_statically_known(self) }
1380+
if intrinsics::is_val_statically_known(self)
13821381
&& self.unsigned_abs().is_power_of_two()
13831382
{
13841383
if self == 1 { // Avoid divide by zero
@@ -2094,8 +2093,7 @@ macro_rules! int_impl {
20942093
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
20952094
#[inline]
20962095
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
2097-
// SAFETY: This path has the same behavior as the other.
2098-
if unsafe { intrinsics::is_val_statically_known(self) }
2096+
if intrinsics::is_val_statically_known(self)
20992097
&& self.unsigned_abs().is_power_of_two()
21002098
{
21012099
if self == 1 { // Avoid divide by zero
@@ -2628,8 +2626,7 @@ macro_rules! int_impl {
26282626
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
26292627
#[inline]
26302628
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
2631-
// SAFETY: This path has the same behavior as the other.
2632-
if unsafe { intrinsics::is_val_statically_known(self) }
2629+
if intrinsics::is_val_statically_known(self)
26332630
&& self.unsigned_abs().is_power_of_two()
26342631
{
26352632
if self == 1 { // Avoid divide by zero
@@ -2709,8 +2706,7 @@ macro_rules! int_impl {
27092706
#[rustc_inherit_overflow_checks]
27102707
#[track_caller] // Hides the hackish overflow check for powers of two.
27112708
pub const fn pow(self, mut exp: u32) -> Self {
2712-
// SAFETY: This path has the same behavior as the other.
2713-
if unsafe { intrinsics::is_val_statically_known(self) }
2709+
if intrinsics::is_val_statically_known(self)
27142710
&& self.unsigned_abs().is_power_of_two()
27152711
{
27162712
if self == 1 { // Avoid divide by zero

library/core/src/num/uint_macros.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -1367,8 +1367,7 @@ macro_rules! uint_impl {
13671367
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
13681368
#[inline]
13691369
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
1370-
// SAFETY: This path has the same behavior as the other.
1371-
if unsafe { intrinsics::is_val_statically_known(self) }
1370+
if intrinsics::is_val_statically_known(self)
13721371
&& self.is_power_of_two()
13731372
{
13741373
if self == 1 { // Avoid divide by zero
@@ -1911,8 +1910,7 @@ macro_rules! uint_impl {
19111910
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
19121911
#[inline]
19131912
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
1914-
// SAFETY: This path has the same behavior as the other.
1915-
if unsafe { intrinsics::is_val_statically_known(self) }
1913+
if intrinsics::is_val_statically_known(self)
19161914
&& self.is_power_of_two()
19171915
{
19181916
if self == 1 { // Avoid divide by zero
@@ -2386,8 +2384,7 @@ macro_rules! uint_impl {
23862384
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
23872385
#[inline]
23882386
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
2389-
// SAFETY: This path has the same behavior as the other.
2390-
if unsafe { intrinsics::is_val_statically_known(self) }
2387+
if intrinsics::is_val_statically_known(self)
23912388
&& self.is_power_of_two()
23922389
{
23932390
if self == 1 { // Avoid divide by zero
@@ -2466,8 +2463,7 @@ macro_rules! uint_impl {
24662463
// get the power of a power of two and the exponent through a `shl`
24672464
// instruction, but we must add a couple more checks for parity with
24682465
// our own `pow`.
2469-
// SAFETY: This path has the same behavior as the other.
2470-
if unsafe { intrinsics::is_val_statically_known(self) }
2466+
if intrinsics::is_val_statically_known(self)
24712467
&& self.is_power_of_two()
24722468
{
24732469
if self == 1 { // Avoid divide by zero

src/tools/miri/tests/pass/intrinsics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn main() {
3737
let mut saw_false = false;
3838

3939
for _ in 0..50 {
40-
if unsafe { intrinsics::is_val_statically_known(0) } {
40+
if intrinsics::is_val_statically_known(0) {
4141
saw_true = true;
4242
} else {
4343
saw_false = true;

tests/codegen/is_val_statically_known.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub enum B {
1111

1212
#[inline]
1313
pub fn _u32(a: u32) -> i32 {
14-
if unsafe { is_val_statically_known(a) } { 1 } else { 0 }
14+
if is_val_statically_known(a) { 1 } else { 0 }
1515
}
1616

1717
// CHECK-LABEL: @_u32_true(
@@ -30,7 +30,7 @@ pub fn _u32_false(a: u32) -> i32 {
3030

3131
#[inline]
3232
pub fn _bool(b: bool) -> i32 {
33-
if unsafe { is_val_statically_known(b) } { 3 } else { 2 }
33+
if is_val_statically_known(b) { 3 } else { 2 }
3434
}
3535

3636
// CHECK-LABEL: @_bool_true(

tests/ui/consts/is_val_statically_known.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use std::intrinsics::is_val_statically_known;
66

7-
const CONST_TEST: bool = unsafe { is_val_statically_known(0) };
7+
const CONST_TEST: bool = is_val_statically_known(0);
88

99
fn main() {
1010
if CONST_TEST {

0 commit comments

Comments
 (0)