mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
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:
commit
0d76b94c90
3 changed files with 14 additions and 48 deletions
|
@ -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",
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue