Skip to content

Commit 9b48862

Browse files
committed
Auto merge of rust-lang#134175 - estebank:manual-default-could-be-derive, r=<try>
Lint against manual `impl Default` that could have been `derive`d ``` error: `impl Default` that could be derived --> $DIR/manual-default-impl-could-be-derived.rs:74:1 | LL | / impl Default for G { LL | | fn default() -> Self { LL | | G { LL | | f: F::Unit, LL | | } LL | | } LL | | } | |_^ | help: you don't need to manually `impl Default`, you can derive it | LL ~ #[derive(Default)] struct G { | ``` As part of rust-lang#132162/rust-lang/rfcs#3681 we want to lint when default fields values could preclude the need of a manual `impl Default`, but there are already cases where these manual impls could be derived. This PR introduces a new `default_could_be_derived` lint that makes a best effort check of the body of the `Default::default()` implementation to see if all the fields of a single expression in that body are either known to be `Default` already (like an explicit call to `Default::default()`, a `0` literal, or `Option::None` path) or are identified to be equivalent to the field's type's `Default` value (by opportunistically looking at the `Default::default()` body for that field's type).
2 parents 83ab648 + 6fa30b6 commit 9b48862

File tree

32 files changed

+1257
-143
lines changed

32 files changed

+1257
-143
lines changed

compiler/rustc_ast/src/ast.rs

+3-16
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
3232
pub use rustc_span::AttrId;
3333
use rustc_span::source_map::{Spanned, respan};
3434
use rustc_span::symbol::{Ident, Symbol, kw, sym};
35-
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
35+
use rustc_span::{ErrorGuaranteed, Span};
3636
use thin_vec::{ThinVec, thin_vec};
3737

3838
pub use crate::format::*;
@@ -388,22 +388,15 @@ impl GenericParam {
388388

389389
/// Represents lifetime, type and const parameters attached to a declaration of
390390
/// a function, enum, trait, etc.
391-
#[derive(Clone, Encodable, Decodable, Debug)]
391+
#[derive(Clone, Encodable, Decodable, Debug, Default)]
392392
pub struct Generics {
393393
pub params: ThinVec<GenericParam>,
394394
pub where_clause: WhereClause,
395395
pub span: Span,
396396
}
397397

398-
impl Default for Generics {
399-
/// Creates an instance of `Generics`.
400-
fn default() -> Generics {
401-
Generics { params: ThinVec::new(), where_clause: Default::default(), span: DUMMY_SP }
402-
}
403-
}
404-
405398
/// A where-clause in a definition.
406-
#[derive(Clone, Encodable, Decodable, Debug)]
399+
#[derive(Clone, Encodable, Decodable, Debug, Default)]
407400
pub struct WhereClause {
408401
/// `true` if we ate a `where` token.
409402
///
@@ -420,12 +413,6 @@ impl WhereClause {
420413
}
421414
}
422415

423-
impl Default for WhereClause {
424-
fn default() -> WhereClause {
425-
WhereClause { has_where_token: false, predicates: ThinVec::new(), span: DUMMY_SP }
426-
}
427-
}
428-
429416
/// A single predicate in a where-clause.
430417
#[derive(Clone, Encodable, Decodable, Debug)]
431418
pub struct WherePredicate {

compiler/rustc_ast_pretty/src/pprust/state/fixup.rs

+3-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use rustc_ast::Expr;
22
use rustc_ast::util::{classify, parser};
33

4-
#[derive(Copy, Clone, Debug)]
4+
// The default amount of fixing is minimal fixing. Fixups should be turned on
5+
// in a targeted fashion where needed.
6+
#[derive(Copy, Clone, Debug, Default)]
57
pub(crate) struct FixupContext {
68
/// Print expression such that it can be parsed back as a statement
79
/// consisting of the original expression.
@@ -93,20 +95,6 @@ pub(crate) struct FixupContext {
9395
parenthesize_exterior_struct_lit: bool,
9496
}
9597

96-
/// The default amount of fixing is minimal fixing. Fixups should be turned on
97-
/// in a targeted fashion where needed.
98-
impl Default for FixupContext {
99-
fn default() -> Self {
100-
FixupContext {
101-
stmt: false,
102-
leftmost_subexpression_in_stmt: false,
103-
match_arm: false,
104-
leftmost_subexpression_in_match_arm: false,
105-
parenthesize_exterior_struct_lit: false,
106-
}
107-
}
108-
}
109-
11098
impl FixupContext {
11199
/// Create the initial fixup for printing an expression in statement
112100
/// position.

compiler/rustc_error_codes/src/error_codes/E0665.md

+15-3
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,30 @@ The `Default` cannot be derived on an enum for the simple reason that the
1616
compiler doesn't know which value to pick by default whereas it can for a
1717
struct as long as all its fields implement the `Default` trait as well.
1818

19-
If you still want to implement `Default` on your enum, you'll have to do it "by
20-
hand":
19+
For the case where the desired default variant has no data, you can annotate
20+
it with `#[default]` to derive it:
2121

2222
```
23+
#[derive(Default)]
2324
enum Food {
25+
#[default]
2426
Sweet,
2527
Salty,
2628
}
29+
```
30+
31+
In the case where the default variant does have data, you will have to
32+
implement `Default` on your enum "by hand":
33+
34+
```
35+
enum Food {
36+
Sweet(i32),
37+
Salty,
38+
}
2739
2840
impl Default for Food {
2941
fn default() -> Food {
30-
Food::Sweet
42+
Food::Sweet(1)
3143
}
3244
}
3345
```

0 commit comments

Comments
 (0)