Auto merge of #3607 - detrumi:limit_infinite_iter_to_known_types, r=phansch
Only trigger `infinite_iter` lint for infinitely allocating `collect()` calls Fixes #3538 ~Oh, I guess this should actually check other methods like `count` as well, not only `collect()`.~ Never mind, `collect` is the only of these functions that allocates a data structure.
This commit is contained in:
commit
84aa027888
@ -7,7 +7,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint};
|
use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint};
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||||
use rustc::{declare_tool_lint, lint_array};
|
use rustc::{declare_tool_lint, lint_array};
|
||||||
@ -200,7 +200,6 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
|
|||||||
/// their iterators
|
/// their iterators
|
||||||
static COMPLETING_METHODS: &[(&str, usize)] = &[
|
static COMPLETING_METHODS: &[(&str, usize)] = &[
|
||||||
("count", 1),
|
("count", 1),
|
||||||
("collect", 1),
|
|
||||||
("fold", 3),
|
("fold", 3),
|
||||||
("for_each", 2),
|
("for_each", 2),
|
||||||
("partition", 2),
|
("partition", 2),
|
||||||
@ -214,6 +213,18 @@ fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
|
|||||||
("product", 1),
|
("product", 1),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// the paths of types that are known to be infinitely allocating
|
||||||
|
static INFINITE_COLLECTORS: &[&[&str]] = &[
|
||||||
|
&paths::BINARY_HEAP,
|
||||||
|
&paths::BTREEMAP,
|
||||||
|
&paths::BTREESET,
|
||||||
|
&paths::HASHMAP,
|
||||||
|
&paths::HASHSET,
|
||||||
|
&paths::LINKED_LIST,
|
||||||
|
&paths::VEC,
|
||||||
|
&paths::VEC_DEQUE,
|
||||||
|
];
|
||||||
|
|
||||||
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
|
fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprKind::MethodCall(ref method, _, ref args) => {
|
ExprKind::MethodCall(ref method, _, ref args) => {
|
||||||
@ -233,6 +244,11 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
|
|||||||
if not_double_ended {
|
if not_double_ended {
|
||||||
return is_infinite(cx, &args[0]);
|
return is_infinite(cx, &args[0]);
|
||||||
}
|
}
|
||||||
|
} else if method.ident.name == "collect" {
|
||||||
|
let ty = cx.tables.expr_ty(expr);
|
||||||
|
if INFINITE_COLLECTORS.iter().any(|path| match_type(cx, ty, path)) {
|
||||||
|
return is_infinite(cx, &args[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::Binary(op, ref l, ref r) => {
|
ExprKind::Binary(op, ref l, ref r) => {
|
||||||
|
@ -58,3 +58,22 @@ fn main() {
|
|||||||
infinite_iters();
|
infinite_iters();
|
||||||
potential_infinite_iters();
|
potential_infinite_iters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod finite_collect {
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
struct C;
|
||||||
|
impl FromIterator<i32> for C {
|
||||||
|
fn from_iter<I: IntoIterator<Item = i32>>(iter: I) -> Self {
|
||||||
|
C
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_collect() {
|
||||||
|
let _: HashSet<i32> = (0..).collect(); // Infinite iter
|
||||||
|
|
||||||
|
// Some data structures don't collect infinitely, such as `ArrayVec`
|
||||||
|
let _: C = (0..).collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -105,5 +105,13 @@ error: possible infinite iteration detected
|
|||||||
LL | (0..).all(|x| x == 24); // maybe infinite iter
|
LL | (0..).all(|x| x == 24); // maybe infinite iter
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 14 previous errors
|
error: infinite iteration detected
|
||||||
|
--> $DIR/infinite_iter.rs:74:31
|
||||||
|
|
|
||||||
|
LL | let _: HashSet<i32> = (0..).collect(); // Infinite iter
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: #[deny(clippy::infinite_iter)] on by default
|
||||||
|
|
||||||
|
error: aborting due to 15 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user