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