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 } ;
33use clippy_utils:: { SpanlessEq , SpanlessHash } ;
44use core:: hash:: { Hash , Hasher } ;
55use if_chain:: if_chain;
@@ -285,34 +285,22 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
285285}
286286
287287fn 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 ) {
293289 let mut map = FxHashMap :: default ( ) ;
294290 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 ;
301295 }
296+ }
302297
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( ) ) ;
316304
317305 let mut traits = map. values( )
318306 . filter_map( |span| snippet_opt( cx, * span) )
@@ -324,7 +312,7 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
324312 cx,
325313 REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND ,
326314 all_trait_span,
327- "this trait bound contains repeated elements" ,
315+ msg ,
328316 "try" ,
329317 traits,
330318 Applicability :: MachineApplicable
@@ -333,50 +321,24 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
333321 }
334322 }
335323
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+ }
350327
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+ }
364334
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+ ) ;
380342 }
381343 }
382344}
0 commit comments