Point to shadowed name when it exists.
This commit is contained in:
parent
6d947e6d48
commit
4bbb163b5d
3 changed files with 51 additions and 9 deletions
|
@ -141,6 +141,22 @@ struct BaseError {
|
||||||
suggestion: Option<(Span, &'static str, String)>,
|
suggestion: Option<(Span, &'static str, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum TypoCandidate {
|
||||||
|
Typo(TypoSuggestion),
|
||||||
|
Shadowed(Res),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypoCandidate {
|
||||||
|
fn to_opt_suggestion(self) -> Option<TypoSuggestion> {
|
||||||
|
match self {
|
||||||
|
TypoCandidate::Typo(sugg) => Some(sugg),
|
||||||
|
TypoCandidate::Shadowed(_) | TypoCandidate::None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
fn def_span(&self, def_id: DefId) -> Option<Span> {
|
fn def_span(&self, def_id: DefId) -> Option<Span> {
|
||||||
match def_id.krate {
|
match def_id.krate {
|
||||||
|
@ -497,7 +513,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try Levenshtein algorithm.
|
// Try Levenshtein algorithm.
|
||||||
let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
|
let typo_sugg =
|
||||||
|
self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion();
|
||||||
if path.len() == 1 && self.self_type_is_available() {
|
if path.len() == 1 && self.self_type_is_available() {
|
||||||
if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) {
|
if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) {
|
||||||
let self_is_available = self.self_value_is_available(path[0].ident.span);
|
let self_is_available = self.self_value_is_available(path[0].ident.span);
|
||||||
|
@ -661,7 +678,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
let is_expected = &|res| source.is_expected(res);
|
let is_expected = &|res| source.is_expected(res);
|
||||||
let ident_span = path.last().map_or(span, |ident| ident.ident.span);
|
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, source.namespace(), is_expected);
|
||||||
|
if let TypoCandidate::Shadowed(res) = typo_sugg
|
||||||
|
&& let Some(id) = res.opt_def_id()
|
||||||
|
&& let Some(sugg_span) = self.r.opt_span(id)
|
||||||
|
{
|
||||||
|
err.span_label(
|
||||||
|
sugg_span,
|
||||||
|
format!("you might have meant to refer to this {}", res.descr()),
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let mut fallback = false;
|
let mut fallback = false;
|
||||||
|
let typo_sugg = typo_sugg.to_opt_suggestion();
|
||||||
if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
|
if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
|
||||||
fallback = true;
|
fallback = true;
|
||||||
match self.diagnostic_metadata.current_let_binding {
|
match self.diagnostic_metadata.current_let_binding {
|
||||||
|
@ -1582,7 +1610,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
path: &[Segment],
|
path: &[Segment],
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
filter_fn: &impl Fn(Res) -> bool,
|
filter_fn: &impl Fn(Res) -> bool,
|
||||||
) -> Option<TypoSuggestion> {
|
) -> TypoCandidate {
|
||||||
let mut names = Vec::new();
|
let mut names = Vec::new();
|
||||||
if path.len() == 1 {
|
if path.len() == 1 {
|
||||||
let mut ctxt = path.last().unwrap().ident.span.ctxt();
|
let mut ctxt = path.last().unwrap().ident.span.ctxt();
|
||||||
|
@ -1671,10 +1699,17 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
name,
|
name,
|
||||||
None,
|
None,
|
||||||
) {
|
) {
|
||||||
Some(found) if found != name => {
|
Some(found) => {
|
||||||
names.into_iter().find(|suggestion| suggestion.candidate == found)
|
let Some(sugg) = names.into_iter().find(|suggestion| suggestion.candidate == found) else {
|
||||||
|
return TypoCandidate::None;
|
||||||
|
};
|
||||||
|
if found == name {
|
||||||
|
TypoCandidate::Shadowed(sugg.res)
|
||||||
|
} else {
|
||||||
|
TypoCandidate::Typo(sugg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => TypoCandidate::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
error[E0574]: expected struct, variant or union type, found type parameter `T`
|
error[E0574]: expected struct, variant or union type, found type parameter `T`
|
||||||
--> $DIR/lexical-scopes.rs:3:13
|
--> $DIR/lexical-scopes.rs:3:13
|
||||||
|
|
|
|
||||||
|
LL | struct T { i: i32 }
|
||||||
|
| ------------------- you might have meant to refer to this struct
|
||||||
LL | fn f<T>() {
|
LL | fn f<T>() {
|
||||||
| - found this type parameter
|
| - found this type parameter
|
||||||
LL | let t = T { i: 0 };
|
LL | let t = T { i: 0 };
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
error[E0574]: expected struct, variant or union type, found type parameter `Baz`
|
error[E0574]: expected struct, variant or union type, found type parameter `Baz`
|
||||||
--> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13
|
--> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13
|
||||||
|
|
|
|
||||||
LL | impl<Baz> Foo<Baz> for Bar {
|
LL | / struct Baz {
|
||||||
| --- found this type parameter
|
LL | | num: usize,
|
||||||
|
LL | | }
|
||||||
|
| |_- you might have meant to refer to this struct
|
||||||
|
LL |
|
||||||
|
LL | impl<Baz> Foo<Baz> for Bar {
|
||||||
|
| --- found this type parameter
|
||||||
...
|
...
|
||||||
LL | Baz { num } => num,
|
LL | Baz { num } => num,
|
||||||
| ^^^ not a struct, variant or union type
|
| ^^^ not a struct, variant or union type
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue