Skip to content

Commit 92d2b01

Browse files
author
Allen Hsu
committed
Refactor repeated where clause or trait bound.
1 parent 0517a6c commit 92d2b01

4 files changed

+55
-97
lines changed

clippy_lints/src/trait_bounds.rs

+44-82
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;
@@ -290,98 +290,60 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
290290
}
291291

292292
fn 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 repeated_spans {
304+
if_chain! {
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

322-
let mut traits = map.values()
323-
.filter_map(|span| snippet_opt(cx, *span))
324-
.collect::<Vec<_>>();
325-
traits.sort_unstable();
326-
let traits = traits.join(" + ");
310+
let mut traits = map.values()
311+
.filter_map(|span| snippet_opt(cx, *span))
312+
.collect::<Vec<_>>();
313+
traits.sort_unstable();
314+
let traits = traits.join(" + ");
327315

328-
span_lint_and_sugg(
329-
cx,
330-
REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND,
331-
all_trait_span,
332-
"this trait bound contains repeated elements",
333-
"try",
334-
traits,
335-
Applicability::MachineApplicable
336-
);
316+
span_lint_and_sugg(
317+
cx,
318+
REPEATED_WHERE_CLAUSE_OR_TRAIT_BOUND,
319+
all_trait_span,
320+
msg,
321+
"try",
322+
traits,
323+
Applicability::MachineApplicable
324+
);
325+
}
337326
}
338327
}
339328
}
329+
if gen.span.from_expansion() || (gen.params.is_empty() && gen.where_clause.predicates.is_empty()) {
330+
return;
331+
}
332+
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+
}
340339

341340
for predicate in gen.where_clause.predicates {
342341
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-
}
355-
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());
369-
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-
}
342+
rollup_traits(
343+
cx,
344+
bound_predicate.bounds,
345+
"this where clause contains repeated elements",
346+
);
385347
}
386348
}
387349
}

tests/ui/repeated_where_clause_or_trait_bound.fixed

+1-3
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

+1-3
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

+9-9
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)