Skip to content

Commit fc7b735

Browse files
committed
fix: derivable_impls FN when enum is qualified with Self
1 parent 450e25b commit fc7b735

File tree

4 files changed

+84
-9
lines changed

4 files changed

+84
-9
lines changed

clippy_lints/src/derivable_impls.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_hir::{
1010
};
1111
use rustc_lint::{LateContext, LateLintPass};
1212
use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
13-
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty, TypeckResults};
13+
use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty, TypeckResults, VariantDef};
1414
use rustc_session::impl_lint_pass;
1515
use rustc_span::sym;
1616

@@ -161,17 +161,42 @@ fn check_struct<'tcx>(
161161
}
162162
}
163163

164-
fn check_enum<'tcx>(
164+
fn extract_enum_variant<'tcx>(
165165
cx: &LateContext<'tcx>,
166-
item: &'tcx Item<'_>,
167-
func_expr: &Expr<'_>,
168-
adt_def: AdtDef<'_>,
169-
is_const: bool,
170-
) {
171-
if let ExprKind::Path(QPath::Resolved(None, p)) = &peel_blocks(func_expr).kind
166+
func_expr: &'tcx Expr<'tcx>,
167+
adt_def: AdtDef<'tcx>,
168+
) -> Option<&'tcx VariantDef> {
169+
let func_expr = peel_blocks(func_expr);
170+
if let ExprKind::Path(QPath::Resolved(None, p)) = &func_expr.kind
172171
&& let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = p.res
173172
&& let variant_id = cx.tcx.parent(id)
174173
&& let Some(variant_def) = adt_def.variants().iter().find(|v| v.def_id == variant_id)
174+
{
175+
return Some(variant_def);
176+
}
177+
178+
if let ExprKind::Path(QPath::TypeRelative(ty, segment)) = &func_expr.kind
179+
&& let TyKind::Path(QPath::Resolved(None, p)) = &ty.kind
180+
&& let Res::SelfTyAlias {
181+
is_trait_impl: true, ..
182+
} = p.res
183+
&& let variant_ident = segment.ident
184+
&& let Some(variant_def) = adt_def.variants().iter().find(|v| v.ident(cx.tcx) == variant_ident)
185+
{
186+
return Some(variant_def);
187+
}
188+
189+
None
190+
}
191+
192+
fn check_enum<'tcx>(
193+
cx: &LateContext<'tcx>,
194+
item: &'tcx Item<'tcx>,
195+
func_expr: &'tcx Expr<'tcx>,
196+
adt_def: AdtDef<'tcx>,
197+
is_const: bool,
198+
) {
199+
if let Some(variant_def) = extract_enum_variant(cx, func_expr, adt_def)
175200
&& variant_def.fields.is_empty()
176201
&& !variant_def.is_field_list_non_exhaustive()
177202
{

tests/ui/derivable_impls.fixed

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,4 +352,16 @@ mod issue15493 {
352352
}
353353
}
354354

355+
mod issue15536 {
356+
#[derive(Copy, Clone)]
357+
#[derive(Default)]
358+
enum Bar {
359+
#[default]
360+
A,
361+
B,
362+
}
363+
364+
365+
}
366+
355367
fn main() {}

tests/ui/derivable_impls.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,4 +422,19 @@ mod issue15493 {
422422
}
423423
}
424424

425+
mod issue15536 {
426+
#[derive(Copy, Clone)]
427+
enum Bar {
428+
A,
429+
B,
430+
}
431+
432+
impl Default for Bar {
433+
//~^ derivable_impls
434+
fn default() -> Self {
435+
Self::A
436+
}
437+
}
438+
}
439+
425440
fn main() {}

tests/ui/derivable_impls.stderr

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,5 +187,28 @@ LL ~ #[default]
187187
LL ~ Bar,
188188
|
189189

190-
error: aborting due to 11 previous errors
190+
error: this `impl` can be derived
191+
--> tests/ui/derivable_impls.rs:432:5
192+
|
193+
LL | / impl Default for Bar {
194+
LL | |
195+
LL | | fn default() -> Self {
196+
LL | | Self::A
197+
LL | | }
198+
LL | | }
199+
| |_____^
200+
|
201+
help: replace the manual implementation with a derive attribute and mark the default variant
202+
|
203+
LL ~ #[derive(Default)]
204+
LL ~ enum Bar {
205+
LL ~ #[default]
206+
LL ~ A,
207+
LL | B,
208+
LL | }
209+
LL |
210+
LL ~
211+
|
212+
213+
error: aborting due to 12 previous errors
191214

0 commit comments

Comments
 (0)