rust/tests/ui/structs/manual-default-impl-could-be-derived.rs
Esteban Küber 01307cf03f Implement default_overrides_default_fields lint
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:14:1
   |
LL | / impl Default for A {
LL | |     fn default() -> Self {
LL | |         A {
LL | |             y: 0,
   | |                - this field has a default value
...  |
LL | | }
   | |_^
   |
   = help: use the default values in the `impl` with `Struct { mandatory_field, .. }` to avoid them diverging over time
note: the lint level is defined here
  --> $DIR/manual-default-impl-could-be-derived.rs:5:9
   |
LL | #![deny(default_overrides_default_fields)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
2024-12-25 23:25:45 +00:00

195 lines
3.2 KiB
Rust

// Warn when we encounter a manual `Default` impl that could be derived.
// Restricted only to types using `default_field_values`.
#![feature(default_field_values)]
#![allow(dead_code)]
#![deny(default_overrides_default_fields)]
struct S(i32);
fn s() -> S { S(1) }
struct A {
x: S,
y: i32 = 1,
}
impl Default for A { //~ ERROR default_overrides_default_fields
fn default() -> Self {
A {
y: 0,
x: s(),
}
}
}
struct B {
x: S = S(3),
y: i32 = 1,
}
impl Default for B { //~ ERROR default_overrides_default_fields
fn default() -> Self {
B {
x: s(),
y: 0,
}
}
}
struct C {
x: S,
y: i32 = 1,
z: i32 = 1,
}
impl Default for C { //~ ERROR default_overrides_default_fields
fn default() -> Self {
C {
x: s(),
y: 0,
..
}
}
}
struct D {
x: S,
y: i32 = 1,
z: i32 = 1,
}
impl Default for D { //~ ERROR default_overrides_default_fields
fn default() -> Self {
D {
y: 0,
x: s(),
..
}
}
}
struct E {
x: S,
y: i32 = 1,
z: i32 = 1,
}
impl Default for E { //~ ERROR default_overrides_default_fields
fn default() -> Self {
E {
y: 0,
z: 0,
x: s(),
}
}
}
// Let's ensure that the span for `x` and the span for `y` don't overlap when suggesting their
// removal in favor of their default field values.
struct E2 {
x: S,
y: i32 = 1,
z: i32 = 1,
}
impl Default for E2 { //~ ERROR default_overrides_default_fields
fn default() -> Self {
E2 {
x: s(),
y: i(),
z: 0,
}
}
}
fn i() -> i32 {
1
}
// Account for a `const fn` being the `Default::default()` of a field's type.
struct F {
x: G,
y: i32 = 1,
}
impl Default for F { //~ ERROR default_overrides_default_fields
fn default() -> Self {
F {
x: g_const(),
y: 0,
}
}
}
struct G;
impl Default for G { // ok
fn default() -> Self {
g_const()
}
}
const fn g_const() -> G {
G
}
// Account for a `const fn` being used in `Default::default()`, even if the type doesn't use it as
// its own `Default`. We suggest setting the default field value in that case.
struct H {
x: I,
y: i32 = 1,
}
impl Default for H { //~ ERROR default_overrides_default_fields
fn default() -> Self {
H {
x: i_const(),
y: 0,
}
}
}
struct I;
const fn i_const() -> I {
I
}
// Account for a `const` and struct literal being the `Default::default()` of a field's type.
struct M {
x: N,
y: i32 = 1,
z: A,
}
impl Default for M { // ok, `y` is not specified
fn default() -> Self {
M {
x: N_CONST,
z: A {
x: S(0),
y: 0,
},
..
}
}
}
struct N;
const N_CONST: N = N;
struct O {
x: Option<i32>,
y: i32 = 1,
}
impl Default for O { //~ ERROR default_overrides_default_fields
fn default() -> Self {
O {
x: None,
y: 1,
}
}
}
fn main() {}