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;
@@ -290,34 +290,22 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
290290}
291291
292292fn 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 ) {
298294 let mut map = FxHashMap :: default ( ) ;
299295 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 ;
306300 }
301+ }
307302
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( ) ) ;
321309
322310 let mut traits = map. values( )
323311 . filter_map( |span| snippet_opt( cx, * span) )
@@ -329,7 +317,7 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
329317 cx,
330318 REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND ,
331319 all_trait_span,
332- "this trait bound contains repeated elements" ,
320+ msg ,
333321 "try" ,
334322 traits,
335323 Applicability :: MachineApplicable
@@ -338,50 +326,24 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
338326 }
339327 }
340328
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+ }
355332
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+ }
369339
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+ ) ;
385347 }
386348 }
387349}
0 commit comments