Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly does __rust_force_expr do?

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?

like image 772
at54321 Avatar asked Dec 18 '21 10:12

at54321


1 Answers

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.

like image 191
Smitop Avatar answered Sep 28 '22 10:09

Smitop