Skip to content

Commit e868a95

Browse files
committed
Marks the adt live if it appears in pattern, removes specifal logic for Default
1 parent a22c560 commit e868a95

8 files changed

+118
-31
lines changed

compiler/rustc_passes/src/dead.rs

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
1010
use rustc_abi::FieldIdx;
1111
use rustc_data_structures::unord::UnordSet;
1212
use rustc_errors::MultiSpan;
13-
use rustc_hir as hir;
1413
use rustc_hir::def::{CtorOf, DefKind, Res};
1514
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
1615
use rustc_hir::intravisit::{self, Visitor};
17-
use rustc_hir::{Node, PatKind, TyKind};
16+
use rustc_hir::{self as hir, Node, PatKind, TyKind};
1817
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1918
use rustc_middle::middle::privacy::Level;
2019
use rustc_middle::query::Providers;
@@ -232,7 +231,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
232231
pats: &[hir::PatField<'_>],
233232
) {
234233
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
235-
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+
}
236238
_ => span_bug!(lhs.span, "non-ADT in struct pattern"),
237239
};
238240
for pat in pats {
@@ -252,7 +254,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
252254
dotdot: hir::DotDotPos,
253255
) {
254256
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
255-
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+
}
256261
_ => {
257262
self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern");
258263
return;
@@ -357,31 +362,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
357362
return false;
358363
}
359364

360-
// don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
361-
// cause external crate may call such methods to construct values of these types
362-
if let Some(local_impl_of) = impl_of.as_local()
363-
&& let Some(local_def_id) = def_id.as_local()
364-
&& let Some(fn_sig) =
365-
self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
366-
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
367-
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
368-
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
369-
&& let Res::Def(def_kind, did) = path.res
370-
{
371-
match def_kind {
372-
// for example, #[derive(Default)] pub struct T(i32);
373-
// external crate can call T::default() to construct T,
374-
// so that don't ignore impl Default for pub Enum and Structs
375-
DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
376-
return false;
377-
}
378-
// don't ignore impl Default for Enums,
379-
// cause we don't know which variant is constructed
380-
DefKind::Enum => return false,
381-
_ => (),
382-
};
383-
}
384-
385365
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
386366
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
387367
{

library/core/src/default.rs

Lines changed: 0 additions & 1 deletion
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-
#[rustc_trivial_field_reads]
107106
pub trait Default: Sized {
108107
/// Returns the "default value" for a type.
109108
///
Lines changed: 19 additions & 0 deletions
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+
}
Lines changed: 37 additions & 0 deletions
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() {}
Lines changed: 20 additions & 0 deletions
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+
Lines changed: 32 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 0 additions & 1 deletion
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)