Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

Struct update syntax is a declarative shorthand in Rust used during struct instantiation to populate unspecified fields with values from an existing instance of the exact same struct type. It utilizes the .. (dot-dot) operator followed by the base instance.
struct Configuration {
    timeout: u32,
    retries: u8,
    caching: bool,
}

let base_config = Configuration {
    timeout: 500,
    retries: 3,
    caching: true,
};

let custom_config = Configuration {
    timeout: 1000,
    ..base_config
};

Syntactic and Visibility Rules

  1. Terminal Position: The ..base_instance expression must be the final element in the struct initialization block. Rust’s grammar strictly forbids a trailing comma after the base instance, and no additional field declarations may appear after it.
  2. Strict Type Matching: The instance provided after the .. operator must be of the exact same struct type being instantiated. Rust does not support structural typing or duck typing for this operation.
  3. Explicit Override: Any field explicitly declared in the initialization block (e.g., timeout: 1000) overrides the corresponding field in the base instance.
  4. Field Visibility: The current scope must have access to all omitted fields. Struct update syntax cannot be used on a base instance if the struct contains private fields and the instantiation occurs outside of the struct’s defining module.
  5. Non-Exhaustive Structs: A struct marked with the #[non_exhaustive] attribute cannot be instantiated or updated using struct update syntax outside of its defining crate, even if all of its fields are public.

Ownership and Memory Semantics

Struct update syntax does not invoke a specialized cloning mechanism; it behaves exactly like a series of individual field assignments. Consequently, it strictly adheres to Rust’s ownership and move semantics.
  • Copy Types: If the omitted fields being transferred implement the Copy trait, their values are bitwise copied to the new instance.
  • Non-Copy Types: If any omitted field does not implement Copy, its value is moved into the new instance.
When a non-Copy field is moved via struct update syntax, it triggers a partial move on the base instance.
struct Payload {
    id: i32,          // Implements Copy
    data: String,     // Non-Copy (Move semantics)
    active: bool,     // Implements Copy
}

let base_payload = Payload {
    id: 1,
    data: String::from("buffer"),
    active: true,
};

let new_payload = Payload {
    id: 2,
    ..base_payload
};
In the example above:
  1. id is explicitly assigned 2.
  2. data is omitted, so base_payload.data is moved into new_payload.
  3. active is omitted, so base_payload.active is copied into new_payload.
Because data was moved, base_payload is now in a partially moved state. The compiler enforces the following restrictions post-update:
  • The base_payload instance as a whole can no longer be used or bound.
  • The base_payload.data field can no longer be accessed.
  • The base_payload.id and base_payload.active fields remain fully accessible and valid, as their ownership was not transferred.
The Drop Trait Restriction Rust strictly forbids partial moves out of any struct that implements the Drop trait. If the base instance implements Drop, attempting to move non-Copy fields via struct update syntax will result in a compiler error (E0509). If the explicit assignments in the new struct cover all non-Copy fields of the base instance, no move occurs. In this scenario, the Drop restriction does not apply, and the base instance remains entirely valid for future use.
Master Rust with Deep Grasping Methodology!Learn More