Skip to content

Commit

Permalink
Auto merge of rust-lang#134175 - estebank:manual-default-could-be-der…
Browse files Browse the repository at this point in the history
…ive, 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).
  • Loading branch information
bors committed Dec 16, 2024
2 parents 83ab648 + 6fa30b6 commit 9b48862
Show file tree
Hide file tree
Showing 32 changed files with 1,257 additions and 143 deletions.
19 changes: 3 additions & 16 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
pub use rustc_span::AttrId;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use rustc_span::{ErrorGuaranteed, Span};
use thin_vec::{ThinVec, thin_vec};

pub use crate::format::*;
Expand Down Expand Up @@ -388,22 +388,15 @@ impl GenericParam {

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

impl Default for Generics {
/// Creates an instance of `Generics`.
fn default() -> Generics {
Generics { params: ThinVec::new(), where_clause: Default::default(), span: DUMMY_SP }
}
}

/// A where-clause in a definition.
#[derive(Clone, Encodable, Decodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug, Default)]
pub struct WhereClause {
/// `true` if we ate a `where` token.
///
Expand All @@ -420,12 +413,6 @@ impl WhereClause {
}
}

impl Default for WhereClause {
fn default() -> WhereClause {
WhereClause { has_where_token: false, predicates: ThinVec::new(), span: DUMMY_SP }
}
}

/// A single predicate in a where-clause.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WherePredicate {
Expand Down
18 changes: 3 additions & 15 deletions compiler/rustc_ast_pretty/src/pprust/state/fixup.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use rustc_ast::Expr;
use rustc_ast::util::{classify, parser};

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

/// The default amount of fixing is minimal fixing. Fixups should be turned on
/// in a targeted fashion where needed.
impl Default for FixupContext {
fn default() -> Self {
FixupContext {
stmt: false,
leftmost_subexpression_in_stmt: false,
match_arm: false,
leftmost_subexpression_in_match_arm: false,
parenthesize_exterior_struct_lit: false,
}
}
}

impl FixupContext {
/// Create the initial fixup for printing an expression in statement
/// position.
Expand Down
18 changes: 15 additions & 3 deletions compiler/rustc_error_codes/src/error_codes/E0665.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,30 @@ The `Default` cannot be derived on an enum for the simple reason that the
compiler doesn't know which value to pick by default whereas it can for a
struct as long as all its fields implement the `Default` trait as well.

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

```
#[derive(Default)]
enum Food {
#[default]
Sweet,
Salty,
}
```

In the case where the default variant does have data, you will have to
implement `Default` on your enum "by hand":

```
enum Food {
Sweet(i32),
Salty,
}
impl Default for Food {
fn default() -> Food {
Food::Sweet
Food::Sweet(1)
}
}
```
Loading

0 comments on commit 9b48862

Please sign in to comment.