about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/trait_bounds.rs18
-rw-r--r--tests/ui-toml/type_repetition_in_bounds/main.rs2
-rw-r--r--tests/ui-toml/type_repetition_in_bounds/main.stderr2
-rw-r--r--tests/ui/type_repetition_in_bounds.rs27
-rw-r--r--tests/ui/type_repetition_in_bounds.stderr30
5 files changed, 52 insertions, 27 deletions
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 8aac3a59102..45e54302e32 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -15,7 +15,7 @@ use rustc_hir::{
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::{BytePos, Span};
+use rustc_span::Span;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -282,18 +282,18 @@ impl TraitBounds {
                     .iter()
                     .copied()
                     .chain(p.bounds.iter())
-                    .filter_map(get_trait_info_from_bound)
-                    .map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability))
+                    .map(|bound| snippet_with_applicability(cx, bound.span(), "_", &mut applicability))
                     .join(" + ");
                 let hint_string = format!(
                     "consider combining the bounds: `{}: {trait_bounds}`",
                     snippet(cx, p.bounded_ty.span, "_"),
                 );
+                let ty_name = snippet(cx, p.bounded_ty.span, "_");
                 span_lint_and_help(
                     cx,
                     TYPE_REPETITION_IN_BOUNDS,
                     bound.span,
-                    "this type has already been used as a bound predicate",
+                    format!("type `{ty_name}` has already been used as a bound predicate"),
                     None,
                     hint_string,
                 );
@@ -395,15 +395,7 @@ impl Hash for ComparableTraitRef<'_, '_> {
 fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'a [PathSegment<'a>], Span)> {
     if let GenericBound::Trait(t) = bound {
         let trait_path = t.trait_ref.path;
-        let trait_span = {
-            let path_span = trait_path.span;
-            if let BoundPolarity::Maybe(_) = t.modifiers.polarity {
-                path_span.with_lo(path_span.lo() - BytePos(1)) // include the `?`
-            } else {
-                path_span
-            }
-        };
-        Some((trait_path.res, trait_path.segments, trait_span))
+        Some((trait_path.res, trait_path.segments, t.span))
     } else {
         None
     }
diff --git a/tests/ui-toml/type_repetition_in_bounds/main.rs b/tests/ui-toml/type_repetition_in_bounds/main.rs
index 7f93d2071c9..b60cb7632e2 100644
--- a/tests/ui-toml/type_repetition_in_bounds/main.rs
+++ b/tests/ui-toml/type_repetition_in_bounds/main.rs
@@ -12,7 +12,7 @@ fn f2<T>()
 where
     T: Copy + Clone + Sync + Send + ?Sized,
     T: Unpin + PartialEq,
-    //~^ ERROR: this type has already been used as a bound predicate
+    //~^ type_repetition_in_bounds
 {
 }
 
diff --git a/tests/ui-toml/type_repetition_in_bounds/main.stderr b/tests/ui-toml/type_repetition_in_bounds/main.stderr
index c5102c39d1c..ba0f41167a0 100644
--- a/tests/ui-toml/type_repetition_in_bounds/main.stderr
+++ b/tests/ui-toml/type_repetition_in_bounds/main.stderr
@@ -1,4 +1,4 @@
-error: this type has already been used as a bound predicate
+error: type `T` has already been used as a bound predicate
   --> tests/ui-toml/type_repetition_in_bounds/main.rs:14:5
    |
 LL |     T: Unpin + PartialEq,
diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs
index d325887bfba..e75678d5fd9 100644
--- a/tests/ui/type_repetition_in_bounds.rs
+++ b/tests/ui/type_repetition_in_bounds.rs
@@ -12,7 +12,7 @@ pub fn foo<T>(_t: T)
 where
     T: Copy,
     T: Clone,
-    //~^ ERROR: this type has already been used as a bound predicate
+    //~^ type_repetition_in_bounds
 {
     unimplemented!();
 }
@@ -30,7 +30,7 @@ trait LintBounds
 where
     Self: Clone,
     Self: Copy + Default + Ord,
-    //~^ ERROR: this type has already been used as a bound predicate
+    //~^ type_repetition_in_bounds
     Self: Add<Output = Self> + AddAssign + Sub<Output = Self> + SubAssign,
     Self: Mul<Output = Self> + MulAssign + Div<Output = Self> + DivAssign,
 {
@@ -105,13 +105,13 @@ where
 pub fn f<T: ?Sized>()
 where
     T: Clone,
-    //~^ ERROR: this type has already been used as a bound predicate
+    //~^ type_repetition_in_bounds
 {
 }
 pub fn g<T: Clone>()
 where
     T: ?Sized,
-    //~^ ERROR: this type has already been used as a bound predicate
+    //~^ type_repetition_in_bounds
 {
 }
 
@@ -137,10 +137,27 @@ mod issue8772_pass {
     pub fn f<T: ?Sized, U>(arg: usize)
     where
         T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
-        //~^ ERROR: this type has already been used as a bound predicate
+        //~^ type_repetition_in_bounds
         U: Clone + Sync + 'static,
     {
     }
 }
 
+struct Issue14744<'a, K: 'a>
+where
+    K: Clone,
+{
+    phantom: std::marker::PhantomData<&'a K>,
+}
+//~^^^^ type_repetition_in_bounds
+
+struct ComplexType<T>
+where
+    Vec<T>: Clone,
+    Vec<T>: Clone,
+{
+    t: T,
+}
+//~^^^^ type_repetition_in_bounds
+
 fn main() {}
diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr
index 77944c95045..de1b14da198 100644
--- a/tests/ui/type_repetition_in_bounds.stderr
+++ b/tests/ui/type_repetition_in_bounds.stderr
@@ -1,4 +1,4 @@
-error: this type has already been used as a bound predicate
+error: type `T` has already been used as a bound predicate
   --> tests/ui/type_repetition_in_bounds.rs:14:5
    |
 LL |     T: Clone,
@@ -11,7 +11,7 @@ note: the lint level is defined here
 LL | #![deny(clippy::type_repetition_in_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: this type has already been used as a bound predicate
+error: type `Self` has already been used as a bound predicate
   --> tests/ui/type_repetition_in_bounds.rs:32:5
    |
 LL |     Self: Copy + Default + Ord,
@@ -19,7 +19,7 @@ LL |     Self: Copy + Default + Ord,
    |
    = help: consider combining the bounds: `Self: Clone + Copy + Default + Ord`
 
-error: this type has already been used as a bound predicate
+error: type `T` has already been used as a bound predicate
   --> tests/ui/type_repetition_in_bounds.rs:107:5
    |
 LL |     T: Clone,
@@ -27,7 +27,7 @@ LL |     T: Clone,
    |
    = help: consider combining the bounds: `T: ?Sized + Clone`
 
-error: this type has already been used as a bound predicate
+error: type `T` has already been used as a bound predicate
   --> tests/ui/type_repetition_in_bounds.rs:113:5
    |
 LL |     T: ?Sized,
@@ -35,13 +35,29 @@ LL |     T: ?Sized,
    |
    = help: consider combining the bounds: `T: Clone + ?Sized`
 
-error: this type has already been used as a bound predicate
+error: type `T` has already been used as a bound predicate
   --> tests/ui/type_repetition_in_bounds.rs:139:9
    |
 LL |         T: Trait<Option<usize>, Box<[String]>, bool> + 'static,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: consider combining the bounds: `T: ?Sized + Trait<Option<usize>, Box<[String]>, bool>`
+   = help: consider combining the bounds: `T: ?Sized + Trait<Option<usize>, Box<[String]>, bool> + 'static`
 
-error: aborting due to 5 previous errors
+error: type `K` has already been used as a bound predicate
+  --> tests/ui/type_repetition_in_bounds.rs:148:5
+   |
+LL |     K: Clone,
+   |     ^^^^^^^^
+   |
+   = help: consider combining the bounds: `K: 'a + Clone`
+
+error: type `Vec<T>` has already been used as a bound predicate
+  --> tests/ui/type_repetition_in_bounds.rs:157:5
+   |
+LL |     Vec<T>: Clone,
+   |     ^^^^^^^^^^^^^
+   |
+   = help: consider combining the bounds: `Vec<T>: Clone + Clone`
+
+error: aborting due to 7 previous errors