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.

The = operator in Rust is the assignment operator, responsible for binding an evaluated expression to a pattern, initializing a memory location, or updating the value of a mutable place expression. Its behavior is strictly dictated by Rust’s ownership model, drop semantics, and the traits implemented by the assigned type.

Syntax

// Variable initialization (binding)
let pattern: Type = expression;

// Reassignment (requires a mutable place expression)
place_expression = expression;

Evaluation and Return Type

Unlike languages such as C or C++, the assignment operation in Rust does not evaluate to the assigned value. Instead, it evaluates to the unit type (). This design choice prevents accidental assignments in conditional statements (e.g., if a = b). Consequently, chained assignments like a = b = c are syntactically valid and parse correctly as right-associative expressions: a = (b = c). However, they are typically semantically invalid. Because the inner assignment b = c evaluates to (), assigning that result to a causes a compile-time type mismatch error, unless a is explicitly declared as the unit type ().
let mut a = 1;
let mut b = 2;

// The expression (a = b) evaluates to (), not 2.
let c: () = (a = b); 

Memory, Ownership, and Drop Semantics

The = operator behaves differently based on the initialization state of the place expression and whether the assigned type implements the Copy trait. 1. Drop Semantics on Reassignment When updating an already-initialized mutable place expression (place_expression = expression;), Rust enforces a strict evaluation and drop order to guarantee memory safety and panic resilience. The right-hand side expression is evaluated first. Rust then moves the existing value at the assignee’s memory location into a temporary, writes the new value into the assignee’s place, and finally drops the temporary containing the old value. This ensures that if the drop implementation of the old value panics, the new value is already safely stored in the variable.
let mut s = String::from("first");
// "second" is evaluated, "first" is moved to a temporary,
// "second" is written to `s`, and then the temporary ("first") is dropped.
s = String::from("second"); 
2. Move Semantics (Default) For types that do not implement the Copy trait (e.g., String, Vec<T>, or custom structs without Copy), the = operator performs a move. Ownership of the memory is transferred from the right-hand side expression to the left-hand side place expression. The original variable is statically invalidated by the borrow checker and can no longer be accessed.
let s1 = String::from("data");
let s2 = s1; // Ownership moves to s2. s1 is now uninitialized.
// println!("{}", s1); // Compiler error: use of moved value
3. Copy Semantics For types that implement the Copy trait (e.g., primitives like i32, f64, bool), the = operator performs a bitwise copy of the data to the destination’s memory location. This location can be on the stack or the heap (such as assigning to a dereferenced Box or a vector element). Ownership is not transferred, and both the source and destination remain valid and independently accessible.
let x = 10;
let y = x; // Bitwise copy. Both x and y are valid and independent.

let mut vec = vec![1, 2, 3];
vec[0] = x; // Bitwise copy to a heap-allocated memory location.

Pattern Destructuring

The left-hand side of the = operator is evaluated as a pattern. This allows the = operator to destructure complex data types (like tuples, structs, or arrays) directly into multiple discrete variables. This applies to both variable initialization (let bindings) and destructuring assignments of existing mutable variables.
// Destructuring during initialization (let binding)
let (x, y) = (1, 2); 

struct Point { x: i32, y: i32 }
let p = Point { x: 10, y: 20 };

// Destructuring a struct into new bindings
let Point { x: a, y: b } = p; 

// Destructuring assignment (updating existing mutable variables)
let mut c = 0;
let mut d = 0;
(c, d) = (100, 200); // Destructuring assignment without the 'let' keyword
Master Rust with Deep Grasping Methodology!Learn More