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