rustfmt can't understand configured module path attributes

Created on 2 Feb 2018  Â·  10Comments  Â·  Source: rust-lang/rustfmt

I have a module that has different implementations depending on what the target is. I use #[cfg_attr(..., path = "...")] to choose the correct implementation.

https://github.com/fitzgen/wee_alloc/blob/master/wee_alloc/src/lib.rs#L237-L246

#[cfg(all(not(unix), not(target_arch = "wasm32")))]
compile_error! {
    "There is no `wee_alloc` implementation for this target; want to send a pull request? :)"
}

#[cfg_attr(target_arch = "wasm32",
           path = "./imp_wasm32.rs")]
#[cfg_attr(all(unix, not(target_arch = "wasm32")),
           path = "./imp_unix.rs")]
mod imp;

rustfmt seems unable to handle this:

$ cargo fmt --all
error[E0583]: file not found for module `imp`
   --> /home/fitzgen/wee_alloc/wee_alloc/src/lib.rs:246:5
    |
246 | mod imp;
    |     ^^^
    |
    = help: name the file either imp.rs or imp/mod.rs inside the directory "/home/fitzgen/wee_alloc/wee_alloc/src"

I would expect that it would use the host target by default, or otherwise maybe hit the compile_error or something.

$ cargo fmt --version
0.3.6-nightly (e0e3e22 2018-01-18)

Full Steps to Reproduce

bug p-high

All 10 comments

For anyone else who hits this issue, as a workaround, if I change my code to

#[cfg(all(not(unix), not(target_arch = "wasm32")))]
compile_error! {
    "There is no `wee_alloc` implementation for this target; want to send a pull request? :)"
}

#[cfg(target_arch = "wasm32")]
mod imp_wasm32;
#[cfg(target_arch = "wasm32")]
use imp_wasm32 as imp;

#[cfg(all(unix, not(target_arch = "wasm32")))]
mod imp_unix;
#[cfg(all(unix, not(target_arch = "wasm32")))]
use imp_unix as imp;

then cargo fmt --all works.

cc #1208.

I think we need to mimic some setups of rustc (ones in librustc_driver). I am not sure how, though.

fwiw, clippy is also having issues with cfg_attr: https://github.com/rust-lang-nursery/rust-clippy/issues/1522

I guess it's the same cause? Unfortunately I don't know enough about the compiler internals yet, to be sure.

Edit: On reflection, I filed a separate issue for this (#3427) as it seems related but separate.

This is now an issue with Rust 2018's path clarity, where submodules no longer require mod.rs. Example:

$ mkdir foo
$ touch foo/bar.rs
$ echo 'mod bar;' > foo.rs
$ rustfmt --edition 2018 foo.rs
error[E0583]: file not found for module `bar`
 --> /private/tmp/demo/foo.rs:1:5
  |
1 | mod bar;
  |     ^^^
  |
  = help: name the file either bar.rs or bar/mod.rs inside the directory "/private/tmp/demo"

For clarity, the file structure is:

$ tree
.
├── foo
│   └── bar.rs
└── foo.rs

Here, foo.rs is the Rust 2018 equivalent of Rust 2015's foo/mod.rs.

Just meet this on my code, my code is:

````

[cfg_attr(feature = "winit", path = "ui_winit.rs")]

[cfg_attr(not(feature = "winit"), path = "ui_apiw.rs")]

mod ui;
````

I have hit this issue as well here.

Note that we cannot completely support the cases like https://github.com/rust-lang/rustfmt/issues/2407#issuecomment-497926838, given the current design of rustfmt, whose main data structure is the AST from the rust compiler. Which files to be formatted will be feature/platform dependent.

@carllerche With respect to your project (loom), are these two files ([1] [2]) part of your crate? IIUC they aren't referenced at all in the crate.

Asking because when testing with #3604 these two files weren't formatted when running cargo fmt. I would like to know if this is a bug or not.

[1] https://github.com/carllerche/loom/blob/981e6f60db2b71c515ab46c4c68c1d975220ce6e/src/rt/scheduler/fringe.rs
[2] https://github.com/carllerche/loom/blob/981e6f60db2b71c515ab46c4c68c1d975220ce6e/src/rt/scheduler/gen.rs

@topecongiro fringe is not currently (commented out), but gen is enabled via feature flag and cfg guard.

Was this page helpful?
0 / 5 - 0 ratings