about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-02-07 22:58:30 +0100
committerCamille GILLOT <gillot.camille@gmail.com>2022-04-30 13:55:13 +0200
commite2d923ac3b138bb69511bb1f6212633ca14e61ee (patch)
treeb452345ec5ba768b02e8647979b51687009c4700
parent67241bb03ca83e132efbce8deffe5ca3438dd529 (diff)
downloadrust-e2d923ac3b138bb69511bb1f6212633ca14e61ee.tar.gz
rust-e2d923ac3b138bb69511bb1f6212633ca14e61ee.zip
Store all generic bounds as where predicates.
-rw-r--r--clippy_lints/src/lifetimes.rs53
-rw-r--r--clippy_lints/src/trait_bounds.rs27
-rw-r--r--clippy_lints/src/types/borrowed_box.rs4
3 files changed, 41 insertions, 43 deletions
diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs
index 4ec7c2362f0..662a561f171 100644
--- a/clippy_lints/src/lifetimes.rs
+++ b/clippy_lints/src/lifetimes.rs
@@ -139,28 +139,35 @@ fn check_fn_inner<'tcx>(
         .iter()
         .filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
     for typ in types {
-        for bound in typ.bounds {
-            let mut visitor = RefVisitor::new(cx);
-            walk_param_bound(&mut visitor, bound);
-            if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
-                return;
+        for pred in generics.bounds_for_param(cx.tcx.hir().local_def_id(typ.hir_id)) {
+            if pred.in_where_clause {
+                // has_where_lifetimes checked that this predicate contains no lifetime.
+                continue;
             }
-            if let GenericBound::Trait(ref trait_ref, _) = *bound {
-                let params = &trait_ref
-                    .trait_ref
-                    .path
-                    .segments
-                    .last()
-                    .expect("a path must have at least one segment")
-                    .args;
-                if let Some(params) = *params {
-                    let lifetimes = params.args.iter().filter_map(|arg| match arg {
-                        GenericArg::Lifetime(lt) => Some(lt),
-                        _ => None,
-                    });
-                    for bound in lifetimes {
-                        if bound.name != LifetimeName::Static && !bound.is_elided() {
-                            return;
+
+            for bound in pred.bounds {
+                let mut visitor = RefVisitor::new(cx);
+                walk_param_bound(&mut visitor, bound);
+                if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
+                    return;
+                }
+                if let GenericBound::Trait(ref trait_ref, _) = *bound {
+                    let params = &trait_ref
+                        .trait_ref
+                        .path
+                        .segments
+                        .last()
+                        .expect("a path must have at least one segment")
+                        .args;
+                    if let Some(params) = *params {
+                        let lifetimes = params.args.iter().filter_map(|arg| match arg {
+                            GenericArg::Lifetime(lt) => Some(lt),
+                            _ => None,
+                        });
+                        for bound in lifetimes {
+                            if bound.name != LifetimeName::Static && !bound.is_elided() {
+                                return;
+                            }
                         }
                     }
                 }
@@ -322,9 +329,7 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxHashSet<RefLt> {
     let mut allowed_lts = FxHashSet::default();
     for par in named_generics.iter() {
         if let GenericParamKind::Lifetime { .. } = par.kind {
-            if par.bounds.is_empty() {
-                allowed_lts.insert(RefLt::Named(par.name.ident().name));
-            }
+            allowed_lts.insert(RefLt::Named(par.name.ident().name));
         }
     }
     allowed_lts.insert(RefLt::Unnamed);
diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs
index c388d2854cc..3d1b2ee925b 100644
--- a/clippy_lints/src/trait_bounds.rs
+++ b/clippy_lints/src/trait_bounds.rs
@@ -8,8 +8,7 @@ use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{
-    GenericBound, Generics, Item, ItemKind, Node, ParamName, Path, PathSegment, QPath, TraitItem, Ty, TyKind,
-    WherePredicate,
+    GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, QPath, TraitItem, Ty, TyKind, WherePredicate,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -219,30 +218,19 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
         return;
     }
 
-    let mut map = FxHashMap::default();
-    for param in gen.params {
-        if let ParamName::Plain(ref ident) = param.name {
-            let res = param
-                .bounds
-                .iter()
-                .filter_map(get_trait_info_from_bound)
-                .collect::<Vec<_>>();
-            map.insert(*ident, res);
-        }
-    }
-
+    let mut map = FxHashMap::<_, Vec<_>>::default();
     for predicate in gen.predicates {
         if_chain! {
             if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
             if !bound_predicate.span.from_expansion();
             if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
             if let Some(segment) = segments.first();
-            if let Some(trait_resolutions_direct) = map.get(&segment.ident);
             then {
-                for (res_where, _,  _) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
-                    if let Some((_, _, span_direct)) = trait_resolutions_direct
+                for (res_where, _, span_where) in bound_predicate.bounds.iter().filter_map(get_trait_info_from_bound) {
+                    let trait_resolutions_direct = map.entry(segment.ident).or_default();
+                    if let Some((_, span_direct)) = trait_resolutions_direct
                                                 .iter()
-                                                .find(|(res_direct, _, _)| *res_direct == res_where) {
+                                                .find(|(res_direct, _)| *res_direct == res_where) {
                         span_lint_and_help(
                             cx,
                             TRAIT_DUPLICATION_IN_BOUNDS,
@@ -252,6 +240,9 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
                             "consider removing this trait bound",
                         );
                     }
+                    else {
+                        trait_resolutions_direct.push((res_where, span_where))
+                    }
                 }
             }
         }
diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs
index 7c06906293b..f35f44eda56 100644
--- a/clippy_lints/src/types/borrowed_box.rs
+++ b/clippy_lints/src/types/borrowed_box.rs
@@ -104,8 +104,10 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id:
         if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did);
         if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
         if synthetic;
+        if let Some(generics) = cx.tcx.hir().get_generics(id.owner);
+        if let Some(pred) = generics.bounds_for_param(did.expect_local()).next();
         then {
-            Some(generic_param.bounds)
+            Some(pred.bounds)
         } else {
             None
         }