Skip to content

Commit b176f5d

Browse files
committed
Improve dead code analysis
1. check impl items later if self ty is private although the trait method is public, cause we must use the ty firstly if it's private 2. mark the adt live if it appears in pattern, like generic argument, this implies the use of the adt 3. based on the above, we can handle the case that private adts impl Default, so that we don't need adding rustc_trivial_field_reads on Default, and the logic in should_ignore_item
1 parent bae813a commit b176f5d

15 files changed

+67
-51
lines changed

compiler/rustc_passes/src/dead.rs

+8-27
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
156156
fn handle_res(&mut self, res: Res) {
157157
match res {
158158
Res::Def(
159-
DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias,
159+
DefKind::Struct
160+
| DefKind::Enum
161+
| DefKind::Const
162+
| DefKind::AssocConst
163+
| DefKind::AssocTy
164+
| DefKind::TyAlias,
160165
def_id,
161166
) => {
162167
self.check_def_id(def_id);
@@ -402,31 +407,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
402407
return false;
403408
}
404409

405-
// don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
406-
// cause external crate may call such methods to construct values of these types
407-
if let Some(local_impl_of) = impl_of.as_local()
408-
&& let Some(local_def_id) = def_id.as_local()
409-
&& let Some(fn_sig) =
410-
self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
411-
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
412-
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
413-
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
414-
&& let Res::Def(def_kind, did) = path.res
415-
{
416-
match def_kind {
417-
// for example, #[derive(Default)] pub struct T(i32);
418-
// external crate can call T::default() to construct T,
419-
// so that don't ignore impl Default for pub Enum and Structs
420-
DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
421-
return false;
422-
}
423-
// don't ignore impl Default for Enums,
424-
// cause we don't know which variant is constructed
425-
DefKind::Enum => return false,
426-
_ => (),
427-
};
428-
}
429-
430410
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
431411
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
432412
{
@@ -687,6 +667,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
687667
match pat.kind {
688668
PatKind::Struct(ref path, fields, _) => {
689669
let res = self.typeck_results().qpath_res(path, pat.hir_id);
670+
self.handle_res(res);
690671
self.handle_field_pattern_match(pat, res, fields);
691672
}
692673
PatKind::Path(ref qpath) => {
@@ -845,7 +826,7 @@ fn check_item<'tcx>(
845826
// mark the method live if the self_ty is public,
846827
// or the method is public and may construct self
847828
if tcx.visibility(local_def_id).is_public()
848-
&& (ty_and_all_fields_are_public || may_construct_self)
829+
&& (ty_and_all_fields_are_public || (ty_is_public && may_construct_self))
849830
{
850831
// if the impl item is public,
851832
// and the ty may be constructed or can be constructed in foreign crates,

library/core/src/default.rs

-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ use crate::ascii::Char as AsciiChar;
103103
/// ```
104104
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
105105
#[stable(feature = "rust1", since = "1.0.0")]
106-
#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
107106
pub trait Default: Sized {
108107
/// Returns the "default value" for a type.
109108
///

tests/ui/const-generics/issues/issue-86535-2.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub trait Foo {
77
fn foo() where [(); Self::ASSOC_C]:;
88
}
99

10+
#[allow(dead_code)]
1011
struct Bar<const N: &'static ()>;
1112
impl<const N: &'static ()> Foo for Bar<N> {
1213
const ASSOC_C: usize = 3;

tests/ui/const-generics/issues/issue-86535.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(adt_const_params, generic_const_exprs)]
33
#![allow(incomplete_features, unused_variables)]
44

5+
#[allow(dead_code)]
56
struct F<const S: &'static str>;
67
impl<const S: &'static str> X for F<{ S }> {
78
const W: usize = 3;

tests/ui/impl-trait/extra-impl-in-trait-impl.fixed

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//@ run-rustfix
22

3+
#[allow(dead_code)]
34
struct S<T>(T);
5+
#[allow(dead_code)]
46
struct S2;
57

68
impl<T: Default> Default for S<T> {

tests/ui/impl-trait/extra-impl-in-trait-impl.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//@ run-rustfix
22

3+
#[allow(dead_code)]
34
struct S<T>(T);
5+
#[allow(dead_code)]
46
struct S2;
57

68
impl<T: Default> impl Default for S<T> {

tests/ui/impl-trait/extra-impl-in-trait-impl.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
error: unexpected `impl` keyword
2-
--> $DIR/extra-impl-in-trait-impl.rs:6:18
2+
--> $DIR/extra-impl-in-trait-impl.rs:8:18
33
|
44
LL | impl<T: Default> impl Default for S<T> {
55
| ^^^^^ help: remove the extra `impl`
66
|
77
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
8-
--> $DIR/extra-impl-in-trait-impl.rs:6:18
8+
--> $DIR/extra-impl-in-trait-impl.rs:8:18
99
|
1010
LL | impl<T: Default> impl Default for S<T> {
1111
| ^^^^^^^^^^^^
1212

1313
error: unexpected `impl` keyword
14-
--> $DIR/extra-impl-in-trait-impl.rs:12:6
14+
--> $DIR/extra-impl-in-trait-impl.rs:14:6
1515
|
1616
LL | impl impl Default for S2 {
1717
| ^^^^^ help: remove the extra `impl`
1818
|
1919
note: this is parsed as an `impl Trait` type, but a trait is expected at this position
20-
--> $DIR/extra-impl-in-trait-impl.rs:12:6
20+
--> $DIR/extra-impl-in-trait-impl.rs:14:6
2121
|
2222
LL | impl impl Default for S2 {
2323
| ^^^^^^^^^^^^

tests/ui/lint/dead-code/issue-59003.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
#![deny(dead_code)]
66

7+
#[allow(dead_code)]
78
struct Foo {
8-
#[allow(dead_code)]
99
inner: u32,
1010
}
1111

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#![deny(dead_code)]
22

33
struct T1; //~ ERROR struct `T1` is never constructed
4-
pub struct T2(i32); //~ ERROR struct `T2` is never constructed
5-
struct T3;
4+
struct T2; //~ ERROR struct `T2` is never constructed
5+
pub struct T3(i32); //~ ERROR struct `T3` is never constructed
6+
pub struct T4(i32); //~ ERROR field `0` is never read
67

78
trait Trait1 { //~ ERROR trait `Trait1` is never used
89
const UNUSED: i32;
@@ -11,13 +12,13 @@ trait Trait1 { //~ ERROR trait `Trait1` is never used
1112
}
1213

1314
pub trait Trait2 {
14-
const USED: i32;
15-
fn used(&self) {}
15+
const MAY_USED: i32;
16+
fn may_used(&self) {}
1617
}
1718

1819
pub trait Trait3 {
19-
const USED: i32;
20-
fn construct_self() -> Self;
20+
const MAY_USED: i32;
21+
fn may_used() -> Self;
2122
}
2223

2324
impl Trait1 for T1 {
@@ -30,23 +31,34 @@ impl Trait1 for T1 {
3031
impl Trait1 for T2 {
3132
const UNUSED: i32 = 0;
3233
fn construct_self() -> Self {
33-
T2(0)
34+
Self
3435
}
3536
}
3637

3738
impl Trait2 for T1 {
38-
const USED: i32 = 0;
39+
const MAY_USED: i32 = 0;
3940
}
4041

4142
impl Trait2 for T2 {
42-
const USED: i32 = 0;
43+
const MAY_USED: i32 = 0;
4344
}
4445

45-
impl Trait3 for T3 {
46-
const USED: i32 = 0;
47-
fn construct_self() -> Self {
46+
impl Trait2 for T3 {
47+
const MAY_USED: i32 = 0;
48+
}
49+
50+
impl Trait3 for T2 {
51+
const MAY_USED: i32 = 0;
52+
fn may_used() -> Self {
4853
Self
4954
}
5055
}
5156

57+
impl Trait3 for T4 {
58+
const MAY_USED: i32 = 0;
59+
fn may_used() -> Self {
60+
T4(0)
61+
}
62+
}
63+
5264
fn main() {}

tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr

+20-4
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,32 @@ LL | #![deny(dead_code)]
1111
| ^^^^^^^^^
1212

1313
error: struct `T2` is never constructed
14-
--> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:12
14+
--> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:8
1515
|
16-
LL | pub struct T2(i32);
16+
LL | struct T2;
17+
| ^^
18+
19+
error: struct `T3` is never constructed
20+
--> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:5:12
21+
|
22+
LL | pub struct T3(i32);
1723
| ^^
1824

25+
error: field `0` is never read
26+
--> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:6:15
27+
|
28+
LL | pub struct T4(i32);
29+
| -- ^^^
30+
| |
31+
| field in this struct
32+
|
33+
= help: consider removing this field
34+
1935
error: trait `Trait1` is never used
20-
--> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7
36+
--> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:8:7
2137
|
2238
LL | trait Trait1 {
2339
| ^^^^^^
2440

25-
error: aborting due to 3 previous errors
41+
error: aborting due to 5 previous errors
2642

tests/ui/lint/dead-code/unused-struct-derive-default.rs

+1
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ pub struct T2 {
2222

2323
fn main() {
2424
let _x: Used = Default::default();
25+
let _e: E = Default::default();
2526
}

tests/ui/lint/dead-code/unused-struct-derive-default.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ error: struct `T` is never constructed
44
LL | struct T;
55
| ^
66
|
7-
= note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis
87
note: the lint level is defined here
98
--> $DIR/unused-struct-derive-default.rs:1:9
109
|

tests/ui/parser/issues/issue-105366.fixed

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ run-rustfix
22

3+
#[allow(dead_code)]
34
struct Foo;
45

56
impl From<i32> for Foo {

tests/ui/parser/issues/issue-105366.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//@ run-rustfix
22

3+
#[allow(dead_code)]
34
struct Foo;
45

56
fn From<i32> for Foo {

tests/ui/parser/issues/issue-105366.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: you might have meant to write `impl` instead of `fn`
2-
--> $DIR/issue-105366.rs:5:1
2+
--> $DIR/issue-105366.rs:6:1
33
|
44
LL | fn From<i32> for Foo {
55
| ^^

0 commit comments

Comments
 (0)