@@ -119,7 +119,6 @@ impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> {
119119
120120// this list contains lists of names that are allowed to be similar
121121// the assumption is that no name is ever contained in multiple lists.
122- #[ rustfmt:: skip]
123122const ALLOWED_TO_BE_SIMILAR : & [ & [ & str ] ] = & [
124123 & [ "parsed" , "parser" ] ,
125124 & [ "lhs" , "rhs" ] ,
@@ -189,7 +188,6 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
189188 }
190189 }
191190
192- #[ expect( clippy:: too_many_lines) ]
193191 fn check_ident ( & mut self , ident : Ident ) {
194192 let interned_name = ident. name . as_str ( ) ;
195193 if interned_name. chars ( ) . any ( char:: is_uppercase) {
@@ -219,71 +217,18 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
219217 if allowed_to_be_similar ( interned_name, existing_name. exemptions ) {
220218 continue ;
221219 }
222- match existing_name. len . cmp ( & count) {
223- Ordering :: Greater => {
224- if existing_name. len - count != 1
225- || levenstein_not_1 ( interned_name, existing_name. interned . as_str ( ) )
226- {
227- continue ;
228- }
229- } ,
230- Ordering :: Less => {
231- if count - existing_name. len != 1
232- || levenstein_not_1 ( existing_name. interned . as_str ( ) , interned_name)
233- {
234- continue ;
235- }
236- } ,
237- Ordering :: Equal => {
238- let mut interned_chars = interned_name. chars ( ) ;
239- let interned_str = existing_name. interned . as_str ( ) ;
240- let mut existing_chars = interned_str. chars ( ) ;
241- let first_i = interned_chars. next ( ) . expect ( "we know we have at least one char" ) ;
242- let first_e = existing_chars. next ( ) . expect ( "we know we have at least one char" ) ;
243- let eq_or_numeric = |( a, b) : ( char , char ) | a == b || a. is_numeric ( ) && b. is_numeric ( ) ;
244-
245- if eq_or_numeric ( ( first_i, first_e) ) {
246- let last_i = interned_chars. next_back ( ) . expect ( "we know we have at least two chars" ) ;
247- let last_e = existing_chars. next_back ( ) . expect ( "we know we have at least two chars" ) ;
248- if eq_or_numeric ( ( last_i, last_e) ) {
249- if interned_chars
250- . zip ( existing_chars)
251- . filter ( |& ie| !eq_or_numeric ( ie) )
252- . count ( )
253- != 1
254- {
255- continue ;
256- }
257- } else {
258- let second_last_i = interned_chars
259- . next_back ( )
260- . expect ( "we know we have at least three chars" ) ;
261- let second_last_e = existing_chars
262- . next_back ( )
263- . expect ( "we know we have at least three chars" ) ;
264- if !eq_or_numeric ( ( second_last_i, second_last_e) )
265- || second_last_i == '_'
266- || !interned_chars. zip ( existing_chars) . all ( eq_or_numeric)
267- {
268- // allowed similarity foo_x, foo_y
269- // or too many chars differ (foo_x, boo_y) or (foox, booy)
270- continue ;
271- }
272- }
273- } else {
274- let second_i = interned_chars. next ( ) . expect ( "we know we have at least two chars" ) ;
275- let second_e = existing_chars. next ( ) . expect ( "we know we have at least two chars" ) ;
276- if !eq_or_numeric ( ( second_i, second_e) )
277- || second_i == '_'
278- || !interned_chars. zip ( existing_chars) . all ( eq_or_numeric)
279- {
280- // allowed similarity x_foo, y_foo
281- // or too many chars differ (x_foo, y_boo) or (xfoo, yboo)
282- continue ;
283- }
284- }
285- } ,
220+
221+ let existing_str = existing_name. interned . as_str ( ) ;
222+ let dissimilar = match existing_name. len . cmp ( & count) {
223+ Ordering :: Greater => existing_name. len - count != 1 || levenstein_not_1 ( interned_name, existing_str) ,
224+ Ordering :: Less => count - existing_name. len != 1 || levenstein_not_1 ( existing_str, interned_name) ,
225+ Ordering :: Equal => Self :: equal_length_strs_not_similar ( interned_name, existing_str) ,
226+ } ;
227+
228+ if dissimilar {
229+ continue ;
286230 }
231+
287232 span_lint_and_then (
288233 self . 0 . cx ,
289234 SIMILAR_NAMES ,
@@ -302,6 +247,57 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
302247 len : count,
303248 } ) ;
304249 }
250+
251+ fn equal_length_strs_not_similar ( interned_name : & str , existing_name : & str ) -> bool {
252+ let mut interned_chars = interned_name. chars ( ) ;
253+ let mut existing_chars = existing_name. chars ( ) ;
254+ let first_i = interned_chars. next ( ) . expect ( "we know we have at least one char" ) ;
255+ let first_e = existing_chars. next ( ) . expect ( "we know we have at least one char" ) ;
256+ let eq_or_numeric = |( a, b) : ( char , char ) | a == b || a. is_numeric ( ) && b. is_numeric ( ) ;
257+
258+ if eq_or_numeric ( ( first_i, first_e) ) {
259+ let last_i = interned_chars. next_back ( ) . expect ( "we know we have at least two chars" ) ;
260+ let last_e = existing_chars. next_back ( ) . expect ( "we know we have at least two chars" ) ;
261+ if eq_or_numeric ( ( last_i, last_e) ) {
262+ if interned_chars
263+ . zip ( existing_chars)
264+ . filter ( |& ie| !eq_or_numeric ( ie) )
265+ . count ( )
266+ != 1
267+ {
268+ return true ;
269+ }
270+ } else {
271+ let second_last_i = interned_chars
272+ . next_back ( )
273+ . expect ( "we know we have at least three chars" ) ;
274+ let second_last_e = existing_chars
275+ . next_back ( )
276+ . expect ( "we know we have at least three chars" ) ;
277+ if !eq_or_numeric ( ( second_last_i, second_last_e) )
278+ || second_last_i == '_'
279+ || !interned_chars. zip ( existing_chars) . all ( eq_or_numeric)
280+ {
281+ // allowed similarity foo_x, foo_y
282+ // or too many chars differ (foo_x, boo_y) or (foox, booy)
283+ return true ;
284+ }
285+ }
286+ } else {
287+ let second_i = interned_chars. next ( ) . expect ( "we know we have at least two chars" ) ;
288+ let second_e = existing_chars. next ( ) . expect ( "we know we have at least two chars" ) ;
289+ if !eq_or_numeric ( ( second_i, second_e) )
290+ || second_i == '_'
291+ || !interned_chars. zip ( existing_chars) . all ( eq_or_numeric)
292+ {
293+ // allowed similarity x_foo, y_foo
294+ // or too many chars differ (x_foo, y_boo) or (xfoo, yboo)
295+ return true ;
296+ }
297+ }
298+
299+ false
300+ }
305301}
306302
307303impl < ' a , ' b > SimilarNamesLocalVisitor < ' a , ' b > {
0 commit comments