Skip to content

mod statements in macro expansions aren't recursively formatted #6587

Closed as not planned
@bal-e

Description

@bal-e

rustfmt will inspect the files it is passed for mod statements, and will recursively traverse them to format entire crates. cargo fmt relies on this too, passing src/lib.rs to get an entire library crate formatted. Unfortunately, rustfmt misses submodules if their mod statements come from macro expansions. For example:

  • src/main.rs:
macro_rules! foo {
    () => {
        mod bar;
    };
}

foo!();

fn main() {
    println!("Hello, world!");
    println!("{}", bar::foo(42));
}
  • src/bar.rs:
pub fn foo
(a: u8)
-> u8
{ a }

Steps:

  • cargo new --bin macro-expn-bug
  • cd macro-expn-bug
  • Set up src/main.rs and src/bar.rs as above
  • cargo fmt --check

Expected output:

rustfmt --check --edition 2021 src/bar.rs
Diff in /tmp/rustfmt-bug/src/bar.rs:1:
-pub fn foo
-(a: u8)
--> u8
-{ a }
+pub fn foo(a: u8) -> u8 {
+    a
+}

Actual output: empty.

We assumed this behavior would work in a production Rust library (https://github.com/NLnetLabs/domain), and misformatted source files have laid dormant in the codebase for over a year. From a practical perspective, I understand that fixing this will not be easy; but silently succeeding isn't okay. Perhaps rustfmt can compare the list of files it traversed to the list of files traversed by cargo check or similar? I'm also not sure how this interacts with feature flags.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions