1
Fork 0

Account for hygiene when suggesting typos.

This commit is contained in:
Camille GILLOT 2022-10-16 08:51:11 +00:00
parent 9b0a099dfc
commit 6d947e6d48
7 changed files with 51 additions and 23 deletions

View file

@ -24,7 +24,7 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span, SyntaxContext};
use crate::imports::{Import, ImportKind, ImportResolver}; use crate::imports::{Import, ImportKind, ImportResolver};
use crate::late::{PatternSource, Rib}; use crate::late::{PatternSource, Rib};
@ -47,6 +47,7 @@ pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
/// similarly named label and whether or not it is reachable. /// similarly named label and whether or not it is reachable.
pub(crate) type LabelSuggestion = (Ident, bool); pub(crate) type LabelSuggestion = (Ident, bool);
#[derive(Debug)]
pub(crate) enum SuggestionTarget { pub(crate) enum SuggestionTarget {
/// The target has a similar name as the name used by the programmer (probably a typo) /// The target has a similar name as the name used by the programmer (probably a typo)
SimilarlyNamed, SimilarlyNamed,
@ -54,6 +55,7 @@ pub(crate) enum SuggestionTarget {
SingleItem, SingleItem,
} }
#[derive(Debug)]
pub(crate) struct TypoSuggestion { pub(crate) struct TypoSuggestion {
pub candidate: Symbol, pub candidate: Symbol,
pub res: Res, pub res: Res,
@ -482,11 +484,12 @@ impl<'a> Resolver<'a> {
module: Module<'a>, module: Module<'a>,
names: &mut Vec<TypoSuggestion>, names: &mut Vec<TypoSuggestion>,
filter_fn: &impl Fn(Res) -> bool, filter_fn: &impl Fn(Res) -> bool,
ctxt: Option<SyntaxContext>,
) { ) {
for (key, resolution) in self.resolutions(module).borrow().iter() { for (key, resolution) in self.resolutions(module).borrow().iter() {
if let Some(binding) = resolution.borrow().binding { if let Some(binding) = resolution.borrow().binding {
let res = binding.res(); let res = binding.res();
if filter_fn(res) { if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
names.push(TypoSuggestion::typo_from_res(key.ident.name, res)); names.push(TypoSuggestion::typo_from_res(key.ident.name, res));
} }
} }
@ -1181,10 +1184,10 @@ impl<'a> Resolver<'a> {
Scope::CrateRoot => { Scope::CrateRoot => {
let root_ident = Ident::new(kw::PathRoot, ident.span); let root_ident = Ident::new(kw::PathRoot, ident.span);
let root_module = this.resolve_crate_root(root_ident); let root_module = this.resolve_crate_root(root_ident);
this.add_module_candidates(root_module, &mut suggestions, filter_fn); this.add_module_candidates(root_module, &mut suggestions, filter_fn, None);
} }
Scope::Module(module, _) => { Scope::Module(module, _) => {
this.add_module_candidates(module, &mut suggestions, filter_fn); this.add_module_candidates(module, &mut suggestions, filter_fn, None);
} }
Scope::MacroUsePrelude => { Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map( suggestions.extend(this.macro_use_prelude.iter().filter_map(
@ -1221,7 +1224,7 @@ impl<'a> Resolver<'a> {
Scope::StdLibPrelude => { Scope::StdLibPrelude => {
if let Some(prelude) = this.prelude { if let Some(prelude) = this.prelude {
let mut tmp_suggestions = Vec::new(); let mut tmp_suggestions = Vec::new();
this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
suggestions.extend( suggestions.extend(
tmp_suggestions tmp_suggestions
.into_iter() .into_iter()

View file

@ -131,6 +131,7 @@ pub(super) enum LifetimeElisionCandidate {
} }
/// Only used for diagnostics. /// Only used for diagnostics.
#[derive(Debug)]
struct BaseError { struct BaseError {
msg: String, msg: String,
fallback_label: String, fallback_label: String,
@ -1584,19 +1585,35 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
) -> Option<TypoSuggestion> { ) -> Option<TypoSuggestion> {
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();
// Search in lexical scope. // Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates. // Walk backwards up the ribs in scope and collect candidates.
for rib in self.ribs[ns].iter().rev() { for rib in self.ribs[ns].iter().rev() {
let rib_ctxt = if rib.kind.contains_params() {
ctxt.normalize_to_macros_2_0()
} else {
ctxt.normalize_to_macro_rules()
};
// Locals and type parameters // Locals and type parameters
for (ident, &res) in &rib.bindings { for (ident, &res) in &rib.bindings {
if filter_fn(res) { if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
names.push(TypoSuggestion::typo_from_res(ident.name, res)); names.push(TypoSuggestion::typo_from_res(ident.name, res));
} }
} }
if let RibKind::MacroDefinition(def) = rib.kind && def == self.r.macro_def(ctxt) {
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
ctxt.remove_mark();
continue;
}
// Items in scope // Items in scope
if let RibKind::ModuleRibKind(module) = rib.kind { if let RibKind::ModuleRibKind(module) = rib.kind {
// Items from this module // Items from this module
self.r.add_module_candidates(module, &mut names, &filter_fn); self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
if let ModuleKind::Block = module.kind { if let ModuleKind::Block = module.kind {
// We can see through blocks // We can see through blocks
@ -1622,7 +1639,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
})); }));
if let Some(prelude) = self.r.prelude { if let Some(prelude) = self.r.prelude {
self.r.add_module_candidates(prelude, &mut names, &filter_fn); self.r.add_module_candidates(prelude, &mut names, &filter_fn, None);
} }
} }
break; break;
@ -1641,7 +1658,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, Some(TypeNS), None) self.resolve_path(mod_path, Some(TypeNS), None)
{ {
self.r.add_module_candidates(module, &mut names, &filter_fn); self.r.add_module_candidates(module, &mut names, &filter_fn, None);
} }
} }

View file

@ -1,9 +1,16 @@
error[E0425]: cannot find function `f` in this scope error[E0425]: cannot find function `f` in this scope
--> $DIR/globs.rs:22:9 --> $DIR/globs.rs:22:9
| |
LL | pub fn g() {}
| ---------- similarly named function `g` defined here
...
LL | f(); LL | f();
| ^ not found in this scope | ^
| |
help: a function with a similar name exists
|
LL | g();
| ~
help: consider importing this function help: consider importing this function
| |
LL | use foo::f; LL | use foo::f;
@ -12,8 +19,11 @@ LL | use foo::f;
error[E0425]: cannot find function `g` in this scope error[E0425]: cannot find function `g` in this scope
--> $DIR/globs.rs:15:5 --> $DIR/globs.rs:15:5
| |
LL | pub fn f() {}
| ---------- similarly named function `f` defined here
...
LL | g(); LL | g();
| ^ not found in this scope | ^
... ...
LL | / m! { LL | / m! {
LL | | use bar::*; LL | | use bar::*;
@ -23,6 +33,10 @@ LL | | }
| |_____- in this macro invocation | |_____- in this macro invocation
| |
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
help: a function with a similar name exists
|
LL | f();
| ~
help: consider importing this function help: consider importing this function
| |
LL | use bar::g; LL | use bar::g;

View file

@ -19,14 +19,8 @@ LL | semitransparent;
error[E0423]: expected value, found macro `opaque` error[E0423]: expected value, found macro `opaque`
--> $DIR/rustc-macro-transparency.rs:30:5 --> $DIR/rustc-macro-transparency.rs:30:5
| |
LL | struct Opaque;
| -------------- similarly named unit struct `Opaque` defined here
...
LL | opaque; LL | opaque;
| ^^^^^^ | ^^^^^^ not a value
| |
| not a value
| help: a unit struct with a similar name exists (notice the capitalization): `Opaque`
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -57,7 +57,7 @@ error[E0425]: cannot find value `i` in this scope
--> $DIR/macro-context.rs:3:13 --> $DIR/macro-context.rs:3:13
| |
LL | () => ( i ; typeof ); LL | () => ( i ; typeof );
| ^ help: a local variable with a similar name exists: `a` | ^ not found in this scope
... ...
LL | let i = m!(); LL | let i = m!();
| ---- in this macro invocation | ---- in this macro invocation

View file

@ -13,7 +13,7 @@ error[E0425]: cannot find value `local_use` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:12:1 --> $DIR/gen-macro-rules-hygiene.rs:12:1
| |
LL | gen_macro_rules!(); LL | gen_macro_rules!();
| ^^^^^^^^^^^^^^^^^^ not found in this scope | ^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def`
... ...
LL | generated!(); LL | generated!();
| ------------ in this macro invocation | ------------ in this macro invocation
@ -24,7 +24,7 @@ error[E0425]: cannot find value `local_def` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:21:9 --> $DIR/gen-macro-rules-hygiene.rs:21:9
| |
LL | local_def; LL | local_def;
| ^^^^^^^^^ not found in this scope | ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -10,7 +10,7 @@ error[E0425]: cannot find value `local_use` in this scope
--> $DIR/mixed-site-span.rs:13:9 --> $DIR/mixed-site-span.rs:13:9
| |
LL | proc_macro_rules!(); LL | proc_macro_rules!();
| ^^^^^^^^^^^^^^^^^^^ not found in this scope | ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def`
| |
= note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info)
@ -18,7 +18,7 @@ error[E0425]: cannot find value `local_def` in this scope
--> $DIR/mixed-site-span.rs:17:9 --> $DIR/mixed-site-span.rs:17:9
| |
LL | local_def; LL | local_def;
| ^^^^^^^^^ not found in this scope | ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
error[E0412]: cannot find type `ItemUse` in crate `$crate` error[E0412]: cannot find type `ItemUse` in crate `$crate`
--> $DIR/mixed-site-span.rs:24:1 --> $DIR/mixed-site-span.rs:24:1