- fn result_check_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>, nested_expr: &Expr<'_>) -> bool {
- Self::is_result(cx, expr) && Self::expression_returns_unmodified_err(nested_expr, expr)
- }
-
- fn option_check_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>, nested_expr: &Expr<'_>) -> bool {
- Self::is_option(cx, expr) && Self::expression_returns_none(cx, nested_expr)
- }
-
- fn moves_by_default(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
- let expr_ty = cx.typeck_results().expr_ty(expression);
-
- !expr_ty.is_copy_modulo_regions(cx.tcx.at(expression.span), cx.param_env)
- }
-
- fn is_option(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
- let expr_ty = cx.typeck_results().expr_ty(expression);
-
- is_type_diagnostic_item(cx, expr_ty, sym::Option)
- }
-
- fn is_result(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
- let expr_ty = cx.typeck_results().expr_ty(expression);
-
- is_type_diagnostic_item(cx, expr_ty, sym::Result)
- }
-
- fn expression_returns_none(cx: &LateContext<'_>, expression: &Expr<'_>) -> bool {
- match peel_blocks_with_stmt(expression).kind {
- ExprKind::Ret(Some(expr)) => Self::expression_returns_none(cx, expr),
- ExprKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
- _ => false,
- }
+fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_>) -> bool {
+ match *if_block {
+ IfBlockType::IfIs(caller, caller_ty, call_sym, if_then, _) => {
+ // If the block could be identified as `if x.is_none()/is_err()`,
+ // we then only need to check the if_then return to see if it is none/err.
+ is_type_diagnostic_item(cx, caller_ty, smbl)
+ && expr_return_none_or_err(smbl, cx, if_then, caller, None)
+ && match smbl {
+ sym::Option => call_sym == sym!(is_none),
+ sym::Result => call_sym == sym!(is_err),
+ _ => false,
+ }
+ },
+ IfBlockType::IfLet(qpath, let_expr_ty, let_pat_sym, let_expr, if_then, if_else) => {
+ is_type_diagnostic_item(cx, let_expr_ty, smbl)
+ && match smbl {
+ sym::Option => {
+ // We only need to check `if let Some(x) = option` not `if let None = option`,
+ // because the later one will be suggested as `if option.is_none()` thus causing conflict.
+ is_lang_ctor(cx, qpath, OptionSome)
+ && if_else.is_some()
+ && expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, None)
+ },
+ sym::Result => {
+ (is_lang_ctor(cx, qpath, ResultOk)
+ && if_else.is_some()
+ && expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, Some(let_pat_sym)))
+ || is_lang_ctor(cx, qpath, ResultErr)
+ && expr_return_none_or_err(smbl, cx, if_then, let_expr, Some(let_pat_sym))
+ },
+ _ => false,
+ }
+ },