Borrowing Sub-parts of Data
In this lesson, you will learn how to gain mutable access to specific fields of a struct without needing to claim ownership or exclusivity over the entire data structure.
The Power of Disjoint Fields
When you have a struct with multiple fields, Rust’s borrow checker is smart enough to see them as distinct, independent pieces of memory. This means you can borrow one field mutably while leaving the rest of the struct available for other operations. You don't have to choose between locking the whole struct or nothing at all.
Consider a simple Player struct:
struct Player {
name: String,
score: i32,
health: i32,
}
fn main() {
let mut player = Player {
name: String::from("Hero"),
score: 0,
health: 100,
};
// We can borrow different fields independently
let score_ref = &mut player.score;
let health_ref = &mut player.health;
*score_ref += 10;
*health_ref -= 5;
println!("{} score: {}, health: {}", player.name, player.score, player.health);
}
Why This Matters
If Rust forced you to lock the entire player variable just to change the score, you would be unable to read or modify the health field at the same time. By allowing "disjoint" (separate) borrows, Rust minimizes contention. As long as your references point to different fields within the struct, the compiler ensures they do not overlap, keeping your memory safe while allowing multiple parts of your code to work on the struct simultaneously.
However, keep in mind that you cannot have a mutable reference to the whole struct (&mut player) at the same time as a reference to a specific field (&mut player.score). A mutable reference to the parent struct "covers" all the fields inside it. By splitting your borrows down to the fields, you are effectively maximizing the efficiency of your data access.
Key Takeaway: Rust allows you to independently borrow distinct fields of a struct, enabling granular, concurrent mutation of your data without requiring exclusive access to the entire object.