Fix #[rustc_deprecated_safe_2024]

It should be considered by the edition of the caller, not the callee.

Technically we still don't do it correctly - we need the span of the method name (if it comes from a macro), but we don't keep it and this is good enough for now.
This commit is contained in:
Chayim Refael Friedman 2025-01-27 14:34:33 +02:00
parent 6862329068
commit 55c63abc59
16 changed files with 274 additions and 100 deletions

View file

@ -24,6 +24,7 @@ use intern::{sym, Symbol};
use rustc_abi::TargetDataLayout;
use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec};
use span::Edition;
use stdx::never;
use crate::{
@ -292,21 +293,38 @@ impl TargetFeatures {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Unsafety {
Safe,
Unsafe,
/// A lint.
DeprecatedSafe2024,
}
pub fn is_fn_unsafe_to_call(
db: &dyn HirDatabase,
func: FunctionId,
caller_target_features: &TargetFeatures,
) -> bool {
call_edition: Edition,
) -> Unsafety {
let data = db.function_data(func);
if data.is_unsafe() {
return true;
return Unsafety::Unsafe;
}
if data.has_target_feature() {
// RFC 2396 <https://rust-lang.github.io/rfcs/2396-target-feature-1.1.html>.
let callee_target_features = TargetFeatures::from_attrs(&db.attrs(func.into()));
if !caller_target_features.enabled.is_superset(&callee_target_features.enabled) {
return true;
return Unsafety::Unsafe;
}
}
if data.is_deprecated_safe_2024() {
if call_edition.at_least_2024() {
return Unsafety::Unsafe;
} else {
return Unsafety::DeprecatedSafe2024;
}
}
@ -319,14 +337,22 @@ pub fn is_fn_unsafe_to_call(
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()
if db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists() {
Unsafety::Safe
} else {
Unsafety::Unsafe
}
} else {
// Function in an `extern` block are always unsafe to call, except when
// it is marked as `safe`.
!data.is_safe()
if data.is_safe() {
Unsafety::Safe
} else {
Unsafety::Unsafe
}
}
}
_ => false,
_ => Unsafety::Safe,
}
}