Skip to content

Add filter with following segment while lookup typo for path #113331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3503,7 +3503,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let report_errors = |this: &mut Self, res: Option<Res>| {
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();
Expand Down Expand Up @@ -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,
Expand Down
66 changes: 47 additions & 19 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ImportSuggestion> {
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,
Expand All @@ -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
}
Expand All @@ -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<Res>,
Expand Down Expand Up @@ -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);
}
Expand All @@ -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.
Expand Down Expand Up @@ -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<Res>,
base_error: &BaseError,
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
29 changes: 29 additions & 0 deletions tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs
Original file line number Diff line number Diff line change
@@ -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() {}
53 changes: 53 additions & 0 deletions tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr
Original file line number Diff line number Diff line change
@@ -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`.
1 change: 1 addition & 0 deletions tests/ui/hygiene/extern-prelude-from-opaque-fail.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// edition:2015
#![feature(decl_macro)]

macro a() {
Expand Down
20 changes: 16 additions & 4 deletions tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -16,21 +16,33 @@ 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`
...
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

Expand Down
4 changes: 0 additions & 4 deletions tests/ui/macros/builtin-prelude-no-accidents.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `vec`
LL | type B = vec::Vec<u8>;
| ^^^ use of undeclared crate or module `vec`
|
help: a struct with a similar name exists
|
LL | type B = Vec::Vec<u8>;
| ~~~
help: consider importing this module
|
LL + use std::vec;
Expand Down
34 changes: 34 additions & 0 deletions tests/ui/resolve/112590-2.fixed
Original file line number Diff line number Diff line change
@@ -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<i32> = MyVec::new(); //~ ERROR failed to resolve
}
}

mod v {
use foo::bar::baz::MyVec;

fn _b() {
let _: Vec<i32> = MyVec::new(); //~ ERROR failed to resolve
}
}

fn main() {
let _t: Vec<i32> = Vec::new(); //~ ERROR failed to resolve
type _B = vec::Vec::<u8>; //~ ERROR failed to resolve
let _t = AtomicBool::new(true); //~ ERROR failed to resolve
}
Loading