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