macros: Trailing expression statement macros expand inconsistently

fab418f
Opened by Jeffrey Seyfried at 2021-04-21 18:24:10

Macro-expanded trailing expression statement macros expand into statements, but unexpanded trailing expression statement macros expand into expressions. For example,

macro_rules! m { () => { let x = 0; } }

macro_rules! n { () => {
    let y = 0;
    m!() // Since `m!()` expands into statements, this is ok
}}

fn main() {
    n!();
    let x = 0;
    m!() // Since `m!()` expands into an expression, this is not ok
}

One way to fix this is to make all trailing expression statement macros expand into statements. When (if?) #34706 gets fixed, this will be backwards compatible. However, today it isn't:

macro_rules! m { () => { 1; } }
fn f() -> i32 {
    m!() // The trailing semicolon on `1` is ignored today, so this typechecks.
         // If `m!()` were expanded into statements, the trailing semicolon
         // would not be ignored, so this would break.
}
  1. cc @nrc

    Jeffrey Seyfried at 2016-07-07 20:27:02

  2. The first crater run in #34660 approximates the breakage from making all trailing expression statement macros expand into statements.

    The second crater run in #34660 approximates the breakage from making all trailing expression statement macros expand into statements.

    Jeffrey Seyfried at 2016-07-07 20:31:22

  3. Triage: still seems to be the case, I think?

    Steve Klabnik at 2021-04-21 18:15:55

  4. https://github.com/rust-lang/rust/pull/78991 tries to fix this, but there's some breakage that needs to be addressed.

    Vadim Petrochenkov at 2021-04-21 18:24:10