Macro parameters order question

I tested some pattern, and I found an unwonted things.
Here is my example code: Rust Playground
If I use macro, the mutable parameters works inversely than the function.

Why?

Try to be more specific with your question. I cannot see any weird behavior w.r.t. order of parameter evaluation anywhere in your code, and the comments don’t point out anything either. The only point of confusion I can spot is in the last line regarding the last compile error. In order to understand the problem there, you’ll need to know that println and other formatting macros implicitly take a reference to all the provided arguments, so calling println!("{} {} {}", FOO, BAR, BAZ); behaves like calling a function print_three_things(&FOO, &BAR, &BAZ)

fn print_three_things(x: &impl Display, y: &impl Display, z: &impl Display) {
    println!("{} {} {}", *x, *y, *z);
}
    let mut x = 42;
    let mut y = 52;
    print_three_things(&dec(&mut x), &x, &dec(&mut y));
    // print_three_things(&dec(&mut x), &y, &dec(&mut y)); // compile error!

Thank you for fast answer. Here is a simpler example:
Rust Playground

I do not understand, why can't compile, if the second parameter is mutable, and why can I compile, if first is mutable?
I think, the "Test2" is good. Why not?

Well, that’s precisely the thing I described above.

Compare your simplified example with this mostly equivalent, and macro-free (in the main function) code

use std::fmt::Display;
fn print_two_things(x: &impl Display, y: &impl Display) {
    println!("{} {}", *x, *y);
}

#[inline(always)]
fn dec(i: &mut i32) -> i32 {
    *i -= 1;
    *i
}

fn main() {
    let mut x = 42;
    print_two_things(&dec(&mut x), &x); // Test1 - ok
    print_two_things(&x, &dec(&mut x)); // Test2 - compile error
}
   Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
  --> src/main.rs:15:31
   |
15 |     print_two_things(&x, &dec(&mut x)); // Test2 - compile error
   |     ---------------- --       ^^^^^^ mutable borrow occurs here
   |     |                |
   |     |                immutable borrow occurs here
   |     immutable borrow later used by call

For more information about this error, try `rustc --explain E0502`.

Or, to be even more clear, let’s break it down into dedicated variables for the function arguments:

fn main() {
    let mut x = 42;
    // Test1 - ok
    {
        let first_arg = &dec(&mut x);
        let second_arg = &x;
        print_two_things(first_arg, second_arg);
    }
    // Test2 - compile error
    {
        let first_arg = &x;
        let second_arg = &dec(&mut x);
        print_two_things(first_arg, second_arg);
    }
}
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
  --> src/main.rs:23:31
   |
22 |         let first_arg = &x;
   |                         -- immutable borrow occurs here
23 |         let second_arg = &dec(&mut x);
   |                               ^^^^^^ mutable borrow occurs here
24 |         print_two_things(first_arg, second_arg);
   |                          --------- immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.

See also: E0502 – Rust Compiler Error Index

2 Likes

In order to fix the compilation error in your simplified example, you can either

  • store the values you want to print in some variables beforehand
    let (a, b) = (x, dec(&mut x));
    println!("macro: {} {}", a, b); // Test2 - ok
    
  • force a copy directly, e.g. by using a block
    println!("macro: {} {}", {x}, dec(&mut x)); // Test2 - ok
    

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.