Skip to content

Macro Invocations Behave Questionable Regarding Semicolons #70432

Open
@steffahn

Description

@steffahn

Calling Statement Macros with “return values”?

Macros can be used both for expressions and for sequences of statements. The latter being useful to create new definitions (e.g. one or even multiple let clause(s)).

I’m observing that the general rule that expressions ending in a “Block” of type () don’t need a semicolon when used as a statement translates in a weird way to even macros with multiple statements. For example

macro_rules! s {
    ($x:ident) => {
        let $x = 1;
        "hello world"
    }
}

can’t be used as s!{x}. However s!{x}; does work (as does s!(x);). I’m questioning how sensible it is to support these kind of macros since they have some kind of “return value”, whose type even is relevant for if they need a trailing ;, while the “return value” cannot actually in any way (that I can think of) be retrieved.

A way nicer approach at resolving the non-working s!{x} is of course to change the macro:

macro_rules! s {
    ($x:ident) => {
        let $x = 1;
        "hello world"; // ⟵ added semicolon
    }
}

Ignored Semicolon

One (or at least I) would expect the macro m1 below to produce just a statement (judging from the semicolon), i.e. be illegal in expression context. However it somehow does pass as an expression, totally ignoring the semicolon. In the return position of a function it does produce () though [when called like m1!{} – on the other hand m1!() would still produce the integer].

macro_rules! m1 {
    () => {
        1;
    }
}
macro_rules! m2 {
    () => {
        1
    }
}

fn main() {
    let x1 = m1!{};
    println!("{}", x1);
    let x2 = m1!{};
    println!("{}", x2);

    m1!();
    m1!{}
    
    m2!();
//  m2!{}     // illegal
    m2!{};
    
    m1!{}     // apparently even returns ()
}

(Playground)

Output:

1
1

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.40s
     Running `target/debug/playground`

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-frontendArea: Compiler frontend (errors, parsing and HIR)A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-parserArea: The lexing & parsing of Rust source code to an ASTC-bugCategory: This is a bug.T-langRelevant to the language team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions