Skip to content

Commit 28b50a4

Browse files
committed
auto merge of #5096 : luqmana/rust/spell, r=catamorphism
Address #2281 ``` -> % cat foo.rs fn foo() -> int { let bar = 10; bad } ``` ``` -> % rustc foo.rs foo.rs:4:4: 4:7 error: unresolved name: `bad`. Did you mean: `bar`? foo.rs:4 bad ^~~ error: aborting due to previous error ```
2 parents 93a7f23 + a0866d0 commit 28b50a4

File tree

10 files changed

+92
-11
lines changed

10 files changed

+92
-11
lines changed

src/libcore/str.rs

+34
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,40 @@ pub pure fn split_str_nonempty(s: &a/str, sep: &b/str) -> ~[~str] {
590590
result
591591
}
592592

593+
/// Levenshtein Distance between two strings
594+
pub fn levdistance(s: &str, t: &str) -> uint {
595+
596+
let slen = str::len(s);
597+
let tlen = str::len(t);
598+
599+
if slen == 0 { return tlen; }
600+
if tlen == 0 { return slen; }
601+
602+
let mut dcol = vec::from_fn(tlen + 1, |x| x);
603+
604+
for str::each_chari(s) |i, sc| {
605+
606+
let mut current = i;
607+
dcol[0] = current + 1;
608+
609+
for str::each_chari(t) |j, tc| {
610+
611+
let mut next = dcol[j + 1];
612+
613+
if sc == tc {
614+
dcol[j + 1] = current;
615+
} else {
616+
dcol[j + 1] = ::cmp::min(current, next);
617+
dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1;
618+
}
619+
620+
current = next;
621+
}
622+
}
623+
624+
return dcol[tlen];
625+
}
626+
593627
/**
594628
* Splits a string into a vector of the substrings separated by LF ('\n')
595629
*/

src/librustc/middle/resolve.rs

+49-2
Original file line numberDiff line numberDiff line change
@@ -4816,6 +4816,42 @@ pub impl Resolver {
48164816
}
48174817
}
48184818
4819+
fn find_best_match_for_name(@mut self, name: &str) -> Option<~str> {
4820+
let mut maybes: ~[~str] = ~[];
4821+
let mut values: ~[uint] = ~[];
4822+
4823+
let mut j = self.value_ribs.len();
4824+
while j != 0 {
4825+
j -= 1;
4826+
let rib = self.value_ribs.get_elt(j);
4827+
for rib.bindings.each_entry |e| {
4828+
vec::push(&mut maybes, copy *self.session.str_of(e.key));
4829+
vec::push(&mut values, uint::max_value);
4830+
}
4831+
}
4832+
4833+
let mut smallest = 0;
4834+
for vec::eachi(maybes) |i, &other| {
4835+
4836+
values[i] = str::levdistance(name, other);
4837+
4838+
if values[i] <= values[smallest] {
4839+
smallest = i;
4840+
}
4841+
}
4842+
4843+
if vec::len(values) > 0 &&
4844+
values[smallest] != uint::max_value &&
4845+
values[smallest] < str::len(name) + 2 &&
4846+
maybes[smallest] != name.to_owned() {
4847+
4848+
Some(vec::swap_remove(&mut maybes, smallest))
4849+
4850+
} else {
4851+
None
4852+
}
4853+
}
4854+
48194855
fn name_exists_in_scope_struct(@mut self, name: &str) -> bool {
48204856
let mut i = self.type_ribs.len();
48214857
while i != 0 {
@@ -4882,9 +4918,20 @@ pub impl Resolver {
48824918
wrong_name));
48834919
}
48844920
else {
4885-
self.session.span_err(expr.span,
4886-
fmt!("unresolved name: %s",
4921+
match self.find_best_match_for_name(wrong_name) {
4922+
4923+
Some(m) => {
4924+
self.session.span_err(expr.span,
4925+
fmt!("unresolved name: `%s`. \
4926+
Did you mean: `%s`?",
4927+
wrong_name, m));
4928+
}
4929+
None => {
4930+
self.session.span_err(expr.span,
4931+
fmt!("unresolved name: `%s`.",
48874932
wrong_name));
4933+
}
4934+
}
48884935
}
48894936
}
48904937
}

src/test/compile-fail/alt-join.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ fn my_fail() -> ! { fail!(); }
1616
fn main() {
1717
match true { false => { my_fail(); } true => { } }
1818

19-
log(debug, x); //~ ERROR unresolved name: x
19+
log(debug, x); //~ ERROR unresolved name: `x`.
2020
let x: int;
2121
}

src/test/compile-fail/bad-expr-path.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

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

1313
mod m1 {}
1414

src/test/compile-fail/bad-expr-path2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

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

1313
mod m1 {
1414
pub mod a {}

src/test/compile-fail/does-nothing.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
// error-pattern: unresolved name: this_does_nothing_what_the
1+
// error-pattern: unresolved name: `this_does_nothing_what_the`.
22
fn main() { debug!("doing"); this_does_nothing_what_the; debug!("boing"); }
33

src/test/compile-fail/issue-1476.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
log(error, x); //~ ERROR unresolved name: x
12+
log(error, x); //~ ERROR unresolved name: `x`.
1313
}

src/test/compile-fail/issue-3021-b.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fn siphash(k0 : u64) {
1919
impl siphash {
2020
fn reset(&mut self) {
2121
self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR attempted dynamic environment-capture
22-
//~^ ERROR unresolved name: k0
22+
//~^ ERROR unresolved name: `k0`.
2323
}
2424
}
2525
}

src/test/compile-fail/issue-3021-d.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ fn siphash(k0 : u64, k1 : u64) -> siphash {
3131
impl siphash for sipstate {
3232
fn reset() {
3333
self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR attempted dynamic environment-capture
34-
//~^ ERROR unresolved name: k0
34+
//~^ ERROR unresolved name: `k0`.
3535
self.v1 = k1 ^ 0x646f72616e646f6d; //~ ERROR attempted dynamic environment-capture
36-
//~^ ERROR unresolved name: k1
36+
//~^ ERROR unresolved name: `k1`.
3737
}
3838
fn result() -> u64 { return mk_result(self); }
3939
}

src/test/compile-fail/issue-3021.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn siphash(k0 : u64) -> siphash {
2323
impl siphash for sipstate {
2424
fn reset() {
2525
self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR attempted dynamic environment-capture
26-
//~^ ERROR unresolved name: k0
26+
//~^ ERROR unresolved name: `k0`.
2727
}
2828
}
2929
fail!();

0 commit comments

Comments
 (0)