Skip to content

Commit 6b71c16

Browse files
Fix question_mark FP on variables used after (#15644)
Closes #15635 changelog: [`question_mark`] fix FP on variables used after
2 parents 7a95605 + fb7e89c commit 6b71c16

File tree

4 files changed

+87
-2
lines changed

4 files changed

+87
-2
lines changed

clippy_lints/src/question_mark.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
66
use clippy_utils::msrvs::{self, Msrv};
77
use clippy_utils::source::snippet_with_applicability;
88
use clippy_utils::sugg::Sugg;
9-
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
9+
use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
10+
use clippy_utils::usage::local_used_after_expr;
1011
use clippy_utils::{
1112
eq_expr_value, fn_def_id_with_node_args, higher, is_else_clause, is_in_const_context, is_lint_allowed,
1213
is_path_lang_item, is_res_lang_ctor, pat_and_expr_can_be_question_mark, path_res, path_to_local, path_to_local_id,
@@ -483,6 +484,13 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
483484
.filter(|e| *e)
484485
.is_none()
485486
{
487+
if !is_copy(cx, caller_ty)
488+
&& let Some(hir_id) = path_to_local(let_expr)
489+
&& local_used_after_expr(cx, hir_id, expr)
490+
{
491+
return;
492+
}
493+
486494
let mut applicability = Applicability::MachineApplicable;
487495
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
488496
let requires_semi = matches!(cx.tcx.parent_hir_node(expr.hir_id), Node::Stmt(_));

tests/ui/question_mark.fixed

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,3 +475,28 @@ fn issue_15679() -> Result<i32, String> {
475475

476476
Ok(0)
477477
}
478+
479+
mod issue14894 {
480+
fn use_after_question_mark(do_something_else: impl Fn() -> Result<String, ()>) -> Result<(), ()> {
481+
let result = do_something_else();
482+
if let Err(reason) = result {
483+
return Err(reason);
484+
}
485+
drop(result);
486+
487+
let result = do_something_else();
488+
let x = result?;
489+
drop(x);
490+
491+
Ok(())
492+
}
493+
494+
#[expect(dropping_copy_types)]
495+
fn use_after_question_mark_but_is_copy(do_something_else: impl Fn() -> Result<i32, ()>) -> Result<(), ()> {
496+
let result = do_something_else();
497+
result?;
498+
drop(result);
499+
500+
Ok(())
501+
}
502+
}

tests/ui/question_mark.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,3 +583,35 @@ fn issue_15679() -> Result<i32, String> {
583583

584584
Ok(0)
585585
}
586+
587+
mod issue14894 {
588+
fn use_after_question_mark(do_something_else: impl Fn() -> Result<String, ()>) -> Result<(), ()> {
589+
let result = do_something_else();
590+
if let Err(reason) = result {
591+
return Err(reason);
592+
}
593+
drop(result);
594+
595+
let result = do_something_else();
596+
let x = match result {
597+
//~^ question_mark
598+
Ok(v) => v,
599+
Err(e) => return Err(e),
600+
};
601+
drop(x);
602+
603+
Ok(())
604+
}
605+
606+
#[expect(dropping_copy_types)]
607+
fn use_after_question_mark_but_is_copy(do_something_else: impl Fn() -> Result<i32, ()>) -> Result<(), ()> {
608+
let result = do_something_else();
609+
if let Err(reason) = result {
610+
//~^ question_mark
611+
return Err(reason);
612+
}
613+
drop(result);
614+
615+
Ok(())
616+
}
617+
}

tests/ui/question_mark.stderr

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,5 +313,25 @@ LL | | Err(err) => return Err(<&str as Into<String>>::into(err)),
313313
LL | | };
314314
| |_____^ help: try instead: `some_result?`
315315

316-
error: aborting due to 33 previous errors
316+
error: this `match` expression can be replaced with `?`
317+
--> tests/ui/question_mark.rs:596:17
318+
|
319+
LL | let x = match result {
320+
| _________________^
321+
LL | |
322+
LL | | Ok(v) => v,
323+
LL | | Err(e) => return Err(e),
324+
LL | | };
325+
| |_________^ help: try instead: `result?`
326+
327+
error: this block may be rewritten with the `?` operator
328+
--> tests/ui/question_mark.rs:609:9
329+
|
330+
LL | / if let Err(reason) = result {
331+
LL | |
332+
LL | | return Err(reason);
333+
LL | | }
334+
| |_________^ help: replace it with: `result?;`
335+
336+
error: aborting due to 35 previous errors
317337

0 commit comments

Comments
 (0)