about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNilstrieb <48135649+Nilstrieb@users.noreply.github.com>2022-12-30 20:29:37 +0100
committerNilstrieb <48135649+Nilstrieb@users.noreply.github.com>2022-12-30 20:29:37 +0100
commit72afcf2cadbd1434150049e4102ccc89251772a0 (patch)
tree948b95c7a357f21362a39c944924dab067994905
parent3033c3ddbfcb0e42084ada8931e88d11eb98dee4 (diff)
downloadrust-72afcf2cadbd1434150049e4102ccc89251772a0.tar.gz
rust-72afcf2cadbd1434150049e4102ccc89251772a0.zip
Use `rustc_safe_intrinsic` attribute to check for intrinsic safety
Instead of maintaining a list that is poorly kept in sync we can just
use the attribute.
-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 39581b33a8d..f7c1e683d0d 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 e54bcb421a2..1f3470a3622 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 7acd9228a89..ea1ea5a216d 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
 }