Skip to content

Commit e2d27da

Browse files
committed
Compare where predicates to trait bounds.
- only compare where predicates to trait bounds when generating where clause specific message to fix rust-lang#9151 - use comparable_trait_ref to account for trait bound generics to fix rust-lang#8757
1 parent 07ab0e8 commit e2d27da

File tree

2 files changed

+36
-70
lines changed

2 files changed

+36
-70
lines changed

clippy_lints/src/trait_bounds.rs

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use clippy_utils::{SpanlessEq, SpanlessHash};
44
use core::hash::{Hash, Hasher};
55
use if_chain::if_chain;
66
use itertools::Itertools;
7-
use rustc_data_structures::fx::FxHashMap;
7+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
88
use rustc_data_structures::unhash::UnhashMap;
99
use rustc_errors::Applicability;
1010
use rustc_hir::def::Res;
@@ -238,31 +238,45 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
238238
return;
239239
}
240240

241-
let mut map = FxHashMap::<_, Vec<_>>::default();
242-
for predicate in gen.predicates {
241+
let where_predicates = gen
242+
.predicates
243+
.iter()
244+
.filter_map(|pred| {
245+
if_chain! {
246+
if pred.in_where_clause();
247+
if let WherePredicate::BoundPredicate(bound) = pred;
248+
if let Ty { kind: TyKind::Path(QPath::Resolved(_, path, ..)) , ..} = bound.bounded_ty;
249+
then {
250+
return Some(bound.bounds.iter().filter_map(|t| {
251+
Some((path.res, into_comparable_trait_ref(t.trait_ref()?)))
252+
}))
253+
}
254+
}
255+
None
256+
})
257+
.flatten()
258+
.collect::<FxHashSet<_>>();
259+
260+
for predicate in gen.predicates.iter().filter(|pred| !pred.in_where_clause()) {
243261
if_chain! {
244262
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
245263
if bound_predicate.origin != PredicateOrigin::ImplTrait;
246264
if !bound_predicate.span.from_expansion();
247-
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
248-
if let Some(segment) = segments.first();
265+
if let Ty { kind: TyKind::Path(QPath::Resolved(_, path, ..)) , ..} = bound_predicate.bounded_ty;
249266
then {
250-
for (res_where, _, span_where) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
251-
let trait_resolutions_direct = map.entry(segment.ident).or_default();
252-
if let Some((_, span_direct)) = trait_resolutions_direct
253-
.iter()
254-
.find(|(res_direct, _)| *res_direct == res_where) {
255-
span_lint_and_help(
256-
cx,
257-
TRAIT_DUPLICATION_IN_BOUNDS,
258-
*span_direct,
259-
"this trait bound is already specified in the where clause",
260-
None,
261-
"consider removing this trait bound",
262-
);
263-
}
264-
else {
265-
trait_resolutions_direct.push((res_where, span_where));
267+
for t in bound_predicate.bounds {
268+
if let Some(trait_ref) = t.trait_ref() {
269+
let key = (path.res, into_comparable_trait_ref(trait_ref));
270+
if where_predicates.contains(&key) {
271+
span_lint_and_help(
272+
cx,
273+
TRAIT_DUPLICATION_IN_BOUNDS,
274+
t.span(),
275+
"this trait bound is already specified in the where clause",
276+
None,
277+
"consider removing this trait bound",
278+
);
279+
}
266280
}
267281
}
268282
}

tests/ui/trait_duplication_in_bounds.stderr

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,12 @@ LL | Self: Iterator<Item = Foo>,
6767
|
6868
= help: consider removing this trait bound
6969

70-
error: this trait bound is already specified in the where clause
71-
--> $DIR/trait_duplication_in_bounds.rs:103:19
72-
|
73-
LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
74-
| ^^^^^
75-
|
76-
= help: consider removing this trait bound
77-
7870
error: these bounds contain repeated elements
7971
--> $DIR/trait_duplication_in_bounds.rs:103:19
8072
|
8173
LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
8274
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
8375

84-
error: this trait bound is already specified in the where clause
85-
--> $DIR/trait_duplication_in_bounds.rs:109:12
86-
|
87-
LL | T: Clone + Clone + Clone + Copy,
88-
| ^^^^^
89-
|
90-
= help: consider removing this trait bound
91-
9276
error: these where clauses contain repeated elements
9377
--> $DIR/trait_duplication_in_bounds.rs:109:12
9478
|
@@ -107,14 +91,6 @@ error: these where clauses contain repeated elements
10791
LL | Self: Clone + Clone + Clone;
10892
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
10993

110-
error: this trait bound is already specified in the where clause
111-
--> $DIR/trait_duplication_in_bounds.rs:158:28
112-
|
113-
LL | trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
114-
| ^^^^^
115-
|
116-
= help: consider removing this trait bound
117-
11894
error: these bounds contain repeated elements
11995
--> $DIR/trait_duplication_in_bounds.rs:158:28
12096
|
@@ -127,41 +103,17 @@ error: these where clauses contain repeated elements
127103
LL | T: Clone + Clone + Clone + Copy,
128104
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
129105

130-
error: this trait bound is already specified in the where clause
131-
--> $DIR/trait_duplication_in_bounds.rs:195:24
132-
|
133-
LL | fn good_generic<T: GenericTrait<u64> + GenericTrait<u32>>(arg0: T) {
134-
| ^^^^^^^^^^^^^^^^^
135-
|
136-
= help: consider removing this trait bound
137-
138-
error: this trait bound is already specified in the where clause
139-
--> $DIR/trait_duplication_in_bounds.rs:199:23
140-
|
141-
LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
142-
| ^^^^^^^^^^^^^^^^^
143-
|
144-
= help: consider removing this trait bound
145-
146106
error: these bounds contain repeated elements
147107
--> $DIR/trait_duplication_in_bounds.rs:199:23
148108
|
149109
LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
150110
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u32> + GenericTrait<u64>`
151111

152-
error: this trait bound is already specified in the where clause
153-
--> $DIR/trait_duplication_in_bounds.rs:207:26
154-
|
155-
LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
156-
| ^^^^^^^^^^^^^^^^^
157-
|
158-
= help: consider removing this trait bound
159-
160112
error: these bounds contain repeated elements
161113
--> $DIR/trait_duplication_in_bounds.rs:207:26
162114
|
163115
LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
164116
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + foo::Clone`
165117

166-
error: aborting due to 22 previous errors
118+
error: aborting due to 16 previous errors
167119

0 commit comments

Comments
 (0)