]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/infinite_iter.rs
Fix clippy build
[rust.git] / clippy_lints / src / infinite_iter.rs
index 48767aa2710d6d12a0ba3d1c4d7db60807a7bed6..01c7eef4e04da87e91fbf45433b532b3911b3600 100644 (file)
@@ -1,42 +1,50 @@
-use rustc::hir::*;
-use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
-use rustc::{declare_lint_pass, declare_tool_lint};
-
-use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::{higher, match_def_path, path_def_id, paths};
+use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::{sym, Symbol};
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for iteration that is guaranteed to be infinite.
+    /// ### What it does
+    /// Checks for iteration that is guaranteed to be infinite.
     ///
-    /// **Why is this bad?** While there may be places where this is acceptable
+    /// ### Why is this bad?
+    /// While there may be places where this is acceptable
     /// (e.g., in event streams), in most cases this is simply an error.
     ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
+    /// ### Example
     /// ```no_run
     /// use std::iter;
     ///
     /// iter::repeat(1_u8).collect::<Vec<_>>();
     /// ```
+    #[clippy::version = "pre 1.29.0"]
     pub INFINITE_ITER,
     correctness,
     "infinite iteration"
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for iteration that may be infinite.
+    /// ### What it does
+    /// Checks for iteration that may be infinite.
     ///
-    /// **Why is this bad?** While there may be places where this is acceptable
+    /// ### Why is this bad?
+    /// While there may be places where this is acceptable
     /// (e.g., in event streams), in most cases this is simply an error.
     ///
-    /// **Known problems:** The code may have a condition to stop iteration, but
+    /// ### Known problems
+    /// The code may have a condition to stop iteration, but
     /// this lint is not clever enough to analyze it.
     ///
-    /// **Example:**
+    /// ### Example
     /// ```rust
     /// let infinite_iter = 0..;
+    /// # #[allow(unused)]
     /// [0..].iter().zip(infinite_iter.take_while(|x| *x > 5));
     /// ```
+    #[clippy::version = "pre 1.29.0"]
     pub MAYBE_INFINITE_ITER,
     pedantic,
     "possible infinite iteration"
@@ -44,8 +52,8 @@
 
 declare_lint_pass!(InfiniteIter => [INFINITE_ITER, MAYBE_INFINITE_ITER]);
 
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InfiniteIter {
-    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
+impl<'tcx> LateLintPass<'tcx> for InfiniteIter {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let (lint, msg) = match complete_infinite_iter(cx, expr) {
             Infinite => (INFINITE_ITER, "infinite iteration detected"),
             MaybeInfinite => (MAYBE_INFINITE_ITER, "possible infinite iteration detected"),
@@ -53,7 +61,7 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
                 return;
             },
         };
-        span_lint(cx, lint, expr.span, msg)
+        span_lint(cx, lint, expr.span, msg);
     }
 }
 
@@ -67,6 +75,7 @@ enum Finiteness {
 use self::Finiteness::{Finite, Infinite, MaybeInfinite};
 
 impl Finiteness {
+    #[must_use]
     fn and(self, b: Self) -> Self {
         match (self, b) {
             (Finite, _) | (_, Finite) => Finite,
@@ -75,6 +84,7 @@ fn and(self, b: Self) -> Self {
         }
     }
 
+    #[must_use]
     fn or(self, b: Self) -> Self {
         match (self, b) {
             (Infinite, _) | (_, Infinite) => Infinite,
@@ -85,12 +95,9 @@ fn or(self, b: Self) -> Self {
 }
 
 impl From<bool> for Finiteness {
+    #[must_use]
     fn from(b: bool) -> Self {
-        if b {
-            Infinite
-        } else {
-            Finite
-        }
+        if b { Infinite } else { Finite }
     }
 }
 
@@ -137,9 +144,9 @@ enum Heuristic {
     ("scan", 3, First, MaybeInfinite),
 ];
 
-fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
-    match expr.node {
-        ExprKind::MethodCall(ref method, _, ref args) => {
+fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
+    match expr.kind {
+        ExprKind::MethodCall(method, args, _) => {
             for &(name, len, heuristic, cap) in &HEURISTICS {
                 if method.ident.name.as_str() == name && args.len() == len {
                     return (match heuristic {
@@ -152,23 +159,19 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
                 }
             }
             if method.ident.name == sym!(flat_map) && args.len() == 2 {
-                if let ExprKind::Closure(_, _, body_id, _, _) = args[1].node {
-                    let body = cx.tcx.hir().body(body_id);
+                if let ExprKind::Closure(&Closure { body, .. }) = args[1].kind {
+                    let body = cx.tcx.hir().body(body);
                     return is_infinite(cx, &body.value);
                 }
             }
             Finite
         },
-        ExprKind::Block(ref block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
-        ExprKind::Box(ref e) | ExprKind::AddrOf(_, ref e) => is_infinite(cx, e),
-        ExprKind::Call(ref path, _) => {
-            if let ExprKind::Path(ref qpath) = path.node {
-                match_qpath(qpath, &paths::REPEAT).into()
-            } else {
-                Finite
-            }
-        },
-        ExprKind::Struct(..) => higher::range(cx, expr).map_or(false, |r| r.end.is_none()).into(),
+        ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
+        ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
+        ExprKind::Call(path, _) => path_def_id(cx, path)
+            .map_or(false, |id| match_def_path(cx, id, &paths::ITER_REPEAT))
+            .into(),
+        ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
         _ => Finite,
     }
 }
@@ -202,20 +205,20 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
 ];
 
 /// the paths of types that are known to be infinitely allocating
-const INFINITE_COLLECTORS: [&[&str]; 8] = [
-    &paths::BINARY_HEAP,
-    &paths::BTREEMAP,
-    &paths::BTREESET,
-    &paths::HASHMAP,
-    &paths::HASHSET,
-    &paths::LINKED_LIST,
-    &paths::VEC,
-    &paths::VEC_DEQUE,
+const INFINITE_COLLECTORS: &[Symbol] = &[
+    sym::BinaryHeap,
+    sym::BTreeMap,
+    sym::BTreeSet,
+    sym::HashMap,
+    sym::HashSet,
+    sym::LinkedList,
+    sym::Vec,
+    sym::VecDeque,
 ];
 
-fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
-    match expr.node {
-        ExprKind::MethodCall(ref method, _, ref args) => {
+fn complete_infinite_iter(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
+    match expr.kind {
+        ExprKind::MethodCall(method, args, _) => {
             for &(name, len) in &COMPLETING_METHODS {
                 if method.ident.name.as_str() == name && args.len() == len {
                     return is_infinite(cx, &args[0]);
@@ -227,19 +230,26 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
                 }
             }
             if method.ident.name == sym!(last) && args.len() == 1 {
-                let not_double_ended = get_trait_def_id(cx, &paths::DOUBLE_ENDED_ITERATOR)
-                    .map_or(false, |id| !implements_trait(cx, cx.tables.expr_ty(&args[0]), id, &[]));
+                let not_double_ended = cx
+                    .tcx
+                    .get_diagnostic_item(sym::DoubleEndedIterator)
+                    .map_or(false, |id| {
+                        !implements_trait(cx, cx.typeck_results().expr_ty(&args[0]), id, &[])
+                    });
                 if not_double_ended {
                     return is_infinite(cx, &args[0]);
                 }
             } else if method.ident.name == sym!(collect) {
-                let ty = cx.tables.expr_ty(expr);
-                if INFINITE_COLLECTORS.iter().any(|path| match_type(cx, ty, path)) {
+                let ty = cx.typeck_results().expr_ty(expr);
+                if INFINITE_COLLECTORS
+                    .iter()
+                    .any(|diag_item| is_type_diagnostic_item(cx, ty, *diag_item))
+                {
                     return is_infinite(cx, &args[0]);
                 }
             }
         },
-        ExprKind::Binary(op, ref l, ref r) => {
+        ExprKind::Binary(op, l, r) => {
             if op.node.is_comparison() {
                 return is_infinite(cx, l).and(is_infinite(cx, r)).and(MaybeInfinite);
             }