Understanding References and Borrowing in Rust

In Rust, references allow you to refer to a value without taking ownership of it. This mechanism is central to Rust’s memory safety guarantees.

Passing Referneces to Functions

When passing data to a function without transferring ownership, you use a reference:

fn main() {
    let mut text = String::from("Rust references and borrowing");
    println!("{}", text);
    
    let length = modify_and_measure(&mut text);
    println!("==={}===", length);
}

fn modify_and_measure(s: &mut String) -> usize {
    s.push_str("===>HelloWorld!");
    println!("Modified string: {}", s);
    s.len()
}

Here, &mut String indicates a mutable reference—allowing the function to modify the data while ensuring only one such reference exists at a time.

Mutablle Borrowing Rules

Rust enforces that within a single scope, only one mutable reference to a particular piece of data may exist:

let mut data = String::from("example");
let ref_a = &mut data;
// let ref_b = &mut data; // ❌ Error: cannot borrow `data` as mutable more than once
println!("Scope 1: {}", ref_a);

{
    let ref_b = &mut data; // ✅ OK: new scope
    println!("Scope 2: {}", ref_b);
}

This prevents data races at compile time.

Immutable vs. Mutable References

Multiple immutable references can coexist, but they cannot coexist with a mutable reference:

let mut content = String::from("shared");
let r1 = &content;
let r2 = &content;
println!("Immutable refs: {}, {}", r1, r2);

let r3 = &mut content; // ✅ OK: r1 and r2 are no longer used after this point
println!("Mutable ref: {}", r3);

// println!("{},{},{}", r1, r2, r3); // ❌ Error: cannot use immutable refs while mutable ref is active

The compiler tracks lifetimes and usage to enforce these rules.

Avoiding Dangling References

Rust prevents dangling references by ensuring that a reference cannot outlive the data it points to:

// ❌ This won't compile:
// fn dangling_ref() -> &String {
//     let s = String::from("hello");
//     &s
// }

// ✅ Return owned data instead:
fn safe_return() -> String {
    let s = String::from("Hello");
    s
}

Attempting to return a reference to a local variable vioaltes Rust’s lifetime rules, as the variable is dropped when the function ends.

These borrowing rules—combined with Rust’s ownership model—eliminate entire classes of memory bugs without requiring a garbage collector.

Tags: rust Borrowing References ownership memory-safety

Posted on Thu, 28 May 2026 21:58:02 +0000 by flying_circus