Skip to content

Commit d0932e6

Browse files
authored
Unrolled build for rust-lang#127107
Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix Improve dead code analysis Fixes rust-lang#120770 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 r? ``@pnkfelix``
2 parents 5c08cc7 + 0adb825 commit d0932e6

21 files changed

+164
-60
lines changed

compiler/rustc_passes/src/dead.rs

+12-28
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
277277
pats: &[hir::PatField<'_>],
278278
) {
279279
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
280-
ty::Adt(adt, _) => adt.variant_of_res(res),
280+
ty::Adt(adt, _) => {
281+
self.check_def_id(adt.did());
282+
adt.variant_of_res(res)
283+
}
281284
_ => span_bug!(lhs.span, "non-ADT in struct pattern"),
282285
};
283286
for pat in pats {
@@ -297,7 +300,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
297300
dotdot: hir::DotDotPos,
298301
) {
299302
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
300-
ty::Adt(adt, _) => adt.variant_of_res(res),
303+
ty::Adt(adt, _) => {
304+
self.check_def_id(adt.did());
305+
adt.variant_of_res(res)
306+
}
301307
_ => {
302308
self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern");
303309
return;
@@ -402,31 +408,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
402408
return false;
403409
}
404410

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-
430411
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
431412
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
432413
{
@@ -690,6 +671,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
690671
self.handle_field_pattern_match(pat, res, fields);
691672
}
692673
PatKind::Path(ref qpath) => {
674+
if let ty::Adt(adt, _) = self.typeck_results().node_type(pat.hir_id).kind() {
675+
self.check_def_id(adt.did());
676+
}
693677
let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
694678
self.handle_res(res);
695679
}
@@ -845,7 +829,7 @@ fn check_item<'tcx>(
845829
// mark the method live if the self_ty is public,
846830
// or the method is public and may construct self
847831
if tcx.visibility(local_def_id).is_public()
848-
&& (ty_and_all_fields_are_public || may_construct_self)
832+
&& (ty_and_all_fields_are_public || (ty_is_public && may_construct_self))
849833
{
850834
// if the impl item is public,
851835
// 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
///

src/tools/rust-analyzer/crates/salsa/salsa-macros/src/database_storage.rs

-8
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,3 @@ impl Parse for QueryGroup {
241241
Ok(QueryGroup { group_path })
242242
}
243243
}
244-
245-
struct Nothing;
246-
247-
impl Parse for Nothing {
248-
fn parse(_input: ParseStream<'_>) -> syn::Result<Self> {
249-
Ok(Nothing)
250-
}
251-
}

tests/ui-fulldeps/deriving-global.rs

+3
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,21 @@ mod submod {
1717
// if any of these are implemented without global calls for any
1818
// function calls, then being in a submodule will (correctly)
1919
// cause errors about unrecognised module `std` (or `extra`)
20+
#[allow(dead_code)]
2021
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
2122
enum A {
2223
A1(usize),
2324
A2(isize),
2425
}
2526

27+
#[allow(dead_code)]
2628
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
2729
struct B {
2830
x: usize,
2931
y: isize,
3032
}
3133

34+
#[allow(dead_code)]
3235
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
3336
struct C(usize, isize);
3437
}

tests/ui-fulldeps/deriving-hygiene.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub const s: u8 = 1;
2020
pub const state: u8 = 1;
2121
pub const cmp: u8 = 1;
2222

23+
#[allow(dead_code)]
2324
#[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)]
2425
struct Foo {}
2526

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
@@ -0,0 +1,37 @@
1+
#![deny(dead_code)]
2+
3+
struct Foo(u8); //~ ERROR struct `Foo` is never constructed
4+
5+
enum Bar { //~ ERROR enum `Bar` is never used
6+
Var1(u8),
7+
Var2(u8),
8+
}
9+
10+
pub trait Tr1 {
11+
fn f1() -> Self;
12+
}
13+
14+
impl Tr1 for Foo {
15+
fn f1() -> Foo {
16+
let f = Foo(0);
17+
let Foo(tag) = f;
18+
Foo(tag)
19+
}
20+
}
21+
22+
impl Tr1 for Bar {
23+
fn f1() -> Bar {
24+
let b = Bar::Var1(0);
25+
let b = if let Bar::Var1(_) = b {
26+
Bar::Var1(0)
27+
} else {
28+
Bar::Var2(0)
29+
};
30+
match b {
31+
Bar::Var1(_) => Bar::Var2(0),
32+
Bar::Var2(_) => Bar::Var1(0),
33+
}
34+
}
35+
}
36+
37+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: struct `Foo` is never constructed
2+
--> $DIR/lint-unused-adt-appeared-in-pattern.rs:3:8
3+
|
4+
LL | struct Foo(u8);
5+
| ^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/lint-unused-adt-appeared-in-pattern.rs:1:9
9+
|
10+
LL | #![deny(dead_code)]
11+
| ^^^^^^^^^
12+
13+
error: enum `Bar` is never used
14+
--> $DIR/lint-unused-adt-appeared-in-pattern.rs:5:6
15+
|
16+
LL | enum Bar {
17+
| ^^^
18+
19+
error: aborting due to 2 previous errors
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//@ check-pass
2+
3+
#![deny(dead_code)]
4+
5+
#[repr(u8)]
6+
#[derive(Copy, Clone, Debug)]
7+
pub enum RecordField {
8+
Target = 1,
9+
Level,
10+
Module,
11+
File,
12+
Line,
13+
NumArgs,
14+
}
15+
16+
unsafe trait Pod {}
17+
18+
#[repr(transparent)]
19+
struct RecordFieldWrapper(RecordField);
20+
21+
unsafe impl Pod for RecordFieldWrapper {}
22+
23+
fn try_read<T: Pod>(buf: &[u8]) -> T {
24+
unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const T) }
25+
}
26+
27+
pub fn foo(buf: &[u8]) -> RecordField {
28+
let RecordFieldWrapper(tag) = try_read(buf);
29+
tag
30+
}
31+
32+
fn main() {}
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

0 commit comments

Comments
 (0)