Skip to content

Cannot generate unit struct with a macros #46927

@RReverser

Description

@RReverser

It doesn't seem possible to generate unit struct declaration from a macros in neither stable nor nightly version of Rust.

A simplified playground sample:

macro_rules! def_struct {
  ($name:ident $($body:tt)*) => {
    pub struct $name $($body)*
  };
}

def_struct!(X {}); // compiles
def_struct!(Y); // doesn't

fn main() {}

When trying to expand the second macro call, Rust complains:

error: expected `where`, `{`, `(`, or `;` after struct name, found `<eof>`
 --> src/main.rs:3:16
  |
3 |     pub struct $name $($body)*
  |                ^^^^^
...
8 | def_struct!(Y); // doesn't
  | --------------- in this macro invocation

If I add a semicolon as it asks right after the struct definition, the unit macro call starts compiling fine:

macro_rules! def_struct {
  ($name:ident $($body:tt)*) => {
    pub struct $name $($body)*;
  };
}

def_struct!(Y); // compiles
def_struct!(X {}); // doesn't

fn main() {}

but the other one fails instead:

error: macro expansion ignores token `;` and any following
 --> src/main.rs:3:31
  |
3 |     pub struct $name $($body)*;
  |                               ^
  |
note: caused by the macro expansion here; the usage of `def_struct!` is likely invalid in item context
 --> src/main.rs:8:1
  |
8 | def_struct!(X {}); // compiles
  | ^^^^^^^^^^^^^^^^^^

The two errors seem to contradict each other here. The only obvious workaround to make both cases work I could find is to split macro definition into two, one with semicolon and another without:

macro_rules! def_struct {
  ($name:ident) => {
    pub struct $name;
  };
  
  ($name:ident $body:tt) => {
    pub struct $name $body
  }
}

def_struct!(X {}); // compiles
def_struct!(Y); // compiles

fn main() {}

But this is not very clean and gets even harder in more complicated macros. Is there any reason for such behaviour or is it a bug and it would be possible to allow macro to generate unit structs that are not followed by a semicolon, just like any other?

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions