9

I was looking at the vec![] macro implementation in Rust and noticed it uses the __rust_force_expr! macro. This is the implementation of the latter:

/// Force AST node to an expression to improve diagnostics in pattern position.
#[doc(hidden)]
#[macro_export]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
macro_rules! __rust_force_expr {
    ($e:expr) => {
        $e
    };
}

Could someone shed more light into what it does exactly?

0

1 Answer 1

9

It doesn't have any result on how the macro is used, it only serves to improve the quality of error messages when the macro is used incorrectly by telling the compiler that the output of the macro is always a single expression, not an item or multiple expressions.

The specific error that this was added to improve was for using vec![] in a pattern match, which is invalid (you can't structually match on a Vec):

let x: Option<Vec<i32>> = Some(vec![]);
match x {
    Some(my_vec![]) => println!("1"),
    _ => println!("2"),
};

results in

error[E0164]: expected tuple struct or tuple variant, found associated function `Vec::new`
  --> src/main.rs:9:9
   |
9  |         Vec::new()
   |         ^^^^^^^^^^ `fn` calls are not allowed in patterns
...
15 |     Some(my_vec![]) => println!("1"),
   |          --------- in this macro invocation
   |
   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
   = note: this error originates in the macro `mvec` (in Nightly builds, run with -Z macro-backtrace for more info)

This is a fairly confusing error, especially when using the vec![1, 2, 3] syntax. It doesn't look like are any function calls in the caller. But by wrapping the body of vec! with __rust_force_expr, we get a better error:

error: arbitrary expressions aren't allowed in patterns
  --> src/main.rs:15:10
   |
15 |     Some(vec![]) => println!("1"),
   |          ^^^^^^
   |
   = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)

This makes a lot more sense: vec![] produces an expression, and there are no reference to function calls that are behind a macro.

Not the answer you're looking for? Browse other questions tagged or ask your own question.