1
- use clippy_utils:: diagnostics:: { span_lint_and_sugg , span_lint_and_help } ;
2
- use clippy_utils:: source:: { snippet, snippet_with_applicability , snippet_opt } ;
1
+ use clippy_utils:: diagnostics:: { span_lint_and_help , span_lint_and_sugg } ;
2
+ use clippy_utils:: source:: { snippet, snippet_opt , snippet_with_applicability } ;
3
3
use clippy_utils:: { SpanlessEq , SpanlessHash } ;
4
4
use core:: hash:: { Hash , Hasher } ;
5
5
use if_chain:: if_chain;
@@ -285,34 +285,22 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
285
285
}
286
286
287
287
fn check_bounds_or_where_duplication ( cx : & LateContext < ' _ > , gen : & ' _ Generics < ' _ > ) {
288
- if gen. span . from_expansion ( ) {
289
- return ;
290
- }
291
-
292
- for param in gen. params {
288
+ fn rollup_traits ( cx : & LateContext < ' _ > , bounds : & [ GenericBound < ' _ > ] , msg : & str ) {
293
289
let mut map = FxHashMap :: default ( ) ;
294
290
let mut repeated_spans = false ;
295
- if let ParamName :: Plain ( name) = param. name { // other alternatives are errors and elided which won't have duplicates
296
- for bound in param. bounds . iter ( ) . filter_map ( get_trait_info_from_bound) {
297
- let ( definition, _, span_direct) = bound;
298
- if let Some ( _) = map. insert ( definition, span_direct) {
299
- repeated_spans = true ;
300
- }
291
+ for bound in bounds. iter ( ) . filter_map ( get_trait_info_from_bound) {
292
+ let ( definition, _, span_direct) = bound;
293
+ if map. insert ( definition, span_direct) . is_some ( ) {
294
+ repeated_spans = true ;
301
295
}
296
+ }
302
297
303
- if repeated_spans {
304
- let all_trait_span = param
305
- . bounds
306
- . get ( 0 )
307
- . unwrap ( )
308
- . span ( )
309
- . to (
310
- param
311
- . bounds
312
- . iter ( )
313
- . last ( )
314
- . unwrap ( )
315
- . span ( ) ) ;
298
+ if_chain ! {
299
+ if repeated_spans;
300
+ if let Some ( first_trait) = bounds. get( 0 ) ;
301
+ if let Some ( last_trait) = bounds. iter( ) . last( ) ;
302
+ then {
303
+ let all_trait_span = first_trait. span( ) . to( last_trait. span( ) ) ;
316
304
317
305
let mut traits = map. values( )
318
306
. filter_map( |span| snippet_opt( cx, * span) )
@@ -324,7 +312,7 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
324
312
cx,
325
313
REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND ,
326
314
all_trait_span,
327
- "this trait bound contains repeated elements" ,
315
+ msg ,
328
316
"try" ,
329
317
traits,
330
318
Applicability :: MachineApplicable
@@ -333,50 +321,24 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
333
321
}
334
322
}
335
323
336
- for predicate in gen. where_clause . predicates {
337
- if let WherePredicate :: BoundPredicate ( ref bound_predicate) = predicate {
338
- let mut where_clauses = FxHashMap :: default ( ) ;
339
- let mut repeated_spans = false ;
340
-
341
- for ( definition, _, span_direct) in bound_predicate
342
- . bounds
343
- . iter ( )
344
- . filter_map ( get_trait_info_from_bound)
345
- {
346
- if let Some ( _) = where_clauses. insert ( definition, span_direct) {
347
- repeated_spans = true ;
348
- }
349
- }
324
+ if gen. span . from_expansion ( ) || ( gen. params . is_empty ( ) && gen. where_clause . predicates . is_empty ( ) ) {
325
+ return ;
326
+ }
350
327
351
- if repeated_spans {
352
- let all_trait_span = bound_predicate
353
- . bounds
354
- . get ( 0 )
355
- . unwrap ( )
356
- . span ( )
357
- . to (
358
- bound_predicate
359
- . bounds
360
- . iter ( )
361
- . last ( )
362
- . unwrap ( )
363
- . span ( ) ) ;
328
+ for param in gen. params {
329
+ if let ParamName :: Plain ( _) = param. name {
330
+ // other alternatives are errors and elided which won't have duplicates
331
+ rollup_traits ( cx, param. bounds , "this trait bound contains repeated elements" ) ;
332
+ }
333
+ }
364
334
365
- let mut traits = where_clauses. values ( )
366
- . filter_map ( |span| snippet_opt ( cx, * span) )
367
- . collect :: < Vec < _ > > ( ) ;
368
- traits. sort_unstable ( ) ;
369
- let traits = traits. join ( " + " ) ;
370
- span_lint_and_sugg (
371
- cx,
372
- REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND ,
373
- all_trait_span,
374
- "this where clause has already been specified" ,
375
- "try" ,
376
- traits,
377
- Applicability :: MachineApplicable
378
- ) ;
379
- }
335
+ for predicate in gen. where_clause . predicates {
336
+ if let WherePredicate :: BoundPredicate ( ref bound_predicate) = predicate {
337
+ rollup_traits (
338
+ cx,
339
+ bound_predicate. bounds ,
340
+ "this where clause contains repeated elements" ,
341
+ ) ;
380
342
}
381
343
}
382
344
}
0 commit comments