Search code examples
rustrust-macros

How to pass a visibility token to the bitflags! macro?


I'm using the bitflags crate. I want to automatically generate some other implementations for my types, so I tried to call the bitflags! macro from another macro. This worked fine until I wanted to be able to handle a visibility token.

I tried the following code.

Playground

use bitflags::bitflags;

macro_rules! my_bitflags {
    (
        $(#[$outer:meta])*
        $vis:vis struct $name:ident: $ty:ty {
            $(
                $(#[$inner:ident $($args:tt)*])*
                const $flag:ident = $value:expr;
            )+
        }
    ) => {
        bitflags! {
            $(#[$outer])*
            $vis struct $name: $ty {
                $(
                    $(#[$inner $($args)*])*
                    const $flag = $value;
                )+
            }
        }
        
        // other implementations on $name here
        // 
    }
}


my_bitflags! {
    pub struct Flags: u32 {
        const A = 0x1;
        const B = 0x2;
        const C = 0x4;
    }
}

I expected this to work but I get the following error

error: no rules expected the token `pub `

Is this an issue with the bitflags! macro? Or am I passing the visibility token incorrectly?


Solution

  • $vis in bitflags! is defined as a token tree (tt), not as visibility (vis). Visibility was only "recently" introduced to rustc and the bitflags! macro stays backward-compatible by not redefining $vis.

    You need to change $vis:vis to $vis:tt in my_bitflags! so it can expand into bitflags!.