Macros and operator precedence
⚓ Rust 📅 2025-09-30 👤 surdeus 👁️ 5I'm trying to understand how declarative macros deal with operator precedence. The following example shows a macro invocation and the expression you would get if you naively unfolded the macro by inlining the argument tokens. These behave differently, which shows that the macro is doing something smarter.
macro_rules! assert_ {
    ($e:expr) => {
        if !$e {
            println!("this doesn't print")
        }
    }
}
pub fn main() {
    assert_!(0usize != 1);
    if !0usize != 1 {
        println!("this prints")
    }
}
One may have their own guesses as to what is going on, but is this behavior actually documented somewhere so I can read more about it?
The reason I was surprised by this is that I had a variant of such a macro where the body is wrapped in a proc macro, which then parses the expansion of !$e naively again. So I'm looking for a semi-formal description of macro expansion to see if there are more surprises of that kind to be aware of.
1 post - 1 participant
🏷️ Rust_feed