]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/clippy/clippy_lints/src/trait_bounds.rs
Merge commit '2ca58e7dda4a9eb142599638c59dc04d15961175' into clippyup
[rust.git] / src / tools / clippy / clippy_lints / src / trait_bounds.rs
index 9eb2079c3ca2dffbec32bb6adb90ac89fe7bdf40..0ef70311fb1cde5a80e9f21b20f21ed511d1093f 100644 (file)
@@ -1,19 +1,19 @@
 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};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
-#[derive(Copy, Clone)]
-pub struct TraitBounds;
-
 declare_clippy_lint! {
     /// **What it does:** This lint warns about unnecessary type repetitions in trait bounds
     ///
     /// **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 {}
     "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
 }
 
+#[derive(Copy, Clone)]
+pub struct TraitBounds {
+    max_trait_bounds: u64,
+}
+
+impl TraitBounds {
+    #[must_use]
+    pub fn new(max_trait_bounds: u64) -> Self {
+        Self { max_trait_bounds }
+    }
+}
+
 impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS]);
 
 impl<'tcx> LateLintPass<'tcx> for TraitBounds {
@@ -44,9 +56,14 @@ fn check_generics(&mut self, cx: &LateContext<'tcx>, gen: &'tcx Generics<'_>) {
         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_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, "_")