Skip to content

Commit c398a89

Browse files
author
Allen Hsu
committed
1 parent e6b34d7 commit c398a89

File tree

3 files changed

+48
-32
lines changed

3 files changed

+48
-32
lines changed

clippy_lints/src/trait_bounds.rs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ 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;
6-
use rustc_data_structures::fx::FxHashMap;
6+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77
use rustc_data_structures::unhash::UnhashMap;
88
use rustc_errors::Applicability;
99
use rustc_hir::def::Res;
@@ -262,30 +262,43 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
262262
return;
263263
}
264264

265-
let mut map = FxHashMap::<_, Vec<_>>::default();
266-
for predicate in gen.predicates {
265+
let where_predicates = gen
266+
.predicates
267+
.iter()
268+
.filter_map(|pred| {
269+
if_chain! {
270+
if pred.in_where_clause();
271+
if let WherePredicate::BoundPredicate(bound) = pred;
272+
if let Ty { kind: TyKind::Path(QPath::Resolved(_, path, ..)) , ..} = bound.bounded_ty;
273+
then {
274+
return Some(bound.bounds.iter().filter_map(|t| {
275+
Some((path.res, into_comparable_trait_ref(t.trait_ref()?)))
276+
}))
277+
}
278+
}
279+
None
280+
})
281+
.flatten()
282+
.collect::<FxHashSet<_>>();
283+
284+
for predicate in gen.predicates.iter().filter(|pred| !pred.in_where_clause()) {
267285
if_chain! {
268-
if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
269-
if !bound_predicate.span.from_expansion();
270-
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
271-
if let Some(segment) = segments.first();
286+
if let WherePredicate::BoundPredicate(bound) = predicate;
287+
if let Ty { kind: TyKind::Path(QPath::Resolved(_, path, ..)) , ..} = bound.bounded_ty;
272288
then {
273-
for (res_where, _, span_where) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
274-
let trait_resolutions_direct = map.entry(segment.ident).or_default();
275-
if let Some((_, span_direct)) = trait_resolutions_direct
276-
.iter()
277-
.find(|(res_direct, _)| *res_direct == res_where) {
278-
span_lint_and_help(
279-
cx,
280-
TRAIT_DUPLICATION_IN_BOUNDS,
281-
*span_direct,
282-
"this trait bound is already specified in the where clause",
283-
None,
284-
"consider removing this trait bound",
285-
);
286-
}
287-
else {
288-
trait_resolutions_direct.push((res_where, span_where));
289+
for t in bound.bounds {
290+
if let Some(trait_ref) = t.trait_ref() {
291+
let key = (path.res, into_comparable_trait_ref(trait_ref));
292+
if where_predicates.contains(&key) {
293+
span_lint_and_help(
294+
cx,
295+
TRAIT_DUPLICATION_IN_BOUNDS,
296+
t.span(),
297+
"this trait bound is already specified in the where clause",
298+
None,
299+
"consider removing this trait bound",
300+
);
301+
}
289302
}
290303
}
291304
}

tests/ui/trait_duplication_in_bounds.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,15 @@ trait FooIter: Iterator<Item = Foo> {
9898
// This should not lint
9999
fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
100100

101+
trait BoundWithGeneric<T> {}
102+
103+
fn good_bounds_with_generic<T: BoundWithGeneric<u32>>(arg0: T, arg1: T)
104+
where
105+
T: BoundWithGeneric<u64>,
106+
{
107+
unimplemented!();
108+
}
109+
110+
fn repeat_should_not_lint<T: Clone + Clone + Default, Z: Copy>(arg0: T, arg1: Z) {}
111+
101112
fn main() {}

tests/ui/trait_duplication_in_bounds.stderr

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,5 @@ 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:99:23
72-
|
73-
LL | fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
74-
| ^^^^^^^^^^
75-
|
76-
= help: consider removing this trait bound
77-
78-
error: aborting due to 9 previous errors
70+
error: aborting due to 8 previous errors
7971

0 commit comments

Comments
 (0)