about summary refs log tree commit diff
path: root/clippy_lints/src/utils/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'clippy_lints/src/utils/mod.rs')
-rw-r--r--clippy_lints/src/utils/mod.rs64
1 files changed, 34 insertions, 30 deletions
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 6dd8fef7e82..7b59917c2bb 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -1,6 +1,8 @@
 #[macro_use]
 pub mod sym;
 
+#[allow(clippy::module_name_repetitions)]
+pub mod ast_utils;
 pub mod attrs;
 pub mod author;
 pub mod camel_case;
@@ -19,7 +21,7 @@ pub mod sugg;
 pub mod usage;
 pub use self::attrs::*;
 pub use self::diagnostics::*;
-pub use self::hir_utils::{SpanlessEq, SpanlessHash};
+pub use self::hir_utils::{both, over, SpanlessEq, SpanlessHash};
 
 use std::borrow::Cow;
 use std::mem;
@@ -40,7 +42,7 @@ use rustc_hir::{
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::map::Map;
-use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Binder, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Ty, TyCtxt, TypeFoldable};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::original_sp;
 use rustc_span::symbol::{self, kw, Symbol};
@@ -72,7 +74,7 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool {
     let parent_id = cx.tcx.hir().get_parent_item(id);
     match cx.tcx.hir().get(parent_id) {
         Node::Item(&Item {
-            kind: ItemKind::Const(..),
+            kind: ItemKind::Const(..) | ItemKind::Static(..),
             ..
         })
         | Node::TraitItem(&TraitItem {
@@ -83,11 +85,7 @@ pub fn in_constant(cx: &LateContext<'_, '_>, id: HirId) -> bool {
             kind: ImplItemKind::Const(..),
             ..
         })
-        | Node::AnonConst(_)
-        | Node::Item(&Item {
-            kind: ItemKind::Static(..),
-            ..
-        }) => true,
+        | Node::AnonConst(_) => true,
         Node::Item(&Item {
             kind: ItemKind::Fn(ref sig, ..),
             ..
@@ -165,8 +163,8 @@ pub fn match_trait_method(cx: &LateContext<'_, '_>, expr: &Expr<'_>, path: &[&st
 /// Checks if an expression references a variable of the given name.
 pub fn match_var(expr: &Expr<'_>, var: Name) -> bool {
     if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind {
-        if path.segments.len() == 1 && path.segments[0].ident.name == var {
-            return true;
+        if let [p] = path.segments {
+            return p.ident.name == var;
         }
     }
     false
@@ -181,8 +179,7 @@ pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
 
 pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
     match *path {
-        QPath::Resolved(_, ref path) if path.segments.len() == 1 => Some(&path.segments[0]),
-        QPath::Resolved(..) => None,
+        QPath::Resolved(_, ref path) => path.segments.get(0),
         QPath::TypeRelative(_, ref seg) => Some(seg),
     }
 }
@@ -201,9 +198,12 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
         QPath::Resolved(_, ref path) => match_path(path, segments),
         QPath::TypeRelative(ref ty, ref segment) => match ty.kind {
             TyKind::Path(ref inner_path) => {
-                !segments.is_empty()
-                    && match_qpath(inner_path, &segments[..(segments.len() - 1)])
-                    && segment.ident.name.as_str() == segments[segments.len() - 1]
+                if let [prefix @ .., end] = segments {
+                    if match_qpath(inner_path, prefix) {
+                        return segment.ident.name.as_str() == *end;
+                    }
+                }
+                false
             },
             _ => false,
         },
@@ -398,7 +398,7 @@ pub fn method_calls<'tcx>(
 /// Matches an `Expr` against a chain of methods, and return the matched `Expr`s.
 ///
 /// For example, if `expr` represents the `.baz()` in `foo.bar().baz()`,
-/// `matched_method_chain(expr, &["bar", "baz"])` will return a `Vec`
+/// `method_chain_args(expr, &["bar", "baz"])` will return a `Vec`
 /// containing the `Expr`s for
 /// `.bar()` and `.baz()`
 pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec<&'a [Expr<'a>]>> {
@@ -882,20 +882,6 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: hir::HirId) -> T
     cx.tcx.erase_late_bound_regions(&ret_ty)
 }
 
-/// Checks if two types are the same.
-///
-/// This discards any lifetime annotations, too.
-//
-// FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` ==
-// `for <'b> Foo<'b>`, but not for type parameters).
-pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-    let a = cx.tcx.erase_late_bound_regions(&Binder::bind(a));
-    let b = cx.tcx.erase_late_bound_regions(&Binder::bind(b));
-    cx.tcx
-        .infer_ctxt()
-        .enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok())
-}
-
 /// Returns `true` if the given type is an `unsafe` function.
 pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.kind {
@@ -1408,6 +1394,24 @@ pub fn run_lints(cx: &LateContext<'_, '_>, lints: &[&'static Lint], id: HirId) -
     })
 }
 
+#[macro_export]
+macro_rules! unwrap_cargo_metadata {
+    ($cx: ident, $lint: ident, $deps: expr) => {{
+        let mut command = cargo_metadata::MetadataCommand::new();
+        if !$deps {
+            command.no_deps();
+        }
+
+        match command.exec() {
+            Ok(metadata) => metadata,
+            Err(err) => {
+                span_lint($cx, $lint, DUMMY_SP, &format!("could not read cargo metadata: {}", err));
+                return;
+            },
+        }
+    }};
+}
+
 #[cfg(test)]
 mod test {
     use super::{trim_multiline, without_block_comments};