Skip to content

Commit f95b514

Browse files
committed
mem_replace_with_default: recognize some std library ctors
1 parent abd2c7e commit f95b514

File tree

5 files changed

+154
-7
lines changed

5 files changed

+154
-7
lines changed

clippy_lints/src/mem_replace.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,22 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
200200
if !in_external_macro(cx.tcx.sess, expr_span);
201201
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
202202
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
203-
if match_def_path(cx, repl_def_id, &paths::DEFAULT_TRAIT_METHOD);
203+
204+
let defaults = &[
205+
paths::DEFAULT_TRAIT_METHOD.as_ref(),
206+
paths::STRING_NEW.as_ref(),
207+
paths::VEC_NEW.as_ref(),
208+
paths::VEC_DEQUE_NEW.as_ref(),
209+
paths::LINKED_LIST_NEW.as_ref(),
210+
paths::HASHMAP_NEW.as_ref(),
211+
paths::BTREEMAP_NEW.as_ref(),
212+
paths::HASHSET_NEW.as_ref(),
213+
paths::BTREESET_NEW.as_ref(),
214+
paths::BINARY_HEAP_NEW.as_ref(),
215+
];
216+
217+
if defaults.iter().any(|x| match_def_path(cx, repl_def_id, &x));
218+
204219
then {
205220
span_lint_and_then(
206221
cx,

clippy_utils/src/paths.rs

+8
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"];
1111
pub(super) const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"];
1212
pub(super) const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"];
1313
pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"];
14+
pub const BINARY_HEAP_NEW: [&str; 5] = ["alloc", "collections", "binary_heap", "BinaryHeap", "new"];
1415
pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"];
1516
pub const BOX: [&str; 3] = ["alloc", "boxed", "Box"];
1617
pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"];
18+
pub const BTREEMAP_NEW: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "new"];
1719
pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "entry", "Entry"];
1820
pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"];
21+
pub const BTREESET_NEW: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "new"];
1922
pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"];
2023
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
2124
pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
@@ -51,8 +54,10 @@ pub const FROM_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "From
5154
pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"];
5255
pub const HASH: [&str; 3] = ["core", "hash", "Hash"];
5356
pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"];
57+
pub const HASHMAP_NEW: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "new"];
5458
pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"];
5559
pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"];
60+
pub const HASHSET_NEW: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "new"];
5661
#[cfg(feature = "internal-lints")]
5762
pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
5863
#[cfg(feature = "internal-lints")]
@@ -72,6 +77,7 @@ pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
7277
#[cfg(feature = "internal-lints")]
7378
pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
7479
pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
80+
pub const LINKED_LIST_NEW: [&str; 5] = ["alloc", "collections", "linked_list", "LinkedList", "new"];
7581
#[cfg(feature = "internal-lints")]
7682
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
7783
pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
@@ -144,6 +150,7 @@ pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
144150
pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"];
145151
pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"];
146152
pub const STRING: [&str; 3] = ["alloc", "string", "String"];
153+
pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
147154
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
148155
pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
149156
pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
@@ -173,6 +180,7 @@ pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
173180
pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
174181
pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
175182
pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"];
183+
pub const VEC_DEQUE_NEW: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "new"];
176184
pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
177185
pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
178186
pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"];

tests/ui/mem_replace.fixed

+29
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
clippy::mem_replace_with_default
88
)]
99

10+
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
1011
use std::mem;
1112

1213
fn replace_option_with_none() {
@@ -19,9 +20,37 @@ fn replace_option_with_none() {
1920
fn replace_with_default() {
2021
let mut s = String::from("foo");
2122
let _ = std::mem::take(&mut s);
23+
2224
let s = &mut String::from("foo");
2325
let _ = std::mem::take(s);
2426
let _ = std::mem::take(s);
27+
28+
let mut v = vec![123];
29+
let _ = std::mem::take(&mut v);
30+
let _ = std::mem::take(&mut v);
31+
let _ = std::mem::take(&mut v);
32+
let _ = std::mem::take(&mut v);
33+
34+
let mut hash_map: HashMap<i32, i32> = HashMap::new();
35+
let _ = std::mem::take(&mut hash_map);
36+
37+
let mut btree_map: BTreeMap<i32, i32> = BTreeMap::new();
38+
let _ = std::mem::take(&mut btree_map);
39+
40+
let mut vd: VecDeque<i32> = VecDeque::new();
41+
let _ = std::mem::take(&mut vd);
42+
43+
let mut hash_set: HashSet<&str> = HashSet::new();
44+
let _ = std::mem::take(&mut hash_set);
45+
46+
let mut btree_set: BTreeSet<&str> = BTreeSet::new();
47+
let _ = std::mem::take(&mut btree_set);
48+
49+
let mut list: LinkedList<i32> = LinkedList::new();
50+
let _ = std::mem::take(&mut list);
51+
52+
let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
53+
let _ = std::mem::take(&mut binary_heap);
2554
}
2655

2756
fn main() {

tests/ui/mem_replace.rs

+29
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
clippy::mem_replace_with_default
88
)]
99

10+
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
1011
use std::mem;
1112

1213
fn replace_option_with_none() {
@@ -19,9 +20,37 @@ fn replace_option_with_none() {
1920
fn replace_with_default() {
2021
let mut s = String::from("foo");
2122
let _ = std::mem::replace(&mut s, String::default());
23+
2224
let s = &mut String::from("foo");
2325
let _ = std::mem::replace(s, String::default());
2426
let _ = std::mem::replace(s, Default::default());
27+
28+
let mut v = vec![123];
29+
let _ = std::mem::replace(&mut v, Vec::default());
30+
let _ = std::mem::replace(&mut v, Default::default());
31+
let _ = std::mem::replace(&mut v, Vec::new());
32+
let _ = std::mem::replace(&mut v, vec![]);
33+
34+
let mut hash_map: HashMap<i32, i32> = HashMap::new();
35+
let _ = std::mem::replace(&mut hash_map, HashMap::new());
36+
37+
let mut btree_map: BTreeMap<i32, i32> = BTreeMap::new();
38+
let _ = std::mem::replace(&mut btree_map, BTreeMap::new());
39+
40+
let mut vd: VecDeque<i32> = VecDeque::new();
41+
let _ = std::mem::replace(&mut vd, VecDeque::new());
42+
43+
let mut hash_set: HashSet<&str> = HashSet::new();
44+
let _ = std::mem::replace(&mut hash_set, HashSet::new());
45+
46+
let mut btree_set: BTreeSet<&str> = BTreeSet::new();
47+
let _ = std::mem::replace(&mut btree_set, BTreeSet::new());
48+
49+
let mut list: LinkedList<i32> = LinkedList::new();
50+
let _ = std::mem::replace(&mut list, LinkedList::new());
51+
52+
let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
53+
let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
2554
}
2655

2756
fn main() {

tests/ui/mem_replace.stderr

+72-6
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,102 @@
11
error: replacing an `Option` with `None`
2-
--> $DIR/mem_replace.rs:14:13
2+
--> $DIR/mem_replace.rs:15:13
33
|
44
LL | let _ = mem::replace(&mut an_option, None);
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
66
|
77
= note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings`
88

99
error: replacing an `Option` with `None`
10-
--> $DIR/mem_replace.rs:16:13
10+
--> $DIR/mem_replace.rs:17:13
1111
|
1212
LL | let _ = mem::replace(an_option, None);
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
1414

1515
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
16-
--> $DIR/mem_replace.rs:21:13
16+
--> $DIR/mem_replace.rs:22:13
1717
|
1818
LL | let _ = std::mem::replace(&mut s, String::default());
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)`
2020
|
2121
= note: `-D clippy::mem-replace-with-default` implied by `-D warnings`
2222

2323
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
24-
--> $DIR/mem_replace.rs:23:13
24+
--> $DIR/mem_replace.rs:25:13
2525
|
2626
LL | let _ = std::mem::replace(s, String::default());
2727
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
2828

2929
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
30-
--> $DIR/mem_replace.rs:24:13
30+
--> $DIR/mem_replace.rs:26:13
3131
|
3232
LL | let _ = std::mem::replace(s, Default::default());
3333
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
3434

35-
error: aborting due to 5 previous errors
35+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
36+
--> $DIR/mem_replace.rs:29:13
37+
|
38+
LL | let _ = std::mem::replace(&mut v, Vec::default());
39+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
40+
41+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
42+
--> $DIR/mem_replace.rs:30:13
43+
|
44+
LL | let _ = std::mem::replace(&mut v, Default::default());
45+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
46+
47+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
48+
--> $DIR/mem_replace.rs:31:13
49+
|
50+
LL | let _ = std::mem::replace(&mut v, Vec::new());
51+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
52+
53+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
54+
--> $DIR/mem_replace.rs:32:13
55+
|
56+
LL | let _ = std::mem::replace(&mut v, vec![]);
57+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
58+
59+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
60+
--> $DIR/mem_replace.rs:35:13
61+
|
62+
LL | let _ = std::mem::replace(&mut hash_map, HashMap::new());
63+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)`
64+
65+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
66+
--> $DIR/mem_replace.rs:38:13
67+
|
68+
LL | let _ = std::mem::replace(&mut btree_map, BTreeMap::new());
69+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)`
70+
71+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
72+
--> $DIR/mem_replace.rs:41:13
73+
|
74+
LL | let _ = std::mem::replace(&mut vd, VecDeque::new());
75+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)`
76+
77+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
78+
--> $DIR/mem_replace.rs:44:13
79+
|
80+
LL | let _ = std::mem::replace(&mut hash_set, HashSet::new());
81+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)`
82+
83+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
84+
--> $DIR/mem_replace.rs:47:13
85+
|
86+
LL | let _ = std::mem::replace(&mut btree_set, BTreeSet::new());
87+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)`
88+
89+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
90+
--> $DIR/mem_replace.rs:50:13
91+
|
92+
LL | let _ = std::mem::replace(&mut list, LinkedList::new());
93+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)`
94+
95+
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
96+
--> $DIR/mem_replace.rs:53:13
97+
|
98+
LL | let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
99+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)`
100+
101+
error: aborting due to 16 previous errors
36102

0 commit comments

Comments
 (0)