Skip to content

Commit 8c8835d

Browse files
authored
Rollup merge of rust-lang#89956 - JohnTitor:suggest-case-insensitive-match-names, r=estebank
Suggest a case insensitive match name regardless of levenshtein distance Fixes rust-lang#86170 Currently, `find_best_match_for_name` only returns a case insensitive match name depending on a Levenshtein distance. It's a bit unfortunate that that hides some suggestions for typos like `Bar` -> `BAR`. That idea is from rust-lang#46347 (comment), but I think it still makes some sense to show a candidate when we find a case insensitive match name as it's more like a typo. Skipped the `candidate != lookup` check because the current (i.e, `levenshtein_match`) returns the exact same `Symbol` anyway but it doesn't seem to confuse anything on UI tests. r? ``@estebank``
2 parents 9dccb7b + d4cc877 commit 8c8835d

File tree

4 files changed

+37
-30
lines changed

4 files changed

+37
-30
lines changed

compiler/rustc_span/src/lev_distance.rs

+15-21
Original file line numberDiff line numberDiff line change
@@ -58,34 +58,28 @@ pub fn find_best_match_for_name(
5858
let lookup = &lookup.as_str();
5959
let max_dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3);
6060

61-
let (case_insensitive_match, levenshtein_match) = name_vec
61+
// Priority of matches:
62+
// 1. Exact case insensitive match
63+
// 2. Levenshtein distance match
64+
// 3. Sorted word match
65+
if let Some(case_insensitive_match) =
66+
name_vec.iter().find(|candidate| candidate.as_str().to_uppercase() == lookup.to_uppercase())
67+
{
68+
return Some(*case_insensitive_match);
69+
}
70+
let levenshtein_match = name_vec
6271
.iter()
6372
.filter_map(|&name| {
6473
let dist = lev_distance(lookup, &name.as_str());
6574
if dist <= max_dist { Some((name, dist)) } else { None }
6675
})
6776
// Here we are collecting the next structure:
68-
// (case_insensitive_match, (levenshtein_match, levenshtein_distance))
69-
.fold((None, None), |result, (candidate, dist)| {
70-
(
71-
if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
72-
Some(candidate)
73-
} else {
74-
result.0
75-
},
76-
match result.1 {
77-
None => Some((candidate, dist)),
78-
Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }),
79-
},
80-
)
77+
// (levenshtein_match, levenshtein_distance)
78+
.fold(None, |result, (candidate, dist)| match result {
79+
None => Some((candidate, dist)),
80+
Some((c, d)) => Some(if dist < d { (candidate, dist) } else { (c, d) }),
8181
});
82-
// Priority of matches:
83-
// 1. Exact case insensitive match
84-
// 2. Levenshtein distance match
85-
// 3. Sorted word match
86-
if let Some(candidate) = case_insensitive_match {
87-
Some(candidate)
88-
} else if levenshtein_match.is_some() {
82+
if levenshtein_match.is_some() {
8983
levenshtein_match.map(|(candidate, _)| candidate)
9084
} else {
9185
find_match_by_sorted_words(name_vec, lookup)

compiler/rustc_span/src/lev_distance/tests.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,12 @@ fn test_find_best_match_for_name() {
3131

3232
assert_eq!(find_best_match_for_name(&input, Symbol::intern("1111111111"), None), None);
3333

34-
let input = vec![Symbol::intern("aAAA")];
34+
let input = vec![Symbol::intern("AAAA")];
3535
assert_eq!(
36-
find_best_match_for_name(&input, Symbol::intern("AAAA"), None),
37-
Some(Symbol::intern("aAAA"))
36+
find_best_match_for_name(&input, Symbol::intern("aaaa"), None),
37+
Some(Symbol::intern("AAAA"))
3838
);
3939

40-
let input = vec![Symbol::intern("AAAA")];
41-
// Returns None because `lev_distance > max_dist / 3`
42-
assert_eq!(find_best_match_for_name(&input, Symbol::intern("aaaa"), None), None);
43-
4440
let input = vec![Symbol::intern("AAAA")];
4541
assert_eq!(
4642
find_best_match_for_name(&input, Symbol::intern("aaaa"), Some(4)),

src/test/ui/hygiene/rustc-macro-transparency.stderr

+15-1
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,43 @@ error[E0425]: cannot find value `Opaque` in this scope
22
--> $DIR/rustc-macro-transparency.rs:26:5
33
|
44
LL | Opaque;
5-
| ^^^^^^ help: a local variable with a similar name exists (notice the capitalization): `opaque`
5+
| ^^^^^^ not found in this scope
66

77
error[E0423]: expected value, found macro `semitransparent`
88
--> $DIR/rustc-macro-transparency.rs:29:5
99
|
10+
LL | struct SemiTransparent;
11+
| ----------------------- similarly named unit struct `SemiTransparent` defined here
12+
...
1013
LL | semitransparent;
1114
| ^^^^^^^^^^^^^^^ not a value
1215
|
1316
help: use `!` to invoke the macro
1417
|
1518
LL | semitransparent!;
1619
| +
20+
help: a unit struct with a similar name exists
21+
|
22+
LL | SemiTransparent;
23+
| ~~~~~~~~~~~~~~~
1724

1825
error[E0423]: expected value, found macro `opaque`
1926
--> $DIR/rustc-macro-transparency.rs:30:5
2027
|
28+
LL | struct Opaque;
29+
| -------------- similarly named unit struct `Opaque` defined here
30+
...
2131
LL | opaque;
2232
| ^^^^^^ not a value
2333
|
2434
help: use `!` to invoke the macro
2535
|
2636
LL | opaque!;
2737
| +
38+
help: a unit struct with a similar name exists
39+
|
40+
LL | Opaque;
41+
| ~~~~~~
2842

2943
error: aborting due to 3 previous errors
3044

src/test/ui/issues/issue-22933-2.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ LL | enum Delicious {
55
| -------------- variant or associated item `PIE` not found here
66
...
77
LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
8-
| ^^^ variant or associated item not found in `Delicious`
8+
| ^^^
9+
| |
10+
| variant or associated item not found in `Delicious`
11+
| help: there is a variant with a similar name: `Pie`
912

1013
error: aborting due to previous error
1114

0 commit comments

Comments
 (0)