๐Ÿฆ€ Functional Rust
๐ŸŽฌ Rust Ownership in 30 seconds Visual walkthrough of ownership, moves, and automatic memory management.
๐Ÿ“ Text version (for readers / accessibility)

โ€ข Each value in Rust has exactly one owner โ€” when the owner goes out of scope, the value is dropped

โ€ข Assignment moves ownership by default; the original binding becomes invalid

โ€ข Borrowing (&T / &mut T) lets you reference data without taking ownership

โ€ข The compiler enforces: many shared references OR one mutable reference, never both

โ€ข No garbage collector needed โ€” memory is freed deterministically at scope exit

546: Reborrowing Patterns

Difficulty: 4 Level: Advanced Reuse a mutable reference across multiple calls without moving or losing it.

The Problem This Solves

Rust's ownership rules say you can only have one mutable reference at a time. This sounds like it would make it impossible to pass `&mut T` to a function and then use it again โ€” but that's not true. The key is reborrowing: the compiler can create a shorter-lived `&mut T` from an existing one, pass that shorter borrow to a function, and then let the original reference resume once the shorter borrow ends. Without reborrowing, you would have to restructure your code around indices, clone values, or redesign your APIs. With it, you can write natural, ergonomic code: pass a mutable reference to a helper, then keep using the original reference afterward. This shows up constantly in real code โ€” sorting a `Vec`, then pushing to it, then reading it back. Or passing `&mut String` to a function that appends, then using the string again. Reborrowing is what makes all of that work silently and safely.

The Intuition

Think of reborrowing like lending someone your pen to sign one document, then getting it back when they're done. You still own the pen. The loan was temporary and bounded. The compiler tracks exactly when the "loan" ends. An implicit reborrow happens when you pass `&mut T` where a function expects `&T` โ€” the compiler silently reborrows it as a shared reference for the duration of the call. An explicit reborrow (`&r` or `&mut r`) creates a new reference at a specific scope, which you can drop early to free the original.

How It Works in Rust

1. Implicit shared reborrow โ€” pass `&mut T` where `&T` is expected; Rust coerces via `Deref`, borrow ends with the call. 2. Explicit reborrow โ€” write `&r` to create a shared borrow, or `&mut r` for a shorter mutable borrow; use blocks `{}` to control scope. 3. Reborrow through Deref โ€” `&mut String` can reborrow as `&str` via `Deref<Target=str>`; lets you call `&str` APIs without consuming the reference. 4. Sequential reborrows โ€” each method call on `r` is a new implicit reborrow; `r.sort()` then `r.push()` both work because each call ends before the next begins. 5. Split reborrows โ€” borrow `r.0` and `r.1` independently; the compiler tracks field-level borrows (NLL).

What This Unlocks

Key Differences

ConceptOCamlRust
Mutable aliasingMultiple refs to same mutable value allowedExactly one `&mut T` at a time; reborrow creates sub-borrow
Reference passingPass by value or `ref`; no lifetime trackingBorrow checker tracks reborrow scope precisely
Implicit coercionNo coercion model`&mut T` implicitly reborrows as `&T` when needed
Field-level borrowsN/ABorrow checker understands struct field independence
//! # 546. Reborrowing Patterns
//! Creating sub-borrows from existing borrows.

fn read_value(r: &i32) -> i32 { *r }
fn increment(r: &mut i32) { *r += 1; }

/// Demonstrate implicit reborrow: &mut T -> &T
fn implicit_reborrow() {
    let mut x = 42;
    let r = &mut x;

    // &mut T coerces to &T automatically (implicit shared reborrow)
    let val = read_value(r); // r reborrowed as &i32 for this call
    // r still valid after โ€” reborrow ended at end of read_value call
    println!("read_value via reborrow: {}", val);
    *r += 1; // r still usable
    println!("after increment: {}", *r);
}

/// Explicit reborrow
fn explicit_reborrow() {
    let mut data = vec![1, 2, 3];
    let r = &mut data;

    // Explicit shared reborrow โ€” can read while r still in scope
    {
        let shared: &Vec<i32> = &*r; // explicit reborrow as shared
        println!("shared reborrow: {:?}", shared);
        // shared ends here
    }

    // r still valid โ€” push more data
    r.push(4);
    println!("after push via r: {:?}", data);
}

/// Reborrow through function argument
fn reborrow_in_fn() {
    let mut s = String::from("hello");
    let r = &mut s;

    // Pass reborrow to function โ€” r still usable after
    fn print_str(s: &str) { println!("{}", s); }
    print_str(r); // implicit reborrow: &mut String -> &str via Deref
    r.push_str(" world"); // r still valid
    println!("after push: {}", *r);
}

/// Sequential reborrows โ€” using &mut multiple times
fn sequential_reborrows() {
    let mut v = vec![3, 1, 4, 1, 5];

    let r = &mut v;
    r.sort();        // mutable reborrow
    r.dedup();       // another mutable reborrow
    r.push(9);       // yet another

    println!("sequential ops: {:?}", v);
}

/// Reborrow to split a mutable ref
fn split_reborrow() {
    let mut pair = (10i32, 20i32);
    let r = &mut pair;

    // Reborrow parts independently
    let first = &mut r.0;
    *first *= 2;
    // Can't borrow r.1 while r.0 is mutably borrowed:
    drop(first);
    let second = &mut r.1;
    *second *= 3;
    drop(second);

    println!("pair: {:?}", pair);
}

fn main() {
    println!("=== Implicit reborrow ===");
    implicit_reborrow();

    println!("\n=== Explicit reborrow ===");
    explicit_reborrow();

    println!("\n=== Reborrow in function call ===");
    reborrow_in_fn();

    println!("\n=== Sequential reborrows ===");
    sequential_reborrows();

    println!("\n=== Split reborrow ===");
    split_reborrow();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_implicit_reborrow() {
        let mut x = 5;
        let r = &mut x;
        let _ = read_value(r); // implicit reborrow
        *r = 10; // r still valid
        assert_eq!(x, 10);
    }

    #[test]
    fn test_sequential_reborrows() {
        let mut v = vec![3, 1, 2];
        let r = &mut v;
        r.sort();
        r.push(4);
        assert_eq!(v, [1, 2, 3, 4]);
    }
}
(* Reborrowing concept in OCaml โ€” refs can be accessed multiple times *)
let () =
  let x = ref 42 in
  (* Can "reborrow" (read) multiple times from same ref *)
  let a = !x in
  let b = !x in
  Printf.printf "a=%d, b=%d\n" a b;

  (* Modify, then read again *)
  x := !x + 10;
  let c = !x in
  Printf.printf "after mutation: c=%d\n" c