where both a and b take self as &mut self. In this case the compiler complains with
error[E0499]: cannot borrow `*self` as mutable more than once at a time and suggests to introduce explicit variables, to look it like this
let b_val = self.b();
It is surprising to me because all argument values of a function should be known before call. This guarantees that no reference is held by argument calculations before calling the outer method, unless some of the returned values still keep references to self, which is not the case in this example. The argument expressions cannot be used anywhere outside the call. Therefore the code with an explicit var should be exactly equivalent with the shorter form.
So I wonder if this is a problem with the compiler implementation so it cannot resolve this situation automatically, or there are some other issues in the language itself that could cause a problem if compiler does it?
self.a(self.b()) can be desugared more or less to:
let receiver = self;
let argument = self.b();
As you can see the receiver is evaluated before the arguments. This was chosen because generally in a.b().c(d()) you don't expect the call to d() to happen before the a.b(). However as you noticed it creates a problem when you want to use the receiver to compute some argument.
There have been proposals to solve this problem, most notably RFC 2025 with the concept of two-phase borrows, however it limits the cases where this can happen to the ones where the borrow to compute the argument is a shared borrow, which is not the case in your example.
Can compiler do a topological sort according to the dependencies, at least within single expression? I believe there can be a procedure that is deterministic so the order will always be the same for the same expression shape. I mean, in this case self.a(...) -needs-> self.b() that would make self.b() to be evaluated first.