Skip to content

Commit 49661ce

Browse files
committed
[unnecessary_lazy_evaluations] Do not suggest switching to early evaluation when type has custom Drop
1 parent 8845f82 commit 49661ce

File tree

4 files changed

+69
-36
lines changed

4 files changed

+69
-36
lines changed

clippy_utils/src/eager_or_lazy.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,17 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
113113
},
114114
args,
115115
) => match self.cx.qpath_res(path, hir_id) {
116-
Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => (),
116+
Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => {
117+
if self
118+
.cx
119+
.typeck_results()
120+
.expr_ty(e)
121+
.has_significant_drop(self.cx.tcx, self.cx.param_env)
122+
{
123+
self.eagerness = Lazy;
124+
return;
125+
}
126+
},
117127
Res::Def(_, id) if self.cx.tcx.is_promotable_const_fn(id) => (),
118128
// No need to walk the arguments here, `is_const_evaluatable` already did
119129
Res::Def(..) if is_const_evaluatable(self.cx, e) => {

tests/ui/unnecessary_lazy_eval.fixed

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ fn some_call<T: Default>() -> T {
2121
T::default()
2222
}
2323

24+
struct Issue9427(i32);
25+
26+
impl Drop for Issue9427 {
27+
fn drop(&mut self) {
28+
println!("{}", self.0);
29+
}
30+
}
31+
32+
2433
fn main() {
2534
let astronomers_pi = 10;
2635
let ext_arr: [usize; 1] = [2];
@@ -73,6 +82,9 @@ fn main() {
7382
let _ = deep.0.or_else(|| some_call());
7483
let _ = opt.ok_or_else(|| ext_arr[0]);
7584

85+
// Should not lint - bool
86+
let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
87+
7688
// should not lint, bind_instead_of_map takes priority
7789
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
7890
let _ = Some(10).and_then(|idx| Some(idx));
@@ -129,4 +141,4 @@ fn main() {
129141
// neither bind_instead_of_map nor unnecessary_lazy_eval applies here
130142
let _: Result<usize, usize> = res.and_then(|x| Err(x));
131143
let _: Result<usize, usize> = res.or_else(|err| Ok(err));
132-
}
144+
}

tests/ui/unnecessary_lazy_eval.rs

+11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ fn some_call<T: Default>() -> T {
2121
T::default()
2222
}
2323

24+
struct Issue9427(i32);
25+
26+
impl Drop for Issue9427 {
27+
fn drop(&mut self) {
28+
println!("{}", self.0);
29+
}
30+
}
31+
2432
fn main() {
2533
let astronomers_pi = 10;
2634
let ext_arr: [usize; 1] = [2];
@@ -73,6 +81,9 @@ fn main() {
7381
let _ = deep.0.or_else(|| some_call());
7482
let _ = opt.ok_or_else(|| ext_arr[0]);
7583

84+
// Should not lint - bool
85+
let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
86+
7687
// should not lint, bind_instead_of_map takes priority
7788
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
7889
let _ = Some(10).and_then(|idx| Some(idx));

tests/ui/unnecessary_lazy_eval.stderr

+34-34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unnecessary closure used to substitute value for `Option::None`
2-
--> $DIR/unnecessary_lazy_eval.rs:36:13
2+
--> $DIR/unnecessary_lazy_eval.rs:45:13
33
|
44
LL | let _ = opt.unwrap_or_else(|| 2);
55
| ^^^^--------------------
@@ -9,263 +9,263 @@ LL | let _ = opt.unwrap_or_else(|| 2);
99
= note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
1010

1111
error: unnecessary closure used to substitute value for `Option::None`
12-
--> $DIR/unnecessary_lazy_eval.rs:37:13
12+
--> $DIR/unnecessary_lazy_eval.rs:46:13
1313
|
1414
LL | let _ = opt.unwrap_or_else(|| astronomers_pi);
1515
| ^^^^---------------------------------
1616
| |
1717
| help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
1818

1919
error: unnecessary closure used to substitute value for `Option::None`
20-
--> $DIR/unnecessary_lazy_eval.rs:38:13
20+
--> $DIR/unnecessary_lazy_eval.rs:47:13
2121
|
2222
LL | let _ = opt.unwrap_or_else(|| ext_str.some_field);
2323
| ^^^^-------------------------------------
2424
| |
2525
| help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
2626

2727
error: unnecessary closure used to substitute value for `Option::None`
28-
--> $DIR/unnecessary_lazy_eval.rs:40:13
28+
--> $DIR/unnecessary_lazy_eval.rs:49:13
2929
|
3030
LL | let _ = opt.and_then(|_| ext_opt);
3131
| ^^^^---------------------
3232
| |
3333
| help: use `and(..)` instead: `and(ext_opt)`
3434

3535
error: unnecessary closure used to substitute value for `Option::None`
36-
--> $DIR/unnecessary_lazy_eval.rs:41:13
36+
--> $DIR/unnecessary_lazy_eval.rs:50:13
3737
|
3838
LL | let _ = opt.or_else(|| ext_opt);
3939
| ^^^^-------------------
4040
| |
4141
| help: use `or(..)` instead: `or(ext_opt)`
4242

4343
error: unnecessary closure used to substitute value for `Option::None`
44-
--> $DIR/unnecessary_lazy_eval.rs:42:13
44+
--> $DIR/unnecessary_lazy_eval.rs:51:13
4545
|
4646
LL | let _ = opt.or_else(|| None);
4747
| ^^^^----------------
4848
| |
4949
| help: use `or(..)` instead: `or(None)`
5050

5151
error: unnecessary closure used to substitute value for `Option::None`
52-
--> $DIR/unnecessary_lazy_eval.rs:43:13
52+
--> $DIR/unnecessary_lazy_eval.rs:52:13
5353
|
5454
LL | let _ = opt.get_or_insert_with(|| 2);
5555
| ^^^^------------------------
5656
| |
5757
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
5858

5959
error: unnecessary closure used to substitute value for `Option::None`
60-
--> $DIR/unnecessary_lazy_eval.rs:44:13
60+
--> $DIR/unnecessary_lazy_eval.rs:53:13
6161
|
6262
LL | let _ = opt.ok_or_else(|| 2);
6363
| ^^^^----------------
6464
| |
6565
| help: use `ok_or(..)` instead: `ok_or(2)`
6666

6767
error: unnecessary closure used to substitute value for `Option::None`
68-
--> $DIR/unnecessary_lazy_eval.rs:45:13
68+
--> $DIR/unnecessary_lazy_eval.rs:54:13
6969
|
7070
LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
7171
| ^^^^^^^^^^^^^^^^^-------------------------------
7272
| |
7373
| help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
7474

7575
error: unnecessary closure used with `bool::then`
76-
--> $DIR/unnecessary_lazy_eval.rs:46:13
76+
--> $DIR/unnecessary_lazy_eval.rs:55:13
7777
|
7878
LL | let _ = cond.then(|| astronomers_pi);
7979
| ^^^^^-----------------------
8080
| |
8181
| help: use `then_some(..)` instead: `then_some(astronomers_pi)`
8282

8383
error: unnecessary closure used to substitute value for `Option::None`
84-
--> $DIR/unnecessary_lazy_eval.rs:49:13
84+
--> $DIR/unnecessary_lazy_eval.rs:58:13
8585
|
8686
LL | let _ = Some(10).unwrap_or_else(|| 2);
8787
| ^^^^^^^^^--------------------
8888
| |
8989
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
9090

9191
error: unnecessary closure used to substitute value for `Option::None`
92-
--> $DIR/unnecessary_lazy_eval.rs:50:13
92+
--> $DIR/unnecessary_lazy_eval.rs:59:13
9393
|
9494
LL | let _ = Some(10).and_then(|_| ext_opt);
9595
| ^^^^^^^^^---------------------
9696
| |
9797
| help: use `and(..)` instead: `and(ext_opt)`
9898

9999
error: unnecessary closure used to substitute value for `Option::None`
100-
--> $DIR/unnecessary_lazy_eval.rs:51:28
100+
--> $DIR/unnecessary_lazy_eval.rs:60:28
101101
|
102102
LL | let _: Option<usize> = None.or_else(|| ext_opt);
103103
| ^^^^^-------------------
104104
| |
105105
| help: use `or(..)` instead: `or(ext_opt)`
106106

107107
error: unnecessary closure used to substitute value for `Option::None`
108-
--> $DIR/unnecessary_lazy_eval.rs:52:13
108+
--> $DIR/unnecessary_lazy_eval.rs:61:13
109109
|
110110
LL | let _ = None.get_or_insert_with(|| 2);
111111
| ^^^^^------------------------
112112
| |
113113
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
114114

115115
error: unnecessary closure used to substitute value for `Option::None`
116-
--> $DIR/unnecessary_lazy_eval.rs:53:35
116+
--> $DIR/unnecessary_lazy_eval.rs:62:35
117117
|
118118
LL | let _: Result<usize, usize> = None.ok_or_else(|| 2);
119119
| ^^^^^----------------
120120
| |
121121
| help: use `ok_or(..)` instead: `ok_or(2)`
122122

123123
error: unnecessary closure used to substitute value for `Option::None`
124-
--> $DIR/unnecessary_lazy_eval.rs:54:28
124+
--> $DIR/unnecessary_lazy_eval.rs:63:28
125125
|
126126
LL | let _: Option<usize> = None.or_else(|| None);
127127
| ^^^^^----------------
128128
| |
129129
| help: use `or(..)` instead: `or(None)`
130130

131131
error: unnecessary closure used to substitute value for `Option::None`
132-
--> $DIR/unnecessary_lazy_eval.rs:57:13
132+
--> $DIR/unnecessary_lazy_eval.rs:66:13
133133
|
134134
LL | let _ = deep.0.unwrap_or_else(|| 2);
135135
| ^^^^^^^--------------------
136136
| |
137137
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
138138

139139
error: unnecessary closure used to substitute value for `Option::None`
140-
--> $DIR/unnecessary_lazy_eval.rs:58:13
140+
--> $DIR/unnecessary_lazy_eval.rs:67:13
141141
|
142142
LL | let _ = deep.0.and_then(|_| ext_opt);
143143
| ^^^^^^^---------------------
144144
| |
145145
| help: use `and(..)` instead: `and(ext_opt)`
146146

147147
error: unnecessary closure used to substitute value for `Option::None`
148-
--> $DIR/unnecessary_lazy_eval.rs:59:13
148+
--> $DIR/unnecessary_lazy_eval.rs:68:13
149149
|
150150
LL | let _ = deep.0.or_else(|| None);
151151
| ^^^^^^^----------------
152152
| |
153153
| help: use `or(..)` instead: `or(None)`
154154

155155
error: unnecessary closure used to substitute value for `Option::None`
156-
--> $DIR/unnecessary_lazy_eval.rs:60:13
156+
--> $DIR/unnecessary_lazy_eval.rs:69:13
157157
|
158158
LL | let _ = deep.0.get_or_insert_with(|| 2);
159159
| ^^^^^^^------------------------
160160
| |
161161
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
162162

163163
error: unnecessary closure used to substitute value for `Option::None`
164-
--> $DIR/unnecessary_lazy_eval.rs:61:13
164+
--> $DIR/unnecessary_lazy_eval.rs:70:13
165165
|
166166
LL | let _ = deep.0.ok_or_else(|| 2);
167167
| ^^^^^^^----------------
168168
| |
169169
| help: use `ok_or(..)` instead: `ok_or(2)`
170170

171171
error: unnecessary closure used to substitute value for `Option::None`
172-
--> $DIR/unnecessary_lazy_eval.rs:81:28
172+
--> $DIR/unnecessary_lazy_eval.rs:93:28
173173
|
174174
LL | let _: Option<usize> = None.or_else(|| Some(3));
175175
| ^^^^^-------------------
176176
| |
177177
| help: use `or(..)` instead: `or(Some(3))`
178178

179179
error: unnecessary closure used to substitute value for `Option::None`
180-
--> $DIR/unnecessary_lazy_eval.rs:82:13
180+
--> $DIR/unnecessary_lazy_eval.rs:94:13
181181
|
182182
LL | let _ = deep.0.or_else(|| Some(3));
183183
| ^^^^^^^-------------------
184184
| |
185185
| help: use `or(..)` instead: `or(Some(3))`
186186

187187
error: unnecessary closure used to substitute value for `Option::None`
188-
--> $DIR/unnecessary_lazy_eval.rs:83:13
188+
--> $DIR/unnecessary_lazy_eval.rs:95:13
189189
|
190190
LL | let _ = opt.or_else(|| Some(3));
191191
| ^^^^-------------------
192192
| |
193193
| help: use `or(..)` instead: `or(Some(3))`
194194

195195
error: unnecessary closure used to substitute value for `Result::Err`
196-
--> $DIR/unnecessary_lazy_eval.rs:89:13
196+
--> $DIR/unnecessary_lazy_eval.rs:101:13
197197
|
198198
LL | let _ = res2.unwrap_or_else(|_| 2);
199199
| ^^^^^---------------------
200200
| |
201201
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
202202

203203
error: unnecessary closure used to substitute value for `Result::Err`
204-
--> $DIR/unnecessary_lazy_eval.rs:90:13
204+
--> $DIR/unnecessary_lazy_eval.rs:102:13
205205
|
206206
LL | let _ = res2.unwrap_or_else(|_| astronomers_pi);
207207
| ^^^^^----------------------------------
208208
| |
209209
| help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
210210

211211
error: unnecessary closure used to substitute value for `Result::Err`
212-
--> $DIR/unnecessary_lazy_eval.rs:91:13
212+
--> $DIR/unnecessary_lazy_eval.rs:103:13
213213
|
214214
LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field);
215215
| ^^^^^--------------------------------------
216216
| |
217217
| help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
218218

219219
error: unnecessary closure used to substitute value for `Result::Err`
220-
--> $DIR/unnecessary_lazy_eval.rs:113:35
220+
--> $DIR/unnecessary_lazy_eval.rs:125:35
221221
|
222222
LL | let _: Result<usize, usize> = res.and_then(|_| Err(2));
223223
| ^^^^--------------------
224224
| |
225225
| help: use `and(..)` instead: `and(Err(2))`
226226

227227
error: unnecessary closure used to substitute value for `Result::Err`
228-
--> $DIR/unnecessary_lazy_eval.rs:114:35
228+
--> $DIR/unnecessary_lazy_eval.rs:126:35
229229
|
230230
LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
231231
| ^^^^---------------------------------
232232
| |
233233
| help: use `and(..)` instead: `and(Err(astronomers_pi))`
234234

235235
error: unnecessary closure used to substitute value for `Result::Err`
236-
--> $DIR/unnecessary_lazy_eval.rs:115:35
236+
--> $DIR/unnecessary_lazy_eval.rs:127:35
237237
|
238238
LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
239239
| ^^^^-------------------------------------
240240
| |
241241
| help: use `and(..)` instead: `and(Err(ext_str.some_field))`
242242

243243
error: unnecessary closure used to substitute value for `Result::Err`
244-
--> $DIR/unnecessary_lazy_eval.rs:117:35
244+
--> $DIR/unnecessary_lazy_eval.rs:129:35
245245
|
246246
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2));
247247
| ^^^^------------------
248248
| |
249249
| help: use `or(..)` instead: `or(Ok(2))`
250250

251251
error: unnecessary closure used to substitute value for `Result::Err`
252-
--> $DIR/unnecessary_lazy_eval.rs:118:35
252+
--> $DIR/unnecessary_lazy_eval.rs:130:35
253253
|
254254
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
255255
| ^^^^-------------------------------
256256
| |
257257
| help: use `or(..)` instead: `or(Ok(astronomers_pi))`
258258

259259
error: unnecessary closure used to substitute value for `Result::Err`
260-
--> $DIR/unnecessary_lazy_eval.rs:119:35
260+
--> $DIR/unnecessary_lazy_eval.rs:131:35
261261
|
262262
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
263263
| ^^^^-----------------------------------
264264
| |
265265
| help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
266266

267267
error: unnecessary closure used to substitute value for `Result::Err`
268-
--> $DIR/unnecessary_lazy_eval.rs:120:35
268+
--> $DIR/unnecessary_lazy_eval.rs:132:35
269269
|
270270
LL | let _: Result<usize, usize> = res.
271271
| ___________________________________^

0 commit comments

Comments
 (0)