From 5377dbaa5566df843a98fc08e817bb819aea160f Mon Sep 17 00:00:00 2001 From: irelaxcn Date: Wed, 3 Dec 2025 02:27:07 +0800 Subject: [PATCH] Fix `if_then_some_else_none` FP when the `then` block contains await codes --- clippy_lints/src/if_then_some_else_none.rs | 7 +++---- clippy_utils/src/ty/mod.rs | 2 +- tests/ui/if_then_some_else_none.fixed | 10 ++++++++++ tests/ui/if_then_some_else_none.rs | 10 ++++++++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/if_then_some_else_none.rs b/clippy_lints/src/if_then_some_else_none.rs index 7f3ef58c93d1..533d4308af74 100644 --- a/clippy_lints/src/if_then_some_else_none.rs +++ b/clippy_lints/src/if_then_some_else_none.rs @@ -5,8 +5,8 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context, walk_span_to_context}; use clippy_utils::sugg::Sugg; use clippy_utils::{ - as_some_expr, contains_return, expr_adjustment_requires_coercion, higher, is_else_clause, is_in_const_context, - is_none_expr, peel_blocks, sym, + as_some_expr, can_move_expr_to_closure, expr_adjustment_requires_coercion, higher, is_else_clause, + is_in_const_context, is_none_expr, peel_blocks, sym, }; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; @@ -76,8 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone { && !is_else_clause(cx.tcx, expr) && !is_in_const_context(cx) && self.msrv.meets(cx, msrvs::BOOL_THEN) - && !contains_return(then_block.stmts) - && then_block.expr.is_none_or(|expr| !contains_return(expr)) + && can_move_expr_to_closure(cx, then).is_some() { let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(cx, msrvs::BOOL_THEN_SOME) { sym::then_some diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index a90d64e972c1..4dff0a044708 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -65,7 +65,7 @@ pub fn can_partially_move_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool return false; } match ty.kind() { - ty::Param(_) => false, + ty::Param(_) | ty::Ref(..) => false, ty::Adt(def, subs) => def.all_fields().any(|f| !is_copy(cx, f.ty(cx.tcx, subs))), _ => true, } diff --git a/tests/ui/if_then_some_else_none.fixed b/tests/ui/if_then_some_else_none.fixed index 7da9401a308f..9d4cbe6baf07 100644 --- a/tests/ui/if_then_some_else_none.fixed +++ b/tests/ui/if_then_some_else_none.fixed @@ -218,3 +218,13 @@ mod issue15770 { Ok(()) } } + +mod issue16176 { + pub async fn foo() -> u32 { + todo!() + } + + pub async fn bar(cond: bool) -> Option { + if cond { Some(foo().await) } else { None } // OK + } +} diff --git a/tests/ui/if_then_some_else_none.rs b/tests/ui/if_then_some_else_none.rs index 02962f83ce8a..6b1ece61e775 100644 --- a/tests/ui/if_then_some_else_none.rs +++ b/tests/ui/if_then_some_else_none.rs @@ -274,3 +274,13 @@ mod issue15770 { Ok(()) } } + +mod issue16176 { + pub async fn foo() -> u32 { + todo!() + } + + pub async fn bar(cond: bool) -> Option { + if cond { Some(foo().await) } else { None } // OK + } +}