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.
This commit is contained in:
@@ -71,9 +71,13 @@ fn equate_intrinsic_type<'tcx>(
|
|||||||
|
|
||||||
/// Returns the unsafety of the given intrinsic.
|
/// Returns the unsafety of the given intrinsic.
|
||||||
pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hir::Unsafety {
|
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) {
|
let has_safe_attr = if tcx.has_attr(intrinsic_id, sym::rustc_intrinsic) {
|
||||||
true => hir::Unsafety::Normal,
|
tcx.fn_sig(intrinsic_id).skip_binder().unsafety()
|
||||||
false => hir::Unsafety::Unsafe,
|
} 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()) {
|
let is_in_list = match tcx.item_name(intrinsic_id.into()) {
|
||||||
// When adding a new intrinsic to this list,
|
// 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::forget
|
||||||
| sym::black_box
|
| sym::black_box
|
||||||
| sym::variant_count
|
| sym::variant_count
|
||||||
|
| sym::is_val_statically_known
|
||||||
| sym::ptr_mask
|
| sym::ptr_mask
|
||||||
| sym::debug_assertions => hir::Unsafety::Normal,
|
| sym::debug_assertions => hir::Unsafety::Normal,
|
||||||
_ => hir::Unsafety::Unsafe,
|
_ => hir::Unsafety::Unsafe,
|
||||||
|
|||||||
@@ -2513,9 +2513,7 @@ extern "rust-intrinsic" {
|
|||||||
/// use std::hint::unreachable_unchecked;
|
/// use std::hint::unreachable_unchecked;
|
||||||
/// use std::intrinsics::is_val_statically_known;
|
/// use std::intrinsics::is_val_statically_known;
|
||||||
///
|
///
|
||||||
/// unsafe {
|
/// if !is_val_statically_known(0) { unsafe { unreachable_unchecked(); } }
|
||||||
/// if !is_val_statically_known(0) { unreachable_unchecked(); }
|
|
||||||
/// }
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// This also means that the following code's behavior is unspecified; it
|
/// This also means that the following code's behavior is unspecified; it
|
||||||
@@ -2527,9 +2525,7 @@ extern "rust-intrinsic" {
|
|||||||
/// # #![allow(internal_features)]
|
/// # #![allow(internal_features)]
|
||||||
/// use std::intrinsics::is_val_statically_known;
|
/// 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
|
/// Unsafe code may not rely on `is_val_statically_known` returning any
|
||||||
@@ -2544,7 +2540,7 @@ extern "rust-intrinsic" {
|
|||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
|
#[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
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2564,7 +2560,7 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
|
|||||||
#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
|
#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
|
||||||
#[unstable(feature = "core_intrinsics", issue = "none")]
|
#[unstable(feature = "core_intrinsics", issue = "none")]
|
||||||
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
|
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
|
||||||
pub(crate) const unsafe fn debug_assertions() -> bool {
|
pub(crate) const fn debug_assertions() -> bool {
|
||||||
cfg!(debug_assertions)
|
cfg!(debug_assertions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ fn main() {
|
|||||||
let mut saw_false = false;
|
let mut saw_false = false;
|
||||||
|
|
||||||
for _ in 0..50 {
|
for _ in 0..50 {
|
||||||
if unsafe { intrinsics::is_val_statically_known(0) } {
|
if intrinsics::is_val_statically_known(0) {
|
||||||
saw_true = true;
|
saw_true = true;
|
||||||
} else {
|
} else {
|
||||||
saw_false = true;
|
saw_false = true;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pub enum B {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn _u32(a: u32) -> i32 {
|
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(
|
// CHECK-LABEL: @_u32_true(
|
||||||
@@ -30,7 +30,7 @@ pub fn _u32_false(a: u32) -> i32 {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn _bool(b: bool) -> i32 {
|
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(
|
// CHECK-LABEL: @_bool_true(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
use std::intrinsics::is_val_statically_known;
|
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() {
|
fn main() {
|
||||||
if CONST_TEST {
|
if CONST_TEST {
|
||||||
|
|||||||
Reference in New Issue
Block a user