1

I understand there can only be one mut& for an object. But what if the object contains another object, are we not allowed to take refernce for the child object as well?

I tried with some exmpales and the result is confusing:

#[derive(Debug)]
struct Value {
    value: i32,
}

#[derive(Debug)]
struct Container {
    value: Value,
    value2: i32,
}

fn main() {
    let mut obj1 = Container { value: Value { value: 12 }, value2: 1 };

    let mut_ref1 = &mut obj1;       
    let mut_ref2 = &mut obj1.value; 
    
    mut_ref2.value = 1; 
}

This one compiles, but the following one does not:

#[derive(Debug)]
struct Value {
    value: i32,
}

#[derive(Debug)]
struct Container {
    value: Value,
    value2: i32,
}

fn main() {
    let mut obj1 = Container { value: Value { value: 12 }, value2: 1 };

    let mut_ref1 = &mut obj1;       
    let mut_ref2 = &mut obj1.value;

    mut_ref1.value2 = 111;
}

The first example shows I can take mutable reference to child object at the same time, but the second example shows I cannot do that.

If in the first example, compiler is smart enough to tell mut_ref1 is not used, why it cannot do the same for mut_ref2 in the second example?

silverwen
  • 287
  • 3
  • 11
  • “The first example shows I can take mutable reference to child object at the same time.” This is incorrect. The lifetimes of `mut_ref1` and `mut_ref2` do not overlap in your first example. – Mark Saving Aug 11 '23 at 23:05
  • Although `mut_ref1` and `mut_ref2` do overlap in the second example, why compiler cannot tell `mut_ref2` is not used? How clever the Rust compiler is now? – silverwen Aug 13 '23 at 23:05
  • The mere existence of overlapping mutable references, even when one is not used, is not allowed. This is how references work in Rust. – Mark Saving Aug 14 '23 at 03:15

1 Answers1

1

Rust compiler checks wether mutable references are overlapping or not. In yout first example they don't because you don't use the first ref after having declared the second one, but in your next example there is an overlap. It would compile if you just swapped the declarations.

#[derive(Debug)]
struct Value {
    value: i32,
}
#[derive(Debug)]
struct Container {
    value: Value,
    value2: i32,
}
fn main() {
    let mut obj1 = Container {
        value: Value { value: 12 },
        value2: 1,
    };
    
    let mut_ref2 = &mut obj1.value;
    let mut_ref1 = &mut obj1;
    mut_ref1.value2 = 111;
}

It's not about being used or not. The following compiles too

fn main() {
    let mut obj1 = Container {
        value: Value { value: 12 },
        value2: 1,
    };
    
    let mut_ref2 = &mut obj1.value;
    mut_ref2.value = 121;

    let mut_ref1 = &mut obj1;
    mut_ref1.value2 = 111;
}
Peterrabbit
  • 2,166
  • 1
  • 3
  • 19