diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 2cb3c5d8965c8..3e355b5bc15d5 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -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) { diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index 49eae718c1690..1b123aa58f205 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -396,7 +396,7 @@ fn show_arc() { // Make sure deriving works with Arc #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] -struct Foo { +struct _Foo { inner: Arc, } diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 4524b352ec817..5cacedcb241a5 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -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")] +#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/tests/ui/deriving/deriving-default-enum.rs b/tests/ui/deriving/deriving-default-enum.rs index 96eba258c97e8..6b59f39a67d48 100644 --- a/tests/ui/deriving/deriving-default-enum.rs +++ b/tests/ui/deriving/deriving-default-enum.rs @@ -22,6 +22,6 @@ enum MyOption { } fn main() { - assert_eq!(Foo::default(), Foo::Alpha); + assert!(matches!(Foo::default(), Foo::Alpha)); assert!(matches!(MyOption::::default(), MyOption::None)); } diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.rs b/tests/ui/lint/dead-code/unused-struct-derive-default.rs new file mode 100644 index 0000000000000..286ee46f37d71 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.rs @@ -0,0 +1,18 @@ +#![deny(dead_code)] + +#[derive(Default)] +struct T; //~ ERROR struct `T` is never constructed + +#[derive(Default)] +struct Used; + +#[derive(Default)] +enum E { + #[default] + A, + B, //~ ERROR variant `B` is never constructed +} + +fn main() { + let _x: Used = Default::default(); +} diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr new file mode 100644 index 0000000000000..bbb0bd7be7064 --- /dev/null +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr @@ -0,0 +1,24 @@ +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: variant `B` is never constructed + --> $DIR/unused-struct-derive-default.rs:13:5 + | +LL | enum E { + | - variant in this enum +... +LL | B, + | ^ + +error: aborting due to 2 previous errors +