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;
@@ -281,34 +281,22 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
281281}
282282
283283fn 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 ) {
289285 let mut map = FxHashMap :: default ( ) ;
290286 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 ;
297291 }
292+ }
298293
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( ) ) ;
312300
313301 let mut traits = map. values( )
314302 . filter_map( |span| snippet_opt( cx, * span) )
@@ -320,7 +308,7 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
320308 cx,
321309 REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND ,
322310 all_trait_span,
323- "this trait bound contains repeated elements" ,
311+ msg ,
324312 "try" ,
325313 traits,
326314 Applicability :: MachineApplicable
@@ -329,50 +317,24 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
329317 }
330318 }
331319
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+ }
346323
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+ }
360330
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+ ) ;
376338 }
377339 }
378340}
0 commit comments