Skip to content

Rustfmt wrongly reformats qualified paths in a match expression in macro #4908

Closed
@tvercruyssen

Description

@tvercruyssen

Describe the bug

Rustfmt incorrectly formats the new qualified paths in a match expression, in a macro. The change rustfmt makes will make the code no longer compile.

To Reproduce

minimal example:

#![feature(more_qualified_paths)]

mod foo_bar {
    pub enum Example {
        Example1 {},
        Example2 {},
    }
}

fn main() {
    foo!(crate::foo_bar::Example, Example1);

    let i1 = foo_bar::Example::Example1{};

    assert_eq!(i1.foo_example(), 1);

    let i2 = foo_bar::Example::Example2{};

    assert_eq!(i2.foo_example(), 2);

}

#[macro_export]
macro_rules! foo {
    ($struct:path, $variant:ident) => {
        impl $struct {
            pub fn foo_example(&self) -> i32{
                match self {
                    <$struct>::$variant { .. } =>  1,
                    _ => 2,
                }
            }
        }
    };
}

This will compile fine. After running rustfmt the diff is as follows:

@@ -25,7 +25,7 @@
         impl $struct {
             pub fn foo_example(&self) -> i32 {
                 match self {
-                    <$struct>::$variant { .. } => 1,
+                    $variant { .. } => 1,
                     _ => 2,
                 }
             }

This makes the code no longer compile and gives the following error:

error[E0422]: cannot find struct, variant or union type `Example1` in this scope
  --> src/main.rs:11:35
   |
11 |     foo!(crate::foo_bar::Example, Example1);
   |                                   ^^^^^^^^ not found in this scope
   |
help: consider importing this variant
   |
3  | use crate::foo_bar::Example::Example1;
   |

No rustfmt configuration was used.

Expected behavior

Rustfmt should not reformat anything.

Meta

  • tested with both:
    • stable: rustfmt 1.4.37-stable (2a3635d 2021-05-04)
    • nightly: rustfmt 1.4.37-nightly (c7331d6 2021-07-17)
  • From where did you install rustfmt?: rustup
  • How do you run rustfmt: rustfmt src/main.rs
[Sidenote]

I'm aware instead of writing <$struct>::$variant, you could write Self::$variant. This will compile and not be reformatted by rustfmt in this case. But in cases where the impl struct and match expression are not on the same this will not work.

[Disclaimer] This is a nightly feature.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions