Skip to content

Commit e5575ea

Browse files
committed
Improve dead code analysis
1 parent bae813a commit e5575ea

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:4: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)