Rollup merge of #45173 - laumann:suggest-misspelled-labels, r=petrochenkov
Add suggestions for misspelled labels Another part of #30197
This commit is contained in:
commit
46d86d3847
3 changed files with 72 additions and 10 deletions
|
@ -137,7 +137,7 @@ enum ResolutionError<'a> {
|
|||
/// error E0416: identifier is bound more than once in the same pattern
|
||||
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
||||
/// error E0426: use of undeclared label
|
||||
UndeclaredLabel(&'a str),
|
||||
UndeclaredLabel(&'a str, Option<Name>),
|
||||
/// error E0429: `self` imports are only allowed within a { } list
|
||||
SelfImportsOnlyAllowedWithin,
|
||||
/// error E0430: `self` import can only appear once in the list
|
||||
|
@ -263,13 +263,17 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
|
|||
err.span_label(span, "used in a pattern more than once");
|
||||
err
|
||||
}
|
||||
ResolutionError::UndeclaredLabel(name) => {
|
||||
ResolutionError::UndeclaredLabel(name, lev_candidate) => {
|
||||
let mut err = struct_span_err!(resolver.session,
|
||||
span,
|
||||
E0426,
|
||||
"use of undeclared label `{}`",
|
||||
name);
|
||||
if let Some(lev_candidate) = lev_candidate {
|
||||
err.span_label(span, format!("did you mean `{}`?", lev_candidate));
|
||||
} else {
|
||||
err.span_label(span, format!("undeclared label `{}`", name));
|
||||
}
|
||||
err
|
||||
}
|
||||
ResolutionError::SelfImportsOnlyAllowedWithin => {
|
||||
|
@ -1790,9 +1794,13 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Searches the current set of local scopes for labels.
|
||||
/// Searches the current set of local scopes for labels. Returns the first non-None label that
|
||||
/// is returned by the given predicate function
|
||||
///
|
||||
/// Stops after meeting a closure.
|
||||
fn search_label(&self, mut ident: Ident) -> Option<Def> {
|
||||
fn search_label<P, R>(&self, mut ident: Ident, pred: P) -> Option<R>
|
||||
where P: Fn(&Rib, Ident) -> Option<R>
|
||||
{
|
||||
for rib in self.label_ribs.iter().rev() {
|
||||
match rib.kind {
|
||||
NormalRibKind => {}
|
||||
|
@ -1808,9 +1816,9 @@ impl<'a> Resolver<'a> {
|
|||
return None;
|
||||
}
|
||||
}
|
||||
let result = rib.bindings.get(&ident).cloned();
|
||||
if result.is_some() {
|
||||
return result;
|
||||
let r = pred(rib, ident);
|
||||
if r.is_some() {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -3202,12 +3210,20 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
|
||||
match self.search_label(label.node) {
|
||||
match self.search_label(label.node, |rib, id| rib.bindings.get(&id).cloned()) {
|
||||
None => {
|
||||
// Search again for close matches...
|
||||
// Picks the first label that is "close enough", which is not necessarily
|
||||
// the closest match
|
||||
let close_match = self.search_label(label.node, |rib, ident| {
|
||||
let names = rib.bindings.iter().map(|(id, _)| &id.name);
|
||||
find_best_match_for_name(names, &*ident.name.as_str(), None)
|
||||
});
|
||||
self.record_def(expr.id, err_path_resolution());
|
||||
resolve_error(self,
|
||||
label.span,
|
||||
ResolutionError::UndeclaredLabel(&label.node.name.as_str()));
|
||||
ResolutionError::UndeclaredLabel(&label.node.name.as_str(),
|
||||
close_match));
|
||||
}
|
||||
Some(def @ Def::Label(_)) => {
|
||||
// Since this def is a label, it is never read.
|
||||
|
|
26
src/test/ui/suggestions/suggest-labels.rs
Normal file
26
src/test/ui/suggestions/suggest-labels.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
fn main() {
|
||||
'foo: loop {
|
||||
break 'fo;
|
||||
}
|
||||
|
||||
'bar: loop {
|
||||
continue 'bor;
|
||||
}
|
||||
|
||||
'longlabel: loop {
|
||||
'longlabel1: loop {
|
||||
break 'longlable;
|
||||
}
|
||||
}
|
||||
}
|
20
src/test/ui/suggestions/suggest-labels.stderr
Normal file
20
src/test/ui/suggestions/suggest-labels.stderr
Normal file
|
@ -0,0 +1,20 @@
|
|||
error[E0426]: use of undeclared label `'fo`
|
||||
--> $DIR/suggest-labels.rs:14:15
|
||||
|
|
||||
14 | break 'fo;
|
||||
| ^^^ did you mean `'foo`?
|
||||
|
||||
error[E0426]: use of undeclared label `'bor`
|
||||
--> $DIR/suggest-labels.rs:18:18
|
||||
|
|
||||
18 | continue 'bor;
|
||||
| ^^^^ did you mean `'bar`?
|
||||
|
||||
error[E0426]: use of undeclared label `'longlable`
|
||||
--> $DIR/suggest-labels.rs:23:19
|
||||
|
|
||||
23 | break 'longlable;
|
||||
| ^^^^^^^^^^ did you mean `'longlabel1`?
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
Loading…
Reference in a new issue