diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9e05d1e14a4..386be405a92 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3499,7 +3499,7 @@ fn smart_resolve_path_fragment( let report_errors = |this: &mut Self, res: Option| { if this.should_report_errs() { let (err, candidates) = - this.smart_resolve_report_errors(path, path_span, source, res); + this.smart_resolve_report_errors(path, path, path_span, source, res); let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); @@ -3556,12 +3556,13 @@ fn smart_resolve_path_fragment( _ => return Some(parent_err), }; - 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); - } + let (mut err, candidates) = this.smart_resolve_report_errors( + prefix_path, + path, + path_span, + PathSource::Type, + None, + ); // There are two different error messages user might receive at // this point: diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b859e8d4c2e..a551f681d5c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -334,16 +334,36 @@ pub(crate) fn smart_resolve_partial_mod_path_errors( prefix_path: &[Segment], path: &[Segment], ) -> Vec { - if path.len() <= 1 { - return Vec::new(); + let next_seg = if path.len() >= prefix_path.len() + 1 && prefix_path.len() == 1 { + path.get(prefix_path.len()) + } else { + None + }; + if let Some(segment) = prefix_path.last() && + let Some(next_seg) = next_seg { + let candidates = self.r.lookup_import_candidates( + segment.ident, + Namespace::TypeNS, + &self.parent_scope, + &|res: Res| matches!(res, Res::Def(DefKind::Mod, _)), + ); + // double check next seg is valid + candidates + .into_iter() + .filter(|candidate| { + if let Some(def_id) = candidate.did && + let Some(module) = self.r.get_module(def_id) { + self.r.resolutions(module).borrow().iter().any(|(key, _r)| { + key.ident.name == next_seg.ident.name + }) + } else { + false + } + }) + .collect::>() + } else { + 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. @@ -351,6 +371,7 @@ pub(crate) fn smart_resolve_partial_mod_path_errors( pub(crate) fn smart_resolve_report_errors( &mut self, path: &[Segment], + full_path: &[Segment], span: Span, source: PathSource<'_>, res: Option, @@ -392,7 +413,7 @@ pub(crate) fn smart_resolve_report_errors( } let (found, candidates) = - self.try_lookup_name_relaxed(&mut err, source, path, span, res, &base_error); + self.try_lookup_name_relaxed(&mut err, source, path, full_path, span, res, &base_error); if found { return (err, candidates); } @@ -498,6 +519,7 @@ fn try_lookup_name_relaxed( err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], + full_path: &[Segment], span: Span, res: Option, base_error: &BaseError, @@ -667,6 +689,10 @@ fn try_lookup_name_relaxed( } } + if candidates.is_empty() { + candidates = self.smart_resolve_partial_mod_path_errors(path, full_path); + } + return (false, candidates); } 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 7de67da9b5d..3bae23a4aaa 100644 --- a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr @@ -13,15 +13,6 @@ 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 1f7df7a2e79..f1f4caee361 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -24,8 +24,6 @@ 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` @@ -33,16 +31,6 @@ 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/parser/const-param-decl-on-type-instead-of-impl.stderr b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr index ce95633d114..96885d11ee0 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,27 +21,17 @@ error: unexpected `const` parameter declaration LL | path::path::Struct::() | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration -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` + +error[E0412]: cannot find type `T` in this scope + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15 | -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::() - | +LL | fn banana(a: >::BAR) {} + | ^ not found in this scope 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-2018.rs b/tests/ui/resolve/export-fully-qualified-2018.rs new file mode 100644 index 00000000000..afd48acb6bb --- /dev/null +++ b/tests/ui/resolve/export-fully-qualified-2018.rs @@ -0,0 +1,13 @@ +// edition:2018 + +// In this test baz isn't resolved when called as foo.baz even though +// it's called from inside foo. This is somewhat surprising and may +// want to change eventually. + +mod foo { + pub fn bar() { foo::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `foo` + + fn baz() { } +} + +fn main() { } diff --git a/tests/ui/resolve/export-fully-qualified-2018.stderr b/tests/ui/resolve/export-fully-qualified-2018.stderr new file mode 100644 index 00000000000..366ffd9bb2b --- /dev/null +++ b/tests/ui/resolve/export-fully-qualified-2018.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `foo` + --> $DIR/export-fully-qualified-2018.rs:8:20 + | +LL | pub fn bar() { foo::baz(); } + | ^^^ use of undeclared crate or module `foo` + | +help: consider importing this module + | +LL + use crate::foo; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/export-fully-qualified.rs b/tests/ui/resolve/export-fully-qualified.rs index 4e73a2c5488..9d4daf4cd79 100644 --- a/tests/ui/resolve/export-fully-qualified.rs +++ b/tests/ui/resolve/export-fully-qualified.rs @@ -1,3 +1,5 @@ +// edition:2015 + // In this test baz isn't resolved when called as foo.baz even though // it's called from inside foo. This is somewhat surprising and may // want to change eventually. diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr index 04d62477062..0cd516ee1b1 100644 --- a/tests/ui/resolve/export-fully-qualified.stderr +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` - --> $DIR/export-fully-qualified.rs:6:20 + --> $DIR/export-fully-qualified.rs:8:20 | LL | pub fn bar() { foo::baz(); } | ^^^ use of undeclared crate or module `foo` diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 8b988beb5c2..5e7a7685ab0 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 `st` + --> $DIR/crate-or-module-typo.rs:14:10 + | +LL | bar: st::cell::Cell + | ^^ use of undeclared crate or module `st` + | +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 | @@ -31,28 +42,6 @@ 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 - | -LL | bar: st::cell::Cell - | ^^ use of undeclared crate or module `st` - | -help: there is a crate or module with a similar name - | -LL | bar: std::cell::Cell - | ~~~ -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 - | - error: aborting due to 4 previous errors Some errors have detailed explanations: E0432, E0433. diff --git a/tests/ui/suggestions/issue-112590-suggest-import.rs b/tests/ui/suggestions/issue-112590-suggest-import.rs new file mode 100644 index 00000000000..0938814c559 --- /dev/null +++ b/tests/ui/suggestions/issue-112590-suggest-import.rs @@ -0,0 +1,10 @@ +pub struct S; + +impl fmt::Debug for S { //~ ERROR failed to resolve: use of undeclared crate or module `fmt` + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { //~ ERROR failed to resolve: use of undeclared crate or module `fmt` + //~^ ERROR failed to resolve: use of undeclared crate or module `fmt` + Ok(()) + } +} + +fn main() { } diff --git a/tests/ui/suggestions/issue-112590-suggest-import.stderr b/tests/ui/suggestions/issue-112590-suggest-import.stderr new file mode 100644 index 00000000000..aeac18c16f0 --- /dev/null +++ b/tests/ui/suggestions/issue-112590-suggest-import.stderr @@ -0,0 +1,36 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `fmt` + --> $DIR/issue-112590-suggest-import.rs:3:6 + | +LL | impl fmt::Debug for S { + | ^^^ use of undeclared crate or module `fmt` + | +help: consider importing this module + | +LL + use std::fmt; + | + +error[E0433]: failed to resolve: use of undeclared crate or module `fmt` + --> $DIR/issue-112590-suggest-import.rs:4:28 + | +LL | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + | ^^^ use of undeclared crate or module `fmt` + | +help: consider importing this module + | +LL + use std::fmt; + | + +error[E0433]: failed to resolve: use of undeclared crate or module `fmt` + --> $DIR/issue-112590-suggest-import.rs:4:51 + | +LL | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + | ^^^ use of undeclared crate or module `fmt` + | +help: consider importing this module + | +LL + use std::fmt; + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`.