rustfmt icon indicating copy to clipboard operation
rustfmt copied to clipboard

Braces are removed from single-item import in macro where they are required

Open junbl opened this issue 1 year ago • 2 comments

In a macro that takes a path as an argument:

macro_rules! get_msg {
    ($module:path) => {
        let message = {
            use $module::{MESSAGE}; // note the (usually unnecessary) brackets
            MESSAGE
        };
        println!("{}", message);
    };
}

The braces around MESSAGE are required, and the code fails to compile without them. However, rustfmt removes them.

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ca5ee49a37c35354f67d82d6303c7f5a

junbl avatar Jan 28 '24 22:01 junbl

@junbl thank you for the report. Confirming I can reproduce this with the latest source version of rustfmt 1.7.0-nightly (cedb7b50 2024-01-25).

Some workarounds until we address this:

  1. You can add a #[rustfmt::skip] attribute to prevent rustfmt from modifying the formatting:

    macro_rules! get_msg {
        ($module:path) => {
            #[rustfmt::skip]
            let message = {
                use $module::{MESSAGE}; // note the (usually unnecessary) brackets
                MESSAGE
            };
            println!("{}", message);
        };
    }
    
  2. If you're using unstable rustfmt features you can turn declarative macro body formatting off by setting format_macro_bodies=false.

Also linking the tracking issue for format_macro_bodies (https://github.com/rust-lang/rustfmt/issues/3355)

ytmimi avatar Jan 28 '24 23:01 ytmimi

Oh, and I'm not sure if this is an option for you, but if the rust playground link shows how you'll actually call the macro (with a single identifier, like get_msg!(x)), then you could possibly rewrite the macro as follows and the code will still compile after rustfmt removes the braces {}:

macro_rules! get_msg {
-    ($module:path) => {
+    ($module:ident) => {
        // this works but the braces in the import get lost on format
        let message = {
            use $module::{MESSAGE};
            MESSAGE
        };

        // this would be nicer but doesn't work
        // let message = $module::MESSAGE;

        println!("{}", message);
    };
}

ytmimi avatar Jan 29 '24 00:01 ytmimi