diff --git a/src/modules.rs b/src/modules.rs index 099a6442821..fd03b16d12c 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -92,11 +92,49 @@ pub(crate) enum ModuleResolutionErrorKind { #[derive(Clone)] enum SubModKind<'a, 'ast> { /// `mod foo;` + /// + /// Can optionally specify a path attribute to explicitly set the module path. + /// ```ignore + /// mod foo; // resolves to `./foo.rs` or `./foo/mod.rs` + /// + /// #[path = "baz.rs"] + /// mod foo; // explicitly resolves to `./baz.rs` + /// ``` External(PathBuf, DirectoryOwnership, Module<'ast>), - /// `mod foo;` with multiple sources. + /// `mod foo;` with multiple `#[cfg_attr]` sources. + /// + /// ```ignore + /// #[cfg_attr(unix, path = "unix.rs")] + /// #[cfg_attr(not(unix), path = "not_unix.rs")] + /// mod foo; // explicitly resolves to both `./unix.rs` and `./not_unix.rs` + /// ``` MultiExternal(Vec<(PathBuf, DirectoryOwnership, Module<'ast>)>), /// `mod foo {}` + /// + /// Can optionally specify a path attribute that changes resolution for nested modules. + /// ```ignore + /// mod foo { + /// mod baz; // resolves to `./foo/baz.rs` or `./foo/baz/mod.rs` + /// } + /// + /// #[path = "bar"] + /// mod foo { + /// mod baz; // resolves to `./bar/baz.rs` or `./bar/baz/mod.rs` + /// } + /// ``` Internal(&'a ast::Item), + /// `mod foo {}` with multiple `#[cfg_attr]` sources. + /// + /// ```ignore + /// #[cfg_attr(unix, path = "unix")] + /// #[cfg_attr(not(unix), path = "not_unix")] + /// mod foo { + /// // explicitly resolves to `./unix/baz.rs` or `./unix/baz/mod.rs` + /// // and `./not_unix/baz.rs` or `./not_unix/baz/mod.rs` + /// mod baz; + /// } + /// ``` + MultiInternal(Vec), } impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { @@ -279,7 +317,24 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { self.find_external_module(item.kind.ident().unwrap(), &item.attrs, sub_mod) } else { // An internal module (`mod foo { /* ... */ }`); - Ok(Some(SubModKind::Internal(item))) + let mut path_visitor = visitor::PathVisitor::default(); + for attr in item.attrs.iter() { + if let Some(meta) = attr.meta() { + path_visitor.visit_meta_item(&meta) + } + } + + let cfg_attr_paths = path_visitor + .paths() + .iter() + .map(|path| self.directory.path.join(path)) + .collect::>(); + + if cfg_attr_paths.is_empty() { + Ok(Some(SubModKind::Internal(item))) + } else { + Ok(Some(SubModKind::MultiInternal(cfg_attr_paths))) + } } } @@ -332,6 +387,16 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> { } Ok(()) } + SubModKind::MultiInternal(cfg_attr_paths) => { + for path in cfg_attr_paths { + let directory = Directory { + path: path, + ownership: DirectoryOwnership::UnownedViaBlock, + }; + self.visit_sub_mod_after_directory_update(sub_mod.clone(), Some(directory))?; + } + Ok(()) + } } } diff --git a/src/test/mod_resolver.rs b/src/test/mod_resolver.rs index aacb2acc684..ab29d06cc1d 100644 --- a/src/test/mod_resolver.rs +++ b/src/test/mod_resolver.rs @@ -80,3 +80,37 @@ fn fallback_and_try_to_resolve_external_submod_relative_to_current_dir_path() { ], ) } + +#[test] +fn inline_modules_with_path_attributes() { + verify_mod_resolution( + "tests/mod-resolver/inline_module_with_path_attribute/main.rs", + &[ + "tests/mod-resolver/inline_module_with_path_attribute/bravo/charlie.rs", + "tests/mod-resolver/inline_module_with_path_attribute/bravo/echo/foxtrot/mod.rs", + "tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/juliet.rs", + "tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/lima.rs", + "tests/mod-resolver/inline_module_with_path_attribute/mike/november.rs", + "tests/mod-resolver/inline_module_with_path_attribute/oscar/papa.rs", + "tests/mod-resolver/inline_module_with_path_attribute/tango.rs", + ], + ) +} + +#[test] +fn cfg_attr_path_on_inline_module() { + verify_mod_resolution( + "tests/mod-resolver/issue-7038/lib.rs", + &[ + "tests/mod-resolver/issue-7038/meow/wasm/dog/woof.rs", + "tests/mod-resolver/issue-7038/meow/wasm/mrrp.rs", + "tests/mod-resolver/issue-7038/meow/wasm/y.rs", + "tests/mod-resolver/issue-7038/meow_unix/dog/woof.rs", + "tests/mod-resolver/issue-7038/meow_unix/mrrp.rs", + "tests/mod-resolver/issue-7038/meow_unix/y.rs", + "tests/mod-resolver/issue-7038/meow_windows/dog/woof.rs", + "tests/mod-resolver/issue-7038/meow_windows/mrrp/mod.rs", + "tests/mod-resolver/issue-7038/meow_windows/y.rs", + ], + ) +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/bravo/charlie.rs b/tests/mod-resolver/inline_module_with_path_attribute/bravo/charlie.rs new file mode 100644 index 00000000000..19d21e82da0 --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/bravo/charlie.rs @@ -0,0 +1,3 @@ +fn main() { + println!("inline_mod_alpha->bravo/charlie.rs") +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/bravo/echo/foxtrot/mod.rs b/tests/mod-resolver/inline_module_with_path_attribute/bravo/echo/foxtrot/mod.rs new file mode 100644 index 00000000000..46f3529034d --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/bravo/echo/foxtrot/mod.rs @@ -0,0 +1,3 @@ +fn main() { + println!("inline_mod_alpha->inline_mod_delta->bravo/echo/fotxtrot/mod.rs") +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/juliet.rs b/tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/juliet.rs new file mode 100644 index 00000000000..bbc10d12635 --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/juliet.rs @@ -0,0 +1,3 @@ +fn main() { + println!("inline_mod_alpha->inline_mod_golf->bravo/hotel/india/juliet.rs") +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/lima.rs b/tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/lima.rs new file mode 100644 index 00000000000..1e32a05faae --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/bravo/hotel/india/lima.rs @@ -0,0 +1,3 @@ +fn main() { + println!("inline_mod_alpha->inline_mod_golf->external_mod_kilo->bravo/hotel/india/lima.rs") +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/main.rs b/tests/mod-resolver/inline_module_with_path_attribute/main.rs new file mode 100644 index 00000000000..b02378236ef --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/main.rs @@ -0,0 +1,38 @@ +#[path = "bravo"] +mod alpha { + mod charlie; + + #[path = "echo"] + mod delta { + mod foxtrot; + } + + #[path = "hotel/india"] + mod golf { + mod juliet; + #[path = "lima.rs"] + mod kilo; + } +} + +mod mike { + mod november; +} + +// Similar to issue https://github.com/rust-lang/rustfmt/issues/4076 +#[path = "oscar"] +mod oscar { + mod papa; +} + +// A more extreme case of https://github.com/rust-lang/rustfmt/issues/3901 +#[path = "."] +mod quebec { + #[path = "."] + mod romeo { + #[path = "."] + mod sierra { + mod tango; + } + } +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/mike/november.rs b/tests/mod-resolver/inline_module_with_path_attribute/mike/november.rs new file mode 100644 index 00000000000..03fdde4f82e --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/mike/november.rs @@ -0,0 +1,3 @@ +fn main() { + println!("inline_mod_mike->mike/november.rs") +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/oscar/papa.rs b/tests/mod-resolver/inline_module_with_path_attribute/oscar/papa.rs new file mode 100644 index 00000000000..36e5d207e70 --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/oscar/papa.rs @@ -0,0 +1,3 @@ +fn main() { + println!("inline_mod_oscar->oscar/papa.rs") +} diff --git a/tests/mod-resolver/inline_module_with_path_attribute/tango.rs b/tests/mod-resolver/inline_module_with_path_attribute/tango.rs new file mode 100644 index 00000000000..f6b5fb30e0f --- /dev/null +++ b/tests/mod-resolver/inline_module_with_path_attribute/tango.rs @@ -0,0 +1,3 @@ +fn main() { + println!("inline_mod_quebec->inline_mod_romeo->inline_mod_sierra->tango.rs") +} diff --git a/tests/mod-resolver/issue-7038/lib.rs b/tests/mod-resolver/issue-7038/lib.rs new file mode 100644 index 00000000000..1df6be153c2 --- /dev/null +++ b/tests/mod-resolver/issue-7038/lib.rs @@ -0,0 +1,14 @@ +#[cfg_attr(unix, path = "meow_unix")] +#[cfg_attr(windows, path = "meow_windows")] +#[cfg_attr(wasm, path = "meow/wasm")] +mod meow { + mod mrrp; + + #[path = "y.rs"] + mod x; + + #[path = "dog"] + mod bark { + mod woof; + } +} diff --git a/tests/mod-resolver/issue-7038/meow/wasm/dog/woof.rs b/tests/mod-resolver/issue-7038/meow/wasm/dog/woof.rs new file mode 100644 index 00000000000..257ebfe9b78 --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow/wasm/dog/woof.rs @@ -0,0 +1 @@ +// meow/wasm/dog/woof.rs diff --git a/tests/mod-resolver/issue-7038/meow/wasm/mrrp.rs b/tests/mod-resolver/issue-7038/meow/wasm/mrrp.rs new file mode 100644 index 00000000000..be79fe1e86c --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow/wasm/mrrp.rs @@ -0,0 +1 @@ +// meow/wasm/mrrp.rs diff --git a/tests/mod-resolver/issue-7038/meow/wasm/y.rs b/tests/mod-resolver/issue-7038/meow/wasm/y.rs new file mode 100644 index 00000000000..a6b48c52e26 --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow/wasm/y.rs @@ -0,0 +1 @@ +// meow/wasm/y.rs diff --git a/tests/mod-resolver/issue-7038/meow_unix/dog/woof.rs b/tests/mod-resolver/issue-7038/meow_unix/dog/woof.rs new file mode 100644 index 00000000000..1d703eab5c4 --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow_unix/dog/woof.rs @@ -0,0 +1 @@ +// meow_unix/dog/woof.rs diff --git a/tests/mod-resolver/issue-7038/meow_unix/mrrp.rs b/tests/mod-resolver/issue-7038/meow_unix/mrrp.rs new file mode 100644 index 00000000000..2e4b8ce036f --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow_unix/mrrp.rs @@ -0,0 +1 @@ +// meow_unix/mrrp.rs diff --git a/tests/mod-resolver/issue-7038/meow_unix/y.rs b/tests/mod-resolver/issue-7038/meow_unix/y.rs new file mode 100644 index 00000000000..be335a76c3e --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow_unix/y.rs @@ -0,0 +1 @@ +// meow_unix/y.rs diff --git a/tests/mod-resolver/issue-7038/meow_windows/dog/woof.rs b/tests/mod-resolver/issue-7038/meow_windows/dog/woof.rs new file mode 100644 index 00000000000..e43f25d6d31 --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow_windows/dog/woof.rs @@ -0,0 +1 @@ +// meow_windows/dog/woof.rs diff --git a/tests/mod-resolver/issue-7038/meow_windows/mrrp/mod.rs b/tests/mod-resolver/issue-7038/meow_windows/mrrp/mod.rs new file mode 100644 index 00000000000..ec829f39e73 --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow_windows/mrrp/mod.rs @@ -0,0 +1 @@ +// meow_windows/mrrp/mod.rs diff --git a/tests/mod-resolver/issue-7038/meow_windows/y.rs b/tests/mod-resolver/issue-7038/meow_windows/y.rs new file mode 100644 index 00000000000..24370771528 --- /dev/null +++ b/tests/mod-resolver/issue-7038/meow_windows/y.rs @@ -0,0 +1 @@ +// meow_windows/y.rs