Skip to content

Commit

Permalink
Auto merge of #26087 - fitzgen:improve-suggestion-hueristics, r=Aatch
Browse files Browse the repository at this point in the history
This makes the maximum edit distance of typo suggestions a function of the typo'd name's length. FWIW, clang uses this same hueristic, and I've found their suggestions to be better than rustc's. Without something like this, you end up with suggestions that aren't related at all when there are short variable names.

See also #20028 (comment)
  • Loading branch information
bors committed Jun 8, 2015
2 parents 8f9f2fe + 93d01eb commit dcc59c0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 14 deletions.
16 changes: 8 additions & 8 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3206,14 +3206,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
NoSuggestion
}

fn find_best_match_for_name(&mut self, name: &str, max_distance: usize)
-> Option<String> {
let this = &mut *self;

fn find_best_match_for_name(&mut self, name: &str) -> Option<String> {
let mut maybes: Vec<token::InternedString> = Vec::new();
let mut values: Vec<usize> = Vec::new();

for rib in this.value_ribs.iter().rev() {
for rib in self.value_ribs.iter().rev() {
for (&k, _) in &rib.bindings {
maybes.push(token::get_name(k));
values.push(usize::MAX);
Expand All @@ -3229,9 +3226,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}

// As a loose rule to avoid obviously incorrect suggestions, clamp the
// maximum edit distance we will accept for a suggestion to one third of
// the typo'd name's length.
let max_distance = std::cmp::max(name.len(), 3) / 3;

if !values.is_empty() &&
values[smallest] != usize::MAX &&
values[smallest] < name.len() + 2 &&
values[smallest] <= max_distance &&
name != &maybes[smallest][..] {

Expand Down Expand Up @@ -3357,7 +3357,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
NoSuggestion => {
// limit search to 5 to reduce the number
// of stupid suggestions
self.find_best_match_for_name(&path_name, 5)
self.find_best_match_for_name(&path_name)
.map_or("".to_string(),
|x| format!("`{}`", x))
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/bad-expr-path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: unresolved name `m1::a`. Did you mean `args`?
// error-pattern: unresolved name `m1::arguments`. Did you mean `arguments`?

mod m1 {}

fn main(args: Vec<String>) { log(debug, m1::a); }
fn main(arguments: Vec<String>) { log(debug, m1::arguments); }
8 changes: 4 additions & 4 deletions src/test/compile-fail/bad-expr-path2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern: unresolved name `m1::a`. Did you mean `args`?
// error-pattern: unresolved name `m1::arguments`. Did you mean `arguments`?

mod m1 {
pub mod a {}
pub mod arguments {}
}

fn main(args: Vec<String>) {
log(debug, m1::a);
fn main(arguments: Vec<String>) {
log(debug, m1::arguments);
}
21 changes: 21 additions & 0 deletions src/test/compile-fail/typo-suggestion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2014 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.

fn main() {
let foo = 1;

// `foo` shouldn't be suggested, it is too dissimilar from `bar`.
println!("Hello {}", bar);
//~^ ERROR: unresolved name `bar`

// But this is close enough.
println!("Hello {}", fob);
//~^ ERROR: unresolved name `fob`. Did you mean `foo`?
}

0 comments on commit dcc59c0

Please sign in to comment.