Skip to content

Implement default_could_be_derived and default_overrides_default_fields lints#134441

Closed
estebank wants to merge 1 commit intorust-lang:masterfrom
estebank:derive-lint-default-fields
Closed

Implement default_could_be_derived and default_overrides_default_fields lints#134441
estebank wants to merge 1 commit intorust-lang:masterfrom
estebank:derive-lint-default-fields

Conversation

@estebank
Copy link
Copy Markdown
Contributor

Detect when a manual Default implementation isn't using the existing default field values and suggest using .. instead:

error: `Default` impl doesn't use the declared default field values
  --> $DIR/manual-default-impl-could-be-derived.rs:13:1
   |
LL | / impl Default for A {
LL | |     fn default() -> Self {
LL | |         A {
LL | |             x: S,
LL | |             y: 0,
   | |                - this field has a default value
...  |
LL | | }
   | |_^
   |
note: the lint level is defined here
  --> $DIR/manual-default-impl-could-be-derived.rs:4:35
   |
LL | #![deny(default_could_be_derived, default_overrides_default_fields)]
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: use the default values in the `impl` to avoid them diverging over time
   |
LL -             x: S,
LL -             y: 0,
LL +             x: S, ..
   |

Detect when a manual Default implementation for a type containing at least one default field value has all fields that could be derived and suggest #[derive(Default)]:

error: `Default` impl that could be derived
  --> $DIR/manual-default-impl-could-be-derived.rs:27:1
   |
LL |   struct B {
   |   -------- all the fields in this struct have default values
LL |       x: S = S,
   |              - default value
LL |       y: i32 = 1,
   |                - default value
...
LL | / impl Default for B {
LL | |     fn default() -> Self {
LL | |         B {
LL | |             x: S,
...  |
LL | | }
   | |_^
   |
note: the lint level is defined here
  --> $DIR/manual-default-impl-could-be-derived.rs:4:9
   |
LL | #![deny(default_could_be_derived, default_overrides_default_fields)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^
help: to avoid divergence in behavior between `Struct { .. }` and `<Struct as Default>::default()`, derive the `Default`
   |
LL ~ #[derive(Default)] struct B {
   |

Store a mapping between the DefId for an impl Default for Ty {} and the DefId of either a Unit variant/struct or an fn with no arguments that is called within <Ty as Default>::default().

When linting impls, if it is for Default, we evaluate the contents of their fn default(). If it is only an ADT literal for Self and every field is either a "known to be defaulted" value (0 or false), an explicit Default::default() call or a call or path to the same "equivalent" DefId from that field's type's Default::default() implementation.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

F-default_field_values `#![feature(default_field_values)]` S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants