Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 67 additions & 2 deletions src/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,49 @@ pub(crate) enum ModuleResolutionErrorKind {
#[derive(Clone)]
enum SubModKind<'a, 'ast> {
/// `mod foo;`
///

@matthewhughes934 matthewhughes934 Aug 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments make this enum much clearer!

View changes since the review

/// 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<PathBuf>),
}

impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
Expand Down Expand Up @@ -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::<Vec<_>>();

if cfg_attr_paths.is_empty() {
Ok(Some(SubModKind::Internal(item)))
} else {
Ok(Some(SubModKind::MultiInternal(cfg_attr_paths)))
}
}
}

Expand Down Expand Up @@ -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(())
}
}
}

Expand Down
34 changes: 34 additions & 0 deletions src/test/mod_resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("inline_mod_alpha->bravo/charlie.rs")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("inline_mod_alpha->inline_mod_delta->bravo/echo/fotxtrot/mod.rs")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("inline_mod_alpha->inline_mod_golf->bravo/hotel/india/juliet.rs")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("inline_mod_alpha->inline_mod_golf->external_mod_kilo->bravo/hotel/india/lima.rs")
}
38 changes: 38 additions & 0 deletions tests/mod-resolver/inline_module_with_path_attribute/main.rs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("inline_mod_mike->mike/november.rs")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("inline_mod_oscar->oscar/papa.rs")
}
3 changes: 3 additions & 0 deletions tests/mod-resolver/inline_module_with_path_attribute/tango.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("inline_mod_quebec->inline_mod_romeo->inline_mod_sierra->tango.rs")
}
14 changes: 14 additions & 0 deletions tests/mod-resolver/issue-7038/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
}
}
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow/wasm/dog/woof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow/wasm/dog/woof.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow/wasm/mrrp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow/wasm/mrrp.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow/wasm/y.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow/wasm/y.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow_unix/dog/woof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow_unix/dog/woof.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow_unix/mrrp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow_unix/mrrp.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow_unix/y.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow_unix/y.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow_windows/dog/woof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow_windows/dog/woof.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow_windows/mrrp/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow_windows/mrrp/mod.rs
1 change: 1 addition & 0 deletions tests/mod-resolver/issue-7038/meow_windows/y.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// meow_windows/y.rs