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?
This commit is contained in:
bors 2022-12-30 22:14:31 +00:00
commit 0d76b94c90
3 changed files with 14 additions and 48 deletions

View file

@ -350,6 +350,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
), ),
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk), ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
ungated!(rustc_const_stable, 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!( gated!(
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
"allow_internal_unstable side-steps feature gating and stability checks", "allow_internal_unstable side-steps feature gating and stability checks",

View file

@ -17,7 +17,7 @@ use hir_def::{
ConstParamId, FunctionId, GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId, ConstParamId, FunctionId, GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId,
TypeOrConstParamId, TypeParamId, TypeOrConstParamId, TypeParamId,
}; };
use hir_expand::name::{known, Name}; use hir_expand::name::Name;
use itertools::Either; use itertools::Either;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec}; 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 // Function in an `extern` block are always unsafe to call, except when it has
// `"rust-intrinsic"` ABI there are a few exceptions. // `"rust-intrinsic"` ABI there are a few exceptions.
let id = block.lookup(db.upcast()).id; let id = block.lookup(db.upcast()).id;
!matches!(
id.item_tree(db.upcast())[id.value].abi.as_deref(), let is_intrinsic =
Some("rust-intrinsic") if !is_intrinsic_fn_unsafe(&data.name) 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, _ => 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)
}

View file

@ -86,6 +86,7 @@ fn main() {
check_diagnostics( check_diagnostics(
r#" r#"
extern "rust-intrinsic" { extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
} }