Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/builtin_attr.rs1
-rw-r--r--crates/hir-ty/src/utils.rs60
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_unsafe.rs1
3 files changed, 14 insertions, 48 deletions
diff --git a/crates/hir-def/src/builtin_attr.rs b/crates/hir-def/src/builtin_attr.rs
index 39581b33a8..f7c1e683d0 100644
--- a/crates/hir-def/src/builtin_attr.rs
+++ b/crates/hir-def/src/builtin_attr.rs
@@ -350,6 +350,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
),
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
+ ungated!(rustc_safe_intrinsic, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
gated!(
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
"allow_internal_unstable side-steps feature gating and stability checks",
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index e54bcb421a..1f3470a362 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -17,7 +17,7 @@ use hir_def::{
ConstParamId, FunctionId, GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId,
TypeOrConstParamId, TypeParamId,
};
-use hir_expand::name::{known, Name};
+use hir_expand::name::Name;
use itertools::Either;
use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec};
@@ -335,54 +335,18 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
// Function in an `extern` block are always unsafe to call, except when it has
// `"rust-intrinsic"` ABI there are a few exceptions.
let id = block.lookup(db.upcast()).id;
- !matches!(
- id.item_tree(db.upcast())[id.value].abi.as_deref(),
- Some("rust-intrinsic") if !is_intrinsic_fn_unsafe(&data.name)
- )
+
+ let is_intrinsic =
+ id.item_tree(db.upcast())[id.value].abi.as_deref() == Some("rust-intrinsic");
+
+ if is_intrinsic {
+ // Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
+ !data.attrs.by_key("rustc_safe_intrinsic").exists()
+ } else {
+ // Extern items are always unsafe
+ true
+ }
}
_ => false,
}
}
-
-/// Returns `true` if the given intrinsic is unsafe to call, or false otherwise.
-fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
- // Should be kept in sync with https://github.com/rust-lang/rust/blob/532d2b14c05f9bc20b2d27cbb5f4550d28343a36/compiler/rustc_typeck/src/check/intrinsic.rs#L72-L106
- ![
- known::abort,
- known::add_with_overflow,
- known::bitreverse,
- known::black_box,
- known::bswap,
- known::caller_location,
- known::ctlz,
- known::ctpop,
- known::cttz,
- known::discriminant_value,
- known::forget,
- known::likely,
- known::maxnumf32,
- known::maxnumf64,
- known::min_align_of,
- known::minnumf32,
- known::minnumf64,
- known::mul_with_overflow,
- known::needs_drop,
- known::ptr_guaranteed_eq,
- known::ptr_guaranteed_ne,
- known::rotate_left,
- known::rotate_right,
- known::rustc_peek,
- known::saturating_add,
- known::saturating_sub,
- known::size_of,
- known::sub_with_overflow,
- known::type_id,
- known::type_name,
- known::unlikely,
- known::variant_count,
- known::wrapping_add,
- known::wrapping_mul,
- known::wrapping_sub,
- ]
- .contains(name)
-}
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index 7acd9228a8..ea1ea5a216 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -86,6 +86,7 @@ fn main() {
check_diagnostics(
r#"
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
}