Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[manual_retain]: add lint case for binary_heap #11329

Merged
merged 2 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions clippy_lints/src/manual_retain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::sym;

const ACCEPTABLE_METHODS: [&[&str]; 4] = [
const ACCEPTABLE_METHODS: [&[&str]; 5] = [
&paths::BINARYHEAP_ITER,
&paths::HASHSET_ITER,
&paths::BTREESET_ITER,
&paths::SLICE_INTO,
&paths::VEC_DEQUE_ITER,
];
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 6] = [
const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [
(sym::BinaryHeap, Some(msrvs::BINARY_HEAP_RETAIN)),
(sym::BTreeSet, Some(msrvs::BTREE_SET_RETAIN)),
(sym::BTreeMap, Some(msrvs::BTREE_MAP_RETAIN)),
(sym::HashSet, Some(msrvs::HASH_SET_RETAIN)),
Expand Down
2 changes: 1 addition & 1 deletion clippy_utils/src/msrvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ macro_rules! msrv_aliases {
// names may refer to stabilized feature flags or library items
msrv_aliases! {
1,71,0 { TUPLE_ARRAY_CONVERSIONS }
1,70,0 { OPTION_IS_SOME_AND }
1,70,0 { OPTION_IS_SOME_AND, BINARY_HEAP_RETAIN }
1,68,0 { PATH_MAIN_SEPARATOR_STR }
1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
Expand Down
1 change: 1 addition & 0 deletions clippy_utils/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
];
#[cfg(feature = "internal")]
pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"];
pub const BINARYHEAP_ITER: [&str; 5] = ["alloc", "collections", "binary_heap", "BinaryHeap", "iter"];
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
Expand Down
39 changes: 27 additions & 12 deletions tests/ui/manual_retain.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,31 @@ fn main() {
}

fn binary_heap_retain() {
// NOTE: Do not lint now, because binary_heap_retain is nightly API.
// And we need to add a test case for msrv if we update this implementation.
// https://github.com/rust-lang/rust/issues/71503
let mut heap = BinaryHeap::from([1, 2, 3]);
heap = heap.into_iter().filter(|x| x % 2 == 0).collect();
heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect();
heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
let mut binary_heap = BinaryHeap::from([1, 2, 3]);
// Do lint.
binary_heap.retain(|x| x % 2 == 0);
binary_heap.retain(|x| x % 2 == 0);
binary_heap.retain(|x| x % 2 == 0);

// Do not lint, because type conversion is performed
heap = heap.into_iter().filter(|x| x % 2 == 0).collect::<BinaryHeap<i8>>();
heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect::<BinaryHeap<i8>>();
heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect::<BinaryHeap<i8>>();
binary_heap = binary_heap
.into_iter()
.filter(|x| x % 2 == 0)
.collect::<BinaryHeap<i8>>();
binary_heap = binary_heap
.iter()
.filter(|&x| x % 2 == 0)
.copied()
.collect::<BinaryHeap<i8>>();
binary_heap = binary_heap
.iter()
.filter(|&x| x % 2 == 0)
.cloned()
.collect::<BinaryHeap<i8>>();

// Do not lint, because this expression is not assign.
let mut bar: BinaryHeap<i8> = heap.iter().filter(|&x| x % 2 == 0).copied().collect();
let mut foobar: BinaryHeap<i8> = heap.into_iter().filter(|x| x % 2 == 0).collect();
let mut bar: BinaryHeap<i8> = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
let mut foobar: BinaryHeap<i8> = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();

// Do not lint, because it is an assignment to a different variable.
bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect();
Expand Down Expand Up @@ -209,6 +218,12 @@ fn vec_deque_retain() {
bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
}

#[clippy::msrv = "1.69"]
fn _msrv_169() {
let mut binary_heap = BinaryHeap::from([1, 2, 3]);
binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
}

#[clippy::msrv = "1.52"]
fn _msrv_153() {
let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
Expand Down
39 changes: 27 additions & 12 deletions tests/ui/manual_retain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,31 @@ fn main() {
}

fn binary_heap_retain() {
// NOTE: Do not lint now, because binary_heap_retain is nightly API.
// And we need to add a test case for msrv if we update this implementation.
// https://github.com/rust-lang/rust/issues/71503
let mut heap = BinaryHeap::from([1, 2, 3]);
heap = heap.into_iter().filter(|x| x % 2 == 0).collect();
heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect();
heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
let mut binary_heap = BinaryHeap::from([1, 2, 3]);
// Do lint.
binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect();

// Do not lint, because type conversion is performed
heap = heap.into_iter().filter(|x| x % 2 == 0).collect::<BinaryHeap<i8>>();
heap = heap.iter().filter(|&x| x % 2 == 0).copied().collect::<BinaryHeap<i8>>();
heap = heap.iter().filter(|&x| x % 2 == 0).cloned().collect::<BinaryHeap<i8>>();
binary_heap = binary_heap
.into_iter()
.filter(|x| x % 2 == 0)
.collect::<BinaryHeap<i8>>();
binary_heap = binary_heap
.iter()
.filter(|&x| x % 2 == 0)
.copied()
.collect::<BinaryHeap<i8>>();
binary_heap = binary_heap
.iter()
.filter(|&x| x % 2 == 0)
.cloned()
.collect::<BinaryHeap<i8>>();

// Do not lint, because this expression is not assign.
let mut bar: BinaryHeap<i8> = heap.iter().filter(|&x| x % 2 == 0).copied().collect();
let mut foobar: BinaryHeap<i8> = heap.into_iter().filter(|x| x % 2 == 0).collect();
let mut bar: BinaryHeap<i8> = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
let mut foobar: BinaryHeap<i8> = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();

// Do not lint, because it is an assignment to a different variable.
bar = foobar.iter().filter(|&x| x % 2 == 0).copied().collect();
Expand Down Expand Up @@ -215,6 +224,12 @@ fn vec_deque_retain() {
bar = foobar.into_iter().filter(|x| x % 2 == 0).collect();
}

#[clippy::msrv = "1.69"]
fn _msrv_169() {
let mut binary_heap = BinaryHeap::from([1, 2, 3]);
binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
}

#[clippy::msrv = "1.52"]
fn _msrv_153() {
let mut btree_map: BTreeMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect();
Expand Down
62 changes: 40 additions & 22 deletions tests/ui/manual_retain.stderr
Original file line number Diff line number Diff line change
@@ -1,19 +1,37 @@
error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:45:5
--> $DIR/manual_retain.rs:22:5
|
LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)`
LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`
|
= note: `-D clippy::manual-retain` implied by `-D warnings`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:46:5
--> $DIR/manual_retain.rs:23:5
|
LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:24:5
|
LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:54:5
|
LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:55:5
|
LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:47:5
--> $DIR/manual_retain.rs:56:5
|
LL | / btree_map = btree_map
LL | | .into_iter()
Expand All @@ -22,37 +40,37 @@ LL | | .collect();
| |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:69:5
--> $DIR/manual_retain.rs:78:5
|
LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:70:5
--> $DIR/manual_retain.rs:79:5
|
LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:71:5
--> $DIR/manual_retain.rs:80:5
|
LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:101:5
--> $DIR/manual_retain.rs:110:5
|
LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:102:5
--> $DIR/manual_retain.rs:111:5
|
LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:103:5
--> $DIR/manual_retain.rs:112:5
|
LL | / hash_map = hash_map
LL | | .into_iter()
Expand All @@ -61,64 +79,64 @@ LL | | .collect();
| |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:124:5
--> $DIR/manual_retain.rs:133:5
|
LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:125:5
--> $DIR/manual_retain.rs:134:5
|
LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:126:5
--> $DIR/manual_retain.rs:135:5
|
LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:155:5
--> $DIR/manual_retain.rs:164:5
|
LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:167:5
--> $DIR/manual_retain.rs:176:5
|
LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:168:5
--> $DIR/manual_retain.rs:177:5
|
LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:169:5
--> $DIR/manual_retain.rs:178:5
|
LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:191:5
--> $DIR/manual_retain.rs:200:5
|
LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:192:5
--> $DIR/manual_retain.rs:201:5
|
LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`

error: this expression can be written more simply using `.retain()`
--> $DIR/manual_retain.rs:193:5
--> $DIR/manual_retain.rs:202:5
|
LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)`

error: aborting due to 19 previous errors
error: aborting due to 22 previous errors