The statement is evaluated left to right. Imagine that f in the expression f.bar() is a method call instead, like get_f().bar(get_f().bar(1)). You can see that a second get_f() is called after the first get_f().
In Rust this f. is not a syntactic detail. It is evaluated as an action of taking an exclusive reference, so the exclusive reference is taken first, before Rust looks at the arguments.
The one-liner runs: get_f(); get_f(); bar(); bar();
The two-line version runs get_f(); bar(); get_f(); bar();
So introduction of a variable is a fine way to solve the issue.