Skip to content

Commit 5d36626

Browse files
committed
Extend support to unit-structs and add comments
1 parent c4896ee commit 5d36626

4 files changed

+82
-22
lines changed

compiler/rustc_lint/src/default_could_be_derived.rs

+49
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,20 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
242242
{
243243
let type_def_id = cx.tcx.parent(ctor_def_id); // From Ctor to struct
244244
if args.iter().all(|expr| check_expr(cx.tcx, expr.kind)) {
245+
// We have a struct literal
246+
//
247+
// struct Foo(Type);
248+
//
249+
// impl Default for Foo {
250+
// fn default() -> Foo {
251+
// Foo(val)
252+
// }
253+
// }
254+
//
255+
// We suggest #[derive(Default)] if
256+
// - `val` is `Default::default()`
257+
// - `val` is `0`
258+
// - `val` is `false`
245259
cx.tcx.node_span_lint(
246260
DEFAULT_COULD_BE_DERIVED,
247261
item.hir_id(),
@@ -264,6 +278,41 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
264278
}
265279
}
266280
}
281+
hir::ExprKind::Path(hir::QPath::Resolved(_, path))
282+
if let Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Const), _) =
283+
path.res =>
284+
{
285+
// We have a struct literal
286+
//
287+
// struct Foo;
288+
//
289+
// impl Default for Foo {
290+
// fn default() -> Foo {
291+
// Foo
292+
// }
293+
// }
294+
//
295+
// We always suggest `#[derive(Default)]`.
296+
cx.tcx.node_span_lint(
297+
DEFAULT_COULD_BE_DERIVED,
298+
item.hir_id(),
299+
item.span,
300+
|diag| {
301+
diag.primary_message("`impl Default` that could be derived");
302+
diag.multipart_suggestion_verbose(
303+
"you don't need to manually `impl Default`, you can derive it",
304+
vec![
305+
(
306+
cx.tcx.def_span(type_def_id).shrink_to_lo(),
307+
"#[derive(Default)] ".to_string(),
308+
),
309+
(item.span, String::new()),
310+
],
311+
Applicability::MachineApplicable,
312+
);
313+
},
314+
);
315+
}
267316
_ => {}
268317
}
269318
}

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

+7-10
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,10 @@
44
#![deny(default_could_be_derived)]
55
#![feature(default_field_values)]
66

7-
// #[derive(Debug)]
8-
// struct A;
9-
//
10-
// impl Default for A {
11-
// fn default() -> Self { A }
12-
// }
13-
//
7+
#[derive(Debug)]
8+
#[derive(Default)] struct A;
9+
10+
1411
#[derive(Debug)]
1512
#[derive(Default)] struct B(Option<i32>);
1613

@@ -63,9 +60,9 @@
6360

6461

6562
fn main() {
66-
// let _ = A::default();
67-
// let _ = B::default();
68-
// let _ = C::default();
63+
let _ = A::default();
64+
let _ = B::default();
65+
let _ = C::default();
6966
let _ = D::default();
7067
let _ = E::default();
7168
let _ = F::<i32>::default();

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
#![deny(default_could_be_derived)]
55
#![feature(default_field_values)]
66

7-
// #[derive(Debug)]
8-
// struct A;
9-
//
10-
// impl Default for A {
11-
// fn default() -> Self { A }
12-
// }
13-
//
7+
#[derive(Debug)]
8+
struct A;
9+
10+
impl Default for A { //~ ERROR
11+
fn default() -> Self { A }
12+
}
13+
1414
#[derive(Debug)]
1515
struct B(Option<i32>);
1616

@@ -111,7 +111,7 @@ impl Default for I { //~ ERROR
111111
}
112112

113113
fn main() {
114-
// let _ = A::default();
114+
let _ = A::default();
115115
let _ = B::default();
116116
let _ = C::default();
117117
let _ = D::default();

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

+18-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: `impl Default` that could be derived
2-
--> $DIR/manual-default-impl-could-be-derived.rs:17:1
2+
--> $DIR/manual-default-impl-could-be-derived.rs:10:1
33
|
4-
LL | / impl Default for B {
5-
LL | | fn default() -> Self { B(Default::default()) }
4+
LL | / impl Default for A {
5+
LL | | fn default() -> Self { A }
66
LL | | }
77
| |_^
88
|
@@ -13,6 +13,20 @@ LL | #![deny(default_could_be_derived)]
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^
1414
help: you don't need to manually `impl Default`, you can derive it
1515
|
16+
LL - struct A;
17+
LL + #[derive(Default)] struct A;
18+
|
19+
20+
error: `impl Default` that could be derived
21+
--> $DIR/manual-default-impl-could-be-derived.rs:17:1
22+
|
23+
LL | / impl Default for B {
24+
LL | | fn default() -> Self { B(Default::default()) }
25+
LL | | }
26+
| |_^
27+
|
28+
help: you don't need to manually `impl Default`, you can derive it
29+
|
1630
LL - struct B(Option<i32>);
1731
LL + #[derive(Default)] struct B(Option<i32>);
1832
|
@@ -144,5 +158,5 @@ help: to avoid divergence in behavior between `Struct { .. }` and `<Struct as De
144158
LL ~ #[derive(Default)] struct I {
145159
|
146160

147-
error: aborting due to 8 previous errors
161+
error: aborting due to 9 previous errors
148162

0 commit comments

Comments
 (0)