about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs23
-rw-r--r--compiler/rustc_passes/src/dead.rs429
-rw-r--r--src/test/ui/associated-consts/associated-const-dead-code.stderr4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-87987.stderr4
-rw-r--r--src/test/ui/derive-uninhabited-enum-38885.stderr2
-rw-r--r--src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr8
-rw-r--r--src/test/ui/derives/clone-debug-dead-code.stderr10
-rw-r--r--src/test/ui/issues/issue-37515.stderr4
-rw-r--r--src/test/ui/lint/dead-code/impl-trait.stderr4
-rw-r--r--src/test/ui/lint/dead-code/issue-85255.stderr44
-rw-r--r--src/test/ui/lint/dead-code/lint-dead-code-1.stderr8
-rw-r--r--src/test/ui/lint/dead-code/lint-dead-code-3.rs11
-rw-r--r--src/test/ui/lint/dead-code/lint-dead-code-3.stderr30
-rw-r--r--src/test/ui/lint/dead-code/lint-dead-code-4.stderr32
-rw-r--r--src/test/ui/lint/dead-code/lint-dead-code-5.stderr4
-rw-r--r--src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr12
-rw-r--r--src/test/ui/lint/dead-code/type-alias.stderr4
-rw-r--r--src/test/ui/lint/dead-code/unused-struct-variant.stderr2
-rw-r--r--src/test/ui/lint/issue-17718-const-naming.stderr4
-rw-r--r--src/test/ui/span/macro-span-replacement.stderr4
-rw-r--r--src/test/ui/union/union-fields-1.mirunsafeck.stderr8
-rw-r--r--src/test/ui/union/union-fields-1.thirunsafeck.stderr8
-rw-r--r--src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr2
-rw-r--r--src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr2
24 files changed, 266 insertions, 397 deletions
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index d853a5e9ee7..62f6a43d1f2 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -5,7 +5,6 @@
 use crate::thir::pattern::pat_from_hir;
 use crate::thir::util::UserAnnotatedTyHelpers;
 
-use rustc_ast as ast;
 use rustc_data_structures::steal::Steal;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
@@ -13,10 +12,8 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::HirId;
 use rustc_hir::Node;
 use rustc_middle::middle::region;
-use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
-use rustc_middle::mir::ConstantKind;
 use rustc_middle::thir::*;
-use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt};
+use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
 use rustc_span::Span;
 
 pub(crate) fn thir_body<'tcx>(
@@ -80,24 +77,6 @@ impl<'tcx> Cx<'tcx> {
         }
     }
 
-    #[instrument(skip(self), level = "debug")]
-    pub(crate) fn const_eval_literal(
-        &mut self,
-        lit: &'tcx ast::LitKind,
-        ty: Ty<'tcx>,
-        sp: Span,
-        neg: bool,
-    ) -> ConstantKind<'tcx> {
-        match self.tcx.at(sp).lit_to_mir_constant(LitToConstInput { lit, ty, neg }) {
-            Ok(c) => c,
-            Err(LitToConstError::Reported) => {
-                // create a dummy value and continue compiling
-                ConstantKind::Ty(self.tcx.const_error(ty))
-            }
-            Err(LitToConstError::TypeError) => bug!("const_eval_literal: had type error"),
-        }
-    }
-
     #[tracing::instrument(level = "debug", skip(self))]
     pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
         let p = match self.tcx.hir().get(p.hir_id) {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 01d93f6ff0c..58c5e5b4dfe 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -10,14 +10,12 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Node, PatKind, TyKind};
-use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::Span;
 use std::mem;
 
 // Any local node that may call something in its body block should be
@@ -82,8 +80,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
 
     fn handle_res(&mut self, res: Res) {
         match res {
-            Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, _) => {
-                self.check_def_id(res.def_id());
+            Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
+                self.check_def_id(def_id);
             }
             _ if self.in_pat => {}
             Res::PrimTy(..) | Res::SelfCtor(..) | Res::Local(..) => {}
@@ -102,6 +100,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     self.check_def_id(variant_id);
                 }
             }
+            Res::Def(_, def_id) => self.check_def_id(def_id),
             Res::SelfTy { trait_: t, alias_to: i } => {
                 if let Some(t) = t {
                     self.check_def_id(t);
@@ -111,9 +110,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                 }
             }
             Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
-            _ => {
-                self.check_def_id(res.def_id());
-            }
         }
     }
 
@@ -285,20 +281,33 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     let def = self.tcx.adt_def(item.def_id);
                     self.repr_has_repr_c = def.repr().c();
 
-                    intravisit::walk_item(self, &item);
-                }
-                hir::ItemKind::Enum(..) => {
-                    intravisit::walk_item(self, &item);
+                    intravisit::walk_item(self, &item)
                 }
                 hir::ItemKind::ForeignMod { .. } => {}
-                _ => {
-                    intravisit::walk_item(self, &item);
-                }
+                _ => intravisit::walk_item(self, &item),
             },
             Node::TraitItem(trait_item) => {
                 intravisit::walk_trait_item(self, trait_item);
             }
             Node::ImplItem(impl_item) => {
+                let item = self.tcx.local_parent(impl_item.def_id);
+                if self.tcx.impl_trait_ref(item).is_none() {
+                    //// If it's a type whose items are live, then it's live, too.
+                    //// This is done to handle the case where, for example, the static
+                    //// method of a private type is used, but the type itself is never
+                    //// called directly.
+                    let self_ty = self.tcx.type_of(item);
+                    match *self_ty.kind() {
+                        ty::Adt(def, _) => self.check_def_id(def.did()),
+                        ty::Foreign(did) => self.check_def_id(did),
+                        ty::Dynamic(data, ..) => {
+                            if let Some(def_id) = data.principal_def_id() {
+                                self.check_def_id(def_id)
+                            }
+                        }
+                        _ => {}
+                    }
+                }
                 intravisit::walk_impl_item(self, impl_item);
             }
             Node::ForeignItem(foreign_item) => {
@@ -624,8 +633,7 @@ fn live_symbols_and_ignored_derived_traits<'tcx>(
 }
 
 struct DeadVariant {
-    hir_id: hir::HirId,
-    span: Span,
+    def_id: LocalDefId,
     name: Symbol,
     level: lint::Level,
 }
@@ -637,85 +645,53 @@ struct DeadVisitor<'tcx> {
 }
 
 impl<'tcx> DeadVisitor<'tcx> {
-    fn should_warn_about_item(&mut self, item: &hir::Item<'_>) -> bool {
-        let should_warn = matches!(
-            item.kind,
-            hir::ItemKind::Static(..)
-                | hir::ItemKind::Const(..)
-                | hir::ItemKind::Fn(..)
-                | hir::ItemKind::TyAlias(..)
-                | hir::ItemKind::Enum(..)
-                | hir::ItemKind::Struct(..)
-                | hir::ItemKind::Union(..)
-        );
-        should_warn && !self.symbol_is_live(item.def_id)
-    }
-
-    fn should_warn_about_field(&mut self, field: &hir::FieldDef<'_>) -> bool {
-        let def_id = self.tcx.hir().local_def_id(field.hir_id);
-        let field_type = self.tcx.type_of(def_id);
-        !field.is_positional()
-            && !self.symbol_is_live(def_id)
-            && !field_type.is_phantom_data()
-            && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id)
-    }
-
-    fn should_warn_about_variant(&mut self, variant: &hir::Variant<'_>) -> bool {
-        let def_id = self.tcx.hir().local_def_id(variant.id);
-        !self.symbol_is_live(def_id) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.id)
-    }
-
-    fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem<'_>) -> bool {
-        !self.symbol_is_live(fi.def_id) && !has_allow_dead_code_or_lang_attr(self.tcx, fi.hir_id())
-    }
-
-    // id := HIR id of an item's definition.
-    fn symbol_is_live(&mut self, def_id: LocalDefId) -> bool {
-        if self.live_symbols.contains(&def_id) {
-            return true;
+    fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> bool {
+        if self.live_symbols.contains(&field.did.expect_local()) {
+            return false;
         }
-        // If it's a type whose items are live, then it's live, too.
-        // This is done to handle the case where, for example, the static
-        // method of a private type is used, but the type itself is never
-        // called directly.
-        let inherent_impls = self.tcx.inherent_impls(def_id);
-        for &impl_did in inherent_impls.iter() {
-            for item_did in self.tcx.associated_item_def_ids(impl_did) {
-                if let Some(def_id) = item_did.as_local()
-                    && self.live_symbols.contains(&def_id)
-                {
-                    return true;
-                }
-            }
+        let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
+        if is_positional {
+            return false;
         }
-        false
+        let field_type = self.tcx.type_of(field.did);
+        !field_type.is_phantom_data()
     }
 
     fn warn_multiple_dead_codes(
         &self,
-        dead_codes: &[(hir::HirId, Span, Symbol)],
+        dead_codes: &[LocalDefId],
         participle: &str,
-        parent_hir_id: Option<hir::HirId>,
+        parent_item: Option<LocalDefId>,
     ) {
-        if let Some((id, _, name)) = dead_codes.first()
-            && !name.as_str().starts_with('_')
-        {
-            self.tcx.struct_span_lint_hir(
+        if let Some(&first_id) = dead_codes.first() {
+            let tcx = self.tcx;
+            let names: Vec<_> = dead_codes
+                .iter()
+                .map(|&def_id| tcx.item_name(def_id.to_def_id()).to_string())
+                .collect();
+            let spans = dead_codes
+                .iter()
+                .map(|&def_id| match tcx.def_ident_span(def_id) {
+                    Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()),
+                    None => tcx.def_span(def_id),
+                })
+                .collect();
+
+            tcx.struct_span_lint_hir(
                 lint::builtin::DEAD_CODE,
-                *id,
-                MultiSpan::from_spans(
-                    dead_codes.iter().map(|(_, span, _)| *span).collect(),
-                ),
+                tcx.hir().local_def_id_to_hir_id(first_id),
+                MultiSpan::from_spans(spans),
                 |lint| {
-                    let def_id = self.tcx.hir().local_def_id(*id);
-                    let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
+                    let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
                     let span_len = dead_codes.len();
-                    let names = match &dead_codes.iter().map(|(_, _, n)| n.to_string()).collect::<Vec<_>>()[..]
-                    {
+                    let names = match &names[..] {
                         _ if span_len > 6 => String::new(),
                         [name] => format!("`{name}` "),
                         [names @ .., last] => {
-                            format!("{} and `{last}` ", names.iter().map(|name| format!("`{name}`")).join(", "))
+                            format!(
+                                "{} and `{last}` ",
+                                names.iter().map(|name| format!("`{name}`")).join(", ")
+                            )
                         }
                         [] => unreachable!(),
                     };
@@ -725,25 +701,17 @@ impl<'tcx> DeadVisitor<'tcx> {
                         s = pluralize!(span_len),
                         are = pluralize!("is", span_len),
                     ));
-                    let hir = self.tcx.hir();
-                    if let Some(parent_hir_id) = parent_hir_id
-                        && let Some(parent_node) = hir.find(parent_hir_id)
-                        && let Node::Item(item) = parent_node
-                    {
-                        let def_id = self.tcx.hir().local_def_id(parent_hir_id);
-                        let parent_descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
+
+                    if let Some(parent_item) = parent_item {
+                        let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id());
                         err.span_label(
-                            item.ident.span,
-                            format!(
-                                "{descr}{s} in this {parent_descr}",
-                                s = pluralize!(span_len)
-                            ),
+                            tcx.def_ident_span(parent_item).unwrap(),
+                            format!("{descr}{s} in this {parent_descr}", s = pluralize!(span_len)),
                         );
                     }
-                    if let Some(encl_scope) = hir.get_enclosing_scope(*id)
-                        && let Some(encl_def_id) = hir.opt_local_def_id(encl_scope)
-                        && let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id)
-                    {
+
+                    let encl_def_id = parent_item.unwrap_or(first_id);
+                    if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) {
                         let traits_str = ign_traits
                             .iter()
                             .map(|(trait_id, _)| format!("`{}`", self.tcx.item_name(*trait_id)))
@@ -764,15 +732,15 @@ impl<'tcx> DeadVisitor<'tcx> {
                         );
                         err.note(&msg);
                     }
-                        err.emit();
-                    },
+                    err.emit();
+                },
             );
         }
     }
 
     fn warn_dead_fields_and_variants(
         &self,
-        hir_id: hir::HirId,
+        def_id: LocalDefId,
         participle: &str,
         dead_codes: Vec<DeadVariant>,
     ) {
@@ -787,207 +755,110 @@ impl<'tcx> DeadVisitor<'tcx> {
         dead_codes.sort_by_key(|v| v.level);
         for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) {
             self.warn_multiple_dead_codes(
-                &group
-                    .map(|v| (v.hir_id, v.span, v.name))
-                    .collect::<Vec<(hir::HirId, Span, Symbol)>>(),
+                &group.map(|v| v.def_id).collect::<Vec<_>>(),
                 participle,
-                Some(hir_id),
+                Some(def_id),
             );
         }
     }
 
-    fn warn_dead_code(
-        &mut self,
-        id: hir::HirId,
-        span: rustc_span::Span,
-        name: Symbol,
-        participle: &str,
-    ) {
-        self.warn_multiple_dead_codes(&[(id, span, name)], participle, None);
+    fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) {
+        self.warn_multiple_dead_codes(&[id], participle, None);
     }
-}
 
-impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    /// Walk nested items in place so that we don't report dead-code
-    /// on inner functions when the outer function is already getting
-    /// an error. We could do this also by checking the parents, but
-    /// this is how the code is setup and it seems harmless enough.
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        if self.should_warn_about_item(item) {
-            // For most items, we want to highlight its identifier
-            let span = match item.kind {
-                hir::ItemKind::Fn(..)
-                | hir::ItemKind::Mod(..)
-                | hir::ItemKind::Enum(..)
-                | hir::ItemKind::Struct(..)
-                | hir::ItemKind::Union(..)
-                | hir::ItemKind::Trait(..)
-                | hir::ItemKind::Impl { .. } => {
-                    // FIXME(66095): Because item.span is annotated with things
-                    // like expansion data, and ident.span isn't, we use the
-                    // def_span method if it's part of a macro invocation
-                    // (and thus has a source_callee set).
-                    // We should probably annotate ident.span with the macro
-                    // context, but that's a larger change.
-                    if item.span.source_callee().is_some() {
-                        self.tcx.sess.source_map().guess_head_span(item.span)
-                    } else {
-                        item.ident.span
-                    }
-                }
-                _ => item.span,
-            };
-            let participle = match item.kind {
-                hir::ItemKind::Struct(..) => "constructed", // Issue #52325
-                _ => "used",
-            };
-            self.warn_dead_code(item.hir_id(), span, item.ident.name, participle);
-        } else {
-            // Only continue if we didn't warn
-            intravisit::walk_item(self, item);
+    fn check_definition(&mut self, def_id: LocalDefId) {
+        if self.live_symbols.contains(&def_id) {
+            return;
+        }
+        let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+        if has_allow_dead_code_or_lang_attr(self.tcx, hir_id) {
+            return;
+        }
+        let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
+            return
+        };
+        if name.as_str().starts_with('_') {
+            return;
+        }
+        match self.tcx.def_kind(def_id) {
+            DefKind::AssocConst
+            | DefKind::AssocFn
+            | DefKind::Fn
+            | DefKind::Static(_)
+            | DefKind::Const
+            | DefKind::TyAlias
+            | DefKind::Enum
+            | DefKind::Union
+            | DefKind::ForeignTy => self.warn_dead_code(def_id, "used"),
+            DefKind::Struct => self.warn_dead_code(def_id, "constructed"),
+            DefKind::Variant | DefKind::Field => bug!("should be handled specially"),
+            _ => {}
         }
     }
+}
 
-    // This visitor should only visit a single module at a time.
-    fn visit_mod(&mut self, _: &'tcx hir::Mod<'tcx>, _: Span, _: hir::HirId) {}
+fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
+    let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(());
+    let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };
 
-    fn visit_enum_def(
-        &mut self,
-        enum_definition: &'tcx hir::EnumDef<'tcx>,
-        generics: &'tcx hir::Generics<'tcx>,
-        item_id: hir::HirId,
-        _: Span,
-    ) {
-        intravisit::walk_enum_def(self, enum_definition, generics, item_id);
-        let dead_variants = enum_definition
-            .variants
-            .iter()
-            .filter_map(|variant| {
-                if self.should_warn_about_variant(&variant) {
-                    Some(DeadVariant {
-                        hir_id: variant.id,
-                        span: variant.span,
-                        name: variant.ident.name,
-                        level: self.tcx.lint_level_at_node(lint::builtin::DEAD_CODE, variant.id).0,
-                    })
-                } else {
-                    None
-                }
-            })
-            .collect();
-        self.warn_dead_fields_and_variants(item_id, "constructed", dead_variants)
-    }
+    let module_items = tcx.hir_module_items(module);
 
-    fn visit_variant(
-        &mut self,
-        variant: &'tcx hir::Variant<'tcx>,
-        g: &'tcx hir::Generics<'tcx>,
-        id: hir::HirId,
-    ) {
-        if !self.should_warn_about_variant(&variant) {
-            intravisit::walk_variant(self, variant, g, id);
+    for item in module_items.items() {
+        if !live_symbols.contains(&item.def_id) {
+            let parent = tcx.local_parent(item.def_id);
+            if parent != module && !live_symbols.contains(&parent) {
+                // We already have diagnosed something.
+                continue;
+            }
+            visitor.check_definition(item.def_id);
+            continue;
         }
-    }
 
-    fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem<'tcx>) {
-        if self.should_warn_about_foreign_item(fi) {
-            self.warn_dead_code(fi.hir_id(), fi.span, fi.ident.name, "used");
-        }
-        intravisit::walk_foreign_item(self, fi);
-    }
+        let def_kind = tcx.def_kind(item.def_id);
+        if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind {
+            let adt = tcx.adt_def(item.def_id);
+            let mut dead_variants = Vec::new();
 
-    fn visit_variant_data(
-        &mut self,
-        def: &'tcx hir::VariantData<'tcx>,
-        _: Symbol,
-        _: &hir::Generics<'_>,
-        id: hir::HirId,
-        _: rustc_span::Span,
-    ) {
-        intravisit::walk_struct_def(self, def);
-        let dead_fields = def
-            .fields()
-            .iter()
-            .filter_map(|field| {
-                if self.should_warn_about_field(&field) {
-                    Some(DeadVariant {
-                        hir_id: field.hir_id,
-                        span: field.span,
-                        name: field.ident.name,
-                        level: self
-                            .tcx
-                            .lint_level_at_node(lint::builtin::DEAD_CODE, field.hir_id)
-                            .0,
-                    })
-                } else {
-                    None
+            for variant in adt.variants() {
+                let def_id = variant.def_id.expect_local();
+                if !live_symbols.contains(&def_id) {
+                    // Record to group diagnostics.
+                    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+                    let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
+                    dead_variants.push(DeadVariant { def_id, name: variant.name, level });
+                    continue;
                 }
-            })
-            .collect();
-        self.warn_dead_fields_and_variants(id, "read", dead_fields)
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
-        match impl_item.kind {
-            hir::ImplItemKind::Const(_, body_id) => {
-                if !self.symbol_is_live(impl_item.def_id) {
-                    self.warn_dead_code(
-                        impl_item.hir_id(),
-                        impl_item.span,
-                        impl_item.ident.name,
-                        "used",
-                    );
-                }
-                self.visit_nested_body(body_id)
-            }
-            hir::ImplItemKind::Fn(_, body_id) => {
-                if !self.symbol_is_live(impl_item.def_id) {
-                    // FIXME(66095): Because impl_item.span is annotated with things
-                    // like expansion data, and ident.span isn't, we use the
-                    // def_span method if it's part of a macro invocation
-                    // (and thus has a source_callee set).
-                    // We should probably annotate ident.span with the macro
-                    // context, but that's a larger change.
-                    let span = if impl_item.span.source_callee().is_some() {
-                        self.tcx.sess.source_map().guess_head_span(impl_item.span)
-                    } else {
-                        impl_item.ident.span
-                    };
-                    self.warn_dead_code(impl_item.hir_id(), span, impl_item.ident.name, "used");
-                }
-                self.visit_nested_body(body_id)
+
+                let dead_fields = variant
+                    .fields
+                    .iter()
+                    .filter_map(|field| {
+                        let def_id = field.did.expect_local();
+                        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+                        if visitor.should_warn_about_field(&field) {
+                            let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
+                            Some(DeadVariant { def_id, name: field.name, level })
+                        } else {
+                            None
+                        }
+                    })
+                    .collect();
+                visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields)
             }
-            hir::ImplItemKind::TyAlias(..) => {}
+
+            visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants);
         }
     }
 
-    // Overwrite so that we don't warn the trait item itself.
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
-        match trait_item.kind {
-            hir::TraitItemKind::Const(_, Some(body_id))
-            | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
-                self.visit_nested_body(body_id)
-            }
-            hir::TraitItemKind::Const(_, None)
-            | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
-            | hir::TraitItemKind::Type(..) => {}
-        }
+    for impl_item in module_items.impl_items() {
+        visitor.check_definition(impl_item.def_id);
     }
-}
 
-fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
-    let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(());
-    let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };
-    let (module, _, module_id) = tcx.hir().get_module(module);
-    // Do not use an ItemLikeVisitor since we may want to skip visiting some items
-    // when a surrounding one is warned against or `_`.
-    intravisit::walk_mod(&mut visitor, module, module_id);
+    for foreign_item in module_items.foreign_items() {
+        visitor.check_definition(foreign_item.def_id);
+    }
+
+    // We do not warn trait items.
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/src/test/ui/associated-consts/associated-const-dead-code.stderr b/src/test/ui/associated-consts/associated-const-dead-code.stderr
index 7a4dbfe087b..cc701cc4b94 100644
--- a/src/test/ui/associated-consts/associated-const-dead-code.stderr
+++ b/src/test/ui/associated-consts/associated-const-dead-code.stderr
@@ -1,8 +1,8 @@
 error: associated constant `BAR` is never used
-  --> $DIR/associated-const-dead-code.rs:6:5
+  --> $DIR/associated-const-dead-code.rs:6:11
    |
 LL |     const BAR: u32 = 1;
-   |     ^^^^^^^^^^^^^^^^^^^
+   |           ^^^
    |
 note: the lint level is defined here
   --> $DIR/associated-const-dead-code.rs:1:9
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr b/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr
index 57b8f7ae609..5696a010c3f 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/issue-87987.stderr
@@ -4,9 +4,9 @@ warning: fields `field_1` and `field_2` are never read
 LL | struct Props {
    |        ----- fields in this struct
 LL |     field_1: u32,
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^
 LL |     field_2: u32,
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default
 
diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr
index 4feaf3ac961..bd36a25686a 100644
--- a/src/test/ui/derive-uninhabited-enum-38885.stderr
+++ b/src/test/ui/derive-uninhabited-enum-38885.stderr
@@ -5,7 +5,7 @@ LL | enum Foo {
    |      --- variant in this enum
 LL |     Bar(u8),
 LL |     Void(Void),
-   |     ^^^^^^^^^^
+   |     ^^^^
    |
    = note: `-W dead-code` implied by `-W unused`
    = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
diff --git a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
index 383e0b4b725..baf34b46d8b 100644
--- a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
+++ b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
@@ -5,13 +5,13 @@ LL | pub struct Whatever {
    |            -------- fields in this struct
 LL |     pub field0: (),
 LL |     field1: (),
-   |     ^^^^^^^^^^
+   |     ^^^^^^
 LL |     field2: (),
-   |     ^^^^^^^^^^
+   |     ^^^^^^
 LL |     field3: (),
-   |     ^^^^^^^^^^
+   |     ^^^^^^
 LL |     field4: (),
-   |     ^^^^^^^^^^
+   |     ^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
diff --git a/src/test/ui/derives/clone-debug-dead-code.stderr b/src/test/ui/derives/clone-debug-dead-code.stderr
index 73a00251188..38be486e332 100644
--- a/src/test/ui/derives/clone-debug-dead-code.stderr
+++ b/src/test/ui/derives/clone-debug-dead-code.stderr
@@ -2,7 +2,7 @@ error: field `f` is never read
   --> $DIR/clone-debug-dead-code.rs:6:12
    |
 LL | struct A { f: () }
-   |        -   ^^^^^
+   |        -   ^
    |        |
    |        field in this struct
    |
@@ -16,7 +16,7 @@ error: field `f` is never read
   --> $DIR/clone-debug-dead-code.rs:10:12
    |
 LL | struct B { f: () }
-   |        -   ^^^^^
+   |        -   ^
    |        |
    |        field in this struct
    |
@@ -26,7 +26,7 @@ error: field `f` is never read
   --> $DIR/clone-debug-dead-code.rs:14:12
    |
 LL | struct C { f: () }
-   |        -   ^^^^^
+   |        -   ^
    |        |
    |        field in this struct
    |
@@ -36,7 +36,7 @@ error: field `f` is never read
   --> $DIR/clone-debug-dead-code.rs:18:12
    |
 LL | struct D { f: () }
-   |        -   ^^^^^
+   |        -   ^
    |        |
    |        field in this struct
    |
@@ -46,7 +46,7 @@ error: field `f` is never read
   --> $DIR/clone-debug-dead-code.rs:21:12
    |
 LL | struct E { f: () }
-   |        -   ^^^^^
+   |        -   ^
    |        |
    |        field in this struct
 
diff --git a/src/test/ui/issues/issue-37515.stderr b/src/test/ui/issues/issue-37515.stderr
index c9bb4c10010..f1e83ca74d8 100644
--- a/src/test/ui/issues/issue-37515.stderr
+++ b/src/test/ui/issues/issue-37515.stderr
@@ -1,8 +1,8 @@
 warning: type alias `Z` is never used
-  --> $DIR/issue-37515.rs:5:1
+  --> $DIR/issue-37515.rs:5:6
    |
 LL | type Z = dyn for<'x> Send;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |      ^
    |
 note: the lint level is defined here
   --> $DIR/issue-37515.rs:3:9
diff --git a/src/test/ui/lint/dead-code/impl-trait.stderr b/src/test/ui/lint/dead-code/impl-trait.stderr
index 9c47c1b5355..e35e13a9ec6 100644
--- a/src/test/ui/lint/dead-code/impl-trait.stderr
+++ b/src/test/ui/lint/dead-code/impl-trait.stderr
@@ -1,8 +1,8 @@
 error: type alias `Unused` is never used
-  --> $DIR/impl-trait.rs:12:1
+  --> $DIR/impl-trait.rs:12:6
    |
 LL | type Unused = ();
-   | ^^^^^^^^^^^^^^^^^
+   |      ^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/impl-trait.rs:1:9
diff --git a/src/test/ui/lint/dead-code/issue-85255.stderr b/src/test/ui/lint/dead-code/issue-85255.stderr
index 7ebbebb1aba..3497b952fdd 100644
--- a/src/test/ui/lint/dead-code/issue-85255.stderr
+++ b/src/test/ui/lint/dead-code/issue-85255.stderr
@@ -4,9 +4,9 @@ warning: fields `a` and `b` are never read
 LL | struct Foo {
    |        --- fields in this struct
 LL |     a: i32,
-   |     ^^^^^^
+   |     ^
 LL |     pub b: i32,
-   |     ^^^^^^^^^^
+   |         ^
    |
 note: the lint level is defined here
   --> $DIR/issue-85255.rs:4:9
@@ -14,6 +14,26 @@ note: the lint level is defined here
 LL | #![warn(dead_code)]
    |         ^^^^^^^^^
 
+warning: fields `a` and `b` are never read
+  --> $DIR/issue-85255.rs:19:5
+   |
+LL | pub(crate) struct Foo1 {
+   |                   ---- fields in this struct
+LL |     a: i32,
+   |     ^
+LL |     pub b: i32,
+   |         ^
+
+warning: fields `a` and `b` are never read
+  --> $DIR/issue-85255.rs:31:5
+   |
+LL | pub(crate) struct Foo2 {
+   |                   ---- fields in this struct
+LL |     a: i32,
+   |     ^
+LL |     pub b: i32,
+   |         ^
+
 warning: associated function `a` is never used
   --> $DIR/issue-85255.rs:14:8
    |
@@ -26,16 +46,6 @@ warning: associated function `b` is never used
 LL |     pub fn b(&self) -> i32 { 6 }
    |            ^
 
-warning: fields `a` and `b` are never read
-  --> $DIR/issue-85255.rs:19:5
-   |
-LL | pub(crate) struct Foo1 {
-   |                   ---- fields in this struct
-LL |     a: i32,
-   |     ^^^^^^
-LL |     pub b: i32,
-   |     ^^^^^^^^^^
-
 warning: associated function `a` is never used
   --> $DIR/issue-85255.rs:26:8
    |
@@ -48,16 +58,6 @@ warning: associated function `b` is never used
 LL |     pub fn b(&self) -> i32 { 6 }
    |            ^
 
-warning: fields `a` and `b` are never read
-  --> $DIR/issue-85255.rs:31:5
-   |
-LL | pub(crate) struct Foo2 {
-   |                   ---- fields in this struct
-LL |     a: i32,
-   |     ^^^^^^
-LL |     pub b: i32,
-   |     ^^^^^^^^^^
-
 warning: associated function `a` is never used
   --> $DIR/issue-85255.rs:38:8
    |
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr
index 2eddc4ce21c..eb728b5b930 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-1.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-1.stderr
@@ -1,8 +1,8 @@
 error: static `priv_static` is never used
-  --> $DIR/lint-dead-code-1.rs:20:1
+  --> $DIR/lint-dead-code-1.rs:20:8
    |
 LL | static priv_static: isize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/lint-dead-code-1.rs:5:9
@@ -11,10 +11,10 @@ LL | #![deny(dead_code)]
    |         ^^^^^^^^^
 
 error: constant `priv_const` is never used
-  --> $DIR/lint-dead-code-1.rs:27:1
+  --> $DIR/lint-dead-code-1.rs:27:7
    |
 LL | const priv_const: isize = 0;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^
 
 error: struct `PrivStruct` is never constructed
   --> $DIR/lint-dead-code-1.rs:35:8
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.rs b/src/test/ui/lint/dead-code/lint-dead-code-3.rs
index c3e56063dc3..293fcdbc5ee 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-3.rs
+++ b/src/test/ui/lint/dead-code/lint-dead-code-3.rs
@@ -73,7 +73,18 @@ mod inner {
     fn f() {}
 }
 
+fn anon_const() -> [(); {
+    fn blah() {} //~ ERROR: function `blah` is never used
+    1
+}] {
+    [(); {
+        fn blah() {} //~ ERROR: function `blah` is never used
+        1
+    }]
+}
+
 pub fn foo() {
     let a: &dyn inner::Trait = &1_isize;
     a.f();
+    anon_const();
 }
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr
index af59c6fec1f..26fc13bae08 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-3.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-3.stderr
@@ -10,12 +10,6 @@ note: the lint level is defined here
 LL | #![deny(dead_code)]
    |         ^^^^^^^^^
 
-error: associated function `foo` is never used
-  --> $DIR/lint-dead-code-3.rs:16:8
-   |
-LL |     fn foo(&self) {
-   |        ^^^
-
 error: function `bar` is never used
   --> $DIR/lint-dead-code-3.rs:21:4
    |
@@ -28,11 +22,29 @@ error: enum `c_void` is never used
 LL | enum c_void {}
    |      ^^^^^^
 
+error: function `blah` is never used
+  --> $DIR/lint-dead-code-3.rs:77:8
+   |
+LL |     fn blah() {}
+   |        ^^^^
+
+error: function `blah` is never used
+  --> $DIR/lint-dead-code-3.rs:81:12
+   |
+LL |         fn blah() {}
+   |            ^^^^
+
+error: associated function `foo` is never used
+  --> $DIR/lint-dead-code-3.rs:16:8
+   |
+LL |     fn foo(&self) {
+   |        ^^^
+
 error: function `free` is never used
-  --> $DIR/lint-dead-code-3.rs:62:5
+  --> $DIR/lint-dead-code-3.rs:62:8
    |
 LL |     fn free(p: *const c_void);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |        ^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
index dcd810b3e48..668c1dacf95 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr
@@ -5,7 +5,7 @@ LL | struct Foo {
    |        --- field in this struct
 LL |     x: usize,
 LL |     b: bool,
-   |     ^^^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/lint-dead-code-4.rs:3:9
@@ -16,16 +16,12 @@ LL | #![deny(dead_code)]
 error: variants `X` and `Y` are never constructed
   --> $DIR/lint-dead-code-4.rs:15:5
    |
-LL |   enum XYZ {
-   |        --- variants in this enum
-LL |       X,
-   |       ^
-LL | /     Y {
-LL | |         a: String,
-LL | |         b: i32,
-LL | |         c: i32,
-LL | |     },
-   | |_____^
+LL | enum XYZ {
+   |      --- variants in this enum
+LL |     X,
+   |     ^
+LL |     Y {
+   |     ^
 
 error: enum `ABC` is never used
   --> $DIR/lint-dead-code-4.rs:24:6
@@ -36,13 +32,13 @@ LL | enum ABC {
 error: fields `b` and `c` are never read
   --> $DIR/lint-dead-code-4.rs:39:9
    |
-LL | enum IJK {
-   |      --- fields in this enum
-...
+LL |     J {
+   |     - fields in this variant
+LL |         a: String,
 LL |         b: i32,
-   |         ^^^^^^
+   |         ^
 LL |         c: i32,
-   |         ^^^^^^
+   |         ^
 
 error: variants `I` and `K` are never constructed
   --> $DIR/lint-dead-code-4.rs:36:5
@@ -61,10 +57,10 @@ error: fields `x` and `c` are never read
 LL | struct Bar {
    |        --- fields in this struct
 LL |     x: usize,
-   |     ^^^^^^^^
+   |     ^
 LL |     b: bool,
 LL |     c: bool,
-   |     ^^^^^^^
+   |     ^
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr
index 037a9be22ad..eaf43e45361 100644
--- a/src/test/ui/lint/dead-code/lint-dead-code-5.stderr
+++ b/src/test/ui/lint/dead-code/lint-dead-code-5.stderr
@@ -20,9 +20,9 @@ LL | enum Enum2 {
    |      ----- variants in this enum
 ...
 LL |     Variant5 { _x: isize },
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^
 LL |     Variant6(isize),
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^
 
 error: enum `Enum3` is never used
   --> $DIR/lint-dead-code-5.rs:35:6
diff --git a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
index 5cc8e06c09d..c0f1ed38f6d 100644
--- a/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
+++ b/src/test/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
@@ -5,12 +5,12 @@ LL | struct Bar {
    |        --- fields in this struct
 ...
 LL |     d: usize,
-   |     ^^^^^^^^
+   |     ^
 ...
 LL |     f: usize,
-   |     ^^^^^^^^
+   |     ^
 LL |     g: usize,
-   |     ^^^^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/multiple-dead-codes-in-the-same-struct.rs:1:9
@@ -25,10 +25,10 @@ LL | struct Bar {
    |        --- fields in this struct
 ...
 LL |     c: usize,
-   |     ^^^^^^^^
+   |     ^
 ...
 LL |     e: usize,
-   |     ^^^^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/multiple-dead-codes-in-the-same-struct.rs:8:12
@@ -43,7 +43,7 @@ LL | struct Bar {
    |        --- field in this struct
 ...
 LL |     b: usize,
-   |     ^^^^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/multiple-dead-codes-in-the-same-struct.rs:6:14
diff --git a/src/test/ui/lint/dead-code/type-alias.stderr b/src/test/ui/lint/dead-code/type-alias.stderr
index 80c6ba962b8..446447d974a 100644
--- a/src/test/ui/lint/dead-code/type-alias.stderr
+++ b/src/test/ui/lint/dead-code/type-alias.stderr
@@ -1,8 +1,8 @@
 error: type alias `Unused` is never used
-  --> $DIR/type-alias.rs:4:1
+  --> $DIR/type-alias.rs:4:6
    |
 LL | type Unused = u8;
-   | ^^^^^^^^^^^^^^^^^
+   |      ^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/type-alias.rs:1:9
diff --git a/src/test/ui/lint/dead-code/unused-struct-variant.stderr b/src/test/ui/lint/dead-code/unused-struct-variant.stderr
index b08402b671b..d26dd3aff95 100644
--- a/src/test/ui/lint/dead-code/unused-struct-variant.stderr
+++ b/src/test/ui/lint/dead-code/unused-struct-variant.stderr
@@ -5,7 +5,7 @@ LL | enum E {
    |      - variant in this enum
 LL |     Foo(F),
 LL |     Bar(B),
-   |     ^^^^^^
+   |     ^^^
    |
 note: the lint level is defined here
   --> $DIR/unused-struct-variant.rs:1:9
diff --git a/src/test/ui/lint/issue-17718-const-naming.stderr b/src/test/ui/lint/issue-17718-const-naming.stderr
index 4c97f6d63d4..7d2aadd5f80 100644
--- a/src/test/ui/lint/issue-17718-const-naming.stderr
+++ b/src/test/ui/lint/issue-17718-const-naming.stderr
@@ -1,8 +1,8 @@
 error: constant `foo` is never used
-  --> $DIR/issue-17718-const-naming.rs:4:1
+  --> $DIR/issue-17718-const-naming.rs:4:7
    |
 LL | const foo: isize = 3;
-   | ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^
    |
 note: the lint level is defined here
   --> $DIR/issue-17718-const-naming.rs:2:9
diff --git a/src/test/ui/span/macro-span-replacement.stderr b/src/test/ui/span/macro-span-replacement.stderr
index 433d02dcbe7..5dd56342889 100644
--- a/src/test/ui/span/macro-span-replacement.stderr
+++ b/src/test/ui/span/macro-span-replacement.stderr
@@ -1,8 +1,8 @@
 warning: struct `S` is never constructed
-  --> $DIR/macro-span-replacement.rs:7:14
+  --> $DIR/macro-span-replacement.rs:7:12
    |
 LL |         $b $a;
-   |              ^
+   |            ^^
 ...
 LL |     m!(S struct);
    |     ------------ in this macro invocation
diff --git a/src/test/ui/union/union-fields-1.mirunsafeck.stderr b/src/test/ui/union/union-fields-1.mirunsafeck.stderr
index 5b932b9626c..0c9981c69fc 100644
--- a/src/test/ui/union/union-fields-1.mirunsafeck.stderr
+++ b/src/test/ui/union/union-fields-1.mirunsafeck.stderr
@@ -5,7 +5,7 @@ LL | union U1 {
    |       -- field in this union
 ...
 LL |     c: u8,
-   |     ^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/union-fields-1.rs:4:9
@@ -19,13 +19,13 @@ error: field `a` is never read
 LL | union U2 {
    |       -- field in this union
 LL |     a: u8,
-   |     ^^^^^
+   |     ^
 
 error: field `a` is never read
   --> $DIR/union-fields-1.rs:16:20
    |
 LL | union NoDropLike { a: u8 }
-   |       ----------   ^^^^^
+   |       ----------   ^
    |       |
    |       field in this union
 
@@ -36,7 +36,7 @@ LL | union U {
    |       - field in this union
 ...
 LL |     c: u8,
-   |     ^^^^^
+   |     ^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/union/union-fields-1.thirunsafeck.stderr b/src/test/ui/union/union-fields-1.thirunsafeck.stderr
index 5b932b9626c..0c9981c69fc 100644
--- a/src/test/ui/union/union-fields-1.thirunsafeck.stderr
+++ b/src/test/ui/union/union-fields-1.thirunsafeck.stderr
@@ -5,7 +5,7 @@ LL | union U1 {
    |       -- field in this union
 ...
 LL |     c: u8,
-   |     ^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/union-fields-1.rs:4:9
@@ -19,13 +19,13 @@ error: field `a` is never read
 LL | union U2 {
    |       -- field in this union
 LL |     a: u8,
-   |     ^^^^^
+   |     ^
 
 error: field `a` is never read
   --> $DIR/union-fields-1.rs:16:20
    |
 LL | union NoDropLike { a: u8 }
-   |       ----------   ^^^^^
+   |       ----------   ^
    |       |
    |       field in this union
 
@@ -36,7 +36,7 @@ LL | union U {
    |       - field in this union
 ...
 LL |     c: u8,
-   |     ^^^^^
+   |     ^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr
index f6e515f8400..6e21584c37c 100644
--- a/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr
+++ b/src/test/ui/union/union-lint-dead-code.mirunsafeck.stderr
@@ -5,7 +5,7 @@ LL | union Foo {
    |       --- field in this union
 LL |     x: usize,
 LL |     b: bool,
-   |     ^^^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/union-lint-dead-code.rs:4:9
diff --git a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr
index f6e515f8400..6e21584c37c 100644
--- a/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr
+++ b/src/test/ui/union/union-lint-dead-code.thirunsafeck.stderr
@@ -5,7 +5,7 @@ LL | union Foo {
    |       --- field in this union
 LL |     x: usize,
 LL |     b: bool,
-   |     ^^^^^^^
+   |     ^
    |
 note: the lint level is defined here
   --> $DIR/union-lint-dead-code.rs:4:9