fix: Handle newstyle rustc_intrinsic safety correctly

This commit is contained in:
Lukas Wirth 2025-01-06 09:20:03 +01:00
parent 6725e046df
commit e462ee79e4
2 changed files with 24 additions and 9 deletions

View file

@ -270,17 +270,15 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
return true;
}
let is_intrinsic = db.attrs(func.into()).by_key(&sym::rustc_intrinsic).exists()
|| data.abi.as_ref() == Some(&sym::rust_dash_intrinsic);
let loc = func.lookup(db.upcast());
match loc.container {
hir_def::ItemContainerId::ExternBlockId(block) => {
if is_intrinsic || {
let id = block.lookup(db.upcast()).id;
id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic)
} {
// Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
let is_intrinsic_block =
id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic);
if is_intrinsic_block {
// legacy intrinsics
// extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
!db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists()
} else {
// Function in an `extern` block are always unsafe to call, except when
@ -288,7 +286,6 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
!data.is_safe()
}
}
_ if is_intrinsic => !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists(),
_ => false,
}
}

View file

@ -237,6 +237,24 @@ fn main() {
fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
check_diagnostics(
r#"
#[rustc_intrinsic]
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
#[rustc_intrinsic]
pub unsafe fn floorf32(x: f32) -> f32; // Unsafe intrinsic
fn main() {
let _ = bitreverse(12);
let _ = floorf32(12.0);
//^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
}
"#,
);
}
#[test]
fn no_missing_unsafe_diagnostic_with_legacy_safe_intrinsic() {
check_diagnostics(
r#"
extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn bitreverse(x: u32) -> u32; // Safe intrinsic