Skip to content

Commit

Permalink
Detect unused structs which derived Default
Browse files Browse the repository at this point in the history
  • Loading branch information
mu001999 committed Jun 12, 2024
1 parent 336e6ab commit c0e7b7d
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 1 deletion.
15 changes: 15 additions & 0 deletions compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,21 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
return false;
}

// don't ignore the impl Default for Enum,
// cause we don't know which variant is constructed
if let Some(local_impl_of) = impl_of.as_local()
&& let Some(local_def_id) = def_id.as_local()
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
&& let Res::Def(DefKind::Enum, did) = path.res
&& did.is_local()
&& let Some(fn_sig) =
self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
{
return false;
}

if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
{
Expand Down
1 change: 1 addition & 0 deletions library/core/src/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ use crate::ascii::Char as AsciiChar;
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_trivial_field_reads]
pub trait Default: Sized {
/// Returns the "default value" for a type.
///
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/deriving/deriving-default-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ enum MyOption<T> {
}

fn main() {
assert_eq!(Foo::default(), Foo::Alpha);
assert!(matches!(Foo::default(), Foo::Alpha));
assert!(matches!(MyOption::<NotDefault>::default(), MyOption::None));
}
11 changes: 11 additions & 0 deletions tests/ui/lint/dead-code/unused-struct-derive-default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#![deny(dead_code)]

#[derive(Default)]
struct T; //~ ERROR struct `T` is never constructed

#[derive(Default)]
struct Used;

fn main() {
let _x: Used = Default::default();
}
15 changes: 15 additions & 0 deletions tests/ui/lint/dead-code/unused-struct-derive-default.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: struct `T` is never constructed
--> $DIR/unused-struct-derive-default.rs:4:8
|
LL | struct T;
| ^
|
= note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis
note: the lint level is defined here
--> $DIR/unused-struct-derive-default.rs:1:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^

error: aborting due to 1 previous error

0 comments on commit c0e7b7d

Please sign in to comment.