about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThibsG <Thibs@debian.com>2020-07-03 11:48:28 +0200
committerThibsG <Thibs@debian.com>2020-07-03 17:29:54 +0200
commit2d5930a3da7048d784489f28b44a769880b6ceff (patch)
tree0f0e5ccb35231dc0d387227bf155d74bca74c88e
parentd5a8f03a350e8a392f0aa1c05707b503f549e90b (diff)
downloadrust-2d5930a3da7048d784489f28b44a769880b6ceff.tar.gz
rust-2d5930a3da7048d784489f28b44a769880b6ceff.zip
Don't lint for predicates generated in macros
-rw-r--r--clippy_lints/src/trait_bounds.rs15
-rw-r--r--tests/ui/type_repetition_in_bounds.rs37
2 files changed, 38 insertions, 14 deletions
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index 650edbb4b11..0ef70311fb1 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -1,4 +1,5 @@
 use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_help, SpanlessHash};
+use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_hir::{GenericBound, Generics, WherePredicate};
@@ -11,6 +12,8 @@ declare_clippy_lint! {
     /// **Why is this bad?** Repeating the type for every bound makes the code
     /// less readable than combining the bounds
     ///
+    /// **Known problems:** None.
+    ///
     /// **Example:**
     /// ```rust
     /// pub fn foo<T>(t: T) where T: Copy, T: Clone {}
@@ -53,12 +56,14 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
         let mut map = FxHashMap::default();
         let mut applicability = Applicability::MaybeIncorrect;
         for bound in gen.where_clause.predicates {
-            if let WherePredicate::BoundPredicate(ref p) = bound {
-                if p.bounds.len() as u64 > self.max_trait_bounds {
-                    return;
-                }
+            if_chain! {
+                if let WherePredicate::BoundPredicate(ref p) = bound;
+                if p.bounds.len() as u64 <= self.max_trait_bounds;
+                if !in_macro(p.span);
                 let h = hash(&p.bounded_ty);
-                if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>()) {
+                if let Some(ref v) = map.insert(h, p.bounds.iter().collect::<Vec<_>>());
+
+                then {
                     let mut hint_string = format!(
                         "consider combining the bounds: `{}:",
                         snippet(cx, p.bounded_ty.span, "_")
diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs
index 9f1700567d1..766190f2099 100644
--- a/tests/ui/type_repetition_in_bounds.rs
+++ b/tests/ui/type_repetition_in_bounds.rs
@@ -37,17 +37,36 @@ where
 }
 
 // Generic distinction (see #4323)
-pub struct Foo<A>(A);
-pub struct Bar<A, B> {
-    a: Foo<A>,
-    b: Foo<B>,
+mod issue4323 {
+    pub struct Foo<A>(A);
+    pub struct Bar<A, B> {
+        a: Foo<A>,
+        b: Foo<B>,
+    }
+
+    impl<A, B> Unpin for Bar<A, B>
+    where
+        Foo<A>: Unpin,
+        Foo<B>: Unpin,
+    {
+    }
 }
 
-impl<A, B> Unpin for Bar<A, B>
-where
-    Foo<A>: Unpin,
-    Foo<B>: Unpin,
-{
+// Extern macros shouldn't lint (see #4326)
+extern crate serde;
+mod issue4326 {
+    use serde::{Deserialize, Serialize};
+
+    trait Foo {}
+    impl Foo for String {}
+
+    #[derive(Debug, Serialize, Deserialize)]
+    struct Bar<S>
+    where
+        S: Foo,
+    {
+        foo: S,
+    }
 }
 
 fn main() {}