Essential Standard Traits

Default

The Default trait provides a standard zero-argument constructor (Default::default()) that produces a sensible initial or empty value for a type.

Trait Definition

pub trait Default: Sized {
    fn default() -> Self;
}

Standard library types implement Default with their natural empty or zero states:

Type Default::default() Value
Numeric types (i32, u64, f64, etc.) 0 or 0.0
bool false
char '\0'
String, Vec<T>, HashMap<K, V> Empty container (does not allocate heap memory)
Option<T> None (even if T does not implement Default)

Deriving Default on Structs and Enums

Applying #[derive(Default)] to a struct initializes every field with Default::default(). Applying #[derive(Default)] to an enum requires marking exactly one unit variant with #[default]:

#[derive(Debug, Default)]
enum LogLevel {
    Debug,
    #[default]
    Info,
    Warn,
    Error,
}

#[derive(Debug, Default)]
struct AppOptions {
    level: LogLevel,
    max_retries: u32,
    log_path: Option<String>,
}

fn main() {
    let opts = AppOptions::default();
    println!("{opts:#?}");
}
AppOptions {
    level: Info,
    max_retries: 0,
    log_path: None,
}

Struct Update Syntax with ..Default::default()

Combining struct update syntax with Default::default() lets callers override only specific fields while leaving all remaining fields at their defaults:

#[derive(Debug)]
struct HttpClientConfig {
    timeout_ms: u64,
    follow_redirects: bool,
    max_connections: usize,
}

impl Default for HttpClientConfig {
    fn default() -> Self {
        Self {
            timeout_ms: 5_000,
            follow_redirects: true,
            max_connections: 32,
        }
    }
}

fn main() {
    let custom = HttpClientConfig {
        timeout_ms: 15_000,
        ..Default::default()
    };

    println!("{custom:?}");
}
HttpClientConfig { timeout_ms: 15000, follow_redirects: true, max_connections: 32 }

Standard Library Methods Powered by Default

Implementing Default unlocks convenience methods across the standard library:

  • Option::unwrap_or_default() returns the contained Some(v) or T::default() if None.
  • Result::unwrap_or_default() returns the Ok(v) value or T::default() on Err(_).
  • std::mem::take(&mut dest) replaces dest with T::default() and returns the old value without requiring T: Clone.
  • HashMap::entry(k).or_default() inserts V::default() if the key is absent and returns &mut V.