Skip to content

Commit

Permalink
Auto merge of #13866 - Nilstrieb:rustc_safe_intrinsic, r=Veykril
Browse files Browse the repository at this point in the history
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?
  • Loading branch information
bors committed Dec 30, 2022
2 parents 09bc37c + 72afcf2 commit 0d76b94
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 0d76b94

Please sign in to comment.