]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/lifetimes.rs
Merge branch 'macro-use' into HEAD
[rust.git] / clippy_lints / src / lifetimes.rs
index 7e22fda4006c2ce159f776b14641ffde24ead43c..7762c4d1cb589a530aebda5b4c2689e5fcfa3647 100644 (file)
@@ -1,5 +1,7 @@
 use crate::reexport::*;
+use matches::matches;
 use rustc::lint::*;
+use rustc::{declare_lint, lint_array};
 use rustc::hir::def::Def;
 use rustc::hir::*;
 use rustc::hir::intravisit::*;
@@ -59,7 +61,7 @@ fn get_lints(&self) -> LintArray {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass {
     fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
-        if let ItemFn(ref decl, _, ref generics, id) = item.node {
+        if let ItemKind::Fn(ref decl, _, ref generics, id) = item.node {
             check_fn_inner(cx, decl, Some(id), generics, item.span);
         }
     }
@@ -101,38 +103,40 @@ fn check_fn_inner<'a, 'tcx>(
     }
 
     let mut bounds_lts = Vec::new();
-    generics.params.iter().for_each(|param| match param.kind {
-        GenericParamKind::Lifetime { .. } => {},
-        GenericParamKind::Type { .. } => {
-            for bound in &param.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(ref params) = *params {
-                        params.args.iter().for_each(|param| match param {
-                            GenericArg::Lifetime(bound) => {
-                                if bound.name.name() != "'static" && !bound.is_elided() {
-                                    return;
-                                }
-                                bounds_lts.push(bound);
-                            },
-                            _ => {},
-                        });
+    let types = generics.params.iter().filter_map(|param| match param.kind {
+        GenericParamKind::Type { .. } => Some(param),
+        GenericParamKind::Lifetime { .. } => None,
+    });
+    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;
+            }
+            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(ref params) = *params {
+                    let lifetimes = params.args.iter().filter_map(|arg| match arg {
+                        GenericArg::Lifetime(lt) => Some(lt),
+                        GenericArg::Type(_) => None,
+                    });
+                    for bound in lifetimes {
+                        if bound.name != LifetimeName::Static && !bound.is_elided() {
+                            return;
+                        }
+                        bounds_lts.push(bound);
                     }
                 }
             }
-        },
-    });
+        }
+    }
     if could_use_elision(cx, decl, body, &generics.params, bounds_lts) {
         span_lint(
             cx,
@@ -238,7 +242,7 @@ fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet<RefLt> {
     for par in named_generics.iter() {
         if let GenericParamKind::Lifetime { .. } = par.kind {
             if par.bounds.is_empty() {
-                allowed_lts.insert(RefLt::Named(par.name.name()));
+                allowed_lts.insert(RefLt::Named(par.name.ident().name));
             }
         }
     }
@@ -249,8 +253,8 @@ fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet<RefLt> {
 
 fn lts_from_bounds<'a, T: Iterator<Item = &'a Lifetime>>(mut vec: Vec<RefLt>, bounds_lts: T) -> Vec<RefLt> {
     for lt in bounds_lts {
-        if lt.name.name() != "'static" {
-            vec.push(RefLt::Named(lt.name.name()));
+        if lt.name != LifetimeName::Static {
+            vec.push(RefLt::Named(lt.name.ident().name));
         }
     }
 
@@ -280,12 +284,12 @@ fn new(cx: &'v LateContext<'v, 't>) -> Self {
 
     fn record(&mut self, lifetime: &Option<Lifetime>) {
         if let Some(ref lt) = *lifetime {
-            if lt.name.name() == "'static" {
+            if lt.name == LifetimeName::Static {
                 self.lts.push(RefLt::Static);
             } else if lt.is_elided() {
                 self.lts.push(RefLt::Unnamed);
             } else {
-                self.lts.push(RefLt::Named(lt.name.name()));
+                self.lts.push(RefLt::Named(lt.name.ident().name));
             }
         } else {
             self.lts.push(RefLt::Unnamed);
@@ -336,22 +340,29 @@ fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
 
     fn visit_ty(&mut self, ty: &'tcx Ty) {
         match ty.node {
-            TyRptr(ref lt, _) if lt.is_elided() => {
+            TyKind::Rptr(ref lt, _) if lt.is_elided() => {
                 self.record(&None);
             },
-            TyPath(ref path) => {
-                self.collect_anonymous_lifetimes(path, ty);
-            },
-            TyImplTraitExistential(exist_ty_id, _, _) => {
-                if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(exist_ty_id.id).node {
-                    for bound in &exist_ty.bounds {
-                        if let GenericBound::Outlives(_) = *bound {
-                            self.record(&None);
+            TyKind::Path(ref path) => {
+                if let QPath::Resolved(_, ref path) = *path {
+                    if let Def::Existential(def_id) = path.def {
+                        let node_id = self.cx.tcx.hir.as_local_node_id(def_id).unwrap();
+                        if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir.expect_item(node_id).node {
+                            for bound in &exist_ty.bounds {
+                                if let GenericBound::Outlives(_) = *bound {
+                                    self.record(&None);
+                                }
+                            }
+                        } else {
+                            unreachable!()
                         }
+                        walk_ty(self, ty);
+                        return;
                     }
                 }
+                self.collect_anonymous_lifetimes(path, ty);
             }
-            TyTraitObject(ref bounds, ref lt) => {
+            TyKind::TraitObject(ref bounds, ref lt) => {
                 if !lt.is_elided() {
                     self.abort = true;
                 }
@@ -419,7 +430,7 @@ struct LifetimeChecker {
 impl<'tcx> Visitor<'tcx> for LifetimeChecker {
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
-        self.map.remove(&lifetime.name.name());
+        self.map.remove(&lifetime.name.ident().name);
     }
 
     fn visit_generic_param(&mut self, param: &'tcx GenericParam) {
@@ -440,7 +451,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
 fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) {
     let hs = generics.params.iter()
         .filter_map(|par| match par.kind {
-            GenericParamKind::Lifetime { .. } => Some((par.name.name(), par.span)),
+            GenericParamKind::Lifetime { .. } => Some((par.name.ident().name, par.span)),
             _ => None,
         })
         .collect();
@@ -461,7 +472,7 @@ struct BodyLifetimeChecker {
 impl<'tcx> Visitor<'tcx> for BodyLifetimeChecker {
     // for lifetimes as parameters of generics
     fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
-        if lifetime.name.name() != keywords::Invalid.name() && lifetime.name.name() != "'static" {
+        if lifetime.name.ident().name != keywords::Invalid.name() && lifetime.name.ident().name != "'static" {
             self.lifetimes_used_in_body = true;
         }
     }