There is no real reason per se, I'd say, it's rather an unhappy byproduct of how everything else in Rust works.
In this case, there are two things going on / to be aware of:
-
Expression / statement temporaries, and when they are dropped.
That is, the "eta-expanded" / "outlined (2nd) arg" version of:
let x1 = t.touch(t.touch(6));
is actually:
// if this expression created temporaries ... // vvvvvvvvvv | let x1 = match t.touch(6) { x0 => { // | t.touch(x0) // -- borrow of `t` ---->| }}; // <-- ... they'd be dropped here ---+
That is, the temporaries created by
t.touch(6)
(if any) are only dropped after the outer call, so if one of these temporaries had drop glue, and borrowed fromt
, then the compiler would be right in forbidding thet.touch( t.touch(6) )
call.- Granted, it is not the case in your example, but a sneakier one could feature it.
This "problem" would not be present if rewriting the code as:
let x1 = { let x0 = t.touch(6); // ---------+ // <-- temporaries dropped here -+ t.touch(x0) };
This is to say that no matter what I'll say in the following section, there is a semantic difference between your two versions; if you want to "eta expand" / "outline a temporary as an expression", then the
match
is the actual way of writing it (featuringlet ... in
/ scopedlet
semantics). -
Order of evaluation of function args.
This has to do with the fact that, if you wrote:
fn touch_into (amt: i32, at_t: &mut Obj) -> i32 { at_t.touch(amt) }
then:
let x0 = touch_into(t.touch(6), &mut t);
How so? Well, because the expression
t.touch(6)
is evaluated first, the borrow has the time to end, and only then is&mut t
evaluated, avoiding the conflicting borrow.but in your example, if we were to write in in fully desugared form, we'd have:
t.touch(t.touch(6))
becomes
Obj::touch(&mut t, t.touch(6))
which becomes:
match &mut t { arg0 => { // vvvvvvvvvv - Error, t is already being borrowed. match t.touch(6) { arg1 => { Obj::touch(arg0, arg1) } }
As you can see, you hit a limitation whereby order of evaluation leads to the borrow on the "left
t
" to start before the borrow on the "rightt
".