← Back to Rust Course | Chapter 7: Structs | Lesson 6 of 7

Struct Update Syntax

Struct update syntax lets you build a new struct that's mostly a copy of an old one, but with a couple of fields swapped out.
Syntax
rust
let new_value = Name {
    field1: v1,
    ..old_value
};

Basic Struct Update Syntax

Struct update syntax lets you create a new instance based on an existing one, explicitly overriding only the fields you want to change and copying the rest with ..base.

Example: Basic Struct Update Syntax

markup
// Auto-generate #[derive(Debug)] for the type below
#[derive(Debug)]
// Define a struct `Config` to group related fields together
struct Config {
    width: u32,
    height: u32,
    fullscreen: bool,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `default_config`, set to `Config { width: 800, height: 600, fullscreen: false }`
    let default_config = Config { width: 800, height: 600, fullscreen: false };
    // Declare an immutable variable `custom`, set to `Config { fullscreen: true, ..default_config }`
    let custom = Config { fullscreen: true, ..default_config };
    // Print "{:?}" to the console, substituting in `custom` (with a trailing newline)
    println!("{:?}", custom);
}

Moving Non-Copy Fields

If the base struct contains non-Copy fields like String that are not overridden, those fields are moved into the new instance, making the original struct partially unusable afterward.

Example: Moving Non-Copy Fields

markup
// Auto-generate #[derive(Debug)] for the type below
#[derive(Debug)]
// Define a struct `Profile` to group related fields together
struct Profile {
    username: String,
    active: bool,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `base`, set to `Profile { username: String::from("guest"), active: false }`
    let base = Profile { username: String::from("guest"), active: false };
    // Declare an immutable variable `updated`, set to `Profile { active: true, ..base }`
    let updated = Profile { active: true, ..base };
    // Print "{:?}" to the console, substituting in `updated` (with a trailing newline)
    println!("{:?}", updated);
}

..base Must Come Last

The ..base syntax must always appear as the final item in a struct literal, after every explicitly assigned field, since it fills in whatever remains.

Example: ..base Must Come Last

markup
// Auto-generate #[derive(Debug)] for the type below
#[derive(Debug)]
// Define a struct `Point3D` to group related fields together
struct Point3D {
    x: i32,
    y: i32,
    z: i32,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `origin`, set to `Point3D { x: 0, y: 0, z: 0 }`
    let origin = Point3D { x: 0, y: 0, z: 0 };
    // Declare an immutable variable `shifted`, set to `Point3D { x: 5, ..origin }`
    let shifted = Point3D { x: 5, ..origin };
    // Print "{:?}" to the console, substituting in `shifted` (with a trailing newline)
    println!("{:?}", shifted);
}

Combining With Copy Structs

When the base struct's fields are all Copy types, using struct update syntax leaves the original instance fully usable afterward, since nothing was moved out of it.

Example: Combining With Copy Structs

markup
// Auto-generate #[derive(Debug, Clone, Copy)] for the type below
#[derive(Debug, Clone, Copy)]
// Define a struct `Settings` to group related fields together
struct Settings {
    volume: u8,
    brightness: u8,
}

// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `defaults`, set to `Settings { volume: 50, brightness: 70 }`
    let defaults = Settings { volume: 50, brightness: 70 };
    // Declare an immutable variable `louder`, set to `Settings { volume: 80, ..defaults }`
    let louder = Settings { volume: 80, ..defaults };
    // Print "defaults still usable: {:?}" to the console, substituting in `defaults` (with a trailing newline)
    println!("defaults still usable: {:?}", defaults);
    // Print "louder: {:?}" to the console, substituting in `louder` (with a trailing newline)
    println!("louder: {:?}", louder);
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting that struct update syntax ..other moves non-Copy fields out of other, potentially invalidating it afterward.
  2. Placing ..other before other field assignments -- it must come last in the struct literal.
  3. Assuming struct update syntax mutates the original struct in place, when it actually creates a brand new instance.
Chapter Summary
  • ..other_instance at the end of a struct literal fills in any remaining fields from an existing instance.
  • Only the fields not explicitly listed are copied or moved from the base instance.
  • If any moved (non-Copy) fields are taken from the base instance, that instance can no longer be used afterward.
  • This syntax is a concise way to create variations of a struct without repeating every field.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.