Skip to content

Commit 3583423

Browse files
committed
suggest declaring modules when file found but module not defined
1 parent 36b2163 commit 3583423

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
24232423
} else {
24242424
let suggestion = if suggestion.is_some() {
24252425
suggestion
2426+
} else if let Some(m) = self.undeclared_module_exists(ident) {
2427+
self.undeclared_module_suggest_declare(ident, m)
24262428
} else if was_invoked_from_cargo() {
24272429
Some((
24282430
vec![],
@@ -2444,6 +2446,55 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
24442446
}
24452447
}
24462448

2449+
fn undeclared_module_suggest_declare(
2450+
&mut self,
2451+
ident: Ident,
2452+
path: std::path::PathBuf,
2453+
) -> Option<(Vec<(Span, String)>, String, Applicability)> {
2454+
Some((
2455+
vec![(self.current_crate_outer_attr_insert_span, format!("mod {ident};\n"))],
2456+
format!(
2457+
"to make use of source file {}, use `mod {ident}` \
2458+
in this file to declare the module",
2459+
path.display()
2460+
),
2461+
Applicability::MaybeIncorrect,
2462+
))
2463+
}
2464+
2465+
fn undeclared_module_exists(&mut self, ident: Ident) -> Option<std::path::PathBuf> {
2466+
let map = self.tcx.sess.source_map();
2467+
2468+
let src = map.span_to_filename(ident.span).into_local_path()?;
2469+
let i = ident.as_str();
2470+
// FIXME: add case where non parent using undeclared module (hard?)
2471+
let dir = src.parent()?;
2472+
let src = src.file_stem()?.to_str()?;
2473+
for file in [
2474+
// …/x.rs
2475+
dir.join(i).with_extension("rs"),
2476+
// …/x/mod.rs
2477+
dir.join(i).join("mod.rs"),
2478+
] {
2479+
if file.exists() {
2480+
return Some(file);
2481+
}
2482+
}
2483+
if !matches!(src, "main" | "lib" | "mod") {
2484+
for file in [
2485+
// …/x/y.rs
2486+
dir.join(src).join(i).with_extension("rs"),
2487+
// …/x/y/mod.rs
2488+
dir.join(src).join(i).join("mod.rs"),
2489+
] {
2490+
if file.exists() {
2491+
return Some(file);
2492+
}
2493+
}
2494+
}
2495+
None
2496+
}
2497+
24472498
/// Adds suggestions for a path that cannot be resolved.
24482499
#[instrument(level = "debug", skip(self, parent_scope))]
24492500
pub(crate) fn make_path_suggestion(

tests/ui/modules_and_files_visibility/mod_file_disambig.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `mod
1212
LL | assert_eq!(mod_file_aux::bar(), 10);
1313
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `mod_file_aux`
1414
|
15-
= help: you might be missing a crate named `mod_file_aux`
15+
help: to make use of source file $DIR/mod_file_aux.rs, use `mod mod_file_aux` in this file to declare the module
16+
|
17+
LL + mod mod_file_aux;
18+
|
1619

1720
error: aborting due to 2 previous errors
1821

0 commit comments

Comments
 (0)