Repository: rust-lang/rust-analyzer
Pull request #19047 (2025-01-27 13:47:07)

fix: Fix syntactic highlighting for renames
CC #19041

Didn't add all of them to the test though. I think the trait alias case already works, even without my change.


Patch:
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index c5bbd4edba..a52a236957 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -95,10 +95,10 @@ impl FunctionData {
             .map(Box::new);
         let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
         if flags.contains(FnFlags::HAS_UNSAFE_KW)
+            && !crate_graph[krate].edition.at_least_2024()
             && attrs.by_key(&sym::rustc_deprecated_safe_2024).exists()
         {
             flags.remove(FnFlags::HAS_UNSAFE_KW);
-            flags.insert(FnFlags::DEPRECATED_SAFE_2024);
         }
 
         if attrs.by_key(&sym::target_feature).exists() {
@@ -152,10 +152,6 @@ impl FunctionData {
         self.flags.contains(FnFlags::HAS_UNSAFE_KW)
     }
 
-    pub fn is_deprecated_safe_2024(&self) -> bool {
-        self.flags.contains(FnFlags::DEPRECATED_SAFE_2024)
-    }
-
     pub fn is_safe(&self) -> bool {
         self.flags.contains(FnFlags::HAS_SAFE_KW)
     }
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index 811fecf91f..3ce00b78a9 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -2238,27 +2238,17 @@ impl ExprCollector<'_> {
         let unsafe_arg_new = self.alloc_expr_desugared(Expr::Path(unsafe_arg_new));
         let unsafe_arg_new =
             self.alloc_expr_desugared(Expr::Call { callee: unsafe_arg_new, args: Box::default() });
-        let mut unsafe_arg_new = self.alloc_expr_desugared(Expr::Unsafe {
+        let unsafe_arg_new = self.alloc_expr_desugared(Expr::Unsafe {
             id: None,
-            statements: Box::new([]),
+            // We collect the unused expressions here so that we still infer them instead of
+            // dropping them out of the expression tree
+            statements: fmt
+                .orphans
+                .into_iter()
+                .map(|expr| Statement::Expr { expr, has_semi: true })
+                .collect(),
             tail: Some(unsafe_arg_new),
         });
-        if !fmt.orphans.is_empty() {
-            unsafe_arg_new = self.alloc_expr_desugared(Expr::Block {
-                id: None,
-                // We collect the unused expressions here so that we still infer them instead of
-                // dropping them out of the expression tree. We cannot store them in the `Unsafe`
-                // block because then unsafe blocks within them will get a false "unused unsafe"
-                // diagnostic (rustc has a notion of builtin unsafe blocks, but we don't).
-                statements: fmt
-                    .orphans
-                    .into_iter()
-                    .map(|expr| Statement::Expr { expr, has_semi: true })
-                    .collect(),
-                tail: Some(unsafe_arg_new),
-                label: None,
-            });
-        }
 
         let idx = self.alloc_expr(
             Expr::Call {
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 82e6ff821b..09fb5f6fd2 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -951,7 +951,6 @@ bitflags::bitflags! {
         /// only very few functions with it. So we only encode its existence here, and lookup
         /// it if needed.
         const HAS_TARGET_FEATURE = 1 << 8;
-        const DEPRECATED_SAFE_2024 = 1 << 9;
     }
 }
 
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index f655692429..03218b4691 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -10,26 +10,24 @@ use hir_def::{
     path::Path,
     resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
     type_ref::Rawness,
-    AdtId, DefWithBodyId, FieldId, FunctionId, VariantId,
+    AdtId, DefWithBodyId, FieldId, VariantId,
 };
-use span::Edition;
 
 use crate::{
     db::HirDatabase, utils::is_fn_unsafe_to_call, InferenceResult, Interner, TargetFeatures, TyExt,
     TyKind,
 };
 
-#[derive(Debug, Default)]
-pub struct MissingUnsafeResult {
-    pub unsafe_exprs: Vec<(ExprOrPatId, UnsafetyReason)>,
-    /// If `fn_is_unsafe` is false, `unsafe_exprs` are hard errors. If true, they're `unsafe_op_in_unsafe_fn`.
-    pub fn_is_unsafe: bool,
-    pub deprecated_safe_calls: Vec<ExprId>,
-}
-
-pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafeResult {
+/// Returns `(unsafe_exprs, fn_is_unsafe)`.
+///
+/// If `fn_is_unsafe` is false, `unsafe_exprs` are hard errors. If true, they're `unsafe_op_in_unsafe_fn`.
+pub fn missing_unsafe(
+    db: &dyn HirDatabase,
+    def: DefWithBodyId,
+) -> (Vec<(ExprOrPatId, UnsafetyReason)>, bool) {
     let _p = tracing::info_span!("missing_unsafe").entered();
 
+    let mut res = Vec::new();
     let is_unsafe = match def {
         DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
         DefWithBodyId::StaticId(_)
@@ -39,19 +37,11 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe
         | DefWithBodyId::FieldId(_) => false,
     };
 
-    let mut res = MissingUnsafeResult { fn_is_unsafe: is_unsafe, ..MissingUnsafeResult::default() };
     let body = db.body(def);
     let infer = db.infer(def);
-    let mut callback = |diag| match diag {
-        UnsafeDiagnostic::UnsafeOperation { node, inside_unsafe_block, reason } => {
-            if inside_unsafe_block == InsideUnsafeBlock::No {
-                res.unsafe_exprs.push((node, reason));
-            }
-        }
-        UnsafeDiagnostic::DeprecatedSafe2024 { node, inside_unsafe_block } => {
-            if inside_unsafe_block == InsideUnsafeBlock::No {
-                res.deprecated_safe_calls.push(node)
-            }
+    let mut callback = |node, inside_unsafe_block, reason| {
+        if inside_unsafe_block == InsideUnsafeBlock::No {
+            res.push((node, reason));
         }
     };
     let mut visitor = UnsafeVisitor::new(db, &infer, &body, def, &mut callback);
@@ -66,7 +56,7 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe
         }
     }
 
-    res
+    (res, is_unsafe)
 }
 
 #[derive(Debug, Clone, Copy)]
@@ -85,31 +75,15 @@ pub enum InsideUnsafeBlock {
     Yes,
 }
 
-#[derive(Debug)]
-enum UnsafeDiagnostic {
-    UnsafeOperation {
-        node: ExprOrPatId,
-        inside_unsafe_block: InsideUnsafeBlock,
-        reason: UnsafetyReason,
-    },
-    /// A lint.
-    DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock },
-}
-
 pub fn unsafe_expressions(
     db: &dyn HirDatabase,
     infer: &InferenceResult,
     def: DefWithBodyId,
     body: &Body,
     current: ExprId,
-    callback: &mut dyn FnMut(InsideUnsafeBlock),
+    unsafe_expr_cb: &mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock, UnsafetyReason),
 ) {
-    let mut visitor_callback = |diag| {
-        if let UnsafeDiagnostic::UnsafeOperation { inside_unsafe_block, .. } = diag {
-            callback(inside_unsafe_block);
-        }
-    };
-    let mut visitor = UnsafeVisitor::new(db, infer, body, def, &mut visitor_callback);
+    let mut visitor = UnsafeVisitor::new(db, infer, body, def, unsafe_expr_cb);
     _ = visitor.resolver.update_to_inner_scope(db.upcast(), def, current);
     visitor.walk_expr(current);
 }
@@ -123,10 +97,8 @@ struct UnsafeVisitor<'a> {
     inside_unsafe_block: InsideUnsafeBlock,
     inside_assignment: bool,
     inside_union_destructure: bool,
-    callback: &'a mut dyn FnMut(UnsafeDiagnostic),
+    unsafe_expr_cb: &'a mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock, UnsafetyReason),
     def_target_features: TargetFeatures,
-    // FIXME: This needs to be the edition of the span of each call.
-    edition: Edition,
 }
 
 impl<'a> UnsafeVisitor<'a> {
@@ -135,14 +107,13 @@ impl<'a> UnsafeVisitor<'a> {
         infer: &'a InferenceResult,
         body: &'a Body,
         def: DefWithBodyId,
-        unsafe_expr_cb: &'a mut dyn FnMut(UnsafeDiagnostic),
+        unsafe_expr_cb: &'a mut dyn FnMut(ExprOrPatId, InsideUnsafeBlock, UnsafetyReason),
     ) -> Self {
         let resolver = def.resolver(db.upcast());
         let def_target_features = match def {
             DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())),
             _ => TargetFeatures::default(),
         };
-        let edition = db.crate_graph()[resolver.module().krate()].edition;
         Self {
             db,
             infer,
@@ -152,34 +123,13 @@ impl<'a> UnsafeVisitor<'a> {
             inside_unsafe_block: InsideUnsafeBlock::No,
             inside_assignment: false,
             inside_union_destructure: false,
-            callback: unsafe_expr_cb,
+            unsafe_expr_cb,
             def_target_features,
-            edition,
         }
     }
 
-    fn on_unsafe_op(&mut self, node: ExprOrPatId, reason: UnsafetyReason) {
-        (self.callback)(UnsafeDiagnostic::UnsafeOperation {
-            node,
-            inside_unsafe_block: self.inside_unsafe_block,
-            reason,
-        });
-    }
-
-    fn check_call(&mut self, node: ExprId, func: FunctionId) {
-        let unsafety = is_fn_unsafe_to_call(self.db, func, &self.def_target_features, self.edition);
-        match unsafety {
-            crate::utils::Unsafety::Safe => {}
-            crate::utils::Unsafety::Unsafe => {
-                self.on_unsafe_op(node.into(), UnsafetyReason::UnsafeFnCall)
-            }
-            crate::utils::Unsafety::DeprecatedSafe2024 => {
-                (self.callback)(UnsafeDiagnostic::DeprecatedSafe2024 {
-                    node,
-                    inside_unsafe_block: self.inside_unsafe_block,
-                })
-            }
-        }
+    fn call_cb(&mut self, node: ExprOrPatId, reason: UnsafetyReason) {
+        (self.unsafe_expr_cb)(node, self.inside_unsafe_block, reason);
     }
 
     fn walk_pats_top(&mut self, pats: impl Iterator<Item = PatId>, parent_expr: ExprId) {
@@ -204,9 +154,7 @@ impl<'a> UnsafeVisitor<'a> {
                 | Pat::Ref { .. }
                 | Pat::Box { .. }
                 | Pat::Expr(..)
-                | Pat::ConstBlock(..) => {
-                    self.on_unsafe_op(current.into(), UnsafetyReason::UnionField)
-                }
+                | Pat::ConstBlock(..) => self.call_cb(current.into(), UnsafetyReason::UnionField),
                 // `Or` only wraps other patterns, and `Missing`/`Wild` do not constitute a read.
                 Pat::Missing | Pat::Wild | Pat::Or(_) => {}
             }
@@ -241,7 +189,9 @@ impl<'a> UnsafeVisitor<'a> {
         match expr {
             &Expr::Call { callee, .. } => {
                 if let Some(func) = self.infer[callee].as_fn_def(self.db) {
-                    self.check_call(current, func);
+                    if is_fn_unsafe_to_call(self.db, func, &self.def_target_features) {
+                        self.call_cb(current.into(), UnsafetyReason::UnsafeFnCall);
+                    }
                 }
             }
             Expr::Path(path) => {
@@ -267,13 +217,18 @@ impl<'a> UnsafeVisitor<'a> {
                 }
             }
             Expr::MethodCall { .. } => {
-                if let Some((func, _)) = self.infer.method_resolution(current) {
-                    self.check_call(current, func);
+                if self
+                    .infer
+                    .method_resolution(current)
+                    .map(|(func, _)| is_fn_unsafe_to_call(self.db, func, &self.def_target_features))
+                    .unwrap_or(false)
+                {
+                    self.call_cb(current.into(), UnsafetyReason::UnsafeFnCall);
                 }
             }
             Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
                 if let TyKind::Raw(..) = &self.infer[*expr].kind(Interner) {
-                    self.on_unsafe_op(current.into(), UnsafetyReason::RawPtrDeref);
+                    self.call_cb(current.into(), UnsafetyReason::RawPtrDeref);
                 }
             }
             Expr::Unsafe { .. } => {
@@ -288,7 +243,7 @@ impl<'a> UnsafeVisitor<'a> {
                 self.walk_pats_top(std::iter::once(target), current);
                 self.inside_assignment = old_inside_assignment;
             }
-            Expr::InlineAsm(_) => self.on_unsafe_op(current.into(), UnsafetyReason::InlineAsm),
+            Expr::InlineAsm(_) => self.call_cb(current.into(), UnsafetyReason::InlineAsm),
             // rustc allows union assignment to propagate through field accesses and casts.
             Expr::Cast { .. } => self.inside_assignment = inside_assignment,
             Expr::Field { .. } => {
@@ -297,7 +252,7 @@ impl<'a> UnsafeVisitor<'a> {
                     if let Some(Either::Left(FieldId { parent: VariantId::UnionId(_), .. })) =
                         self.infer.field_resolution(current)
                     {
-                        self.on_unsafe_op(current.into(), UnsafetyReason::UnionField);
+                        self.call_cb(current.into(), UnsafetyReason::UnionField);
                     }
                 }
             }
@@ -332,9 +287,9 @@ impl<'a> UnsafeVisitor<'a> {
         if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
             let static_data = self.db.static_data(id);
             if static_data.mutable {
-                self.on_unsafe_op(node, UnsafetyReason::MutableStatic);
+                self.call_cb(node, UnsafetyReason::MutableStatic);
             } else if static_data.is_extern && !static_data.has_safe_kw {
-                self.on_unsafe_op(node, UnsafetyReason::ExternStatic);
+                self.call_cb(node, UnsafetyReason::ExternStatic);
             }
         }
     }
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 4b159b7541..37de501e98 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -100,9 +100,7 @@ pub use mapping::{
 };
 pub use method_resolution::check_orphan_rules;
 pub use traits::TraitEnvironment;
-pub use utils::{
-    all_super_traits, direct_super_traits, is_fn_unsafe_to_call, TargetFeatures, Unsafety,
-};
+pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call, TargetFeatures};
 pub use variance::Variance;
 
 pub use chalk_ir::{
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index c131e97bc4..ffd0b5b5e2 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -24,7 +24,6 @@ use intern::{sym, Symbol};
 use rustc_abi::TargetDataLayout;
 use rustc_hash::FxHashSet;
 use smallvec::{smallvec, SmallVec};
-use span::Edition;
 use stdx::never;
 
 use crate::{
@@ -293,38 +292,21 @@ 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,
-    call_edition: Edition,
-) -> Unsafety {
+) -> bool {
     let data = db.function_data(func);
     if data.is_unsafe() {
-        return Unsafety::Unsafe;
+        return true;
     }
 
     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 Unsafety::Unsafe;
-        }
-    }
-
-    if data.is_deprecated_safe_2024() {
-        if call_edition.at_least_2024() {
-            return Unsafety::Unsafe;
-        } else {
-            return Unsafety::DeprecatedSafe2024;
+            return true;
         }
     }
 
@@ -337,22 +319,14 @@ 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
-                if db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists() {
-                    Unsafety::Safe
-                } else {
-                    Unsafety::Unsafe
-                }
+                !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`.
-                if data.is_safe() {
-                    Unsafety::Safe
-                } else {
-                    Unsafety::Unsafe
-                }
+                !data.is_safe()
             }
         }
-        _ => Unsafety::Safe,
+        _ => false,
     }
 }
 
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 64e982c42d..066a322e32 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -271,17 +271,11 @@ pub struct PrivateField {
     pub field: Field,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum UnsafeLint {
-    HardError,
-    UnsafeOpInUnsafeFn,
-    DeprecatedSafe2024,
-}
-
 #[derive(Debug)]
 pub struct MissingUnsafe {
     pub node: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
-    pub lint: UnsafeLint,
+    /// If true, the diagnostics is an `unsafe_op_in_unsafe_fn` lint instead of a hard error.
+    pub only_lint: bool,
     pub reason: UnsafetyReason,
 }
 
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 6f4168ab08..6f40497055 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -82,7 +82,7 @@ impl HirDisplay for Function {
         }
         // FIXME: This will show `unsafe` for functions that are `#[target_feature]` but not unsafe
         // (they are conditionally unsafe to call). We probably should show something else.
-        if self.is_unsafe_to_call(db, None, f.edition()) {
+        if self.is_unsafe_to_call(db, None) {
             f.write_str("unsafe ")?;
         }
         if let Some(abi) = &data.abi {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index b414ef0d71..5b35b0168a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2040,40 +2040,16 @@ impl DefWithBody {
             );
         }
 
-        let missing_unsafe = hir_ty::diagnostics::missing_unsafe(db, self.into());
-        for (node, reason) in missing_unsafe.unsafe_exprs {
+        let (unsafe_exprs, only_lint) = hir_ty::diagnostics::missing_unsafe(db, self.into());
+        for (node, reason) in unsafe_exprs {
             match source_map.expr_or_pat_syntax(node) {
-                Ok(node) => acc.push(
-                    MissingUnsafe {
-                        node,
-                        lint: if missing_unsafe.fn_is_unsafe {
-                            UnsafeLint::UnsafeOpInUnsafeFn
-                        } else {
-                            UnsafeLint::HardError
-                        },
-                        reason,
-                    }
-                    .into(),
-                ),
+                Ok(node) => acc.push(MissingUnsafe { node, only_lint, reason }.into()),
                 Err(SyntheticSyntax) => {
                     // FIXME: Here and elsewhere in this file, the `expr` was
                     // desugared, report or assert that this doesn't happen.
                 }
             }
         }
-        for node in missing_unsafe.deprecated_safe_calls {
-            match source_map.expr_syntax(node) {
-                Ok(node) => acc.push(
-                    MissingUnsafe {
-                        node: node.map(|it| it.wrap_left()),
-                        lint: UnsafeLint::DeprecatedSafe2024,
-                        reason: UnsafetyReason::UnsafeFnCall,
-                    }
-                    .into(),
-                ),
-                Err(SyntheticSyntax) => never!("synthetic DeprecatedSafe2024"),
-            }
-        }
 
         if let Ok(borrowck_results) = db.borrowck(self.into()) {
             for borrowck_result in borrowck_results.iter() {
@@ -2449,19 +2425,11 @@ impl Function {
         db.attrs(self.id.into()).is_unstable()
     }
 
-    pub fn is_unsafe_to_call(
-        self,
-        db: &dyn HirDatabase,
-        caller: Option<Function>,
-        call_edition: Edition,
-    ) -> bool {
+    pub fn is_unsafe_to_call(self, db: &dyn HirDatabase, caller: Option<Function>) -> bool {
         let target_features = caller
             .map(|caller| hir_ty::TargetFeatures::from_attrs(&db.attrs(caller.id.into())))
             .unwrap_or_default();
-        matches!(
-            hir_ty::is_fn_unsafe_to_call(db, self.id, &target_features, call_edition),
-            hir_ty::Unsafety::Unsafe
-        )
+        hir_ty::is_fn_unsafe_to_call(db, self.id, &target_features)
     }
 
     /// Whether this function declaration has a definition.
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 7d6f110181..9f230c2251 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -1107,9 +1107,16 @@ impl SourceAnalyzer {
             if let Some(expanded_expr) = sm.macro_expansion_expr(macro_expr) {
                 let mut is_unsafe = false;
                 let mut walk_expr = |expr_id| {
-                    unsafe_expressions(db, infer, *def, body, expr_id, &mut |inside_unsafe_block| {
-                        is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No
-                    })
+                    unsafe_expressions(
+                        db,
+                        infer,
+                        *def,
+                        body,
+                        expr_id,
+                        &mut |_, inside_unsafe_block, _| {
+                            is_unsafe |= inside_unsafe_block == InsideUnsafeBlock::No
+                        },
+                    )
                 };
                 match expanded_expr {
                     ExprOrPatId::ExprId(expanded_expr) => walk_expr(expanded_expr),
diff --git a/crates/hir/src/term_search/tactics.rs b/crates/hir/src/term_search/tactics.rs
index 847304d503..1ff9b6dec9 100644
--- a/crates/hir/src/term_search/tactics.rs
+++ b/crates/hir/src/term_search/tactics.rs
@@ -15,7 +15,6 @@ use hir_ty::mir::BorrowKind;
 use hir_ty::TyBuilder;
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
-use span::Edition;
 
 use crate::{
     Adt, AssocItem, GenericDef, GenericParam, HasAttrs, HasVisibility, Impl, ModuleDef, ScopeDef,
@@ -366,7 +365,7 @@ pub(super) fn free_function<'a, DB: HirDatabase>(
                         let ret_ty = it.ret_type_with_args(db, generics.iter().cloned());
                         // Filter out private and unsafe functions
                         if !it.is_visible_from(db, module)
-                            || it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
+                            || it.is_unsafe_to_call(db, None)
                             || it.is_unstable(db)
                             || ctx.config.enable_borrowcheck && ret_ty.contains_reference(db)
                             || ret_ty.is_raw_ptr()
@@ -472,7 +471,7 @@ pub(super) fn impl_method<'a, DB: HirDatabase>(
 
             // Filter out private and unsafe functions
             if !it.is_visible_from(db, module)
-                || it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
+                || it.is_unsafe_to_call(db, None)
                 || it.is_unstable(db)
             {
                 return None;
@@ -663,7 +662,7 @@ pub(super) fn impl_static_method<'a, DB: HirDatabase>(
 
             // Filter out private and unsafe functions
             if !it.is_visible_from(db, module)
-                || it.is_unsafe_to_call(db, None, Edition::CURRENT_FIXME)
+                || it.is_unsafe_to_call(db, None)
                 || it.is_unstable(db)
             {
                 return None;
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index fd90613964..4931f8d090 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -320,7 +320,7 @@ fn detail(ctx: &CompletionContext<'_>, func: hir::Function, edition: Edition) ->
             ret_ty = async_ret;
         }
     }
-    if func.is_unsafe_to_call(ctx.db, ctx.containing_function, ctx.edition) {
+    if func.is_unsafe_to_call(ctx.db, ctx.containing_function) {
         format_to!(detail, "unsafe ");
     }
 
diff --git a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index d48464769c..cea8bc5e95 100644
--- a/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -1,5 +1,5 @@
 use hir::db::ExpandDatabase;
-use hir::{HirFileIdExt, UnsafeLint, UnsafetyReason};
+use hir::{HirFileIdExt, UnsafetyReason};
 use ide_db::text_edit::TextEdit;
 use ide_db::{assists::Assist, source_change::SourceChange};
 use syntax::{ast, SyntaxNode};
@@ -11,10 +11,10 @@ use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext};
 //
 // This diagnostic is triggered if an operation marked as `unsafe` is used outside of an `unsafe` function or block.
 pub(crate) fn missing_unsafe(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Diagnostic {
-    let code = match d.lint {
-        UnsafeLint::HardError => DiagnosticCode::RustcHardError("E0133"),
-        UnsafeLint::UnsafeOpInUnsafeFn => DiagnosticCode::RustcLint("unsafe_op_in_unsafe_fn"),
-        UnsafeLint::DeprecatedSafe2024 => DiagnosticCode::RustcLint("deprecated_safe_2024"),
+    let code = if d.only_lint {
+        DiagnosticCode::RustcLint("unsafe_op_in_unsafe_fn")
+    } else {
+        DiagnosticCode::RustcHardError("E0133")
     };
     let operation = display_unsafety_reason(d.reason);
     Diagnostic::new_with_syntax_node_ptr(
@@ -585,58 +585,24 @@ fn main() {
             r#"
 //- /ed2021.rs crate:ed2021 edition:2021
 #[rustc_deprecated_safe_2024]
-unsafe fn deprecated_safe() -> u8 {
+unsafe fn safe() -> u8 {
     0
 }
-
 //- /ed2024.rs crate:ed2024 edition:2024
 #[rustc_deprecated_safe_2024]
-unsafe fn deprecated_safe() -> u8 {
+unsafe fn not_safe() -> u8 {
     0
 }
-
-//- /dep1.rs crate:dep1 deps:ed2021,ed2024 edition:2021
-fn main() {
-    ed2021::deprecated_safe();
-    ed2024::deprecated_safe();
-}
-
-//- /dep2.rs crate:dep2 deps:ed2021,ed2024 edition:2024
-fn main() {
-    ed2021::deprecated_safe();
- // ^^^^^^^^^^^^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
-    ed2024::deprecated_safe();
- // ^^^^^^^^^^^^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
-}
-
-//- /dep3.rs crate:dep3 deps:ed2021,ed2024 edition:2021
-#![warn(deprecated_safe)]
-
+//- /main.rs crate:main deps:ed2021,ed2024
 fn main() {
-    ed2021::deprecated_safe();
- // ^^^^^^^^^^^^^^^^^^^^^^^^^💡 warn: call to unsafe function is unsafe and requires an unsafe function or block
-    ed2024::deprecated_safe();
- // ^^^^^^^^^^^^^^^^^^^^^^^^^💡 warn: call to unsafe function is unsafe and requires an unsafe function or block
+    ed2021::safe();
+    ed2024::not_safe();
+  //^^^^^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
 }
             "#,
         )
     }
 
-    #[test]
-    fn orphan_unsafe_format_args() {
-        // Checks that we don't place orphan arguments for formatting under an unsafe block.
-        check_diagnostics(
-            r#"
-//- minicore: fmt
-fn foo() {
-    let p = 0xDEADBEEF as *const i32;
-    format_args!("", *p);
-                  // ^^ error: dereference of raw pointer is unsafe and requires an unsafe function or block
-}
-        "#,
-        );
-    }
-
     #[test]
     fn unsafe_op_in_unsafe_fn_allowed_by_default_in_edition_2021() {
         check_diagnostics(
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 95f2bf1139..f53f0aec09 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -478,15 +478,7 @@ fn traverse(
                     {
                         continue;
                     }
-                    highlight_format_string(
-                        hl,
-                        sema,
-                        krate,
-                        &string,
-                        &expanded_string,
-                        range,
-                        file_id.edition(),
-                    );
+                    highlight_format_string(hl, sema, krate, &string, &expanded_string, range);
 
                     if !string.is_raw() {
                         highlight_escape_string(hl, &string, range.start());
@@ -534,7 +526,6 @@ fn traverse(
                 &mut bindings_shadow_count,
                 config.syntactic_name_ref_highlighting,
                 name_like,
-                file_id.edition(),
             ),
             NodeOrToken::Token(token) => {
                 highlight::token(sema, token, file_id.edition()).zip(Some(None))
diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs
index 43a6bdad7e..7234108701 100644
--- a/crates/ide/src/syntax_highlighting/format.rs
+++ b/crates/ide/src/syntax_highlighting/format.rs
@@ -4,7 +4,6 @@ use ide_db::{
     syntax_helpers::format_string::{is_format_string, lex_format_specifiers, FormatSpecifier},
     SymbolKind,
 };
-use span::Edition;
 use syntax::{ast, TextRange};
 
 use crate::{
@@ -19,7 +18,6 @@ pub(super) fn highlight_format_string(
     string: &ast::String,
     expanded_string: &ast::String,
     range: TextRange,
-    edition: Edition,
 ) {
     if is_format_string(expanded_string) {
         // FIXME: Replace this with the HIR info we have now.
@@ -41,7 +39,7 @@ pub(super) fn highlight_format_string(
             if let Some(res) = res {
                 stack.add(HlRange {
                     range,
-                    highlight: highlight_def(sema, krate, Definition::from(res), edition),
+                    highlight: highlight_def(sema, krate, Definition::from(res)),
                     binding_hash: None,
                 })
             }
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 842b86d2d0..939f0c70b1 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -58,7 +58,6 @@ pub(super) fn name_like(
     bindings_shadow_count: &mut FxHashMap<hir::Name, u32>,
     syntactic_name_ref_highlighting: bool,
     name_like: ast::NameLike,
-    edition: Edition,
 ) -> Option<(Highlight, Option<u64>)> {
     let mut binding_hash = None;
     let highlight = match name_like {
@@ -69,17 +68,16 @@ pub(super) fn name_like(
             &mut binding_hash,
             syntactic_name_ref_highlighting,
             name_ref,
-            edition,
         ),
         ast::NameLike::Name(name) => {
-            highlight_name(sema, bindings_shadow_count, &mut binding_hash, krate, name, edition)
+            highlight_name(sema, bindings_shadow_count, &mut binding_hash, krate, name)
         }
         ast::NameLike::Lifetime(lifetime) => match IdentClass::classify_lifetime(sema, &lifetime) {
             Some(IdentClass::NameClass(NameClass::Definition(def))) => {
-                highlight_def(sema, krate, def, edition) | HlMod::Definition
+                highlight_def(sema, krate, def) | HlMod::Definition
             }
             Some(IdentClass::NameRefClass(NameRefClass::Definition(def, _))) => {
-                highlight_def(sema, krate, def, edition)
+                highlight_def(sema, krate, def)
             }
             // FIXME: Fallback for 'static and '_, as we do not resolve these yet
             _ => SymbolKind::LifetimeParam.into(),
@@ -236,17 +234,16 @@ fn highlight_name_ref(
     binding_hash: &mut Option<u64>,
     syntactic_name_ref_highlighting: bool,
     name_ref: ast::NameRef,
-    edition: Edition,
 ) -> Highlight {
     let db = sema.db;
-    if let Some(res) = highlight_method_call_by_name_ref(sema, krate, &name_ref, edition) {
+    if let Some(res) = highlight_method_call_by_name_ref(sema, krate, &name_ref) {
         return res;
     }
 
     let name_class = match NameRefClass::classify(sema, &name_ref) {
         Some(name_kind) => name_kind,
         None if syntactic_name_ref_highlighting => {
-            return highlight_name_ref_by_syntax(name_ref, sema, krate, edition)
+            return highlight_name_ref_by_syntax(name_ref, sema, krate)
         }
         // FIXME: This is required for helper attributes used by proc-macros, as those do not map down
         // to anything when used.
@@ -270,7 +267,7 @@ fn highlight_name_ref(
                 *binding_hash = Some(calc_binding_hash(&name, *shadow_count))
             };
 
-            let mut h = highlight_def(sema, krate, def, edition);
+            let mut h = highlight_def(sema, krate, def);
 
             match def {
                 Definition::Local(local) if is_consumed_lvalue(name_ref.syntax(), &local, db) => {
@@ -308,7 +305,7 @@ fn highlight_name_ref(
             h
         }
         NameRefClass::FieldShorthand { field_ref, .. } => {
-            highlight_def(sema, krate, field_ref.into(), edition)
+            highlight_def(sema, krate, field_ref.into())
         }
         NameRefClass::ExternCrateShorthand { decl, krate: resolved_krate } => {
             let mut h = HlTag::Symbol(SymbolKind::Module).into();
@@ -344,7 +341,6 @@ fn highlight_name(
     binding_hash: &mut Option<u64>,
     krate: hir::Crate,
     name: ast::Name,
-    edition: Edition,
 ) -> Highlight {
     let name_kind = NameClass::classify(sema, &name);
     if let Some(NameClass::Definition(Definition::Local(local))) = &name_kind {
@@ -355,7 +351,7 @@ fn highlight_name(
     };
     match name_kind {
         Some(NameClass::Definition(def)) => {
-            let mut h = highlight_def(sema, krate, def, edition) | HlMod::Definition;
+            let mut h = highlight_def(sema, krate, def) | HlMod::Definition;
             if let Definition::Trait(trait_) = &def {
                 if trait_.is_unsafe(sema.db) {
                     h |= HlMod::Unsafe;
@@ -363,7 +359,7 @@ fn highlight_name(
             }
             h
         }
-        Some(NameClass::ConstReference(def)) => highlight_def(sema, krate, def, edition),
+        Some(NameClass::ConstReference(def)) => highlight_def(sema, krate, def),
         Some(NameClass::PatFieldShorthand { field_ref, .. }) => {
             let mut h = HlTag::Symbol(SymbolKind::Field).into();
             if let hir::VariantDef::Union(_) = field_ref.parent_def(sema.db) {
@@ -383,7 +379,6 @@ pub(super) fn highlight_def(
     sema: &Semantics<'_, RootDatabase>,
     krate: hir::Crate,
     def: Definition,
-    edition: Edition,
 ) -> Highlight {
     let db = sema.db;
     let mut h = match def {
@@ -436,8 +431,7 @@ pub(super) fn highlight_def(
             // highlighted as unsafe, even when the current target features set is a superset (RFC 2396).
             // We probably should consider checking the current function, but I found no easy way to do
             // that (also I'm worried about perf). There's also an instance below.
-            // FIXME: This should be the edition of the call.
-            if func.is_unsafe_to_call(db, None, edition) {
+            if func.is_unsafe_to_call(db, None) {
                 h |= HlMod::Unsafe;
             }
             if func.is_async(db) {
@@ -585,23 +579,21 @@ fn highlight_method_call_by_name_ref(
     sema: &Semantics<'_, RootDatabase>,
     krate: hir::Crate,
     name_ref: &ast::NameRef,
-    edition: Edition,
 ) -> Option<Highlight> {
     let mc = name_ref.syntax().parent().and_then(ast::MethodCallExpr::cast)?;
-    highlight_method_call(sema, krate, &mc, edition)
+    highlight_method_call(sema, krate, &mc)
 }
 
 fn highlight_method_call(
     sema: &Semantics<'_, RootDatabase>,
     krate: hir::Crate,
     method_call: &ast::MethodCallExpr,
-    edition: Edition,
 ) -> Option<Highlight> {
     let func = sema.resolve_method_call(method_call)?;
 
     let mut h = SymbolKind::Method.into();
 
-    if func.is_unsafe_to_call(sema.db, None, edition) || sema.is_unsafe_method_call(method_call) {
+    if func.is_unsafe_to_call(sema.db, None) || sema.is_unsafe_method_call(method_call) {
         h |= HlMod::Unsafe;
     }
     if func.is_async(sema.db) {
@@ -677,6 +669,12 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight {
         STATIC => SymbolKind::Static,
         IDENT_PAT => SymbolKind::Local,
         FORMAT_ARGS_ARG => SymbolKind::Local,
+        RENAME => SymbolKind::Local,
+        MACRO_RULES => SymbolKind::Macro,
+        CONST_PARAM => SymbolKind::ConstParam,
+        SELF_PARAM => SymbolKind::SelfParam,
+        TRAIT_ALIAS => SymbolKind::TraitAlias,
+        ASM_OPERAND_NAMED => SymbolKind::Local,
         _ => return default.into(),
     };
 
@@ -687,7 +685,6 @@ fn highlight_name_ref_by_syntax(
     name: ast::NameRef,
     sema: &Semantics<'_, RootDatabase>,
     krate: hir::Crate,
-    edition: Edition,
 ) -> Highlight {
     let default = HlTag::UnresolvedReference;
 
@@ -698,7 +695,7 @@ fn highlight_name_ref_by_syntax(
 
     match parent.kind() {
         METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent)
-            .and_then(|it| highlight_method_call(sema, krate, &it, edition))
+            .and_then(|it| highlight_method_call(sema, krate, &it))
             .unwrap_or_else(|| SymbolKind::Method.into()),
         FIELD_EXPR => {
             let h = HlTag::Symbol(SymbolKind::Field);
diff --git a/crates/rust-analyzer/src/lsp/semantic_tokens.rs b/crates/rust-analyzer/src/lsp/semantic_tokens.rs
index 3c21e19925..991c10743f 100644
--- a/crates/rust-analyzer/src/lsp/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/lsp/semantic_tokens.rs
@@ -24,7 +24,7 @@ macro_rules! define_semantic_token_types {
         }
 
         pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
-            $(self::types::$standard,)*
+            $(SemanticTokenType::$standard,)*
             $(self::types::$custom),*
         ];
 
@@ -32,7 +32,7 @@ macro_rules! define_semantic_token_types {
             use self::types::*;
             $(
                 if token == $custom {
-                    None $(.or(Some(self::types::$fallback)))?
+                    None $(.or(Some(SemanticTokenType::$fallback)))?
                 } else
             )*
             { Some(token )}
@@ -60,7 +60,6 @@ define_semantic_token_types![
         STRUCT,
         TYPE_PARAMETER,
         VARIABLE,
-        TYPE,
     }
 
     custom {


Test patch:
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 0a7e273950..1794d7dbfe 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -82,6 +82,10 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="colon">:</span>literal<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">{</span>stringify<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="semicolon">;</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="brace">}</span><span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
+<span class="keyword">use</span> <span class="unresolved_reference">foo</span><span class="operator">::</span><span class="unresolved_reference">bar</span> <span class="keyword">as</span> <span class="variable declaration">baz</span><span class="semicolon">;</span>
+<span class="keyword">trait</span> <span class="trait_alias declaration">Bar</span> <span class="operator">=</span> <span class="unresolved_reference">Baz</span><span class="semicolon">;</span>
+<span class="keyword">trait</span> <span class="trait_alias declaration">Foo</span> <span class="operator">=</span> <span class="trait_alias">Bar</span><span class="semicolon">;</span>
+
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\n</span><span class="char_literal">'</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="char_literal">'</span><span class="escape_sequence">\t</span><span class="char_literal">'</span><span class="semicolon">;</span>
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs
index af52b33de6..b9520ae2bb 100644
--- a/crates/ide/src/syntax_highlighting/tests.rs
+++ b/crates/ide/src/syntax_highlighting/tests.rs
@@ -466,6 +466,10 @@ macro_rules! reuse_twice {
     ($literal:literal) => {{stringify!($literal); format_args!($literal)}};
 }
 
+use foo::bar as baz;
+trait Bar = Baz;
+trait Foo = Bar;
+
 fn main() {
     let a = '\n';
     let a = '\t';