Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13866 - Nilstrieb:rustc_safe_intrinsic, r=Veykril
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.
This will make new RA versions unusable with old toolchains that don't have the attribute yet. Should we keep maintaining the list as a fallback or just don't care?
| -rw-r--r-- | crates/hir-def/src/builtin_attr.rs | 1 | ||||
| -rw-r--r-- | crates/hir-ty/src/utils.rs | 60 | ||||
| -rw-r--r-- | crates/ide-diagnostics/src/handlers/missing_unsafe.rs | 1 |
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 } |