Rust method calls are desugared to fully-qualified-syntax and function parameters are evaluated left to right. Why then does s.by_mut(s.by_ref(())) compile while other
expressions don't?
struct S;
impl S {
fn by_ref(&self, _arg: ()) {}
fn by_mut(&mut self, _arg: ()) {}
}
fn foo() {
let mut s = S;
s.by_mut(s.by_ref(())); // compiles, but why?
s.by_mut(s.by_mut(())); // [E0499] cannot borrow `s` as mutable more than once at a time
// expected desugarings as per https://doc.rust-lang.org/reference/expressions/call-expr.html#r-expr.call.desugar
S::by_mut(&mut s, S::by_ref(&s, ())); // [E0502] cannot borrow `s` as immutable because it is also borrowed as mutable
S::by_mut(&mut s, S::by_mut(&mut s, ())); // [E0499] cannot borrow `s` as mutable more than once at a time
(&mut s).by_mut((&s).by_ref(())); // [E0502] cannot borrow `s` as immutable because it is also borrowed as mutable
(&mut s).by_mut((&mut s).by_mut(())); // [E0499] cannot borrow `s` as mutable more than once at a time
}
Switching by_ref to take self and using #[derive(Clone, Copy)], or using a type like String rather than () changes nothing.
Switching the order of by_ref and by_mut gives similar results. Notably s.by_ref(s.by_mut(())) does not compile.
fn bar() {
let mut s = S;
s.by_ref(s.by_mut(())); // [E0502] cannot borrow `s` as mutable because it is also borrowed as immutable
s.by_ref(s.by_ref(())); // very much okay
// expected desugarings
S::by_ref(&s, S::by_mut(&mut s, ())); // [E0502] cannot borrow `s` as mutable because it is also borrowed as immutable
S::by_ref(&s, S::by_ref(&s, ())); // very much okay
(&s).by_ref((&mut s).by_mut(())); // [E0502] cannot borrow `s` as mutable because it is also borrowed as immutable
(&s).by_ref((&s).by_ref(())); // very much okay
}
I expected s.by_mut(s.by_ref(())), s.by_mut(s.by_mut(())), and s.by_ref(s.by_mut(())) to either all compile or all not to compile.