What exactly does __rust_force_expr do?
Asked Answered
H

1

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?

Halden answered 18/12, 2021 at 10:9 Comment(0)
U
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.

Unbound answered 18/12, 2021 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.