Skip to content

Commit fe6d42f

Browse files
author
Allen Hsu
committed
Refactor repeated where clause or trait bound.
1 parent ef36890 commit fe6d42f

File tree

4 files changed

+42
-84
lines changed

4 files changed

+42
-84
lines changed

clippy_lints/src/trait_bounds.rs

Lines changed: 31 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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};
33
use clippy_utils::{SpanlessEq, SpanlessHash};
44
use core::hash::{Hash, Hasher};
55
use if_chain::if_chain;
@@ -285,34 +285,22 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
285285
}
286286

287287
fn 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
}

tests/ui/repeated_where_clause_or_trait_bound.fixed

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// run-rustfix
22
//
3-
#![allow(
4-
unused,
5-
)]
3+
#![allow(unused)]
64
#![deny(clippy::repeated_where_clause_or_trait_bound)]
75

86
fn bad_foo<T: Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {

tests/ui/repeated_where_clause_or_trait_bound.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// run-rustfix
22
//
3-
#![allow(
4-
unused,
5-
)]
3+
#![allow(unused)]
64
#![deny(clippy::repeated_where_clause_or_trait_bound)]
75

86
fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {

tests/ui/repeated_where_clause_or_trait_bound.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
error: this trait bound contains repeated elements
2-
--> $DIR/repeated_where_clause_or_trait_bound.rs:8:15
2+
--> $DIR/repeated_where_clause_or_trait_bound.rs:6:15
33
|
44
LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
66
|
77
note: the lint level is defined here
8-
--> $DIR/repeated_where_clause_or_trait_bound.rs:6:9
8+
--> $DIR/repeated_where_clause_or_trait_bound.rs:4:9
99
|
1010
LL | #![deny(clippy::repeated_where_clause_or_trait_bound)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13-
error: this where clause has already been specified
14-
--> $DIR/repeated_where_clause_or_trait_bound.rs:14:8
13+
error: this where clause contains repeated elements
14+
--> $DIR/repeated_where_clause_or_trait_bound.rs:12:8
1515
|
1616
LL | T: Clone + Clone + Clone + Copy,
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
1818

19-
error: this where clause has already been specified
20-
--> $DIR/repeated_where_clause_or_trait_bound.rs:49:15
19+
error: this where clause contains repeated elements
20+
--> $DIR/repeated_where_clause_or_trait_bound.rs:47:15
2121
|
2222
LL | Self: Clone + Clone + Clone;
2323
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
2424

2525
error: this trait bound contains repeated elements
26-
--> $DIR/repeated_where_clause_or_trait_bound.rs:63:24
26+
--> $DIR/repeated_where_clause_or_trait_bound.rs:61:24
2727
|
2828
LL | trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
3030

31-
error: this where clause has already been specified
32-
--> $DIR/repeated_where_clause_or_trait_bound.rs:70:12
31+
error: this where clause contains repeated elements
32+
--> $DIR/repeated_where_clause_or_trait_bound.rs:68:12
3333
|
3434
LL | T: Clone + Clone + Clone + Copy,
3535
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`

0 commit comments

Comments
 (0)