The key aspect of mutable links is that they are only guaranteed to have access to a specific value during their existence (unless they are reinstalled, which temporarily disables them).
When you write
self.a.do_something(&self.b);
the compiler can see that the loan on self.a (which is implicitly used to call the method) is different from borrowing on self.b because it can talk about direct calls to the field.
However, when you write
self.a.do_something(self.get_b());
then the compiler does not see a loan on self.b , but rather a loan on self . This is because lifetime parameters on method signatures cannot propagate such detailed information about records. Therefore, the compiler cannot guarantee that the value returned by self.get_b() will not give you access to self.a , which will create two links that can access self.a , one of which is mutable, which is illegal.
Reason field fields are not propagated through functions to simplify type checking and borrow checking (for cars and people). The principle is that the signature should be sufficient to perform these tasks: a change in the implementation of a function should not cause errors in its callers.
What if I need to do something more complex than just returning a member to get an argument for a.do_something() ?
I would move get_b from State to B and get_b on self.b Thus, the compiler can see individual entries on self.a and self.b and will accept the code.
self.a.do_something(self.b.get_b());
source share