diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 90cb312edd2..f6c7aecf8b0 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3503,7 +3503,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let report_errors = |this: &mut Self, res: Option| { if this.should_report_errs() { let (err, candidates) = - this.smart_resolve_report_errors(path, path, path_span, source, res); + this.smart_resolve_report_errors(path, None, path_span, source, res); let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); @@ -3555,14 +3555,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Before we start looking for candidates, we have to get our hands // on the type user is trying to perform invocation on; basically: // we're transforming `HashMap::new` into just `HashMap`. - let prefix_path = match path.split_last() { - Some((_, path)) if !path.is_empty() => path, + let (following_seg, prefix_path) = match path.split_last() { + Some((last, path)) if !path.is_empty() => (Some(last), path), _ => return Some(parent_err), }; let (mut err, candidates) = this.smart_resolve_report_errors( prefix_path, - path, + following_seg, path_span, PathSource::Type, None, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index c0e3f1aaf01..78ef72a7e34 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -332,15 +332,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { pub(crate) fn smart_resolve_partial_mod_path_errors( &mut self, prefix_path: &[Segment], - path: &[Segment], + following_seg: Option<&Segment>, ) -> Vec { - 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 Some(following_seg) = following_seg + { let candidates = self.r.lookup_import_candidates( segment.ident, Namespace::TypeNS, @@ -353,9 +349,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .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 - }) + Some(def_id) != self.parent_scope.module.opt_def_id() && + self.r.resolutions(module).borrow().iter().any(|(key, _r)| { + key.ident.name == following_seg.ident.name + }) } else { false } @@ -371,7 +368,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { pub(crate) fn smart_resolve_report_errors( &mut self, path: &[Segment], - full_path: &[Segment], + following_seg: Option<&Segment>, span: Span, source: PathSource<'_>, res: Option, @@ -412,8 +409,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { return (err, Vec::new()); } - let (found, candidates) = - self.try_lookup_name_relaxed(&mut err, source, path, full_path, span, res, &base_error); + let (found, candidates) = self.try_lookup_name_relaxed( + &mut err, + source, + path, + following_seg, + span, + res, + &base_error, + ); if found { return (err, candidates); } @@ -422,7 +426,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { // if we have suggested using pattern matching, then don't add needless suggestions // for typos. - fallback |= self.suggest_typo(&mut err, source, path, span, &base_error); + fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error); if fallback { // Fallback label. @@ -519,7 +523,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], - full_path: &[Segment], + following_seg: Option<&Segment>, span: Span, res: Option, base_error: &BaseError, @@ -590,8 +594,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } // Try finding a suitable replacement. - let typo_sugg = - self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion(); + let typo_sugg = self + .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected) + .to_opt_suggestion(); if path.len() == 1 && self.self_type_is_available() { if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call()) @@ -690,7 +695,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } if candidates.is_empty() { - candidates = self.smart_resolve_partial_mod_path_errors(path, full_path); + candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } return (false, candidates); @@ -776,12 +781,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, source: PathSource<'_>, path: &[Segment], + following_seg: Option<&Segment>, span: Span, base_error: &BaseError, ) -> bool { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); - let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected); + let typo_sugg = + self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); let is_in_same_file = &|sp1, sp2| { let source_map = self.r.tcx.sess.source_map(); let file1 = source_map.span_to_filename(sp1); @@ -1715,6 +1722,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { fn lookup_typo_candidate( &mut self, path: &[Segment], + following_seg: Option<&Segment>, ns: Namespace, filter_fn: &impl Fn(Res) -> bool, ) -> TypoCandidate { @@ -1793,6 +1801,26 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } + // if next_seg is present, let's filter everything that does not continue the path + if let Some(following_seg) = following_seg { + names.retain(|suggestion| match suggestion.res { + Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _) => { + // FIXME: this is not totally accurate, but mostly works + suggestion.candidate != following_seg.ident.name + } + Res::Def(DefKind::Mod, def_id) => self.r.get_module(def_id).map_or_else( + || false, + |module| { + self.r + .resolutions(module) + .borrow() + .iter() + .any(|(key, _)| key.ident.name == following_seg.ident.name) + }, + ), + _ => true, + }); + } let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. names.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 62c070221dc..b386b000bef 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -39,7 +39,6 @@ const EXCEPTION_PATHS: &[&str] = &[ "library/panic_unwind", "library/unwind", "library/rtstartup", // Not sure what to do about this. magic stuff for mingw - "library/term", // Not sure how to make this crate portable, but test crate needs it. "library/test", // Probably should defer to unstable `std::sys` APIs. // The `VaList` implementation must have platform specific code. // The Windows implementation of a `va_list` is always a character 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-2018.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs new file mode 100644 index 00000000000..40c5eacee3b --- /dev/null +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs @@ -0,0 +1,29 @@ +// edition:2018 +#![feature(decl_macro)] + +macro a() { + extern crate core as my_core; + mod v { + // Early resolution. + use my_core; //~ ERROR unresolved import `my_core` + } + mod u { + // Late resolution. + fn f() { my_core::mem::drop(0); } + //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` + } +} + +a!(); + +mod v { + // Early resolution. + use my_core; //~ ERROR unresolved import `my_core` +} +mod u { + // Late resolution. + fn f() { my_core::mem::drop(0); } + //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` +} + +fn main() {} diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr new file mode 100644 index 00000000000..7ed15e89caa --- /dev/null +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr @@ -0,0 +1,53 @@ +error[E0432]: unresolved import `my_core` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:21:9 + | +LL | use my_core; + | ^^^^^^^ no external crate `my_core` + +error[E0432]: unresolved import `my_core` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:8:13 + | +LL | use my_core; + | ^^^^^^^ no external crate `my_core` +... +LL | a!(); + | ---- in this macro invocation + | + = 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` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:12:18 + | +LL | fn f() { my_core::mem::drop(0); } + | ^^^^^^^ use of undeclared crate or module `my_core` +... +LL | a!(); + | ---- in this macro invocation + | + = help: consider importing one of these items: + std::mem + 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` + --> $DIR/extern-prelude-from-opaque-fail-2018.rs:25:14 + | +LL | fn f() { my_core::mem::drop(0); } + | ^^^^^^^ use of undeclared crate or module `my_core` + | +help: consider importing one of these items + | +LL + use core::mem; + | +LL + use std::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 + +Some errors have detailed explanations: E0432, E0433. +For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs index 571017df4d7..f3fa2dddaef 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs @@ -1,3 +1,4 @@ +// edition:2015 #![feature(decl_macro)] macro a() { diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr index f1f4caee361..13b2827ef39 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -1,11 +1,11 @@ error[E0432]: unresolved import `my_core` - --> $DIR/extern-prelude-from-opaque-fail.rs:20:9 + --> $DIR/extern-prelude-from-opaque-fail.rs:21:9 | LL | use my_core; | ^^^^^^^ no `my_core` in the root error[E0432]: unresolved import `my_core` - --> $DIR/extern-prelude-from-opaque-fail.rs:7:13 + --> $DIR/extern-prelude-from-opaque-fail.rs:8:13 | LL | use my_core; | ^^^^^^^ no `my_core` in the root @@ -16,7 +16,7 @@ LL | a!(); = 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` - --> $DIR/extern-prelude-from-opaque-fail.rs:11:18 + --> $DIR/extern-prelude-from-opaque-fail.rs:12:18 | LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` @@ -24,13 +24,25 @@ 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` - --> $DIR/extern-prelude-from-opaque-fail.rs:24:14 + --> $DIR/extern-prelude-from-opaque-fail.rs:25:14 | 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 b726e186241..c1054230bc9 100644 --- a/tests/ui/macros/builtin-prelude-no-accidents.stderr +++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr @@ -26,10 +26,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `vec` 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; diff --git a/tests/ui/resolve/112590-2.fixed b/tests/ui/resolve/112590-2.fixed new file mode 100644 index 00000000000..3bfe81ae8d0 --- /dev/null +++ b/tests/ui/resolve/112590-2.fixed @@ -0,0 +1,34 @@ +// run-rustfix +use std::vec; + +use std::sync::atomic::AtomicBool; + +mod foo { + pub mod bar { + pub mod baz { + pub use std::vec::Vec as MyVec; + } + } +} + +mod u { + use foo::bar::baz::MyVec; + +fn _a() { + let _: Vec = MyVec::new(); //~ ERROR failed to resolve + } +} + +mod v { + use foo::bar::baz::MyVec; + +fn _b() { + let _: Vec = MyVec::new(); //~ ERROR failed to resolve + } +} + +fn main() { + let _t: Vec = Vec::new(); //~ ERROR failed to resolve + type _B = vec::Vec::; //~ ERROR failed to resolve + let _t = AtomicBool::new(true); //~ ERROR failed to resolve +} diff --git a/tests/ui/resolve/112590-2.rs b/tests/ui/resolve/112590-2.rs new file mode 100644 index 00000000000..e5914cd676e --- /dev/null +++ b/tests/ui/resolve/112590-2.rs @@ -0,0 +1,26 @@ +// run-rustfix +mod foo { + pub mod bar { + pub mod baz { + pub use std::vec::Vec as MyVec; + } + } +} + +mod u { + fn _a() { + let _: Vec = super::foo::baf::baz::MyVec::new(); //~ ERROR failed to resolve + } +} + +mod v { + fn _b() { + let _: Vec = fox::bar::baz::MyVec::new(); //~ ERROR failed to resolve + } +} + +fn main() { + let _t: Vec = vec::new(); //~ ERROR failed to resolve + type _B = vec::Vec::; //~ ERROR failed to resolve + let _t = std::sync_error::atomic::AtomicBool::new(true); //~ ERROR failed to resolve +} diff --git a/tests/ui/resolve/112590-2.stderr b/tests/ui/resolve/112590-2.stderr new file mode 100644 index 00000000000..0db20249d27 --- /dev/null +++ b/tests/ui/resolve/112590-2.stderr @@ -0,0 +1,71 @@ +error[E0433]: failed to resolve: could not find `baf` in `foo` + --> $DIR/112590-2.rs:12:39 + | +LL | let _: Vec = super::foo::baf::baz::MyVec::new(); + | ^^^ could not find `baf` in `foo` + | +help: consider importing this struct through its public re-export + | +LL + use foo::bar::baz::MyVec; + | +help: if you import `MyVec`, refer to it directly + | +LL - let _: Vec = super::foo::baf::baz::MyVec::new(); +LL + let _: Vec = MyVec::new(); + | + +error[E0433]: failed to resolve: use of undeclared crate or module `fox` + --> $DIR/112590-2.rs:18:27 + | +LL | let _: Vec = fox::bar::baz::MyVec::new(); + | ^^^ use of undeclared crate or module `fox` + | +help: consider importing this struct through its public re-export + | +LL + use foo::bar::baz::MyVec; + | +help: if you import `MyVec`, refer to it directly + | +LL - let _: Vec = fox::bar::baz::MyVec::new(); +LL + let _: Vec = MyVec::new(); + | + +error[E0433]: failed to resolve: use of undeclared crate or module `vec` + --> $DIR/112590-2.rs:24:15 + | +LL | type _B = vec::Vec::; + | ^^^ use of undeclared crate or module `vec` + | +help: consider importing this module + | +LL + use std::vec; + | + +error[E0433]: failed to resolve: could not find `sync_error` in `std` + --> $DIR/112590-2.rs:25:19 + | +LL | let _t = std::sync_error::atomic::AtomicBool::new(true); + | ^^^^^^^^^^ could not find `sync_error` in `std` + | +help: consider importing this struct + | +LL + use std::sync::atomic::AtomicBool; + | +help: if you import `AtomicBool`, refer to it directly + | +LL - let _t = std::sync_error::atomic::AtomicBool::new(true); +LL + let _t = AtomicBool::new(true); + | + +error[E0433]: failed to resolve: use of undeclared crate or module `vec` + --> $DIR/112590-2.rs:23:24 + | +LL | let _t: Vec = vec::new(); + | ^^^ + | | + | use of undeclared crate or module `vec` + | help: a struct with a similar name exists (notice the capitalization): `Vec` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/export-fully-qualified-2018.stderr b/tests/ui/resolve/export-fully-qualified-2018.stderr index 366ffd9bb2b..b724da930df 100644 --- a/tests/ui/resolve/export-fully-qualified-2018.stderr +++ b/tests/ui/resolve/export-fully-qualified-2018.stderr @@ -3,11 +3,6 @@ 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 crate::foo; - | error: aborting due to previous error diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr index 0cd516ee1b1..a8af0c7c9b8 100644 --- a/tests/ui/resolve/export-fully-qualified.stderr +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -3,11 +3,6 @@ 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 5e7a7685ab0..9ece31e76f0 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -30,17 +30,23 @@ 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[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: aborting due to 4 previous errors