Skip to content

Commit faf7f16

Browse files
committed
Also lint enums with type parameters with unit variant default
1 parent 52788fa commit faf7f16

File tree

3 files changed

+13
-9
lines changed

3 files changed

+13
-9
lines changed

compiler/rustc_lint/src/default_could_be_derived.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,13 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
5050
}
5151
let hir_self_ty = data.self_ty;
5252
let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = hir_self_ty.kind else { return };
53-
let Res::Def(_, type_def_id) = path.res else { return };
53+
let Res::Def(def_kind, type_def_id) = path.res else { return };
5454
let generics = cx.tcx.generics_of(type_def_id);
55-
if !generics.own_params.is_empty() {
55+
if !generics.own_params.is_empty() && def_kind != DefKind::Enum {
56+
// For enums, `#[derive(Default)]` forces you to select a unit variant to avoid
57+
// "imperfect derives", unnecessary bounds on type parameters, so even if the enum has
58+
// type parameters we can still lint on the manual impl if the return is a unit
59+
// variant.
5660
return;
5761
}
5862
// We have a manual `impl Default for Ty {}` item, where `Ty` has no type parameters.

tests/ui/structs/manual-default-impl-could-be-derived.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,20 @@ impl Default for E { //~ ERROR
5555
}
5656

5757
// Detection of unit variant ctors that could have been marked `#[default]`.
58-
enum F {
58+
enum F<T> {
5959
Unit,
60-
Tuple(i32),
60+
Tuple(T),
6161
}
6262

63-
impl Default for F { //~ ERROR
63+
impl<T> Default for F<T> { //~ ERROR
6464
fn default() -> Self {
6565
F::Unit
6666
}
6767
}
6868

6969
// Comparison of `impl` *fields* with their `Default::default()` bodies.
7070
struct G {
71-
f: F,
71+
f: F<i32>,
7272
}
7373

7474
impl Default for G { //~ ERROR
@@ -85,6 +85,6 @@ fn main() {
8585
// let _ = C::default();
8686
let _ = D::default();
8787
let _ = E::default();
88-
let _ = F::default();
88+
let _ = F::<i32>::default();
8989
let _ = G::default();
9090
}

tests/ui/structs/manual-default-impl-could-be-derived.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ LL ~ #[derive(Default)] struct E {
4040
error: `impl Default` that could be derived
4141
--> $DIR/manual-default-impl-could-be-derived.rs:63:1
4242
|
43-
LL | / impl Default for F {
43+
LL | / impl<T> Default for F<T> {
4444
LL | | fn default() -> Self {
4545
LL | | F::Unit
4646
LL | | }
@@ -49,7 +49,7 @@ LL | | }
4949
|
5050
help: you don't need to manually `impl Default`, you can derive it
5151
|
52-
LL ~ #[derive(Default)] enum F {
52+
LL ~ #[derive(Default)] enum F<T> {
5353
LL ~ #[default] Unit,
5454
|
5555

0 commit comments

Comments
 (0)