Skip to content

Commit

Permalink
Auto merge of rust-lang#126302 - mu001999-contrib:ignore/default, r=m…
Browse files Browse the repository at this point in the history
…ichaelwoerister

Detect unused structs which derived Default

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->

Fixes rust-lang#98871
  • Loading branch information
bors committed Jun 25, 2024
2 parents d929a42 + e3aa980 commit 0521fe5
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 2 deletions.
25 changes: 25 additions & 0 deletions compiler/rustc_passes/src/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
return false;
}

// don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
// cause external crate may call such methods to construct values of these types
if let Some(local_impl_of) = impl_of.as_local()
&& let Some(local_def_id) = def_id.as_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)
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
&& let Res::Def(def_kind, did) = path.res
{
match def_kind {
// for example, #[derive(Default)] pub struct T(i32);
// external crate can call T::default() to construct T,
// so that don't ignore impl Default for pub Enum and Structs
DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
return false;
}
// don't ignore impl Default for Enums,
// cause we don't know which variant is constructed
DefKind::Enum => 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
2 changes: 1 addition & 1 deletion library/alloc/src/sync/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ fn show_arc() {

// Make sure deriving works with Arc<T>
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
struct Foo {
struct _Foo {
inner: Arc<i32>,
}

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")]
#[cfg_attr(not(bootstrap), 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));
}
25 changes: 25 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,25 @@
#![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
}

// external crate can call T2::default() to construct T2,
// so that no warnings for pub adts
#[derive(Default)]
pub struct T2 {
_unread: i32,
}

fn main() {
let _x: Used = Default::default();
}
24 changes: 24 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,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

0 comments on commit 0521fe5

Please sign in to comment.