Skip to content

Commit 4a8b7ea

Browse files
authored
Do not replace .unwrap_or(vec![]) by .unwrap_or_default() (#15699)
`.unwrap_or(vec![])` is as readable as `.unwrap_or_default()`. Also, this ensures by adding tests that expressions such as `.unwrap_or(DEFAULT_LITERAL)` (`0`, `""`, etc.) are not replaced by `.unwrap_or_default()` either. Related to the discussion in the [Zulip discussion](https://rust-lang.zulipchat.com/#narrow/channel/257328-clippy/topic/FCP.20concealed_obvious_default) about PR #15037. changelog: [`unwrap_or_default`]: do not replace `.unwrap_or(vec![])` by `.unwrap_or_default()`
2 parents 8428b16 + ad21dff commit 4a8b7ea

File tree

4 files changed

+86
-47
lines changed

4 files changed

+86
-47
lines changed

clippy_lints/src/methods/or_fun_call.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::ops::ControlFlow;
22

33
use clippy_utils::diagnostics::span_lint_and_sugg;
44
use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
5+
use clippy_utils::higher::VecArgs;
56
use clippy_utils::source::snippet_with_context;
67
use clippy_utils::ty::{expr_type_is_certain, implements_trait, is_type_diagnostic_item};
78
use clippy_utils::visitors::for_each_expr;
@@ -97,6 +98,12 @@ pub(super) fn check<'tcx>(
9798
return false;
9899
}
99100

101+
// `.unwrap_or(vec![])` is as readable as `.unwrap_or_default()`. And if the expression is a
102+
// non-empty `Vec`, then it will not be a default value anyway. Bail out in all cases.
103+
if call_expr.and_then(|call_expr| VecArgs::hir(cx, call_expr)).is_some() {
104+
return false;
105+
}
106+
100107
// needs to target Default::default in particular or be *::new and have a Default impl
101108
// available
102109
if (is_new(fun) && output_type_implements_default(fun))

tests/ui/or_fun_call.fixed

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ fn or_fun_call() {
7777
with_default_type.unwrap_or_default();
7878
//~^ unwrap_or_default
7979

80+
let with_default_literal = Some(1);
81+
with_default_literal.unwrap_or(0);
82+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
83+
84+
let with_default_literal = Some(1.0);
85+
with_default_literal.unwrap_or(0.0);
86+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
87+
88+
let with_default_literal = Some("foo");
89+
with_default_literal.unwrap_or("");
90+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
91+
92+
let with_default_vec_macro = Some(vec![1, 2, 3]);
93+
with_default_vec_macro.unwrap_or(vec![]);
94+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
95+
8096
let self_default = None::<FakeDefault>;
8197
self_default.unwrap_or_else(<FakeDefault>::default);
8298
//~^ or_fun_call

tests/ui/or_fun_call.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ fn or_fun_call() {
7777
with_default_type.unwrap_or(u64::default());
7878
//~^ unwrap_or_default
7979

80+
let with_default_literal = Some(1);
81+
with_default_literal.unwrap_or(0);
82+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
83+
84+
let with_default_literal = Some(1.0);
85+
with_default_literal.unwrap_or(0.0);
86+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
87+
88+
let with_default_literal = Some("foo");
89+
with_default_literal.unwrap_or("");
90+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
91+
92+
let with_default_vec_macro = Some(vec![1, 2, 3]);
93+
with_default_vec_macro.unwrap_or(vec![]);
94+
// Do not lint because `.unwrap_or_default()` wouldn't be simpler
95+
8096
let self_default = None::<FakeDefault>;
8197
self_default.unwrap_or(<FakeDefault>::default());
8298
//~^ or_fun_call
@@ -86,7 +102,7 @@ fn or_fun_call() {
86102
//~^ unwrap_or_default
87103

88104
let with_vec = Some(vec![1]);
89-
with_vec.unwrap_or(vec![]);
105+
with_vec.unwrap_or(Vec::new());
90106
//~^ unwrap_or_default
91107

92108
let without_default = Some(Foo);
@@ -98,15 +114,15 @@ fn or_fun_call() {
98114
//~^ unwrap_or_default
99115

100116
let mut map_vec = HashMap::<u64, Vec<i32>>::new();
101-
map_vec.entry(42).or_insert(vec![]);
117+
map_vec.entry(42).or_insert(Vec::new());
102118
//~^ unwrap_or_default
103119

104120
let mut btree = BTreeMap::<u64, String>::new();
105121
btree.entry(42).or_insert(String::new());
106122
//~^ unwrap_or_default
107123

108124
let mut btree_vec = BTreeMap::<u64, Vec<i32>>::new();
109-
btree_vec.entry(42).or_insert(vec![]);
125+
btree_vec.entry(42).or_insert(Vec::new());
110126
//~^ unwrap_or_default
111127

112128
let stringy = Some(String::new());

tests/ui/or_fun_call.stderr

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -47,175 +47,175 @@ LL | with_default_type.unwrap_or(u64::default());
4747
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
4848

4949
error: function call inside of `unwrap_or`
50-
--> tests/ui/or_fun_call.rs:81:18
50+
--> tests/ui/or_fun_call.rs:97:18
5151
|
5252
LL | self_default.unwrap_or(<FakeDefault>::default());
5353
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(<FakeDefault>::default)`
5454

5555
error: use of `unwrap_or` to construct default value
56-
--> tests/ui/or_fun_call.rs:85:18
56+
--> tests/ui/or_fun_call.rs:101:18
5757
|
5858
LL | real_default.unwrap_or(<FakeDefault as Default>::default());
5959
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
6060

6161
error: use of `unwrap_or` to construct default value
62-
--> tests/ui/or_fun_call.rs:89:14
62+
--> tests/ui/or_fun_call.rs:105:14
6363
|
64-
LL | with_vec.unwrap_or(vec![]);
65-
| ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
64+
LL | with_vec.unwrap_or(Vec::new());
65+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
6666

6767
error: function call inside of `unwrap_or`
68-
--> tests/ui/or_fun_call.rs:93:21
68+
--> tests/ui/or_fun_call.rs:109:21
6969
|
7070
LL | without_default.unwrap_or(Foo::new());
7171
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)`
7272

7373
error: use of `or_insert` to construct default value
74-
--> tests/ui/or_fun_call.rs:97:19
74+
--> tests/ui/or_fun_call.rs:113:19
7575
|
7676
LL | map.entry(42).or_insert(String::new());
7777
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
7878

7979
error: use of `or_insert` to construct default value
80-
--> tests/ui/or_fun_call.rs:101:23
80+
--> tests/ui/or_fun_call.rs:117:23
8181
|
82-
LL | map_vec.entry(42).or_insert(vec![]);
83-
| ^^^^^^^^^^^^^^^^^ help: try: `or_default()`
82+
LL | map_vec.entry(42).or_insert(Vec::new());
83+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
8484

8585
error: use of `or_insert` to construct default value
86-
--> tests/ui/or_fun_call.rs:105:21
86+
--> tests/ui/or_fun_call.rs:121:21
8787
|
8888
LL | btree.entry(42).or_insert(String::new());
8989
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
9090

9191
error: use of `or_insert` to construct default value
92-
--> tests/ui/or_fun_call.rs:109:25
92+
--> tests/ui/or_fun_call.rs:125:25
9393
|
94-
LL | btree_vec.entry(42).or_insert(vec![]);
95-
| ^^^^^^^^^^^^^^^^^ help: try: `or_default()`
94+
LL | btree_vec.entry(42).or_insert(Vec::new());
95+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
9696

9797
error: use of `unwrap_or` to construct default value
98-
--> tests/ui/or_fun_call.rs:113:21
98+
--> tests/ui/or_fun_call.rs:129:21
9999
|
100100
LL | let _ = stringy.unwrap_or(String::new());
101101
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
102102

103103
error: function call inside of `ok_or`
104-
--> tests/ui/or_fun_call.rs:118:17
104+
--> tests/ui/or_fun_call.rs:134:17
105105
|
106106
LL | let _ = opt.ok_or(format!("{} world.", hello));
107107
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ok_or_else(|| format!("{} world.", hello))`
108108

109109
error: function call inside of `unwrap_or`
110-
--> tests/ui/or_fun_call.rs:123:21
110+
--> tests/ui/or_fun_call.rs:139:21
111111
|
112112
LL | let _ = Some(1).unwrap_or(map[&1]);
113113
| ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])`
114114

115115
error: function call inside of `unwrap_or`
116-
--> tests/ui/or_fun_call.rs:126:21
116+
--> tests/ui/or_fun_call.rs:142:21
117117
|
118118
LL | let _ = Some(1).unwrap_or(map[&1]);
119119
| ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])`
120120

121121
error: function call inside of `or`
122-
--> tests/ui/or_fun_call.rs:151:35
122+
--> tests/ui/or_fun_call.rs:167:35
123123
|
124124
LL | let _ = Some("a".to_string()).or(Some("b".to_string()));
125125
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))`
126126

127127
error: function call inside of `unwrap_or`
128-
--> tests/ui/or_fun_call.rs:194:18
128+
--> tests/ui/or_fun_call.rs:210:18
129129
|
130130
LL | None.unwrap_or(ptr_to_ref(s));
131131
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))`
132132

133133
error: function call inside of `unwrap_or`
134-
--> tests/ui/or_fun_call.rs:202:14
134+
--> tests/ui/or_fun_call.rs:218:14
135135
|
136136
LL | None.unwrap_or(unsafe { ptr_to_ref(s) });
137137
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
138138

139139
error: function call inside of `unwrap_or`
140-
--> tests/ui/or_fun_call.rs:205:14
140+
--> tests/ui/or_fun_call.rs:221:14
141141
|
142142
LL | None.unwrap_or( unsafe { ptr_to_ref(s) } );
143143
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
144144

145145
error: function call inside of `map_or`
146-
--> tests/ui/or_fun_call.rs:281:25
146+
--> tests/ui/or_fun_call.rs:297:25
147147
|
148148
LL | let _ = Some(4).map_or(g(), |v| v);
149149
| ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)`
150150

151151
error: function call inside of `map_or`
152-
--> tests/ui/or_fun_call.rs:283:25
152+
--> tests/ui/or_fun_call.rs:299:25
153153
|
154154
LL | let _ = Some(4).map_or(g(), f);
155155
| ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)`
156156

157157
error: function call inside of `map_or`
158-
--> tests/ui/or_fun_call.rs:286:25
158+
--> tests/ui/or_fun_call.rs:302:25
159159
|
160160
LL | let _ = Some(4).map_or("asd".to_string().len() as i32, f);
161161
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| "asd".to_string().len() as i32, f)`
162162

163163
error: use of `unwrap_or_else` to construct default value
164-
--> tests/ui/or_fun_call.rs:317:18
164+
--> tests/ui/or_fun_call.rs:333:18
165165
|
166166
LL | with_new.unwrap_or_else(Vec::new);
167167
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
168168

169169
error: use of `unwrap_or_else` to construct default value
170-
--> tests/ui/or_fun_call.rs:321:28
170+
--> tests/ui/or_fun_call.rs:337:28
171171
|
172172
LL | with_default_trait.unwrap_or_else(Default::default);
173173
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
174174

175175
error: use of `unwrap_or_else` to construct default value
176-
--> tests/ui/or_fun_call.rs:325:27
176+
--> tests/ui/or_fun_call.rs:341:27
177177
|
178178
LL | with_default_type.unwrap_or_else(u64::default);
179179
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
180180

181181
error: use of `unwrap_or_else` to construct default value
182-
--> tests/ui/or_fun_call.rs:329:22
182+
--> tests/ui/or_fun_call.rs:345:22
183183
|
184184
LL | real_default.unwrap_or_else(<FakeDefault as Default>::default);
185185
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
186186

187187
error: use of `or_insert_with` to construct default value
188-
--> tests/ui/or_fun_call.rs:333:23
188+
--> tests/ui/or_fun_call.rs:349:23
189189
|
190190
LL | map.entry(42).or_insert_with(String::new);
191191
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
192192

193193
error: use of `or_insert_with` to construct default value
194-
--> tests/ui/or_fun_call.rs:337:25
194+
--> tests/ui/or_fun_call.rs:353:25
195195
|
196196
LL | btree.entry(42).or_insert_with(String::new);
197197
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
198198

199199
error: use of `unwrap_or_else` to construct default value
200-
--> tests/ui/or_fun_call.rs:341:25
200+
--> tests/ui/or_fun_call.rs:357:25
201201
|
202202
LL | let _ = stringy.unwrap_or_else(String::new);
203203
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
204204

205205
error: function call inside of `unwrap_or`
206-
--> tests/ui/or_fun_call.rs:383:17
206+
--> tests/ui/or_fun_call.rs:399:17
207207
|
208208
LL | let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)`
209209
| ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)`
210210

211211
error: function call inside of `unwrap_or`
212-
--> tests/ui/or_fun_call.rs:388:17
212+
--> tests/ui/or_fun_call.rs:404:17
213213
|
214214
LL | let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)`
215215
| ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)`
216216

217217
error: function call inside of `unwrap_or`
218-
--> tests/ui/or_fun_call.rs:393:17
218+
--> tests/ui/or_fun_call.rs:409:17
219219
|
220220
LL | let _ = opt.unwrap_or({
221221
| _________________^
@@ -235,55 +235,55 @@ LL ~ });
235235
|
236236

237237
error: function call inside of `map_or`
238-
--> tests/ui/or_fun_call.rs:399:17
238+
--> tests/ui/or_fun_call.rs:415:17
239239
|
240240
LL | let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)`
241241
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)`
242242

243243
error: use of `unwrap_or` to construct default value
244-
--> tests/ui/or_fun_call.rs:404:17
244+
--> tests/ui/or_fun_call.rs:420:17
245245
|
246246
LL | let _ = opt.unwrap_or({ i32::default() });
247247
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
248248

249249
error: function call inside of `unwrap_or`
250-
--> tests/ui/or_fun_call.rs:411:21
250+
--> tests/ui/or_fun_call.rs:427:21
251251
|
252252
LL | let _ = opt_foo.unwrap_or(Foo { val: String::default() });
253253
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })`
254254

255255
error: function call inside of `map_or`
256-
--> tests/ui/or_fun_call.rs:426:19
256+
--> tests/ui/or_fun_call.rs:442:19
257257
|
258258
LL | let _ = x.map_or(g(), |v| v);
259259
| ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), |v| v)`
260260

261261
error: function call inside of `map_or`
262-
--> tests/ui/or_fun_call.rs:428:19
262+
--> tests/ui/or_fun_call.rs:444:19
263263
|
264264
LL | let _ = x.map_or(g(), f);
265265
| ^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), f)`
266266

267267
error: function call inside of `map_or`
268-
--> tests/ui/or_fun_call.rs:431:19
268+
--> tests/ui/or_fun_call.rs:447:19
269269
|
270270
LL | let _ = x.map_or("asd".to_string().len() as i32, f);
271271
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|_| "asd".to_string().len() as i32, f)`
272272

273273
error: function call inside of `get_or_insert`
274-
--> tests/ui/or_fun_call.rs:442:15
274+
--> tests/ui/or_fun_call.rs:458:15
275275
|
276276
LL | let _ = x.get_or_insert(g());
277277
| ^^^^^^^^^^^^^^^^^^ help: try: `get_or_insert_with(g)`
278278

279279
error: function call inside of `and`
280-
--> tests/ui/or_fun_call.rs:452:15
280+
--> tests/ui/or_fun_call.rs:468:15
281281
|
282282
LL | let _ = x.and(g());
283283
| ^^^^^^^^ help: try: `and_then(|_| g())`
284284

285285
error: function call inside of `and`
286-
--> tests/ui/or_fun_call.rs:462:15
286+
--> tests/ui/or_fun_call.rs:478:15
287287
|
288288
LL | let _ = x.and(g());
289289
| ^^^^^^^^ help: try: `and_then(|_| g())`

0 commit comments

Comments
 (0)