Skip to content

Commit 820b20e

Browse files
committed
Marks the adt live if it appears in pattern, removes specifal logic for Default
1 parent 27ddb1b commit 820b20e

8 files changed

+121
-29
lines changed

compiler/rustc_passes/src/dead.rs

+12-27
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
231231
pats: &[hir::PatField<'_>],
232232
) {
233233
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
234-
ty::Adt(adt, _) => adt.variant_of_res(res),
234+
ty::Adt(adt, _) => {
235+
self.check_def_id(adt.did());
236+
adt.variant_of_res(res)
237+
}
235238
_ => span_bug!(lhs.span, "non-ADT in struct pattern"),
236239
};
237240
for pat in pats {
@@ -251,7 +254,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
251254
dotdot: hir::DotDotPos,
252255
) {
253256
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
254-
ty::Adt(adt, _) => adt.variant_of_res(res),
257+
ty::Adt(adt, _) => {
258+
self.check_def_id(adt.did());
259+
adt.variant_of_res(res)
260+
}
255261
_ => {
256262
self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern");
257263
return;
@@ -356,31 +362,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
356362
return false;
357363
}
358364

359-
// don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
360-
// cause external crate may call such methods to construct values of these types
361-
if let Some(local_impl_of) = impl_of.as_local()
362-
&& let Some(local_def_id) = def_id.as_local()
363-
&& let Some(fn_sig) =
364-
self.tcx.hir_fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
365-
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
366-
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
367-
self.tcx.hir_expect_item(local_impl_of).expect_impl().self_ty.kind
368-
&& let Res::Def(def_kind, did) = path.res
369-
{
370-
match def_kind {
371-
// for example, #[derive(Default)] pub struct T(i32);
372-
// external crate can call T::default() to construct T,
373-
// so that don't ignore impl Default for pub Enum and Structs
374-
DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
375-
return false;
376-
}
377-
// don't ignore impl Default for Enums,
378-
// cause we don't know which variant is constructed
379-
DefKind::Enum => return false,
380-
_ => (),
381-
};
382-
}
383-
384365
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
385366
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
386367
{
@@ -622,6 +603,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
622603
fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) {
623604
match &expr.kind {
624605
rustc_hir::PatExprKind::Path(qpath) => {
606+
// mark the type of variant live when meeting E::V in expr
607+
if let ty::Adt(adt, _) = self.typeck_results().node_type(expr.hir_id).kind() {
608+
self.check_def_id(adt.did());
609+
}
625610
let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
626611
self.handle_res(res);
627612
}

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
#[rustc_diagnostic_item = "Default"]
105105
#[stable(feature = "rust1", since = "1.0.0")]
106-
#[rustc_trivial_field_reads]
107106
pub trait Default: Sized {
108107
/// Returns the "default value" for a type.
109108
///
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//@ check-pass
2+
3+
#![deny(dead_code)]
4+
5+
struct T<X>(X);
6+
7+
type A<X> = T<X>;
8+
9+
trait Tr {
10+
fn foo();
11+
}
12+
13+
impl<X> Tr for T<A<X>> {
14+
fn foo() {}
15+
}
16+
17+
fn main() {
18+
T::<T<()>>::foo();
19+
}
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() {}

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
|

0 commit comments

Comments
 (0)