Skip to content

rustfmt breaks macro code #6629

@sisungo

Description

@sisungo

I tried this code:

#[macro_export]
macro_rules! bitflags_impl_to_apple {
    ($self:ident = $($x:ident),*) => {{
        let mut apple = 0;
        $(
            if $self.contains(Self::$x) {
                apple |= libc::$x;
            }
        )*
        apple
    }};
}

#[macro_export]
macro_rules! bitflags_impl_from_apple {
    ($apple:ident = $($x:ident),*) => {{
        let mut linux = Self::empty();
        $(
            if ($apple & libc::$x) != 0 {
                linux |= Self::$x;
            }
        )*
        linux
    }};
}

#[macro_export]
macro_rules! bitflags_impl_from_to_apple_permissive {
    (type Apple = $ty:ty; values = $($x:ident),*) => {
        pub fn from_apple(apple: $ty) -> Self {
            $crate::bitflags_impl_from_apple!(apple = $($x),*)
        }

        pub fn to_apple(self) -> $ty {
            $crate::bitflags_impl_to_apple!(self = $($x),*)
        }
    };
}

bitflags::bitflags! {
    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub struct OpenFlags: u32 {
        const O_RDONLY = 0;
        const O_WRONLY = 1;
        const O_RDWR = 2;
        const O_CREAT = 0o100;
        const O_EXCL = 0o200;
        const O_NOCTTY = 0o400;
        const O_TRUNC = 0o1000;
        const O_NONBLOCK = 0o4000;
        const O_DSYNC = 0o10000;
        const O_ASYNC = 0o20000;
        const O_DIRECT = 0o40000;
        const O_LARGEFILE = 0o100000;
        const O_DIRECTORY = 0o200000;
        const O_NOFOLLOW = 0o400000;
        const O_NOATIME = 0o1000000;
        const O_CLOEXEC = 0o2000000;
        const O_SYNC = 0o4010000;
        const O_PATH = 0o10000000;
        const O_TMPFILE = 0o20200000;
    }
}
impl OpenFlags {
    bitflags_impl_from_to_apple_permissive!(
        type Apple = libc::c_int;
        values = O_RDONLY,
        O_WRONLY,
        O_RDWR,
        O_CREAT,
        O_EXCL,
        O_NOCTTY,
        O_TRUNC,
        O_NONBLOCK,
        O_DSYNC,
        O_ASYNC,
        O_DIRECTORY,
        O_NOFOLLOW,
        O_CLOEXEC,
        O_SYNC
    );
}

The source is available at Rust Playground. It compiles and runs well.

I will run rustfmt for this using latest nightly Rust.

I expected to see this happen: The code is correctly formatted.

Instead, this happened: It formats to:

// ...
bitflags_impl_from_to_apple_permissive!(
        type Apple = libc::c_int;,
// ...

The resulted code won't compile.

Meta

rustc --version --verbose:

rustc 1.91.0-nightly (de3efa79f 2025-08-08)
binary: rustc
commit-hash: de3efa79f95852c7427587f1d535bfea7c0d6779
commit-date: 2025-08-08
host: aarch64-apple-darwin
release: 1.91.0-nightly
LLVM version: 21.1.0
Backtrace

<backtrace>

Metadata

Metadata

Assignees

No one assigned

    Labels

    a-macrosbugPanic, non-idempotency, invalid code, etc.

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions