diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-06-27 22:13:02 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-27 22:13:02 +0200 |
| commit | 190a1a7f747408d1936a81065665c687013f6141 (patch) | |
| tree | 8323759b9e16757fae6d36e92f0d54db355e121c /compiler/rustc_resolve/src | |
| parent | 9d15167921ead28946d8d603470dbe9a57e74eff (diff) | |
| parent | 57cb419cc5c57afb2456d9e4af0e722a5b9324b9 (diff) | |
| download | rust-190a1a7f747408d1936a81065665c687013f6141.tar.gz rust-190a1a7f747408d1936a81065665c687013f6141.zip | |
Rollup merge of #142730 - bend-n:suggest_declaring_modules_when_file_found_but_module_not_defined, r=petrochenkov
suggest declaring modules when file found but module not defined
suggests declaring modules when a module is found but not defined, i.e
```
├── main.rs: `use thing::thang;`
└── thing.rs: `struct thang`
```
or
```
├── main.rs: `use thing::thang;`
└── thing
└── mod.rs: `struct thang`
```
which currently is just
```rust
error[E0432]: unresolved import `yeah`
--> src/main.rs:1:1
|
1 | use thing::thang;
| ^^^^^ use of unresolved module or unlinked crate `thing`
|
```
but now would have this nice help:
```text
= help: you may have forgotten to declare the module `thing`. use `mod thing` in this file to declare this module.
```
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 8bca350c8ba..18078b760c3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2421,6 +2421,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![], @@ -2442,6 +2444,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( |
