Skip to content

suggest declaring modules when file found but module not defined #142730

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
51 changes: 51 additions & 0 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2423,6 +2423,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
} else {
let suggestion = if suggestion.is_some() {
suggestion
} else if let Some(m) = self.undeclared_module_exists(ident) {
self.undeclared_module_suggest_declare(ident, m)
} else if was_invoked_from_cargo() {
Some((
vec![],
Expand All @@ -2444,6 +2446,55 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}

fn undeclared_module_suggest_declare(
&mut self,
ident: Ident,
path: std::path::PathBuf,
) -> Option<(Vec<(Span, String)>, String, Applicability)> {
Some((
vec![(self.current_crate_outer_attr_insert_span, format!("mod {ident};\n"))],
format!(
"to make use of source file {}, use `mod {ident}` \
in this file to declare the module",
path.display()
),
Applicability::MaybeIncorrect,
))
}

fn undeclared_module_exists(&mut self, ident: Ident) -> Option<std::path::PathBuf> {
let map = self.tcx.sess.source_map();

let src = map.span_to_filename(ident.span).into_local_path()?;
let i = ident.as_str();
// FIXME: add case where non parent using undeclared module (hard?)
let dir = src.parent()?;
let src = src.file_stem()?.to_str()?;
for file in [
// …/x.rs
dir.join(i).with_extension("rs"),
// …/x/mod.rs
dir.join(i).join("mod.rs"),
] {
if file.exists() {
return Some(file);
}
}
if !matches!(src, "main" | "lib" | "mod") {
for file in [
// …/x/y.rs
dir.join(src).join(i).with_extension("rs"),
// …/x/y/mod.rs
dir.join(src).join(i).join("mod.rs"),
] {
if file.exists() {
return Some(file);
}
}
}
None
}

/// Adds suggestions for a path that cannot be resolved.
#[instrument(level = "debug", skip(self, parent_scope))]
pub(crate) fn make_path_suggestion(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//@ ignore-auxiliary
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//@ ignore-auxiliary
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//@ ignore-auxiliary

use submodule3::ferris; // these modules are unresolved.
use submodule4::error;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//@ edition:2024
use submodule::cat; //~ ERROR unresolved import `submodule`
use submodule2::help; //~ ERROR unresolved import `submodule2`
mod success;
fn main() {}
//~? ERROR unresolved import `submodule3`
//~? ERROR unresolved import `submodule4`
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
error[E0432]: unresolved import `submodule`
--> $DIR/suggestion.rs:2:5
|
LL | use submodule::cat;
| ^^^^^^^^^ use of unresolved module or unlinked crate `submodule`
|
help: to make use of source file $DIR/submodule/mod.rs, use `mod submodule` in this file to declare the module
|
LL + mod submodule;
|

error[E0432]: unresolved import `submodule2`
--> $DIR/suggestion.rs:3:5
|
LL | use submodule2::help;
| ^^^^^^^^^^ use of unresolved module or unlinked crate `submodule2`
|
help: to make use of source file $DIR/submodule2.rs, use `mod submodule2` in this file to declare the module
|
LL + mod submodule2;
|

error[E0432]: unresolved import `submodule3`
--> $DIR/success.rs:3:5
|
LL | use submodule3::ferris; // these modules are unresolved.
| ^^^^^^^^^^ use of unresolved module or unlinked crate `submodule3`
|
help: to make use of source file $DIR/success/submodule3/mod.rs, use `mod submodule3` in this file to declare the module
--> $DIR/suggestion.rs:2:1
|
LL + mod submodule3;
|

error[E0432]: unresolved import `submodule4`
--> $DIR/success.rs:4:5
|
LL | use submodule4::error;
| ^^^^^^^^^^ use of unresolved module or unlinked crate `submodule4`
|
help: to make use of source file $DIR/success/submodule4.rs, use `mod submodule4` in this file to declare the module
--> $DIR/suggestion.rs:2:1
|
LL + mod submodule4;
|

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0432`.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `mod
LL | assert_eq!(mod_file_aux::bar(), 10);
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `mod_file_aux`
|
= help: you might be missing a crate named `mod_file_aux`
help: to make use of source file $DIR/mod_file_aux.rs, use `mod mod_file_aux` in this file to declare the module
|
LL + mod mod_file_aux;
|

error: aborting due to 2 previous errors

Expand Down
Loading