I'm trying to learn rust and came upon an issue with function evaluation order. When I call something such as a.do(f(x)), I expect f(x) to be evaluated before .do(), but the borrow checker doesn't seem to agree. The following example shows such a case:
When I call something such as a.do(f(x)) , I expect f(x) to be evaluated before .do() ,
It's not that .do is evaluated sooner; it's that a is. Consider this more complex case:
f1().foo(f2()).bar(f3())
I imagine you would agree that f1(), f2(), f3() should be called in that order. So, method call receivers must be evaluated before method call arguments. (The full ordering of calls is f1() f2() foo() f3() bar().)
Now, Rust does actually have a convenience to make this common pattern work for mutable borrows, called “two-phase borrows”. That is, this code works:
However, that works by creating the &mut blob that mutate_with needs in a special “reserved” state, which doesn't conflict with &blob because it isn't actually used until we're done with f(&blob). There's no analogue of this for moves. (Perhaps there should be, but the language doesn't have it.)