Skip to content

Commit

Permalink
fix: Handle newstyle rustc_intrinsic safety correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Jan 6, 2025
1 parent 6725e04 commit a8cc937
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
9 changes: 3 additions & 6 deletions crates/hir-ty/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,25 +270,22 @@ 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 || {
if {
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
// 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
// it is marked as `safe`.
!data.is_safe()
}
}
_ if is_intrinsic => !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists(),
_ => false,
}
}
Expand Down
18 changes: 18 additions & 0 deletions crates/ide-diagnostics/src/handlers/missing_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a8cc937

Please sign in to comment.