Skip to content

Commit c18c0ed

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

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;
@@ -272,34 +272,22 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
272272
}
273273

274274
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) {
280276
let mut map = FxHashMap::default();
281277
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;
288282
}
283+
}
289284

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());
303291

304292
let mut traits = map.values()
305293
.filter_map(|span| snippet_opt(cx, *span))
@@ -311,7 +299,7 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
311299
cx,
312300
REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND,
313301
all_trait_span,
314-
"this trait bound contains repeated elements",
302+
msg,
315303
"try",
316304
traits,
317305
Applicability::MachineApplicable
@@ -320,50 +308,24 @@ fn check_bounds_or_where_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>
320308
}
321309
}
322310

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+
}
337314

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+
}
351321

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+
);
367329
}
368330
}
369331
}

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)