Skip to content

Commit a3d5dd7

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

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

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

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)