Skip to content

Commit 72afcf2

Browse files
committed
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.
1 parent 3033c3d commit 72afcf2

File tree

3 files changed

+14
-48
lines changed

3 files changed

+14
-48
lines changed

crates/hir-def/src/builtin_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
350350
),
351351
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
352352
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
353+
ungated!(rustc_safe_intrinsic, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
353354
gated!(
354355
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
355356
"allow_internal_unstable side-steps feature gating and stability checks",

crates/hir-ty/src/utils.rs

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use hir_def::{
1717
ConstParamId, FunctionId, GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId,
1818
TypeOrConstParamId, TypeParamId,
1919
};
20-
use hir_expand::name::{known, Name};
20+
use hir_expand::name::Name;
2121
use itertools::Either;
2222
use rustc_hash::FxHashSet;
2323
use smallvec::{smallvec, SmallVec};
@@ -335,54 +335,18 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
335335
// Function in an `extern` block are always unsafe to call, except when it has
336336
// `"rust-intrinsic"` ABI there are a few exceptions.
337337
let id = block.lookup(db.upcast()).id;
338-
!matches!(
339-
id.item_tree(db.upcast())[id.value].abi.as_deref(),
340-
Some("rust-intrinsic") if !is_intrinsic_fn_unsafe(&data.name)
341-
)
338+
339+
let is_intrinsic =
340+
id.item_tree(db.upcast())[id.value].abi.as_deref() == Some("rust-intrinsic");
341+
342+
if is_intrinsic {
343+
// Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
344+
!data.attrs.by_key("rustc_safe_intrinsic").exists()
345+
} else {
346+
// Extern items are always unsafe
347+
true
348+
}
342349
}
343350
_ => false,
344351
}
345352
}
346-
347-
/// Returns `true` if the given intrinsic is unsafe to call, or false otherwise.
348-
fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
349-
// Should be kept in sync with https://github.com/rust-lang/rust/blob/532d2b14c05f9bc20b2d27cbb5f4550d28343a36/compiler/rustc_typeck/src/check/intrinsic.rs#L72-L106
350-
![
351-
known::abort,
352-
known::add_with_overflow,
353-
known::bitreverse,
354-
known::black_box,
355-
known::bswap,
356-
known::caller_location,
357-
known::ctlz,
358-
known::ctpop,
359-
known::cttz,
360-
known::discriminant_value,
361-
known::forget,
362-
known::likely,
363-
known::maxnumf32,
364-
known::maxnumf64,
365-
known::min_align_of,
366-
known::minnumf32,
367-
known::minnumf64,
368-
known::mul_with_overflow,
369-
known::needs_drop,
370-
known::ptr_guaranteed_eq,
371-
known::ptr_guaranteed_ne,
372-
known::rotate_left,
373-
known::rotate_right,
374-
known::rustc_peek,
375-
known::saturating_add,
376-
known::saturating_sub,
377-
known::size_of,
378-
known::sub_with_overflow,
379-
known::type_id,
380-
known::type_name,
381-
known::unlikely,
382-
known::variant_count,
383-
known::wrapping_add,
384-
known::wrapping_mul,
385-
known::wrapping_sub,
386-
]
387-
.contains(name)
388-
}

crates/ide-diagnostics/src/handlers/missing_unsafe.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ fn main() {
8686
check_diagnostics(
8787
r#"
8888
extern "rust-intrinsic" {
89+
#[rustc_safe_intrinsic]
8990
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
9091
pub fn floorf32(x: f32) -> f32; // Unsafe intrinsic
9192
}

0 commit comments

Comments
 (0)