default_field_values

The tracking issue for this feature is: #132162

The RFC for this feature is: #3681


The default_field_values feature allows users to specify a const value for individual fields in struct definitions, allowing those to be omitted from initializers.

Examples

#![feature(default_field_values)]

#[derive(Default)]
struct Pet {
    name: Option<String>, // impl Default for Pet will use Default::default() for name
    age: i128 = 42, // impl Default for Pet will use the literal 42 for age
}

fn main() {
    let a = Pet { name: Some(String::new()), .. }; // Pet { name: Some(""), age: 42 }
    let b = Pet::default(); // Pet { name: None, age: 42 }
    assert_eq!(a.age, b.age);
    // The following would be a compilation error: `name` needs to be specified
    // let _ = Pet { .. };
}

#[derive(Default)]

When deriving Default, the provided values are then used. On enum variants, the variant must still be marked with #[default] and have all its fields with default values.

#![allow(unused)]
#![feature(default_field_values)]

fn main() {
#[derive(Default)]
enum A {
    #[default]
    B {
        x: i32 = 0,
        y: i32 = 0,
    },
    C,
}
}

Enum variants

This feature also supports enum variants for both specifying default values and #[derive(Default)].

Interaction with #[non_exhaustive]

A struct or enum variant marked with #[non_exhaustive] is not allowed to have default field values.

Lints

When manually implementing the Default trait for a type that has default field values, if any of these are overriden in the impl the default_overrides_default_fields lint will trigger. This lint is in place to avoid surprising diverging behavior between S { .. } and S::default(), where using the same type in both ways could result in different values. The appropriate way to write a manual Default implementation is to use the functional update syntax:

#![allow(unused)]
#![feature(default_field_values)]

fn main() {
struct Pet {
    name: String,
    age: i128 = 42, // impl Default for Pet will use the literal 42 for age
}

impl Default for Pet {
    fn default() -> Pet {
        Pet {
            name: "no-name".to_string(),
            ..
        }
    }
}
}