about summary refs log tree commit diff
path: root/tests/ui
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-14 14:46:26 +0000
committerbors <bors@rust-lang.org>2022-08-14 14:46:26 +0000
commit84df61c06eb36602022e758878afe66479ba0769 (patch)
treea27f76ca61d8ba7e733a31346a53d2d298780eea /tests/ui
parent4d5d191f6af4d4697e9b983b655aa7dd96fd966f (diff)
parent8bae517c2d540dcf62bff12ba7404a23a4233d99 (diff)
downloadrust-84df61c06eb36602022e758878afe66479ba0769.tar.gz
rust-84df61c06eb36602022e758878afe66479ba0769.zip
Auto merge of #9167 - aldhsu:fix-trait-duplication-false-pos, r=flip1995
Fixes [`trait_duplication_in_bounds`] false positives

Fixes #9076 #9151 #8757.
Partially fixes #8771.

changelog: [`trait_duplication_in_bounds`]: Reduce number of false positives.
Diffstat (limited to 'tests/ui')
-rw-r--r--tests/ui/trait_duplication_in_bounds.fixed112
-rw-r--r--tests/ui/trait_duplication_in_bounds.rs218
-rw-r--r--tests/ui/trait_duplication_in_bounds.stderr165
-rw-r--r--tests/ui/trait_duplication_in_bounds_unfixable.rs166
-rw-r--r--tests/ui/trait_duplication_in_bounds_unfixable.stderr71
5 files changed, 435 insertions, 297 deletions
diff --git a/tests/ui/trait_duplication_in_bounds.fixed b/tests/ui/trait_duplication_in_bounds.fixed
new file mode 100644
index 00000000000..b4e6bf0ea1c
--- /dev/null
+++ b/tests/ui/trait_duplication_in_bounds.fixed
@@ -0,0 +1,112 @@
+// run-rustfix
+#![deny(clippy::trait_duplication_in_bounds)]
+#![allow(unused)]
+
+fn bad_foo<T: Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
+    unimplemented!();
+}
+
+fn bad_bar<T, U>(arg0: T, arg1: U)
+where
+    T: Clone + Copy,
+    U: Clone + Copy,
+{
+    unimplemented!();
+}
+
+fn good_bar<T: Clone + Copy, U: Clone + Copy>(arg0: T, arg1: U) {
+    unimplemented!();
+}
+
+fn good_foo<T, U>(arg0: T, arg1: U)
+where
+    T: Clone + Copy,
+    U: Clone + Copy,
+{
+    unimplemented!();
+}
+
+trait GoodSelfTraitBound: Clone + Copy {
+    fn f();
+}
+
+trait GoodSelfWhereClause {
+    fn f()
+    where
+        Self: Clone + Copy;
+}
+
+trait BadSelfTraitBound: Clone {
+    fn f();
+}
+
+trait BadSelfWhereClause {
+    fn f()
+    where
+        Self: Clone;
+}
+
+trait GoodTraitBound<T: Clone + Copy, U: Clone + Copy> {
+    fn f();
+}
+
+trait GoodWhereClause<T, U> {
+    fn f()
+    where
+        T: Clone + Copy,
+        U: Clone + Copy;
+}
+
+trait BadTraitBound<T: Clone + Copy, U: Clone + Copy> {
+    fn f();
+}
+
+trait BadWhereClause<T, U> {
+    fn f()
+    where
+        T: Clone + Copy,
+        U: Clone + Copy;
+}
+
+struct GoodStructBound<T: Clone + Copy, U: Clone + Copy> {
+    t: T,
+    u: U,
+}
+
+impl<T: Clone + Copy, U: Clone + Copy> GoodTraitBound<T, U> for GoodStructBound<T, U> {
+    // this should not warn
+    fn f() {}
+}
+
+struct GoodStructWhereClause;
+
+impl<T, U> GoodTraitBound<T, U> for GoodStructWhereClause
+where
+    T: Clone + Copy,
+    U: Clone + Copy,
+{
+    // this should not warn
+    fn f() {}
+}
+
+fn no_error_separate_arg_bounds(program: impl AsRef<()>, dir: impl AsRef<()>, args: &[impl AsRef<()>]) {}
+
+trait GenericTrait<T> {}
+
+fn good_generic<T: GenericTrait<u64> + GenericTrait<u32>>(arg0: T) {
+    unimplemented!();
+}
+
+fn bad_generic<T: GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
+    unimplemented!();
+}
+
+mod foo {
+    pub trait Clone {}
+}
+
+fn qualified_path<T: Clone + foo::Clone>(arg0: T) {
+    unimplemented!();
+}
+
+fn main() {}
diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs
index a5751c58aab..7f2e96a22e6 100644
--- a/tests/ui/trait_duplication_in_bounds.rs
+++ b/tests/ui/trait_duplication_in_bounds.rs
@@ -1,212 +1,112 @@
+// run-rustfix
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
 
-use std::collections::BTreeMap;
-use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
+fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
+    unimplemented!();
+}
 
-fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
+fn bad_bar<T, U>(arg0: T, arg1: U)
 where
-    T: Clone,
-    T: Default,
+    T: Clone + Clone + Clone + Copy,
+    U: Clone + Copy,
 {
     unimplemented!();
 }
 
-fn good_bar<T: Clone + Default>(arg: T) {
+fn good_bar<T: Clone + Copy, U: Clone + Copy>(arg0: T, arg1: U) {
     unimplemented!();
 }
 
-fn good_foo<T>(arg: T)
+fn good_foo<T, U>(arg0: T, arg1: U)
 where
-    T: Clone + Default,
+    T: Clone + Copy,
+    U: Clone + Copy,
 {
     unimplemented!();
 }
 
-fn good_foobar<T: Default>(arg: T)
-where
-    T: Clone,
-{
-    unimplemented!();
+trait GoodSelfTraitBound: Clone + Copy {
+    fn f();
 }
 
-trait T: Default {
+trait GoodSelfWhereClause {
     fn f()
     where
-        Self: Default;
+        Self: Clone + Copy;
 }
 
-trait U: Default {
+trait BadSelfTraitBound: Clone + Clone + Clone {
+    fn f();
+}
+
+trait BadSelfWhereClause {
     fn f()
     where
-        Self: Clone;
+        Self: Clone + Clone + Clone;
+}
+
+trait GoodTraitBound<T: Clone + Copy, U: Clone + Copy> {
+    fn f();
 }
 
-trait ZZ: Default {
-    fn g();
-    fn h();
+trait GoodWhereClause<T, U> {
     fn f()
     where
-        Self: Default + Clone;
+        T: Clone + Copy,
+        U: Clone + Copy;
 }
 
-trait BadTrait: Default + Clone {
+trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
+    fn f();
+}
+
+trait BadWhereClause<T, U> {
     fn f()
     where
-        Self: Default + Clone;
-    fn g()
-    where
-        Self: Default;
-    fn h()
-    where
-        Self: Copy;
+        T: Clone + Clone + Clone + Copy,
+        U: Clone + Copy;
 }
 
-#[derive(Default, Clone)]
-struct Life;
+struct GoodStructBound<T: Clone + Copy, U: Clone + Copy> {
+    t: T,
+    u: U,
+}
 
-impl T for Life {
+impl<T: Clone + Copy, U: Clone + Copy> GoodTraitBound<T, U> for GoodStructBound<T, U> {
     // this should not warn
     fn f() {}
 }
 
-impl U for Life {
+struct GoodStructWhereClause;
+
+impl<T, U> GoodTraitBound<T, U> for GoodStructWhereClause
+where
+    T: Clone + Copy,
+    U: Clone + Copy,
+{
     // this should not warn
     fn f() {}
 }
 
-// should not warn
-trait Iter: Iterator {
-    fn into_group_btreemap<K, V>(self) -> BTreeMap<K, Vec<V>>
-    where
-        Self: Iterator<Item = (K, V)> + Sized,
-        K: Ord + Eq,
-    {
-        unimplemented!();
-    }
-}
+fn no_error_separate_arg_bounds(program: impl AsRef<()>, dir: impl AsRef<()>, args: &[impl AsRef<()>]) {}
 
-struct Foo;
+trait GenericTrait<T> {}
 
-trait FooIter: Iterator<Item = Foo> {
-    fn bar()
-    where
-        Self: Iterator<Item = Foo>,
-    {
-    }
+fn good_generic<T: GenericTrait<u64> + GenericTrait<u32>>(arg0: T) {
+    unimplemented!();
 }
 
-// This should not lint
-fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
-
-mod repeated_where_clauses_or_trait_bounds {
-    fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
-        unimplemented!();
-    }
-
-    fn bad_bar<T, U>(arg0: T, arg1: U)
-    where
-        T: Clone + Clone + Clone + Copy,
-        U: Clone + Copy,
-    {
-        unimplemented!();
-    }
-
-    fn good_bar<T: Clone + Copy, U: Clone + Copy>(arg0: T, arg1: U) {
-        unimplemented!();
-    }
-
-    fn good_foo<T, U>(arg0: T, arg1: U)
-    where
-        T: Clone + Copy,
-        U: Clone + Copy,
-    {
-        unimplemented!();
-    }
-
-    trait GoodSelfTraitBound: Clone + Copy {
-        fn f();
-    }
-
-    trait GoodSelfWhereClause {
-        fn f()
-        where
-            Self: Clone + Copy;
-    }
-
-    trait BadSelfTraitBound: Clone + Clone + Clone {
-        fn f();
-    }
-
-    trait BadSelfWhereClause {
-        fn f()
-        where
-            Self: Clone + Clone + Clone;
-    }
-
-    trait GoodTraitBound<T: Clone + Copy, U: Clone + Copy> {
-        fn f();
-    }
-
-    trait GoodWhereClause<T, U> {
-        fn f()
-        where
-            T: Clone + Copy,
-            U: Clone + Copy;
-    }
-
-    trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
-        fn f();
-    }
-
-    trait BadWhereClause<T, U> {
-        fn f()
-        where
-            T: Clone + Clone + Clone + Copy,
-            U: Clone + Copy;
-    }
-
-    struct GoodStructBound<T: Clone + Copy, U: Clone + Copy> {
-        t: T,
-        u: U,
-    }
-
-    impl<T: Clone + Copy, U: Clone + Copy> GoodTraitBound<T, U> for GoodStructBound<T, U> {
-        // this should not warn
-        fn f() {}
-    }
-
-    struct GoodStructWhereClause;
-
-    impl<T, U> GoodTraitBound<T, U> for GoodStructWhereClause
-    where
-        T: Clone + Copy,
-        U: Clone + Copy,
-    {
-        // this should not warn
-        fn f() {}
-    }
-
-    fn no_error_separate_arg_bounds(program: impl AsRef<()>, dir: impl AsRef<()>, args: &[impl AsRef<()>]) {}
-
-    trait GenericTrait<T> {}
-
-    // This should not warn but currently does see #8757
-    fn good_generic<T: GenericTrait<u64> + GenericTrait<u32>>(arg0: T) {
-        unimplemented!();
-    }
-
-    fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
-        unimplemented!();
-    }
+fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
+    unimplemented!();
+}
 
-    mod foo {
-        pub trait Clone {}
-    }
+mod foo {
+    pub trait Clone {}
+}
 
-    fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
-        unimplemented!();
-    }
+fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
+    unimplemented!();
 }
 
 fn main() {}
diff --git a/tests/ui/trait_duplication_in_bounds.stderr b/tests/ui/trait_duplication_in_bounds.stderr
index 7ef04e52708..86c593811a7 100644
--- a/tests/ui/trait_duplication_in_bounds.stderr
+++ b/tests/ui/trait_duplication_in_bounds.stderr
@@ -1,167 +1,56 @@
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:7:15
+error: these bounds contain repeated elements
+  --> $DIR/trait_duplication_in_bounds.rs:5:15
    |
-LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
-   |               ^^^^^
+LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
    |
 note: the lint level is defined here
-  --> $DIR/trait_duplication_in_bounds.rs:1:9
+  --> $DIR/trait_duplication_in_bounds.rs:2:9
    |
 LL | #![deny(clippy::trait_duplication_in_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:7:23
-   |
-LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
-   |                       ^^^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:36:15
-   |
-LL |         Self: Default;
-   |               ^^^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:50:15
-   |
-LL |         Self: Default + Clone;
-   |               ^^^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:56:15
-   |
-LL |         Self: Default + Clone;
-   |               ^^^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:56:25
-   |
-LL |         Self: Default + Clone;
-   |                         ^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:59:15
-   |
-LL |         Self: Default;
-   |               ^^^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in trait declaration
-  --> $DIR/trait_duplication_in_bounds.rs:94:15
-   |
-LL |         Self: Iterator<Item = Foo>,
-   |               ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:103:19
-   |
-LL |     fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
-   |                   ^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:103:19
-   |
-LL |     fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
-
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:109:12
-   |
-LL |         T: Clone + Clone + Clone + Copy,
-   |            ^^^^^
-   |
-   = help: consider removing this trait bound
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:109:12
+  --> $DIR/trait_duplication_in_bounds.rs:11:8
    |
-LL |         T: Clone + Clone + Clone + Copy,
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
+LL |     T: Clone + Clone + Clone + Copy,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:137:30
+  --> $DIR/trait_duplication_in_bounds.rs:39:26
    |
-LL |     trait BadSelfTraitBound: Clone + Clone + Clone {
-   |                              ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
+LL | trait BadSelfTraitBound: Clone + Clone + Clone {
+   |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:144:19
-   |
-LL |             Self: Clone + Clone + Clone;
-   |                   ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
-
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:158:28
+  --> $DIR/trait_duplication_in_bounds.rs:46:15
    |
-LL |     trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
-   |                            ^^^^^
-   |
-   = help: consider removing this trait bound
+LL |         Self: Clone + Clone + Clone;
+   |               ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:158:28
+  --> $DIR/trait_duplication_in_bounds.rs:60:24
    |
-LL |     trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
+LL | trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:165:16
-   |
-LL |             T: Clone + Clone + Clone + Copy,
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
-
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:195:24
-   |
-LL |     fn good_generic<T: GenericTrait<u64> + GenericTrait<u32>>(arg0: T) {
-   |                        ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider removing this trait bound
-
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:199:23
+  --> $DIR/trait_duplication_in_bounds.rs:67:12
    |
-LL |     fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
-   |                       ^^^^^^^^^^^^^^^^^
-   |
-   = help: consider removing this trait bound
+LL |         T: Clone + Clone + Clone + Copy,
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:199:23
-   |
-LL |     fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u32> + GenericTrait<u64>`
-
-error: this trait bound is already specified in the where clause
-  --> $DIR/trait_duplication_in_bounds.rs:207:26
-   |
-LL |     fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
-   |                          ^^^^^^^^^^^^^^^^^
+  --> $DIR/trait_duplication_in_bounds.rs:100:19
    |
-   = help: consider removing this trait bound
+LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u32> + GenericTrait<u64>`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:207:26
+  --> $DIR/trait_duplication_in_bounds.rs:108:22
    |
-LL |     fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + foo::Clone`
+LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + foo::Clone`
 
-error: aborting due to 22 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/trait_duplication_in_bounds_unfixable.rs b/tests/ui/trait_duplication_in_bounds_unfixable.rs
new file mode 100644
index 00000000000..5630a0345ad
--- /dev/null
+++ b/tests/ui/trait_duplication_in_bounds_unfixable.rs
@@ -0,0 +1,166 @@
+#![deny(clippy::trait_duplication_in_bounds)]
+
+use std::collections::BTreeMap;
+use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
+
+fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
+where
+    T: Clone,
+    T: Default,
+{
+    unimplemented!();
+}
+
+fn good_bar<T: Clone + Default>(arg: T) {
+    unimplemented!();
+}
+
+fn good_foo<T>(arg: T)
+where
+    T: Clone + Default,
+{
+    unimplemented!();
+}
+
+fn good_foobar<T: Default>(arg: T)
+where
+    T: Clone,
+{
+    unimplemented!();
+}
+
+trait T: Default {
+    fn f()
+    where
+        Self: Default;
+}
+
+trait U: Default {
+    fn f()
+    where
+        Self: Clone;
+}
+
+trait ZZ: Default {
+    fn g();
+    fn h();
+    fn f()
+    where
+        Self: Default + Clone;
+}
+
+trait BadTrait: Default + Clone {
+    fn f()
+    where
+        Self: Default + Clone;
+    fn g()
+    where
+        Self: Default;
+    fn h()
+    where
+        Self: Copy;
+}
+
+#[derive(Default, Clone)]
+struct Life;
+
+impl T for Life {
+    // this should not warn
+    fn f() {}
+}
+
+impl U for Life {
+    // this should not warn
+    fn f() {}
+}
+
+// should not warn
+trait Iter: Iterator {
+    fn into_group_btreemap<K, V>(self) -> BTreeMap<K, Vec<V>>
+    where
+        Self: Iterator<Item = (K, V)> + Sized,
+        K: Ord + Eq,
+    {
+        unimplemented!();
+    }
+}
+
+struct Foo;
+
+trait FooIter: Iterator<Item = Foo> {
+    fn bar()
+    where
+        Self: Iterator<Item = Foo>,
+    {
+    }
+}
+
+// The below should not lint and exist to guard against false positives
+fn impl_trait(_: impl AsRef<str>, _: impl AsRef<str>) {}
+
+pub mod one {
+    #[derive(Clone, Debug)]
+    struct MultiProductIter<I>
+    where
+        I: Iterator + Clone,
+        I::Item: Clone,
+    {
+        _marker: I,
+    }
+
+    pub struct MultiProduct<I>(Vec<MultiProductIter<I>>)
+    where
+        I: Iterator + Clone,
+        I::Item: Clone;
+
+    pub fn multi_cartesian_product<H>(_: H) -> MultiProduct<<H::Item as IntoIterator>::IntoIter>
+    where
+        H: Iterator,
+        H::Item: IntoIterator,
+        <H::Item as IntoIterator>::IntoIter: Clone,
+        <H::Item as IntoIterator>::Item: Clone,
+    {
+        todo!()
+    }
+}
+
+pub mod two {
+    use std::iter::Peekable;
+
+    pub struct MergeBy<I, J, F>
+    where
+        I: Iterator,
+        J: Iterator<Item = I::Item>,
+    {
+        _i: Peekable<I>,
+        _j: Peekable<J>,
+        _f: F,
+    }
+
+    impl<I, J, F> Clone for MergeBy<I, J, F>
+    where
+        I: Iterator,
+        J: Iterator<Item = I::Item>,
+        std::iter::Peekable<I>: Clone,
+        std::iter::Peekable<J>: Clone,
+        F: Clone,
+    {
+        fn clone(&self) -> Self {
+            Self {
+                _i: self._i.clone(),
+                _j: self._j.clone(),
+                _f: self._f.clone(),
+            }
+        }
+    }
+}
+
+pub trait Trait {}
+
+pub fn f(_a: impl Trait, _b: impl Trait) {}
+
+pub trait ImplTrait<T> {}
+
+impl<A, B> ImplTrait<(A, B)> for Foo where Foo: ImplTrait<A> + ImplTrait<B> {}
+
+fn main() {}
diff --git a/tests/ui/trait_duplication_in_bounds_unfixable.stderr b/tests/ui/trait_duplication_in_bounds_unfixable.stderr
new file mode 100644
index 00000000000..aa44114eb6c
--- /dev/null
+++ b/tests/ui/trait_duplication_in_bounds_unfixable.stderr
@@ -0,0 +1,71 @@
+error: this trait bound is already specified in the where clause
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:6:23
+   |
+LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
+   |                       ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:1:9
+   |
+LL | #![deny(clippy::trait_duplication_in_bounds)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider removing this trait bound
+
+error: this trait bound is already specified in the where clause
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:6:15
+   |
+LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
+   |               ^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:35:15
+   |
+LL |         Self: Default;
+   |               ^^^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:49:15
+   |
+LL |         Self: Default + Clone;
+   |               ^^^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:55:15
+   |
+LL |         Self: Default + Clone;
+   |               ^^^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:55:25
+   |
+LL |         Self: Default + Clone;
+   |                         ^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:58:15
+   |
+LL |         Self: Default;
+   |               ^^^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds_unfixable.rs:93:15
+   |
+LL |         Self: Iterator<Item = Foo>,
+   |               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider removing this trait bound
+
+error: aborting due to 8 previous errors
+