A key aspect of mutable references is that they are guaranteed to be the only way to access a particular value while they exist (unless they're reborrowed, which "disables" them temporarily).
When you write
self.a.do_something(&self.b);
the compiler is able to see that the borrow on self.a
(which is taken implicitly to perform the method call) is distinct from the borrow on self.b
, because it can reason about direct field accesses.
However, when you write
self.a.do_something(self.get_b());
then the compiler doesn't see a borrow on self.b
, but rather a borrow on self
. That's because lifetime parameters on method signatures cannot propagate such detailed information about borrows. Therefore, the compiler cannot guarantee that the value returned by self.get_b()
doesn't give you access to self.a
, which would create two references that can access self.a
, one of them being mutable, which is illegal.
The reason field borrows don't propagate across functions is to simplify type checking and borrow checking (for machines and for humans). The principle is that the signature should be sufficient for performing those tasks: changing 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 in order to get the argument for a.do_something()
?
I would move get_b
from State
to B
and call get_b
on self.b
. This way, the compiler can see the distinct borrows on self.a
and self.b
and will accept the code.
self.a.do_something(self.b.get_b());
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…