Skip to content

Commit 5262ab2

Browse files
Fix unnecessary_unwrap emitted twice in closure (#14763) (#14770)
The problem is that `check_fn` is triggered by both function and closure, and `visit_expr` can visit expressions in another closures within a function or closure. So just skip walking in a inner closure. changelog: Fix [`unnecessary_unwrap`] emitted twice in closure which inside in a function or another closure. Fixes: #14763
2 parents 3c5e403 + e61886a commit 5262ab2

File tree

3 files changed

+89
-1
lines changed

3 files changed

+89
-1
lines changed

clippy_lints/src/unwrap.rs

+4
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ impl<'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'_, 'tcx> {
292292
if expr.span.in_external_macro(self.cx.tcx.sess.source_map()) {
293293
return;
294294
}
295+
// Skip checking inside closures since they are visited through `Unwrap::check_fn()` already.
296+
if matches!(expr.kind, ExprKind::Closure(_)) {
297+
return;
298+
}
295299
if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr) {
296300
walk_expr(self, cond);
297301
self.visit_branch(expr, cond, then, false);

tests/ui/checked_unwrap/simple_conditionals.rs

+33
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,39 @@ fn issue14725() {
240240
}
241241
}
242242

243+
fn issue14763(x: Option<String>, r: Result<(), ()>) {
244+
_ = || {
245+
if x.is_some() {
246+
_ = x.unwrap();
247+
//~^ unnecessary_unwrap
248+
} else {
249+
_ = x.unwrap();
250+
//~^ panicking_unwrap
251+
}
252+
};
253+
_ = || {
254+
if r.is_ok() {
255+
_ = r.as_ref().unwrap();
256+
//~^ unnecessary_unwrap
257+
} else {
258+
_ = r.as_ref().unwrap();
259+
//~^ panicking_unwrap
260+
}
261+
};
262+
}
263+
264+
const ISSUE14763: fn(Option<String>) = |x| {
265+
_ = || {
266+
if x.is_some() {
267+
_ = x.unwrap();
268+
//~^ unnecessary_unwrap
269+
} else {
270+
_ = x.unwrap();
271+
//~^ panicking_unwrap
272+
}
273+
}
274+
};
275+
243276
fn check_expect() {
244277
let x = Some(());
245278
if x.is_some() {

tests/ui/checked_unwrap/simple_conditionals.stderr

+52-1
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,57 @@ LL | if result.is_ok() {
271271
LL | result.as_ref().unwrap();
272272
| ^^^^^^^^^^^^^^^^^^^^^^^^
273273

274+
error: called `unwrap` on `x` after checking its variant with `is_some`
275+
--> tests/ui/checked_unwrap/simple_conditionals.rs:246:17
276+
|
277+
LL | if x.is_some() {
278+
| -------------- help: try: `if let Some(<item>) = x`
279+
LL | _ = x.unwrap();
280+
| ^^^^^^^^^^
281+
282+
error: this call to `unwrap()` will always panic
283+
--> tests/ui/checked_unwrap/simple_conditionals.rs:249:17
284+
|
285+
LL | if x.is_some() {
286+
| ----------- because of this check
287+
...
288+
LL | _ = x.unwrap();
289+
| ^^^^^^^^^^
290+
291+
error: called `unwrap` on `r` after checking its variant with `is_ok`
292+
--> tests/ui/checked_unwrap/simple_conditionals.rs:255:17
293+
|
294+
LL | if r.is_ok() {
295+
| ------------ help: try: `if let Ok(<item>) = &r`
296+
LL | _ = r.as_ref().unwrap();
297+
| ^^^^^^^^^^^^^^^^^^^
298+
299+
error: this call to `unwrap()` will always panic
300+
--> tests/ui/checked_unwrap/simple_conditionals.rs:258:17
301+
|
302+
LL | if r.is_ok() {
303+
| --------- because of this check
304+
...
305+
LL | _ = r.as_ref().unwrap();
306+
| ^^^^^^^^^^^^^^^^^^^
307+
308+
error: called `unwrap` on `x` after checking its variant with `is_some`
309+
--> tests/ui/checked_unwrap/simple_conditionals.rs:267:17
310+
|
311+
LL | if x.is_some() {
312+
| -------------- help: try: `if let Some(<item>) = x`
313+
LL | _ = x.unwrap();
314+
| ^^^^^^^^^^
315+
316+
error: this call to `unwrap()` will always panic
317+
--> tests/ui/checked_unwrap/simple_conditionals.rs:270:17
318+
|
319+
LL | if x.is_some() {
320+
| ----------- because of this check
321+
...
322+
LL | _ = x.unwrap();
323+
| ^^^^^^^^^^
324+
274325
error: creating a shared reference to mutable static
275326
--> tests/ui/checked_unwrap/simple_conditionals.rs:183:12
276327
|
@@ -281,5 +332,5 @@ LL | if X.is_some() {
281332
= note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
282333
= note: `#[deny(static_mut_refs)]` on by default
283334

284-
error: aborting due to 30 previous errors
335+
error: aborting due to 36 previous errors
285336

0 commit comments

Comments
 (0)