mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
Limit infinite_iter collect() check to known types
This commit is contained in:
parent
529f698c23
commit
f38fb56baf
@ -7,7 +7,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// 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::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
||||
use rustc::{declare_tool_lint, lint_array};
|
||||
@ -200,7 +200,6 @@ static POSSIBLY_COMPLETING_METHODS: &[(&str, usize)] = &[
|
||||
/// their iterators
|
||||
static COMPLETING_METHODS: &[(&str, usize)] = &[
|
||||
("count", 1),
|
||||
("collect", 1),
|
||||
("fold", 3),
|
||||
("for_each", 2),
|
||||
("partition", 2),
|
||||
@ -214,6 +213,18 @@ static COMPLETING_METHODS: &[(&str, usize)] = &[
|
||||
("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 {
|
||||
match expr.node {
|
||||
ExprKind::MethodCall(ref method, _, ref args) => {
|
||||
@ -233,6 +244,11 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness {
|
||||
if not_double_ended {
|
||||
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) => {
|
||||
|
@ -58,3 +58,22 @@ fn main() {
|
||||
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
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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