Skip to content

Commit 09f18f6

Browse files
committed
[similar_names] don't raise if the first character is different
A lot of cases of the "noise" cases of `similar_names` come from two idents with a different first letter, which is easy enough to differentiate visually but causes this lint to be raised. Do not raise the lint in these cases, as long as the first character does not have a lookalike. Link: #10926
1 parent 4a5e30d commit 09f18f6

File tree

3 files changed

+32
-41
lines changed

3 files changed

+32
-41
lines changed

clippy_lints/src/non_expressive_names.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,14 @@ const ALLOWED_TO_BE_SIMILAR: &[&[&str]] = &[
131131
&["iter", "item"],
132132
];
133133

134+
/// Characters that look visually similar
135+
const SIMILAR_CHARS: &[(char, char)] = &[('l', 'i'), ('l', '1'), ('i', '1'), ('u', 'v')];
136+
137+
/// Return true if two characters are visually similar
138+
fn chars_are_similar(a: char, b: char) -> bool {
139+
a == b || SIMILAR_CHARS.contains(&(a, b)) || SIMILAR_CHARS.contains(&(b, a))
140+
}
141+
134142
struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);
135143

136144
impl<'a, 'tcx, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> {
@@ -219,6 +227,16 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
219227
}
220228

221229
let existing_str = existing_name.interned.as_str();
230+
231+
// The first char being different is usually enough to set identifiers apart, as long
232+
// as the characters aren't too similar.
233+
if !chars_are_similar(
234+
interned_name.chars().next().expect("len >= 1"),
235+
existing_str.chars().next().expect("len >= 1"),
236+
) {
237+
continue;
238+
}
239+
222240
let dissimilar = match existing_name.len.cmp(&count) {
223241
Ordering::Greater => existing_name.len - count != 1 || levenstein_not_1(interned_name, existing_str),
224242
Ordering::Less => count - existing_name.len != 1 || levenstein_not_1(existing_str, interned_name),

tests/ui/similar_names.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,10 @@ fn main() {
1717
let specter: i32;
1818
let spectre: i32;
1919

20+
// ok; first letter is different enough
2021
let apple: i32;
21-
2222
let bpple: i32;
23-
//~^ ERROR: binding's name is too similar to existing binding
24-
2523
let cpple: i32;
26-
//~^ ERROR: binding's name is too similar to existing binding
2724

2825
let a_bar: i32;
2926
let b_bar: i32;

tests/ui/similar_names.stderr

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,64 @@
11
error: binding's name is too similar to existing binding
2-
--> $DIR/similar_names.rs:22:9
3-
|
4-
LL | let bpple: i32;
5-
| ^^^^^
6-
|
7-
note: existing binding defined here
8-
--> $DIR/similar_names.rs:20:9
9-
|
10-
LL | let apple: i32;
11-
| ^^^^^
12-
= note: `-D clippy::similar-names` implied by `-D warnings`
13-
= help: to override `-D warnings` add `#[allow(clippy::similar_names)]`
14-
15-
error: binding's name is too similar to existing binding
16-
--> $DIR/similar_names.rs:25:9
17-
|
18-
LL | let cpple: i32;
19-
| ^^^^^
20-
|
21-
note: existing binding defined here
22-
--> $DIR/similar_names.rs:20:9
23-
|
24-
LL | let apple: i32;
25-
| ^^^^^
26-
27-
error: binding's name is too similar to existing binding
28-
--> $DIR/similar_names.rs:50:9
2+
--> $DIR/similar_names.rs:47:9
293
|
304
LL | let bluby: i32;
315
| ^^^^^
326
|
337
note: existing binding defined here
34-
--> $DIR/similar_names.rs:49:9
8+
--> $DIR/similar_names.rs:46:9
359
|
3610
LL | let blubx: i32;
3711
| ^^^^^
12+
= note: `-D clippy::similar-names` implied by `-D warnings`
13+
= help: to override `-D warnings` add `#[allow(clippy::similar_names)]`
3814

3915
error: binding's name is too similar to existing binding
40-
--> $DIR/similar_names.rs:55:9
16+
--> $DIR/similar_names.rs:52:9
4117
|
4218
LL | let coke: i32;
4319
| ^^^^
4420
|
4521
note: existing binding defined here
46-
--> $DIR/similar_names.rs:53:9
22+
--> $DIR/similar_names.rs:50:9
4723
|
4824
LL | let cake: i32;
4925
| ^^^^
5026

5127
error: binding's name is too similar to existing binding
52-
--> $DIR/similar_names.rs:74:9
28+
--> $DIR/similar_names.rs:71:9
5329
|
5430
LL | let xyzeabc: i32;
5531
| ^^^^^^^
5632
|
5733
note: existing binding defined here
58-
--> $DIR/similar_names.rs:72:9
34+
--> $DIR/similar_names.rs:69:9
5935
|
6036
LL | let xyz1abc: i32;
6137
| ^^^^^^^
6238

6339
error: binding's name is too similar to existing binding
64-
--> $DIR/similar_names.rs:79:9
40+
--> $DIR/similar_names.rs:76:9
6541
|
6642
LL | let parsee: i32;
6743
| ^^^^^^
6844
|
6945
note: existing binding defined here
70-
--> $DIR/similar_names.rs:77:9
46+
--> $DIR/similar_names.rs:74:9
7147
|
7248
LL | let parser: i32;
7349
| ^^^^^^
7450

7551
error: binding's name is too similar to existing binding
76-
--> $DIR/similar_names.rs:101:16
52+
--> $DIR/similar_names.rs:98:16
7753
|
7854
LL | bpple: sprang,
7955
| ^^^^^^
8056
|
8157
note: existing binding defined here
82-
--> $DIR/similar_names.rs:100:16
58+
--> $DIR/similar_names.rs:97:16
8359
|
8460
LL | apple: spring,
8561
| ^^^^^^
8662

87-
error: aborting due to 7 previous errors
63+
error: aborting due to 5 previous errors
8864

0 commit comments

Comments
 (0)