Confusion with &mut inside an & reference

โš“ Rust    ๐Ÿ“… 2026-02-07    ๐Ÿ‘ค surdeus    ๐Ÿ‘๏ธ 1      

surdeus

Iโ€™m trying to pass a โ€œcontextโ€ parameter that contains some refs or mutable refs, and Iโ€™m getting confused by when the language allows me to use a mutable ref. An example, in this code, you can modify the Thing through a &mut Thing of course, but also through a non-mutable Ctx that contains the &mut Thing. However, if I have a & shared ref to that same Ctx, it doesnโ€™t like it.

What is the mental model here? Why is the first allowed and the second disallowed?

#[derive(Debug, Default)]
struct Thing {
    num: u32
}
struct Ctx<'a> {
    thing: &'a mut Thing
}

impl Thing {
    fn change(&mut self) { self.num += 1; }
}

fn faa(mr: &mut Thing) {
    mr.change();
}
fn fee(ctx: &Ctx) {
    ctx.thing.change();  // Not allowed!
}


fn main() {
    let mut thing = Thing::default();
    thing.change();       // Works, of course.
    let mr = &mut thing;
    mr.change();          // Works, even though `mr` is not `mut`
    faa(mr);              // Works, you can pass it.
    let ctx = Ctx { thing: mr };
    ctx.thing.change();   // Works, even though `ctx` is not `mut`

    // But...
    let ctx_ref = &ctx;
    ctx_ref.thing.change();   // Not allowed
    fee(&ctx);

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

The error:

error[E0596]: cannot borrow `*ctx.thing` as mutable, as it is behind a `&` reference
  --> learning/rust_lang/examples/mut_refs.rs:20:5
   |
20 |     ctx.thing.change();
   |     ^^^^^^^^^ `ctx` is a `&` reference, so it cannot be borrowed as mutable

5 posts - 3 participants

Read full topic

๐Ÿท๏ธ Rust_feed