From e7e1a39fa0ff1da2f408af3fac253839cbd74848 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 22 Jun 2023 11:18:48 +0800 Subject: [PATCH] suggest importing for partial mod path in name resolving --- compiler/rustc_resolve/src/late.rs | 6 +++- .../rustc_resolve/src/late/diagnostics.rs | 30 ++++++++++++++++- .../feature-gate-extern_absolute_paths.stderr | 9 ++++++ .../extern-prelude-from-opaque-fail.stderr | 12 +++++++ .../builtin-prelude-no-accidents.stderr | 32 ++++++++++++++----- ...-param-decl-on-type-instead-of-impl.stderr | 22 +++++++++---- .../ui/resolve/export-fully-qualified.stderr | 5 +++ .../suggestions/crate-or-module-typo.stderr | 26 ++++++++++++--- 8 files changed, 121 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9f4573ea025..9e05d1e14a4 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3556,9 +3556,13 @@ fn smart_resolve_path_fragment( _ => return Some(parent_err), }; - let (mut err, candidates) = + let (mut err, mut candidates) = this.smart_resolve_report_errors(prefix_path, path_span, PathSource::Type, None); + if candidates.is_empty() { + candidates = this.smart_resolve_partial_mod_path_errors(prefix_path, path); + } + // There are two different error messages user might receive at // this point: // - E0412 cannot find type `{}` in this scope diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7284b33f09d..b859e8d4c2e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -4,6 +4,7 @@ use crate::{errors, path_names_to_string}; use crate::{Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; +use rustc_hir::def::Namespace::{self, *}; use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt}; use rustc_ast::{ @@ -17,7 +18,6 @@ MultiSpan, }; use rustc_hir as hir; -use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::PrimTy; @@ -221,10 +221,14 @@ fn make_base_error( let suggestion = if self.current_trait_ref.is_none() && let Some((fn_kind, _)) = self.diagnostic_metadata.current_function && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt() + && let FnKind::Fn(_, _, sig, ..) = fn_kind && let Some(items) = self.diagnostic_metadata.current_impl_items && let Some(item) = items.iter().find(|i| { if let AssocItemKind::Fn(..) | AssocItemKind::Const(..) = &i.kind && i.ident.name == item_str.name + // don't suggest if the item is in Fn signature arguments + // issue #112590 + && !sig.span.contains(item_span) { debug!(?item_str.name); return true @@ -318,6 +322,30 @@ fn make_base_error( } } + /// Try to suggest for a module path that cannot be resolved. + /// Such as `fmt::Debug` where `fmt` is not resolved without importing, + /// here we search with `lookup_import_candidates` for a module named `fmt` + /// with `TypeNS` as namespace. + /// + /// We need a separate function here because we won't suggest for a path with single segment + /// and we won't change `SourcePath` api `is_expected` to match `Type` with `DefKind::Mod` + pub(crate) fn smart_resolve_partial_mod_path_errors( + &mut self, + prefix_path: &[Segment], + path: &[Segment], + ) -> Vec { + if path.len() <= 1 { + return Vec::new(); + } + let ident = prefix_path.last().unwrap().ident; + self.r.lookup_import_candidates( + ident, + Namespace::TypeNS, + &self.parent_scope, + &|res: Res| matches!(res, Res::Def(DefKind::Mod, _)), + ) + } + /// Handles error reporting for `smart_resolve_path_fragment` function. /// Creates base error and amends it with one short label and possibly some longer helps/notes. pub(crate) fn smart_resolve_report_errors( diff --git a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr index 3bae23a4aaa..7de67da9b5d 100644 --- a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr @@ -13,6 +13,15 @@ LL | let _: u8 = ::core::default::Default(); | ^^^^ maybe a missing crate `core`? | = help: consider adding `extern crate core` to use the `core` crate +help: consider importing this module + | +LL + use std::default; + | +help: if you import `default`, refer to it directly + | +LL - let _: u8 = ::core::default::Default(); +LL + let _: u8 = default::Default(); + | error: aborting due to 2 previous errors diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr index f1f4caee361..1f7df7a2e79 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -24,6 +24,8 @@ LL | fn f() { my_core::mem::drop(0); } LL | a!(); | ---- in this macro invocation | + = help: consider importing this module: + my_core::mem = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: failed to resolve: use of undeclared crate or module `my_core` @@ -31,6 +33,16 @@ error[E0433]: failed to resolve: use of undeclared crate or module `my_core` | LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` + | +help: consider importing this module + | +LL + use my_core::mem; + | +help: if you import `mem`, refer to it directly + | +LL - fn f() { my_core::mem::drop(0); } +LL + fn f() { mem::drop(0); } + | error: aborting due to 4 previous errors diff --git a/tests/ui/macros/builtin-prelude-no-accidents.stderr b/tests/ui/macros/builtin-prelude-no-accidents.stderr index 8cd9a63b808..b726e186241 100644 --- a/tests/ui/macros/builtin-prelude-no-accidents.stderr +++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr @@ -3,21 +3,37 @@ error[E0433]: failed to resolve: use of undeclared crate or module `env` | LL | env::current_dir; | ^^^ use of undeclared crate or module `env` - -error[E0433]: failed to resolve: use of undeclared crate or module `vec` - --> $DIR/builtin-prelude-no-accidents.rs:7:14 | -LL | type B = vec::Vec; - | ^^^ - | | - | use of undeclared crate or module `vec` - | help: a struct with a similar name exists (notice the capitalization): `Vec` +help: consider importing this module + | +LL + use std::env; + | error[E0433]: failed to resolve: use of undeclared crate or module `panic` --> $DIR/builtin-prelude-no-accidents.rs:6:14 | LL | type A = panic::PanicInfo; | ^^^^^ use of undeclared crate or module `panic` + | +help: consider importing this module + | +LL + use std::panic; + | + +error[E0433]: failed to resolve: use of undeclared crate or module `vec` + --> $DIR/builtin-prelude-no-accidents.rs:7:14 + | +LL | type B = vec::Vec; + | ^^^ use of undeclared crate or module `vec` + | +help: a struct with a similar name exists + | +LL | type B = Vec::Vec; + | ~~~ +help: consider importing this module + | +LL + use std::vec; + | error: aborting due to 3 previous errors diff --git a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr index 96885d11ee0..ce95633d114 100644 --- a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr +++ b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr @@ -21,18 +21,28 @@ error: unexpected `const` parameter declaration LL | path::path::Struct::() | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration -error[E0433]: failed to resolve: use of undeclared crate or module `path` - --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5 - | -LL | path::path::Struct::() - | ^^^^ use of undeclared crate or module `path` - error[E0412]: cannot find type `T` in this scope --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15 | LL | fn banana(a: >::BAR) {} | ^ not found in this scope +error[E0433]: failed to resolve: use of undeclared crate or module `path` + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5 + | +LL | path::path::Struct::() + | ^^^^ use of undeclared crate or module `path` + | +help: consider importing this module + | +LL + use std::path; + | +help: if you import `path`, refer to it directly + | +LL - path::path::Struct::() +LL + path::Struct::() + | + error[E0308]: mismatched types --> $DIR/const-param-decl-on-type-instead-of-impl.rs:5:17 | diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr index 7ee352e1232..04d62477062 100644 --- a/tests/ui/resolve/export-fully-qualified.stderr +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -3,6 +3,11 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` | LL | pub fn bar() { foo::baz(); } | ^^^ use of undeclared crate or module `foo` + | +help: consider importing this module + | +LL + use foo; + | error: aborting due to previous error diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 98b88b4fb92..8b988beb5c2 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -20,6 +20,17 @@ help: there is a crate or module with a similar name LL | use bar::bar; | ~~~ +error[E0433]: failed to resolve: use of undeclared crate or module `bar` + --> $DIR/crate-or-module-typo.rs:6:20 + | +LL | pub fn bar() { bar::baz(); } + | ^^^ use of undeclared crate or module `bar` + | +help: consider importing this module + | +LL + use crate::bar; + | + error[E0433]: failed to resolve: use of undeclared crate or module `st` --> $DIR/crate-or-module-typo.rs:14:10 | @@ -30,12 +41,17 @@ help: there is a crate or module with a similar name | LL | bar: std::cell::Cell | ~~~ - -error[E0433]: failed to resolve: use of undeclared crate or module `bar` - --> $DIR/crate-or-module-typo.rs:6:20 +help: consider importing one of these items + | +LL + use core::cell; + | +LL + use std::cell; + | +help: if you import `cell`, refer to it directly + | +LL - bar: st::cell::Cell +LL + bar: cell::Cell | -LL | pub fn bar() { bar::baz(); } - | ^^^ use of undeclared crate or module `bar` error: aborting due to 4 previous errors