Skip to content

Commit

Permalink
Use rustc_safe_intrinsic attribute to check for intrinsic safety
Browse files Browse the repository at this point in the history
Instead of maintaining a list that is poorly kept in sync we can just
use the attribute.
  • Loading branch information
Nilstrieb committed Dec 30, 2022
1 parent 3033c3d commit 72afcf2
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 48 deletions.
1 change: 1 addition & 0 deletions crates/hir-def/src/builtin_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
60 changes: 12 additions & 48 deletions crates/hir-ty/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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)
}
1 change: 1 addition & 0 deletions crates/ide-diagnostics/src/handlers/missing_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit 72afcf2

Please sign in to comment.