about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-04-13 21:58:38 +0200
committerGitHub <noreply@github.com>2023-04-13 21:58:38 +0200
commit759d4e86514de200a6d335518e4e912816f12477 (patch)
tree7c7d5e7b33d0b7c097aa73ba73047c054d3de078
parente86de74c27c2721abdadc943ea5cc13f9c53b5c1 (diff)
parent2bafc0fcee7c2ef0ea8c8a8af112e07a83304f79 (diff)
downloadrust-759d4e86514de200a6d335518e4e912816f12477.tar.gz
rust-759d4e86514de200a6d335518e4e912816f12477.zip
Rollup merge of #110277 - Ezrashaw:combine-assoc-fns-dlint, r=lcnr
dead-code-lint: de-dup multiple unused assoc functions

Fixes #109600

Prior art: #97853
-rw-r--r--compiler/rustc_passes/src/dead.rs62
-rw-r--r--tests/ui/associated-consts/associated-const-dead-code.stderr2
-rw-r--r--tests/ui/lint/dead-code/issue-85255.rs12
-rw-r--r--tests/ui/lint/dead-code/issue-85255.stderr54
-rw-r--r--tests/ui/lint/dead-code/lint-dead-code-3.stderr14
-rw-r--r--tests/ui/lint/dead-code/lint-dead-code-6.rs9
-rw-r--r--tests/ui/lint/dead-code/lint-dead-code-6.stderr18
-rw-r--r--tests/ui/lint/dead-code/unused-assoc-fns.rs35
-rw-r--r--tests/ui/lint/dead-code/unused-assoc-fns.stderr29
9 files changed, 157 insertions, 78 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 91483fe3de7..5cfe691df17 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -700,6 +700,13 @@ impl<'tcx> DeadVisitor<'tcx> {
             .collect();
 
         let descr = tcx.def_descr(first_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) {
+            "associated item"
+        } else {
+            descr
+        };
         let num = dead_codes.len();
         let multiple = num > 6;
         let name_list = names.into();
@@ -712,12 +719,12 @@ impl<'tcx> DeadVisitor<'tcx> {
 
         let parent_info = if let Some(parent_item) = parent_item {
             let parent_descr = tcx.def_descr(parent_item.to_def_id());
-            Some(ParentInfo {
-                num,
-                descr,
-                parent_descr,
-                span: tcx.def_ident_span(parent_item).unwrap(),
-            })
+            let span = if let DefKind::Impl { .. } = tcx.def_kind(parent_item) {
+                tcx.def_span(parent_item)
+            } else {
+                tcx.def_ident_span(parent_item).unwrap()
+            };
+            Some(ParentInfo { num, descr, parent_descr, span })
         } else {
             None
         };
@@ -800,16 +807,7 @@ impl<'tcx> DeadVisitor<'tcx> {
     }
 
     fn check_definition(&mut self, def_id: LocalDefId) {
-        if self.live_symbols.contains(&def_id) {
-            return;
-        }
-        if has_allow_dead_code_or_lang_attr(self.tcx, def_id) {
-            return;
-        }
-        let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
-            return
-        };
-        if name.as_str().starts_with('_') {
+        if self.is_live_code(def_id) {
             return;
         }
         match self.tcx.def_kind(def_id) {
@@ -827,6 +825,18 @@ impl<'tcx> DeadVisitor<'tcx> {
             _ => {}
         }
     }
+
+    fn is_live_code(&self, def_id: LocalDefId) -> bool {
+        // if we cannot get a name for the item, then we just assume that it is
+        // live. I mean, we can't really emit a lint.
+        let Some(name) = self.tcx.opt_item_name(def_id.to_def_id()) else {
+            return true;
+        };
+
+        self.live_symbols.contains(&def_id)
+            || has_allow_dead_code_or_lang_attr(self.tcx, def_id)
+            || name.as_str().starts_with('_')
+    }
 }
 
 fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
@@ -836,6 +846,22 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
     let module_items = tcx.hir_module_items(module);
 
     for item in module_items.items() {
+        if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind {
+            let mut dead_items = Vec::new();
+            for item in impl_item.items {
+                let did = item.id.owner_id.def_id;
+                if !visitor.is_live_code(did) {
+                    dead_items.push(did)
+                }
+            }
+            visitor.warn_multiple_dead_codes(
+                &dead_items,
+                "used",
+                Some(item.owner_id.def_id),
+                false,
+            );
+        }
+
         if !live_symbols.contains(&item.owner_id.def_id) {
             let parent = tcx.local_parent(item.owner_id.def_id);
             if parent != module && !live_symbols.contains(&parent) {
@@ -900,10 +926,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
         }
     }
 
-    for impl_item in module_items.impl_items() {
-        visitor.check_definition(impl_item.owner_id.def_id);
-    }
-
     for foreign_item in module_items.foreign_items() {
         visitor.check_definition(foreign_item.owner_id.def_id);
     }
diff --git a/tests/ui/associated-consts/associated-const-dead-code.stderr b/tests/ui/associated-consts/associated-const-dead-code.stderr
index cc701cc4b94..7e485a314c5 100644
--- a/tests/ui/associated-consts/associated-const-dead-code.stderr
+++ b/tests/ui/associated-consts/associated-const-dead-code.stderr
@@ -1,6 +1,8 @@
 error: associated constant `BAR` is never used
   --> $DIR/associated-const-dead-code.rs:6:11
    |
+LL | impl MyFoo {
+   | ---------- associated constant in this implementation
 LL |     const BAR: u32 = 1;
    |           ^^^
    |
diff --git a/tests/ui/lint/dead-code/issue-85255.rs b/tests/ui/lint/dead-code/issue-85255.rs
index 1978bd4e824..d75a8e2dd41 100644
--- a/tests/ui/lint/dead-code/issue-85255.rs
+++ b/tests/ui/lint/dead-code/issue-85255.rs
@@ -11,8 +11,8 @@ struct Foo {
 struct Bar;
 
 impl Bar {
-    fn a(&self) -> i32 { 5 } //~ WARNING: method `a` is never used
-    pub fn b(&self) -> i32 { 6 } //~ WARNING: method `b` is never used
+    fn a(&self) -> i32 { 5 } //~ WARNING: methods `a` and `b` are never used [dead_code]
+    pub fn b(&self) -> i32 { 6 }
 }
 
 pub(crate) struct Foo1 {
@@ -23,8 +23,8 @@ pub(crate) struct Foo1 {
 pub(crate) struct Bar1;
 
 impl Bar1 {
-    fn a(&self) -> i32 { 5 } //~ WARNING: method `a` is never used
-    pub fn b(&self) -> i32 { 6 } //~ WARNING: method `b` is never used
+    fn a(&self) -> i32 { 5 } //~ WARNING: methods `a` and `b` are never used [dead_code]
+    pub fn b(&self) -> i32 { 6 }
 }
 
 pub(crate) struct Foo2 {
@@ -35,8 +35,8 @@ pub(crate) struct Foo2 {
 pub(crate) struct Bar2;
 
 impl Bar2 {
-    fn a(&self) -> i32 { 5 } //~ WARNING: method `a` is never used
-    pub fn b(&self) -> i32 { 6 } //~ WARNING: method `b` is never used
+    fn a(&self) -> i32 { 5 } //~ WARNING: methods `a` and `b` are never used [dead_code]
+    pub fn b(&self) -> i32 { 6 }
 }
 
 
diff --git a/tests/ui/lint/dead-code/issue-85255.stderr b/tests/ui/lint/dead-code/issue-85255.stderr
index 58a19cf3c99..d981085a4fa 100644
--- a/tests/ui/lint/dead-code/issue-85255.stderr
+++ b/tests/ui/lint/dead-code/issue-85255.stderr
@@ -14,6 +14,16 @@ note: the lint level is defined here
 LL | #![warn(dead_code)]
    |         ^^^^^^^^^
 
+warning: methods `a` and `b` are never used
+  --> $DIR/issue-85255.rs:14:8
+   |
+LL | impl Bar {
+   | -------- methods in this implementation
+LL |     fn a(&self) -> i32 { 5 }
+   |        ^
+LL |     pub fn b(&self) -> i32 { 6 }
+   |            ^
+
 warning: fields `a` and `b` are never read
   --> $DIR/issue-85255.rs:19:5
    |
@@ -24,6 +34,16 @@ LL |     a: i32,
 LL |     pub b: i32,
    |         ^
 
+warning: methods `a` and `b` are never used
+  --> $DIR/issue-85255.rs:26:8
+   |
+LL | impl Bar1 {
+   | --------- methods in this implementation
+LL |     fn a(&self) -> i32 { 5 }
+   |        ^
+LL |     pub fn b(&self) -> i32 { 6 }
+   |            ^
+
 warning: fields `a` and `b` are never read
   --> $DIR/issue-85255.rs:31:5
    |
@@ -34,41 +54,15 @@ LL |     a: i32,
 LL |     pub b: i32,
    |         ^
 
-warning: method `a` is never used
-  --> $DIR/issue-85255.rs:14:8
-   |
-LL |     fn a(&self) -> i32 { 5 }
-   |        ^
-
-warning: method `b` is never used
-  --> $DIR/issue-85255.rs:15:12
-   |
-LL |     pub fn b(&self) -> i32 { 6 }
-   |            ^
-
-warning: method `a` is never used
-  --> $DIR/issue-85255.rs:26:8
-   |
-LL |     fn a(&self) -> i32 { 5 }
-   |        ^
-
-warning: method `b` is never used
-  --> $DIR/issue-85255.rs:27:12
-   |
-LL |     pub fn b(&self) -> i32 { 6 }
-   |            ^
-
-warning: method `a` is never used
+warning: methods `a` and `b` are never used
   --> $DIR/issue-85255.rs:38:8
    |
+LL | impl Bar2 {
+   | --------- methods in this implementation
 LL |     fn a(&self) -> i32 { 5 }
    |        ^
-
-warning: method `b` is never used
-  --> $DIR/issue-85255.rs:39:12
-   |
 LL |     pub fn b(&self) -> i32 { 6 }
    |            ^
 
-warning: 9 warnings emitted
+warning: 6 warnings emitted
 
diff --git a/tests/ui/lint/dead-code/lint-dead-code-3.stderr b/tests/ui/lint/dead-code/lint-dead-code-3.stderr
index 797b7559c01..5c68cf0e18b 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-3.stderr
+++ b/tests/ui/lint/dead-code/lint-dead-code-3.stderr
@@ -10,6 +10,14 @@ note: the lint level is defined here
 LL | #![deny(dead_code)]
    |         ^^^^^^^^^
 
+error: method `foo` is never used
+  --> $DIR/lint-dead-code-3.rs:16:8
+   |
+LL | impl Foo {
+   | -------- method in this implementation
+LL |     fn foo(&self) {
+   |        ^^^
+
 error: function `bar` is never used
   --> $DIR/lint-dead-code-3.rs:21:4
    |
@@ -34,12 +42,6 @@ error: function `blah` is never used
 LL |         fn blah() {}
    |            ^^^^
 
-error: method `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:8
    |
diff --git a/tests/ui/lint/dead-code/lint-dead-code-6.rs b/tests/ui/lint/dead-code/lint-dead-code-6.rs
index e3074acf129..5b2b76b76ec 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-6.rs
+++ b/tests/ui/lint/dead-code/lint-dead-code-6.rs
@@ -2,17 +2,16 @@
 
 struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed
 impl UnusedStruct {
-    fn unused_impl_fn_1() { //~ ERROR associated function `unused_impl_fn_1` is never used
+    fn unused_impl_fn_1() {
+        //~^ ERROR associated functions `unused_impl_fn_1`, `unused_impl_fn_2`, and `unused_impl_fn_3` are never used [dead_code]
         println!("blah");
     }
 
-    fn unused_impl_fn_2(var: i32) { //~ ERROR associated function `unused_impl_fn_2` is never used
+    fn unused_impl_fn_2(var: i32) {
         println!("foo {}", var);
     }
 
-    fn unused_impl_fn_3( //~ ERROR associated function `unused_impl_fn_3` is never used
-        var: i32,
-    ) {
+    fn unused_impl_fn_3(var: i32) {
         println!("bar {}", var);
     }
 }
diff --git a/tests/ui/lint/dead-code/lint-dead-code-6.stderr b/tests/ui/lint/dead-code/lint-dead-code-6.stderr
index f9d83308a3d..ce41100866a 100644
--- a/tests/ui/lint/dead-code/lint-dead-code-6.stderr
+++ b/tests/ui/lint/dead-code/lint-dead-code-6.stderr
@@ -10,23 +10,19 @@ note: the lint level is defined here
 LL | #![deny(dead_code)]
    |         ^^^^^^^^^
 
-error: associated function `unused_impl_fn_1` is never used
+error: associated functions `unused_impl_fn_1`, `unused_impl_fn_2`, and `unused_impl_fn_3` are never used
   --> $DIR/lint-dead-code-6.rs:5:8
    |
+LL | impl UnusedStruct {
+   | ----------------- associated functions in this implementation
 LL |     fn unused_impl_fn_1() {
    |        ^^^^^^^^^^^^^^^^
-
-error: associated function `unused_impl_fn_2` is never used
-  --> $DIR/lint-dead-code-6.rs:9:8
-   |
+...
 LL |     fn unused_impl_fn_2(var: i32) {
    |        ^^^^^^^^^^^^^^^^
-
-error: associated function `unused_impl_fn_3` is never used
-  --> $DIR/lint-dead-code-6.rs:13:8
-   |
-LL |     fn unused_impl_fn_3(
+...
+LL |     fn unused_impl_fn_3(var: i32) {
    |        ^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/dead-code/unused-assoc-fns.rs b/tests/ui/lint/dead-code/unused-assoc-fns.rs
new file mode 100644
index 00000000000..b111f4b9463
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-assoc-fns.rs
@@ -0,0 +1,35 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+#![deny(unused)]
+
+struct Foo;
+
+impl Foo {
+    fn one() {}
+    //~^ ERROR associated items `one`, `two`, `CONSTANT`, `Type`, and `three` are never used [dead_code]
+
+    fn two(&self) {}
+
+    // seperation between items
+    // ...
+    // ...
+
+    fn used() {}
+
+    const CONSTANT: usize = 5;
+
+    // more seperation
+    // ...
+    // ...
+
+    type Type = usize;
+
+    fn three(&self) {
+        Foo::one();
+        // ...
+    }
+}
+
+fn main() {
+    Foo::used();
+}
diff --git a/tests/ui/lint/dead-code/unused-assoc-fns.stderr b/tests/ui/lint/dead-code/unused-assoc-fns.stderr
new file mode 100644
index 00000000000..6344a70ea3a
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-assoc-fns.stderr
@@ -0,0 +1,29 @@
+error: associated items `one`, `two`, `CONSTANT`, `Type`, and `three` are never used
+  --> $DIR/unused-assoc-fns.rs:8:8
+   |
+LL | impl Foo {
+   | -------- associated items in this implementation
+LL |     fn one() {}
+   |        ^^^
+...
+LL |     fn two(&self) {}
+   |        ^^^
+...
+LL |     const CONSTANT: usize = 5;
+   |           ^^^^^^^^
+...
+LL |     type Type = usize;
+   |          ^^^^
+LL |
+LL |     fn three(&self) {
+   |        ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-assoc-fns.rs:3:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: `#[deny(dead_code)]` implied by `#[deny(unused)]`
+
+error: aborting due to previous error
+