-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #6791 - TaKO8Ki:iter-count, r=matthiaskrgr
New lint: `iter_count` This pull request adds a new lint named `iter_count`. --- closes #6262 changelog: new lint `iter_count`
- Loading branch information
Showing
10 changed files
with
414 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use crate::methods::derefs_to_slice; | ||
use crate::utils::{is_type_diagnostic_item, match_type, paths, snippet_with_applicability, span_lint_and_sugg}; | ||
|
||
use rustc_errors::Applicability; | ||
use rustc_hir::Expr; | ||
use rustc_lint::LateContext; | ||
use rustc_span::sym; | ||
|
||
use super::ITER_COUNT; | ||
|
||
pub(crate) fn lints<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, iter_args: &'tcx [Expr<'tcx>], iter_method: &str) { | ||
let ty = cx.typeck_results().expr_ty(&iter_args[0]); | ||
let caller_type = if derefs_to_slice(cx, &iter_args[0], ty).is_some() { | ||
"slice" | ||
} else if is_type_diagnostic_item(cx, ty, sym::vec_type) { | ||
"Vec" | ||
} else if is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) { | ||
"VecDeque" | ||
} else if is_type_diagnostic_item(cx, ty, sym!(hashset_type)) { | ||
"HashSet" | ||
} else if is_type_diagnostic_item(cx, ty, sym!(hashmap_type)) { | ||
"HashMap" | ||
} else if match_type(cx, ty, &paths::BTREEMAP) { | ||
"BTreeMap" | ||
} else if match_type(cx, ty, &paths::BTREESET) { | ||
"BTreeSet" | ||
} else if match_type(cx, ty, &paths::LINKED_LIST) { | ||
"LinkedList" | ||
} else if match_type(cx, ty, &paths::BINARY_HEAP) { | ||
"BinaryHeap" | ||
} else { | ||
return; | ||
}; | ||
let mut applicability = Applicability::MachineApplicable; | ||
span_lint_and_sugg( | ||
cx, | ||
ITER_COUNT, | ||
expr.span, | ||
&format!("called `.{}().count()` on a `{}`", iter_method, caller_type), | ||
"try", | ||
format!( | ||
"{}.len()", | ||
snippet_with_applicability(cx, iter_args[0].span, "..", &mut applicability), | ||
), | ||
applicability, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// run-rustfix | ||
// aux-build:option_helpers.rs | ||
|
||
#![warn(clippy::iter_count)] | ||
#![allow( | ||
unused_variables, | ||
array_into_iter, | ||
unused_mut, | ||
clippy::into_iter_on_ref, | ||
clippy::unnecessary_operation | ||
)] | ||
|
||
extern crate option_helpers; | ||
|
||
use option_helpers::IteratorFalsePositives; | ||
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; | ||
|
||
/// Struct to generate false positives for things with `.iter()`. | ||
#[derive(Copy, Clone)] | ||
struct HasIter; | ||
|
||
impl HasIter { | ||
fn iter(self) -> IteratorFalsePositives { | ||
IteratorFalsePositives { foo: 0 } | ||
} | ||
|
||
fn iter_mut(self) -> IteratorFalsePositives { | ||
IteratorFalsePositives { foo: 0 } | ||
} | ||
|
||
fn into_iter(self) -> IteratorFalsePositives { | ||
IteratorFalsePositives { foo: 0 } | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut vec = vec![0, 1, 2, 3]; | ||
let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); | ||
let mut vec_deque: VecDeque<_> = vec.iter().cloned().collect(); | ||
let mut hash_set = HashSet::new(); | ||
let mut hash_map = HashMap::new(); | ||
let mut b_tree_map = BTreeMap::new(); | ||
let mut b_tree_set = BTreeSet::new(); | ||
let mut linked_list = LinkedList::new(); | ||
let mut binary_heap = BinaryHeap::new(); | ||
hash_set.insert(1); | ||
hash_map.insert(1, 2); | ||
b_tree_map.insert(1, 2); | ||
b_tree_set.insert(1); | ||
linked_list.push_back(1); | ||
binary_heap.push(1); | ||
|
||
&vec[..].len(); | ||
vec.len(); | ||
boxed_slice.len(); | ||
vec_deque.len(); | ||
hash_set.len(); | ||
hash_map.len(); | ||
b_tree_map.len(); | ||
b_tree_set.len(); | ||
linked_list.len(); | ||
binary_heap.len(); | ||
|
||
vec.len(); | ||
&vec[..].len(); | ||
vec_deque.len(); | ||
hash_map.len(); | ||
b_tree_map.len(); | ||
linked_list.len(); | ||
|
||
&vec[..].len(); | ||
vec.len(); | ||
vec_deque.len(); | ||
hash_set.len(); | ||
hash_map.len(); | ||
b_tree_map.len(); | ||
b_tree_set.len(); | ||
linked_list.len(); | ||
binary_heap.len(); | ||
|
||
// Make sure we don't lint for non-relevant types. | ||
let false_positive = HasIter; | ||
false_positive.iter().count(); | ||
false_positive.iter_mut().count(); | ||
false_positive.into_iter().count(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// run-rustfix | ||
// aux-build:option_helpers.rs | ||
|
||
#![warn(clippy::iter_count)] | ||
#![allow( | ||
unused_variables, | ||
array_into_iter, | ||
unused_mut, | ||
clippy::into_iter_on_ref, | ||
clippy::unnecessary_operation | ||
)] | ||
|
||
extern crate option_helpers; | ||
|
||
use option_helpers::IteratorFalsePositives; | ||
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; | ||
|
||
/// Struct to generate false positives for things with `.iter()`. | ||
#[derive(Copy, Clone)] | ||
struct HasIter; | ||
|
||
impl HasIter { | ||
fn iter(self) -> IteratorFalsePositives { | ||
IteratorFalsePositives { foo: 0 } | ||
} | ||
|
||
fn iter_mut(self) -> IteratorFalsePositives { | ||
IteratorFalsePositives { foo: 0 } | ||
} | ||
|
||
fn into_iter(self) -> IteratorFalsePositives { | ||
IteratorFalsePositives { foo: 0 } | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut vec = vec![0, 1, 2, 3]; | ||
let mut boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]); | ||
let mut vec_deque: VecDeque<_> = vec.iter().cloned().collect(); | ||
let mut hash_set = HashSet::new(); | ||
let mut hash_map = HashMap::new(); | ||
let mut b_tree_map = BTreeMap::new(); | ||
let mut b_tree_set = BTreeSet::new(); | ||
let mut linked_list = LinkedList::new(); | ||
let mut binary_heap = BinaryHeap::new(); | ||
hash_set.insert(1); | ||
hash_map.insert(1, 2); | ||
b_tree_map.insert(1, 2); | ||
b_tree_set.insert(1); | ||
linked_list.push_back(1); | ||
binary_heap.push(1); | ||
|
||
&vec[..].iter().count(); | ||
vec.iter().count(); | ||
boxed_slice.iter().count(); | ||
vec_deque.iter().count(); | ||
hash_set.iter().count(); | ||
hash_map.iter().count(); | ||
b_tree_map.iter().count(); | ||
b_tree_set.iter().count(); | ||
linked_list.iter().count(); | ||
binary_heap.iter().count(); | ||
|
||
vec.iter_mut().count(); | ||
&vec[..].iter_mut().count(); | ||
vec_deque.iter_mut().count(); | ||
hash_map.iter_mut().count(); | ||
b_tree_map.iter_mut().count(); | ||
linked_list.iter_mut().count(); | ||
|
||
&vec[..].into_iter().count(); | ||
vec.into_iter().count(); | ||
vec_deque.into_iter().count(); | ||
hash_set.into_iter().count(); | ||
hash_map.into_iter().count(); | ||
b_tree_map.into_iter().count(); | ||
b_tree_set.into_iter().count(); | ||
linked_list.into_iter().count(); | ||
binary_heap.into_iter().count(); | ||
|
||
// Make sure we don't lint for non-relevant types. | ||
let false_positive = HasIter; | ||
false_positive.iter().count(); | ||
false_positive.iter_mut().count(); | ||
false_positive.into_iter().count(); | ||
} |
Oops, something went wrong.