about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-12-25 13:14:12 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-12-25 13:15:28 +0000
commit8bb74c0187482f92cd1347d670d5680a457c37a9 (patch)
tree3486e682a3d4e41d3b616107c240b168e096491f
parent08cc634f1a26f30801daa1cbe7b866b12aaf1edd (diff)
downloadrust-8bb74c0187482f92cd1347d670d5680a457c37a9.tar.gz
rust-8bb74c0187482f92cd1347d670d5680a457c37a9.zip
Pass DeadItem and lint as consistent group in dead-code.
-rw-r--r--compiler/rustc_passes/src/dead.rs107
-rw-r--r--compiler/rustc_passes/src/lib.rs1
-rw-r--r--tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs4
3 files changed, 50 insertions, 62 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index d270794978b..22aac1e775e 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -4,7 +4,6 @@
 // is dead.
 
 use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
-use itertools::Itertools;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::MultiSpan;
 use rustc_hir as hir;
@@ -16,7 +15,8 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::lint;
+use rustc_session::lint::builtin::{DEAD_CODE, UNUSED_TUPLE_STRUCT_FIELDS};
+use rustc_session::lint::{self, Lint, LintId};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::FieldIdx;
 use std::mem;
@@ -762,7 +762,7 @@ struct DeadVisitor<'tcx> {
 }
 
 enum ShouldWarnAboutField {
-    Yes(bool), // positional?
+    Yes,
     No,
 }
 
@@ -784,7 +784,12 @@ impl<'tcx> DeadVisitor<'tcx> {
         {
             return ShouldWarnAboutField::No;
         }
-        ShouldWarnAboutField::Yes(is_positional)
+        ShouldWarnAboutField::Yes
+    }
+
+    fn def_lint_level(&self, lint: &'static Lint, id: LocalDefId) -> lint::Level {
+        let hir_id = self.tcx.local_def_id_to_hir_id(id);
+        self.tcx.lint_level_at_node(lint, hir_id).0
     }
 
     // # Panics
@@ -795,38 +800,33 @@ impl<'tcx> DeadVisitor<'tcx> {
     // since those methods group by lint level before calling this method.
     fn lint_at_single_level(
         &self,
-        dead_codes: &[LocalDefId],
+        dead_codes: &[&DeadItem],
         participle: &str,
         parent_item: Option<LocalDefId>,
-        is_positional: bool,
+        lint: &'static Lint,
     ) {
-        let Some(&first_id) = dead_codes.first() else {
+        let Some(&first_item) = dead_codes.first() else {
             return;
         };
         let tcx = self.tcx;
 
-        let first_hir_id = tcx.local_def_id_to_hir_id(first_id);
-        let first_lint_level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, first_hir_id).0;
-        assert!(dead_codes.iter().skip(1).all(|id| {
-            let hir_id = tcx.local_def_id_to_hir_id(*id);
-            let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
-            level == first_lint_level
-        }));
+        let first_lint_level = first_item.level;
+        assert!(dead_codes.iter().skip(1).all(|item| item.level == first_lint_level));
 
-        let names: Vec<_> =
-            dead_codes.iter().map(|&def_id| tcx.item_name(def_id.to_def_id())).collect();
+        let names: Vec<_> = dead_codes.iter().map(|item| item.name).collect();
         let spans: Vec<_> = 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),
+            .map(|item| match tcx.def_ident_span(item.def_id) {
+                Some(s) => s.with_ctxt(tcx.def_span(item.def_id).ctxt()),
+                None => tcx.def_span(item.def_id),
             })
             .collect();
 
-        let descr = tcx.def_descr(first_id.to_def_id());
+        let descr = tcx.def_descr(first_item.def_id.to_def_id());
         // `impl` blocks are "batched" and (unlike other batching) might
         // contain different kinds of associated items.
-        let descr = if dead_codes.iter().any(|did| tcx.def_descr(did.to_def_id()) != descr) {
+        let descr = if dead_codes.iter().any(|item| tcx.def_descr(item.def_id.to_def_id()) != descr)
+        {
             "associated item"
         } else {
             descr
@@ -835,12 +835,6 @@ impl<'tcx> DeadVisitor<'tcx> {
         let multiple = num > 6;
         let name_list = names.into();
 
-        let lint = if is_positional {
-            lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
-        } else {
-            lint::builtin::DEAD_CODE
-        };
-
         let parent_info = if let Some(parent_item) = parent_item {
             let parent_descr = tcx.def_descr(parent_item.to_def_id());
             let span = if let DefKind::Impl { .. } = tcx.def_kind(parent_item) {
@@ -853,7 +847,7 @@ impl<'tcx> DeadVisitor<'tcx> {
             None
         };
 
-        let encl_def_id = parent_item.unwrap_or(first_id);
+        let encl_def_id = parent_item.unwrap_or(first_item.def_id);
         let ignored_derived_impls =
             if let Some(ign_traits) = self.ignored_derived_traits.get(&encl_def_id) {
                 let trait_list = ign_traits
@@ -870,7 +864,7 @@ impl<'tcx> DeadVisitor<'tcx> {
                 None
             };
 
-        let diag = if is_positional {
+        let diag = if LintId::of(lint) == LintId::of(UNUSED_TUPLE_STRUCT_FIELDS) {
             MultipleDeadCodes::UnusedTupleStructFields {
                 multiple,
                 num,
@@ -893,7 +887,8 @@ impl<'tcx> DeadVisitor<'tcx> {
             }
         };
 
-        self.tcx.emit_spanned_lint(lint, first_hir_id, MultiSpan::from_spans(spans), diag);
+        let hir_id = tcx.local_def_id_to_hir_id(first_item.def_id);
+        self.tcx.emit_spanned_lint(lint, hir_id, MultiSpan::from_spans(spans), diag);
     }
 
     fn warn_multiple(
@@ -901,7 +896,7 @@ impl<'tcx> DeadVisitor<'tcx> {
         def_id: LocalDefId,
         participle: &str,
         dead_codes: Vec<DeadItem>,
-        is_positional: bool,
+        lint: &'static Lint,
     ) {
         let mut dead_codes = dead_codes
             .iter()
@@ -911,18 +906,18 @@ impl<'tcx> DeadVisitor<'tcx> {
             return;
         }
         dead_codes.sort_by_key(|v| v.level);
-        for (_, group) in &dead_codes.into_iter().group_by(|v| v.level) {
-            self.lint_at_single_level(
-                &group.map(|v| v.def_id).collect::<Vec<_>>(),
-                participle,
-                Some(def_id),
-                is_positional,
-            );
+        for group in dead_codes[..].group_by(|a, b| a.level == b.level) {
+            self.lint_at_single_level(&group, participle, Some(def_id), lint);
         }
     }
 
     fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) {
-        self.lint_at_single_level(&[id], participle, None, false);
+        let item = DeadItem {
+            def_id: id,
+            name: self.tcx.item_name(id.to_def_id()),
+            level: self.def_lint_level(DEAD_CODE, id),
+        };
+        self.lint_at_single_level(&[&item], participle, None, DEAD_CODE);
     }
 
     fn check_definition(&mut self, def_id: LocalDefId) {
@@ -969,13 +964,12 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
                 let def_id = item.id.owner_id.def_id;
                 if !visitor.is_live_code(def_id) {
                     let name = tcx.item_name(def_id.to_def_id());
-                    let hir_id = tcx.local_def_id_to_hir_id(def_id);
-                    let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
+                    let level = visitor.def_lint_level(DEAD_CODE, def_id);
 
                     dead_items.push(DeadItem { def_id, name, level })
                 }
             }
-            visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, false);
+            visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, DEAD_CODE);
         }
 
         if !live_symbols.contains(&item.owner_id.def_id) {
@@ -997,43 +991,32 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
                 let def_id = variant.def_id.expect_local();
                 if !live_symbols.contains(&def_id) {
                     // Record to group diagnostics.
-                    let hir_id = tcx.local_def_id_to_hir_id(def_id);
-                    let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
+                    let level = visitor.def_lint_level(DEAD_CODE, def_id);
                     dead_variants.push(DeadItem { def_id, name: variant.name, level });
                     continue;
                 }
 
-                let mut is_positional = false;
+                let is_positional = variant.fields.raw.first().map_or(false, |field| {
+                    field.name.as_str().starts_with(|c: char| c.is_ascii_digit())
+                });
+                let lint = if is_positional { UNUSED_TUPLE_STRUCT_FIELDS } else { DEAD_CODE };
                 let dead_fields = variant
                     .fields
                     .iter()
                     .filter_map(|field| {
                         let def_id = field.did.expect_local();
-                        let hir_id = tcx.local_def_id_to_hir_id(def_id);
-                        if let ShouldWarnAboutField::Yes(is_pos) =
-                            visitor.should_warn_about_field(field)
-                        {
-                            let level = tcx
-                                .lint_level_at_node(
-                                    if is_pos {
-                                        is_positional = true;
-                                        lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
-                                    } else {
-                                        lint::builtin::DEAD_CODE
-                                    },
-                                    hir_id,
-                                )
-                                .0;
+                        if let ShouldWarnAboutField::Yes = visitor.should_warn_about_field(field) {
+                            let level = visitor.def_lint_level(lint, def_id);
                             Some(DeadItem { def_id, name: field.name, level })
                         } else {
                             None
                         }
                     })
                     .collect();
-                visitor.warn_multiple(def_id, "read", dead_fields, is_positional);
+                visitor.warn_multiple(def_id, "read", dead_fields, lint);
             }
 
-            visitor.warn_multiple(item.owner_id.def_id, "constructed", dead_variants, false);
+            visitor.warn_multiple(item.owner_id.def_id, "constructed", dead_variants, DEAD_CODE);
         }
     }
 
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index c969867e871..bb33a4feb05 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -12,6 +12,7 @@
 #![feature(let_chains)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
+#![feature(slice_group_by)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs
index 2003e1e293a..a478153b3f4 100644
--- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs
+++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs
@@ -15,6 +15,10 @@ struct Bar {
     _h: usize,
 }
 
+// Issue 119267: this should not ICE.
+#[derive(Debug)]
+struct Foo(usize, #[allow(unused)] usize);
+
 fn main() {
     Bar {
         a: 1,