about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2015-06-07 17:56:18 -0700
committerNick Fitzgerald <fitzgen@gmail.com>2015-06-07 18:01:33 -0700
commit93d01eb443d0f871716c9d7faa3b69dc49662663 (patch)
treeaec856f46642ee7e3e3f1fff93c02c24eb36da8c
parentae74652b4a0e0e56a91d9a9dd71ab01e51131dc5 (diff)
downloadrust-93d01eb443d0f871716c9d7faa3b69dc49662663.tar.gz
rust-93d01eb443d0f871716c9d7faa3b69dc49662663.zip
Make the maximum edit distance of typo suggestions a function of the typo'd name's length.
-rw-r--r--src/librustc_resolve/lib.rs16
-rw-r--r--src/test/compile-fail/bad-expr-path.rs4
-rw-r--r--src/test/compile-fail/bad-expr-path2.rs8
-rw-r--r--src/test/compile-fail/typo-suggestion.rs21
4 files changed, 35 insertions, 14 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index cae0c7c7f57..ba8680a35cb 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -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);
@@ -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][..] {
 
@@ -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))
                                     }
diff --git a/src/test/compile-fail/bad-expr-path.rs b/src/test/compile-fail/bad-expr-path.rs
index 38ba652f53b..c35c9255ed2 100644
--- a/src/test/compile-fail/bad-expr-path.rs
+++ b/src/test/compile-fail/bad-expr-path.rs
@@ -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); }
diff --git a/src/test/compile-fail/bad-expr-path2.rs b/src/test/compile-fail/bad-expr-path2.rs
index f397d0b387d..af34887dec9 100644
--- a/src/test/compile-fail/bad-expr-path2.rs
+++ b/src/test/compile-fail/bad-expr-path2.rs
@@ -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);
 }
diff --git a/src/test/compile-fail/typo-suggestion.rs b/src/test/compile-fail/typo-suggestion.rs
new file mode 100644
index 00000000000..d5cf6a294ee
--- /dev/null
+++ b/src/test/compile-fail/typo-suggestion.rs
@@ -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`?
+}