Skip to content

Commit 05de59d

Browse files
committed
Auto merge of rust-lang#118257 - mu001999:dead_code/trait, r=cjgillot
Make traits / trait methods detected by the dead code lint Fixes rust-lang#118139 and rust-lang#41883
2 parents 867d39c + e68bffe commit 05de59d

File tree

269 files changed

+1167
-250
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

269 files changed

+1167
-250
lines changed

compiler/rustc_passes/src/dead.rs

+71-20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// is dead.
55

66
use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
7+
use hir::ItemKind;
78
use rustc_data_structures::unord::UnordSet;
89
use rustc_errors::MultiSpan;
910
use rustc_hir as hir;
@@ -14,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
1415
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1516
use rustc_middle::middle::privacy::Level;
1617
use rustc_middle::query::Providers;
17-
use rustc_middle::ty::{self, TyCtxt};
18+
use rustc_middle::ty::{self, TyCtxt, Visibility};
1819
use rustc_session::lint;
1920
use rustc_session::lint::builtin::DEAD_CODE;
2021
use rustc_span::symbol::{sym, Symbol};
@@ -381,9 +382,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
381382
intravisit::walk_item(self, item)
382383
}
383384
hir::ItemKind::ForeignMod { .. } => {}
385+
hir::ItemKind::Trait(..) => {
386+
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
387+
if let Some(local_def_id) = impl_def_id.as_local()
388+
&& let ItemKind::Impl(impl_ref) =
389+
self.tcx.hir().expect_item(local_def_id).kind
390+
{
391+
// skip items
392+
// mark dependent traits live
393+
intravisit::walk_generics(self, impl_ref.generics);
394+
// mark dependent parameters live
395+
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
396+
}
397+
}
398+
399+
intravisit::walk_item(self, item)
400+
}
384401
_ => intravisit::walk_item(self, item),
385402
},
386403
Node::TraitItem(trait_item) => {
404+
// mark corresponing ImplTerm live
405+
let trait_item_id = trait_item.owner_id.to_def_id();
406+
if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) {
407+
// mark the trait live
408+
self.check_def_id(trait_id);
409+
410+
for impl_id in self.tcx.all_impls(trait_id) {
411+
if let Some(local_impl_id) = impl_id.as_local()
412+
&& let ItemKind::Impl(impl_ref) =
413+
self.tcx.hir().expect_item(local_impl_id).kind
414+
{
415+
// mark self_ty live
416+
intravisit::walk_ty(self, impl_ref.self_ty);
417+
if let Some(&impl_item_id) =
418+
self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id)
419+
{
420+
self.check_def_id(impl_item_id);
421+
}
422+
}
423+
}
424+
}
387425
intravisit::walk_trait_item(self, trait_item);
388426
}
389427
Node::ImplItem(impl_item) => {
@@ -632,10 +670,6 @@ fn check_item<'tcx>(
632670
}
633671
}
634672
DefKind::Impl { of_trait } => {
635-
if of_trait {
636-
worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No));
637-
}
638-
639673
// get DefIds from another query
640674
let local_def_ids = tcx
641675
.associated_item_def_ids(id.owner_id)
@@ -644,7 +678,11 @@ fn check_item<'tcx>(
644678

645679
// And we access the Map here to get HirId from LocalDefId
646680
for id in local_def_ids {
647-
if of_trait {
681+
// for impl trait blocks, mark associate functions live if the trait is public
682+
if of_trait
683+
&& (!matches!(tcx.def_kind(id), DefKind::AssocFn)
684+
|| tcx.local_visibility(id) == Visibility::Public)
685+
{
648686
worklist.push((id, ComesFromAllowExpect::No));
649687
} else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) {
650688
worklist.push((id, comes_from_allow));
@@ -675,7 +713,7 @@ fn check_trait_item(
675713
use hir::TraitItemKind::{Const, Fn};
676714
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
677715
let trait_item = tcx.hir().trait_item(id);
678-
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_)))
716+
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
679717
&& let Some(comes_from_allow) =
680718
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
681719
{
@@ -944,7 +982,8 @@ impl<'tcx> DeadVisitor<'tcx> {
944982
| DefKind::TyAlias
945983
| DefKind::Enum
946984
| DefKind::Union
947-
| DefKind::ForeignTy => self.warn_dead_code(def_id, "used"),
985+
| DefKind::ForeignTy
986+
| DefKind::Trait => self.warn_dead_code(def_id, "used"),
948987
DefKind::Struct => self.warn_dead_code(def_id, "constructed"),
949988
DefKind::Variant | DefKind::Field => bug!("should be handled specially"),
950989
_ => {}
@@ -969,18 +1008,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9691008
let module_items = tcx.hir_module_items(module);
9701009

9711010
for item in module_items.items() {
972-
if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind {
973-
let mut dead_items = Vec::new();
974-
for item in impl_item.items {
975-
let def_id = item.id.owner_id.def_id;
976-
if !visitor.is_live_code(def_id) {
977-
let name = tcx.item_name(def_id.to_def_id());
978-
let level = visitor.def_lint_level(def_id);
1011+
let def_kind = tcx.def_kind(item.owner_id);
9791012

980-
dead_items.push(DeadItem { def_id, name, level })
1013+
let mut dead_codes = Vec::new();
1014+
// if we have diagnosed the trait, do not diagnose unused methods
1015+
if matches!(def_kind, DefKind::Impl { .. })
1016+
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
1017+
{
1018+
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
1019+
// We have diagnosed unused methods in traits
1020+
if matches!(def_kind, DefKind::Impl { of_trait: true })
1021+
&& tcx.def_kind(def_id) == DefKind::AssocFn
1022+
|| def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn
1023+
{
1024+
continue;
1025+
}
1026+
1027+
if let Some(local_def_id) = def_id.as_local()
1028+
&& !visitor.is_live_code(local_def_id)
1029+
{
1030+
let name = tcx.item_name(def_id);
1031+
let level = visitor.def_lint_level(local_def_id);
1032+
dead_codes.push(DeadItem { def_id: local_def_id, name, level });
9811033
}
9821034
}
983-
visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, ReportOn::NamedField);
1035+
}
1036+
if !dead_codes.is_empty() {
1037+
visitor.warn_multiple(item.owner_id.def_id, "used", dead_codes, ReportOn::NamedField);
9841038
}
9851039

9861040
if !live_symbols.contains(&item.owner_id.def_id) {
@@ -993,7 +1047,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9931047
continue;
9941048
}
9951049

996-
let def_kind = tcx.def_kind(item.owner_id);
9971050
if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind {
9981051
let adt = tcx.adt_def(item.owner_id);
9991052
let mut dead_variants = Vec::new();
@@ -1040,8 +1093,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
10401093
for foreign_item in module_items.foreign_items() {
10411094
visitor.check_definition(foreign_item.owner_id.def_id);
10421095
}
1043-
1044-
// We do not warn trait items.
10451096
}
10461097

10471098
pub(crate) fn provide(providers: &mut Providers) {

compiler/rustc_span/src/source_map/tests.rs

+2-47
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::*;
22

3+
use rustc_data_structures::sync::FreezeLock;
4+
35
fn init_source_map() -> SourceMap {
46
let sm = SourceMap::new(FilePathMapping::empty());
57
sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string());
@@ -263,53 +265,6 @@ fn t10() {
263265
);
264266
}
265267

266-
/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`.
267-
trait SourceMapExtension {
268-
fn span_substr(
269-
&self,
270-
file: &Lrc<SourceFile>,
271-
source_text: &str,
272-
substring: &str,
273-
n: usize,
274-
) -> Span;
275-
}
276-
277-
impl SourceMapExtension for SourceMap {
278-
fn span_substr(
279-
&self,
280-
file: &Lrc<SourceFile>,
281-
source_text: &str,
282-
substring: &str,
283-
n: usize,
284-
) -> Span {
285-
eprintln!(
286-
"span_substr(file={:?}/{:?}, substring={:?}, n={})",
287-
file.name, file.start_pos, substring, n
288-
);
289-
let mut i = 0;
290-
let mut hi = 0;
291-
loop {
292-
let offset = source_text[hi..].find(substring).unwrap_or_else(|| {
293-
panic!(
294-
"source_text `{}` does not have {} occurrences of `{}`, only {}",
295-
source_text, n, substring, i
296-
);
297-
});
298-
let lo = hi + offset;
299-
hi = lo + substring.len();
300-
if i == n {
301-
let span = Span::with_root_ctxt(
302-
BytePos(lo as u32 + file.start_pos.0),
303-
BytePos(hi as u32 + file.start_pos.0),
304-
);
305-
assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring);
306-
return span;
307-
}
308-
i += 1;
309-
}
310-
}
311-
}
312-
313268
// Takes a unix-style path and returns a platform specific path.
314269
fn path(p: &str) -> PathBuf {
315270
path_str(p).into()

library/core/tests/macros.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[allow(dead_code)]
12
trait Trait {
23
fn blah(&self);
34
}

src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
trait T1 {
2+
#[allow(dead_code)]
23
fn method1(self: Box<Self>);
34
}
45
trait T2 {

src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
2+
#[allow(dead_code)]
23
fn a(&self) -> i32 {
34
10
45
}
56

7+
#[allow(dead_code)]
68
fn z(&self) -> i32 {
79
11
810
}
911

12+
#[allow(dead_code)]
1013
fn y(&self) -> i32 {
1114
12
1215
}
1316
}
1417

1518
trait Bar: Foo {
19+
#[allow(dead_code)]
1620
fn b(&self) -> i32 {
1721
20
1822
}
1923

24+
#[allow(dead_code)]
2025
fn w(&self) -> i32 {
2126
21
2227
}
2328
}
2429

2530
trait Baz: Bar {
31+
#[allow(dead_code)]
2632
fn c(&self) -> i32 {
2733
30
2834
}

src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ trait Foo<T> {
99
}
1010
}
1111

12+
#[allow(dead_code)]
1213
trait Bar {
1314
fn bar(&self) {
1415
println!("Bar!");

src/tools/miri/tests/pass/dyn-upcast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -380,14 +380,17 @@ fn struct_() {
380380

381381
fn replace_vptr() {
382382
trait A {
383+
#[allow(dead_code)]
383384
fn foo_a(&self);
384385
}
385386

386387
trait B {
388+
#[allow(dead_code)]
387389
fn foo_b(&self);
388390
}
389391

390392
trait C: A + B {
393+
#[allow(dead_code)]
391394
fn foo_c(&self);
392395
}
393396

src/tools/miri/tests/pass/weak_memory/weak.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::sync::atomic::Ordering::*;
1111
use std::sync::atomic::{fence, AtomicUsize};
1212
use std::thread::spawn;
1313

14+
#[allow(dead_code)]
1415
#[derive(Copy, Clone)]
1516
struct EvilSend<T>(pub T);
1617

src/tools/tidy/src/ui_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use std::path::{Path, PathBuf};
1010

1111
const ENTRY_LIMIT: usize = 900;
1212
// FIXME: The following limits should be reduced eventually.
13-
const ISSUES_ENTRY_LIMIT: usize = 1849;
14-
const ROOT_ENTRY_LIMIT: usize = 870;
13+
const ISSUES_ENTRY_LIMIT: usize = 1861;
14+
const ROOT_ENTRY_LIMIT: usize = 872;
1515

1616
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
1717
"rs", // test source files

tests/codegen-units/item-collection/instantiation-through-vtable.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ fn start(_: isize, _: *const *const u8) -> isize {
2626
//~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u32>> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal]
2727
//~ MONO_ITEM fn <Struct<u32> as Trait>::foo
2828
//~ MONO_ITEM fn <Struct<u32> as Trait>::bar
29-
let _ = &s1 as &Trait;
29+
let r1 = &s1 as &Trait;
30+
r1.foo();
31+
r1.bar();
3032

3133
let s1 = Struct { _a: 0u64 };
3234
//~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u64>> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal]

tests/codegen-units/item-collection/trait-method-default-impl.rs

+3
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,8 @@ fn start(_: isize, _: *const *const u8) -> isize {
5757
//~ MONO_ITEM fn <u32 as SomeGenericTrait<i16>>::bar::<()>
5858
0u32.bar(0i16, ());
5959

60+
0i8.foo();
61+
0i32.foo();
62+
6063
0
6164
}

tests/codegen-units/item-collection/unsizing.rs

+2
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,7 @@ fn start(_: isize, _: *const *const u8) -> isize {
7575
//~ MONO_ITEM fn <u32 as Trait>::foo
7676
let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
7777

78+
false.foo();
79+
7880
0
7981
}

tests/ui-fulldeps/rustc_encodable_hygiene.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// run-pass
1+
// check-pass
22

33
#![feature(rustc_private)]
44

tests/ui/anon-params/anon-params-deprecated.fixed

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// edition:2015
66
// run-rustfix
77

8+
#[allow(dead_code)]
89
trait T {
910
fn foo(_: i32); //~ WARNING anonymous parameters are deprecated
1011
//~| WARNING this is accepted in the current edition

tests/ui/anon-params/anon-params-deprecated.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// edition:2015
66
// run-rustfix
77

8+
#[allow(dead_code)]
89
trait T {
910
fn foo(i32); //~ WARNING anonymous parameters are deprecated
1011
//~| WARNING this is accepted in the current edition

tests/ui/anon-params/anon-params-deprecated.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: anonymous parameters are deprecated and will be removed in the next edition
2-
--> $DIR/anon-params-deprecated.rs:9:12
2+
--> $DIR/anon-params-deprecated.rs:10:12
33
|
44
LL | fn foo(i32);
55
| ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32`
@@ -13,7 +13,7 @@ LL | #![warn(anonymous_parameters)]
1313
| ^^^^^^^^^^^^^^^^^^^^
1414

1515
warning: anonymous parameters are deprecated and will be removed in the next edition
16-
--> $DIR/anon-params-deprecated.rs:12:30
16+
--> $DIR/anon-params-deprecated.rs:13:30
1717
|
1818
LL | fn bar_with_default_impl(String, String) {}
1919
| ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`
@@ -22,7 +22,7 @@ LL | fn bar_with_default_impl(String, String) {}
2222
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
2323

2424
warning: anonymous parameters are deprecated and will be removed in the next edition
25-
--> $DIR/anon-params-deprecated.rs:12:38
25+
--> $DIR/anon-params-deprecated.rs:13:38
2626
|
2727
LL | fn bar_with_default_impl(String, String) {}
2828
| ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String`

0 commit comments

Comments
 (0)