Skip to content

rustfmt fails to resolve mod foo; decorated by an attribute macro #6959

Closed
rust-lang/rust
#159737

Description

@zhoukezi

Summary

#[my_macro] mod foo; (an "outlined" module supplied to an attribute/derive proc
macro) was recently stabilized on nightly by rust-lang/rust#157857.
In this form the module body can be provided by the macro, so there is intentionally
no foo.rs / foo/mod.rs on disk.

rustfmt, however, seems unconditionally try to resolve every mod foo; to a file
on disk and aborts the entire run when the file is missing, regardless of whether
the module is decorated by an attribute macro.

Expected behavior

rustfmt formats the file (or at least leaves the #[my_macro] mod foo; item
untouched and continues) without requiring a foo.rs file to exist on disk,
since the attribute macro provides the module body.

Actual behavior

rustfmt aborts with a module resolution error and exits non-zero:

Error writing files: failed to resolve mod `foo`: /tmp/foo.rs does not exist

Configuration

Nothing special. Nightly rustfmt.

Reproduction Steps

> cat test.rs
#[my_macro]
mod foo;
> rustfmt +nightly --edition 2024 test.rs
Error writing files: failed to resolve mod `foo`: /tmp/foo.rs does not exist

Nightly rust currently accepts this code (after replacing the placeholder with a real proc-macro that supports this syntax).

Meta

rustfmt --version:

rustfmt 1.9.0-nightly (d0babd8b6b 2026-07-15)

Activity

  1. added
    C-bugCategory: this is a bug; use also I-* labels for specific bug kinds, e.g. I-non-idempotency or I-ICE
    on Jul 16, 2026
  2. added
    needs-triageThis issue or PR needs triaging to determine its status. Remove label once sufficiently triaged.
    on Jul 16, 2026
  3. ytmimi commented on Jul 16, 2026

    @ytmimi
    Contributor

    I had no idea that #[my_macro] was even a thing. Is rust-lang/rust#54727 the right tracking issue for this?

    So basically if rustfmt sees a #[my_macro] over a module declaration then it shouldn't try to resolve it? @zhoukezi let me know if I'm understanding that correctly.

  4. zhoukezi commented on Jul 20, 2026

    @zhoukezi
    Author

    @ytmimi

    Is rust-lang/rust#54727 the right tracking issue for this?

    As far as I know, rust-lang/rust#54727 is the larger tracking issue for #![feature(proc_macro_hygiene)], of which #[my_macro] mod foo; is a part. #[my_macro] mod foo; itself was discussed in rust-lang/rust#54727 (comment) and independently stabilized in rust-lang/rust#157857. I'm not entirely sure whether rust-lang/rust#54727 is the right reference in your context.

    So basically if rustfmt sees a #[my_macro] over a module declaration then it shouldn't try to resolve it?

    I think that would address the issue I'm running into. rust-lang/rust#157857 passes mod foo; as tokens directly to #[my_macro], so there's no reason to assume foo.rs exists on disk, or even that the macro will emit any module at all. That said, to be cautious, I'm not sure whether this would affect rustfmt's own internals or other edge cases. mod is admittedly special syntax.

  5. TimNN commented on Jul 21, 2026

    @TimNN

    For my use case, the module always really exists (even when annotated with #[my_macro]), so I never ran into this. Annotating the module with #[rustfmt::skip] seems to work to suppress the error.

    Maybe rustfmt could just fail more gracefully if it cannot resolve a module, if that module is also annotated with a custom proc macro?

  6. petrochenkov commented on Jul 21, 2026

    @petrochenkov
    Contributor

    Can rustfmt try to load the module (there's a good chance that the module will indeed be there), and not report anything if the module loading fails?

    How does rustfmt work with cases like this?

    #[cfg(false)]
    mod foo;
    
    #[cfg(false)]
    mod foo {
      mod bar;
    }
  7. ytmimi commented on Jul 21, 2026

    @ytmimi
    Contributor

    Can rustfmt try to load the module (there's a good chance that the module will indeed be there), and not report anything if the module loading fails?

    @petrochenkov I think your idea could work. We could special case the fallback behavior for#[my_macro] to just ignore errors and move on. I feel like it's probably okay to special case things for #[my_macro], but I'm not sure I'd want to ignore module resolution errors in all cases.

    In the example above rustfmt will try to load mod foo;, which fails. Even if modules are annotated with #[cfg(false)] rustfmt will try to find the file that the module corresponds to (unless you're running rustfmt with --skip-children or via stdin).

  8. added 2 commits that reference this issue on Jul 23, 2026
    6ab31dd
    e701378
  9. removed
    needs-triageThis issue or PR needs triaging to determine its status. Remove label once sufficiently triaged.
    on Jul 27, 2026
  10. added a commit that references this issue on Aug 28, 2026
    7ec361d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: this is a bug; use also I-* labels for specific bug kinds, e.g. I-non-idempotency or I-ICE

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions