title: Destructuring
Destructuring lets you unpack values from compound types directly into variables. It works in let bindings, function parameters, match arms, and for loops.
Tuples
let point = (10, 20);
let (x, y) = point;
println!("{x}, {y}"); // 10, 20Ignore values with _:
let (x, _, z) = (1, 2, 3); // ignore the middle valueNested tuples:
let ((a, b), c) = ((1, 2), 3);Structs
struct Point {
x: i32,
y: i32,
}
let p = Point { x: 10, y: 20 };
let Point { x, y } = p;
println!("{x}, {y}"); // 10, 20Rename fields while destructuring:
let Point { x: horizontal, y: vertical } = p;Ignore remaining fields with ..:
struct Config {
debug: bool,
verbose: bool,
timeout: u32,
}
let Config { debug, .. } = config; // only extract debugEnums
enum Message {
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
match msg {
Message::Move { x, y } => println!("move to {x}, {y}"),
Message::Write(text) => println!("write: {text}"),
Message::ChangeColor(r, g, b) => println!("color: {r}, {g}, {b}"),
}Arrays and slices
Fixed-size arrays:
let [a, b, c] = [1, 2, 3];Slices with .. to match a variable number of elements:
let numbers = [1, 2, 3, 4, 5];
match numbers {
[first, .., last] => println!("first: {first}, last: {last}"),
}
match numbers {
[first, second, ..] => println!("starts with {first}, {second}"),
}References
Prefix with & to destructure a reference:
let reference = &42;
let &value = reference; // value is i32, not &i32More commonly, use ref inside a pattern to bind by reference rather than by value:
let name = String::from("Alice");
match name {
ref s => println!("got a reference to: {s}"), // name is not moved
}In practice you’ll rarely need ref explicitly — borrowing with & in match is more common:
match &name {
s => println!("{s}"), // s is &String
}In function parameters
Destructure directly in the parameter list:
fn print_point(&(x, y): &(i32, i32)) {
println!("{x}, {y}");
}
fn print_user(&User { ref name, age }: &User) {
println!("{name} is {age}");
}In for loops
let pairs = vec![(1, 'a'), (2, 'b'), (3, 'c')];
for (number, letter) in &pairs {
println!("{number}: {letter}");
}With HashMap:
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("one", 1);
map.insert("two", 2);
for (key, value) in &map {
println!("{key} = {value}");
}Nested destructuring
Patterns can be nested as deeply as needed:
let ((feet, inches), Point { x, y }) = ((6, 1), Point { x: 3, y: 10 });if let and while let
Destructure while conditionally matching:
if let Some((x, y)) = get_point() {
println!("{x}, {y}");
}
while let Some(top) = stack.pop() {
println!("{top}");
}