diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/unresolved_import.md_-_Unresolved_import_di\342\200\246_-_Using_`from`_with_to\342\200\246_(4b8ba6ee48180cdd).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/unresolved_import.md_-_Unresolved_import_di\342\200\246_-_Using_`from`_with_to\342\200\246_(4b8ba6ee48180cdd).snap" index 54a26313aeb6a..2df94a06f57a8 100644 --- "a/crates/ty_python_semantic/resources/mdtest/snapshots/unresolved_import.md_-_Unresolved_import_di\342\200\246_-_Using_`from`_with_to\342\200\246_(4b8ba6ee48180cdd).snap" +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/unresolved_import.md_-_Unresolved_import_di\342\200\246_-_Using_`from`_with_to\342\200\246_(4b8ba6ee48180cdd).snap" @@ -40,6 +40,8 @@ error[unresolved-import]: Cannot resolve imported module `....foo` 2 | 3 | stat = add(10, 15) | +help: The module can be resolved if the number of leading dots is reduced +help: Did you mean `...foo`? info: Searched in the following paths during module resolution: info: 1. /src (first-party code) info: 2. vendored://stdlib (stdlib typeshed stubs vendored by ty) diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index cd93f59526df4..0e8a218f2ad14 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -5799,9 +5799,8 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { return; }; let mut diagnostic = builder.into_diagnostic(format_args!( - "Cannot resolve imported module `{}{}`", - ".".repeat(level as usize), - module.unwrap_or_default() + "Cannot resolve imported module `{}`", + format_import_from_module(level, module) )); if level == 0 { @@ -5832,6 +5831,30 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { } } } + } else { + if let Some(better_level) = (0..level).rev().find(|reduced_level| { + let Ok(module_name) = ModuleName::from_identifier_parts( + self.db(), + self.file(), + module, + *reduced_level, + ) else { + return false; + }; + resolve_module(self.db(), &module_name).is_some() + }) { + diagnostic + .help("The module can be resolved if the number of leading dots is reduced"); + diagnostic.help(format_args!( + "Did you mean `{}`?", + format_import_from_module(better_level, module) + )); + diagnostic.set_concise_message(format_args!( + "Cannot resolve imported module `{}` - did you mean `{}`?", + format_import_from_module(level, module), + format_import_from_module(better_level, module) + )); + } } // Add search paths information to the diagnostic @@ -6039,7 +6062,8 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { } Err(ModuleNameResolutionError::UnknownCurrentModule) => { tracing::debug!( - "Relative module resolution `{}` failed; could not resolve file `{}` to a module", + "Relative module resolution `{}` failed: could not resolve file `{}` to a module \ + (try adjusting configured search paths?)", format_import_from_module(*level, module), self.file().path(self.db()) );