diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs
index 899568a933f..f0155ed6051 100644
--- a/clippy_lints/src/question_mark.rs
+++ b/clippy_lints/src/question_mark.rs
@@ -1,16 +1,19 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{eq_expr_value, is_lang_ctor, path_to_local, path_to_local_id, peel_blocks, peel_blocks_with_stmt};
+use clippy_utils::{
+    eq_expr_value, get_parent_node, is_else_clause, is_lang_ctor, path_to_local, path_to_local_id, peel_blocks,
+    peel_blocks_with_stmt,
+};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionNone, OptionSome, ResultOk};
-use rustc_hir::{BindingAnnotation, Expr, ExprKind, PatKind};
+use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::{BindingAnnotation, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
+use rustc_span::{sym, symbol::Symbol};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -39,135 +42,190 @@ declare_clippy_lint! {
 
 declare_lint_pass!(QuestionMark => [QUESTION_MARK]);
 
-impl QuestionMark {
-    /// Checks if the given expression on the given context matches the following structure:
+enum IfBlockType<'hir> {
+    /// An `if x.is_xxx() { a } else { b } ` expression.
     ///
-    /// ```ignore
-    /// if option.is_none() {
-    ///    return None;
-    /// }
-    /// ```
+    /// Contains: caller (x), caller_type, call_sym (is_xxx), if_then (a), if_else (b)
+    IfIs(
+        &'hir Expr<'hir>,
+        Ty<'hir>,
+        Symbol,
+        &'hir Expr<'hir>,
+        Option<&'hir Expr<'hir>>,
+    ),
+    /// An `if let Xxx(a) = b { c } else { d }` expression.
     ///
-    /// ```ignore
-    /// if result.is_err() {
-    ///     return result;
-    /// }
-    /// ```
-    ///
-    /// If it matches, it will suggest to use the question mark operator instead
-    fn check_is_none_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if_chain! {
-            if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
-            if let ExprKind::MethodCall(segment, args, _) = &cond.kind;
-            if let Some(subject) = args.get(0);
-            if (Self::option_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_none)) ||
-                (Self::result_check_and_early_return(cx, subject, then) && segment.ident.name == sym!(is_err));
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let receiver_str = &Sugg::hir_with_applicability(cx, subject, "..", &mut applicability);
-                let mut replacement: Option<String> = None;
-                if let Some(else_inner) = r#else {
-                    if eq_expr_value(cx, subject, peel_blocks(else_inner)) {
-                        replacement = Some(format!("Some({}?)", receiver_str));
-                    }
-                } else if Self::moves_by_default(cx, subject)
-                    && !matches!(subject.kind, ExprKind::Call(..) | ExprKind::MethodCall(..))
-                {
-                    replacement = Some(format!("{}.as_ref()?;", receiver_str));
+    /// Contains: let_pat_qpath (Xxx), let_pat_type, let_pat_sym (a), let_expr (b), if_then (c),
+    /// if_else (d)
+    IfLet(
+        &'hir QPath<'hir>,
+        Ty<'hir>,
+        Symbol,
+        &'hir Expr<'hir>,
+        &'hir Expr<'hir>,
+        Option<&'hir Expr<'hir>>,
+    ),
+}
+
+/// Checks if the given expression on the given context matches the following structure:
+///
+/// ```ignore
+/// if option.is_none() {
+///    return None;
+/// }
+/// ```
+///
+/// ```ignore
+/// if result.is_err() {
+///     return result;
+/// }
+/// ```
+///
+/// If it matches, it will suggest to use the question mark operator instead
+fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+    if_chain! {
+        if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr);
+        if !is_else_clause(cx.tcx, expr);
+        if let ExprKind::MethodCall(segment, args, _) = &cond.kind;
+        if let Some(caller) = args.get(0);
+        let caller_ty = cx.typeck_results().expr_ty(caller);
+        let if_block = IfBlockType::IfIs(caller, caller_ty, segment.ident.name, then, r#else);
+        if is_early_return(sym::Option, cx, &if_block) || is_early_return(sym::Result, cx, &if_block);
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+            let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
+            let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx.at(caller.span), cx.param_env) &&
+                !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
+            let sugg = if let Some(else_inner) = r#else {
+                if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
+                    format!("Some({}?)", receiver_str)
                 } else {
-                    replacement = Some(format!("{}?;", receiver_str));
+                    return;
                 }
+            } else {
+                format!("{}{}?;", receiver_str, if by_ref { ".as_ref()" } else { "" })
+            };
 
-                if let Some(replacement_str) = replacement {
-                    span_lint_and_sugg(
-                        cx,
-                        QUESTION_MARK,
-                        expr.span,
-                        "this block may be rewritten with the `?` operator",
-                        "replace it with",
-                        replacement_str,
-                        applicability,
-                    );
-                }
-            }
+            span_lint_and_sugg(
+                cx,
+                QUESTION_MARK,
+                expr.span,
+                "this block may be rewritten with the `?` operator",
+                "replace it with",
+                sugg,
+                applicability,
+            );
         }
     }
+}
 
-    fn check_if_let_some_or_err_and_early_return(cx: &LateContext<'_>, expr: &Expr<'_>) {
-        if_chain! {
-            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) })
-                = higher::IfLet::hir(cx, expr);
-            if let PatKind::TupleStruct(ref path1, fields, None) = let_pat.kind;
-            if (Self::option_check_and_early_return(cx, let_expr, if_else) && is_lang_ctor(cx, path1, OptionSome)) ||
-                (Self::result_check_and_early_return(cx, let_expr, if_else) && is_lang_ctor(cx, path1, ResultOk));
-
-            if let PatKind::Binding(annot, bind_id, _, _) = fields[0].kind;
+fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+    if_chain! {
+        if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else }) = higher::IfLet::hir(cx, expr);
+        if !is_else_clause(cx.tcx, expr);
+        if let PatKind::TupleStruct(ref path1, fields, None) = let_pat.kind;
+        if let PatKind::Binding(annot, bind_id, ident, _) = fields[0].kind;
+        let caller_ty = cx.typeck_results().expr_ty(let_expr);
+        let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
+        if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
+            || is_early_return(sym::Result, cx, &if_block);
+        if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none();
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+            let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
             let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);
-            if path_to_local_id(peel_blocks(if_then), bind_id);
-            then {
-                let mut applicability = Applicability::MachineApplicable;
-                let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
-                let replacement = format!("{}{}?", receiver_str, if by_ref { ".as_ref()" } else { "" },);
+            let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
+            let sugg = format!(
+                "{}{}?{}",
+                receiver_str,
+                if by_ref { ".as_ref()" } else { "" },
+                if requires_semi { ";" } else { "" }
+            );
+            span_lint_and_sugg(
+                cx,
+                QUESTION_MARK,
+                expr.span,
+                "this block may be rewritten with the `?` operator",
+                "replace it with",
+                sugg,
+                applicability,
+            );
+        }
+    }
+}
 
-                span_lint_and_sugg(
-                    cx,
-                    QUESTION_MARK,
-                    expr.span,
-                    "this if-let-else may be rewritten with the `?` operator",
-                    "replace it with",
-                    replacement,
-                    applicability,
-                );
+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,
+                }
+        },
+    }
+}
+
+fn expr_return_none_or_err(
+    smbl: Symbol,
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    cond_expr: &Expr<'_>,
+    err_sym: Option<Symbol>,
+) -> bool {
+    match peel_blocks_with_stmt(expr).kind {
+        ExprKind::Ret(Some(ret_expr)) => expr_return_none_or_err(smbl, cx, ret_expr, cond_expr, err_sym),
+        ExprKind::Path(ref qpath) => match smbl {
+            sym::Option => is_lang_ctor(cx, qpath, OptionNone),
+            sym::Result => path_to_local(expr).is_some() && path_to_local(expr) == path_to_local(cond_expr),
+            _ => false,
+        },
+        ExprKind::Call(call_expr, args_expr) => {
+            if_chain! {
+                if smbl == sym::Result;
+                if let ExprKind::Path(QPath::Resolved(_, path)) = &call_expr.kind;
+                if let Some(segment) = path.segments.first();
+                if let Some(err_sym) = err_sym;
+                if let Some(arg) = args_expr.first();
+                if let ExprKind::Path(QPath::Resolved(_, arg_path)) = &arg.kind;
+                if let Some(PathSegment { ident, .. }) = arg_path.segments.first();
+                then {
+                    return segment.ident.name == sym::Err && err_sym == ident.name;
+                }
             }
-        }
-    }
-
-    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 expression_returns_unmodified_err(expr: &Expr<'_>, cond_expr: &Expr<'_>) -> bool {
-        match peel_blocks_with_stmt(expr).kind {
-            ExprKind::Ret(Some(ret_expr)) => Self::expression_returns_unmodified_err(ret_expr, cond_expr),
-            ExprKind::Path(_) => path_to_local(expr).is_some() && path_to_local(expr) == path_to_local(cond_expr),
-            _ => false,
-        }
+            false
+        },
+        _ => false,
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for QuestionMark {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        Self::check_is_none_or_err_and_early_return(cx, expr);
-        Self::check_if_let_some_or_err_and_early_return(cx, expr);
+        check_is_none_or_err_and_early_return(cx, expr);
+        check_if_let_some_or_err_and_early_return(cx, expr);
     }
 }
diff --git a/tests/ui/needless_match.fixed b/tests/ui/needless_match.fixed
index b997e5316cf..0c9178fb85e 100644
--- a/tests/ui/needless_match.fixed
+++ b/tests/ui/needless_match.fixed
@@ -99,6 +99,7 @@ fn if_let_result() {
     let _: Result<i32, i32> = x;
     let _: Result<i32, i32> = x;
     // Input type mismatch, don't trigger
+    #[allow(clippy::question_mark)]
     let _: Result<i32, i32> = if let Err(e) = Ok(1) { Err(e) } else { x };
 }
 
diff --git a/tests/ui/needless_match.rs b/tests/ui/needless_match.rs
index 90482775a1e..f66f01d7cca 100644
--- a/tests/ui/needless_match.rs
+++ b/tests/ui/needless_match.rs
@@ -122,6 +122,7 @@ fn if_let_result() {
     let _: Result<i32, i32> = if let Err(e) = x { Err(e) } else { x };
     let _: Result<i32, i32> = if let Ok(val) = x { Ok(val) } else { x };
     // Input type mismatch, don't trigger
+    #[allow(clippy::question_mark)]
     let _: Result<i32, i32> = if let Err(e) = Ok(1) { Err(e) } else { x };
 }
 
diff --git a/tests/ui/needless_match.stderr b/tests/ui/needless_match.stderr
index 2d679631c6f..5bc79800a1a 100644
--- a/tests/ui/needless_match.stderr
+++ b/tests/ui/needless_match.stderr
@@ -84,7 +84,7 @@ LL |     let _: Result<i32, i32> = if let Ok(val) = x { Ok(val) } else { x };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x`
 
 error: this if-let expression is unnecessary
-  --> $DIR/needless_match.rs:129:21
+  --> $DIR/needless_match.rs:130:21
    |
 LL |       let _: Simple = if let Simple::A = x {
    |  _____________________^
@@ -97,7 +97,7 @@ LL | |     };
    | |_____^ help: replace it with: `x`
 
 error: this match expression is unnecessary
-  --> $DIR/needless_match.rs:168:26
+  --> $DIR/needless_match.rs:169:26
    |
 LL |           let _: Complex = match ce {
    |  __________________________^
diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed
index 13ce0f32d4b..c4c9c821433 100644
--- a/tests/ui/question_mark.fixed
+++ b/tests/ui/question_mark.fixed
@@ -1,5 +1,6 @@
 // run-rustfix
 #![allow(unreachable_code)]
+#![allow(dead_code)]
 #![allow(clippy::unnecessary_wraps)]
 
 fn some_func(a: Option<u32>) -> Option<u32> {
@@ -154,26 +155,56 @@ fn f() -> NotOption {
     NotOption::First
 }
 
-fn main() {
-    some_func(Some(42));
-    some_func(None);
-    some_other_func(Some(42));
+fn do_something() {}
 
-    let copy_struct = CopyStruct { opt: Some(54) };
-    copy_struct.func();
-
-    let move_struct = MoveStruct {
-        opt: Some(vec![42, 1337]),
-    };
-    move_struct.ref_func();
-    move_struct.clone().mov_func_reuse();
-    move_struct.mov_func_no_use();
-
-    let so = SeemsOption::Some(45);
-    returns_something_similar_to_option(so);
-
-    func();
-
-    let _ = result_func(Ok(42));
-    let _ = f();
+fn err_immediate_return() -> Result<i32, i32> {
+    func_returning_result()?;
+    Ok(1)
 }
+
+fn err_immediate_return_and_do_something() -> Result<i32, i32> {
+    func_returning_result()?;
+    do_something();
+    Ok(1)
+}
+
+// No warning
+fn no_immediate_return() -> Result<i32, i32> {
+    if let Err(err) = func_returning_result() {
+        do_something();
+        return Err(err);
+    }
+    Ok(1)
+}
+
+// No warning
+fn mixed_result_and_option() -> Option<i32> {
+    if let Err(err) = func_returning_result() {
+        return Some(err);
+    }
+    None
+}
+
+// No warning
+fn else_if_check() -> Result<i32, i32> {
+    if true {
+        Ok(1)
+    } else if let Err(e) = func_returning_result() {
+        Err(e)
+    } else {
+        Err(-1)
+    }
+}
+
+// No warning
+#[allow(clippy::manual_map)]
+#[rustfmt::skip]
+fn option_map() -> Option<bool> {
+    if let Some(a) = Some(false) {
+        Some(!a)
+    } else {
+        None
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs
index 60590fd9311..cdbc7b1606f 100644
--- a/tests/ui/question_mark.rs
+++ b/tests/ui/question_mark.rs
@@ -1,5 +1,6 @@
 // run-rustfix
 #![allow(unreachable_code)]
+#![allow(dead_code)]
 #![allow(clippy::unnecessary_wraps)]
 
 fn some_func(a: Option<u32>) -> Option<u32> {
@@ -186,26 +187,60 @@ fn f() -> NotOption {
     NotOption::First
 }
 
-fn main() {
-    some_func(Some(42));
-    some_func(None);
-    some_other_func(Some(42));
+fn do_something() {}
 
-    let copy_struct = CopyStruct { opt: Some(54) };
-    copy_struct.func();
-
-    let move_struct = MoveStruct {
-        opt: Some(vec![42, 1337]),
-    };
-    move_struct.ref_func();
-    move_struct.clone().mov_func_reuse();
-    move_struct.mov_func_no_use();
-
-    let so = SeemsOption::Some(45);
-    returns_something_similar_to_option(so);
-
-    func();
-
-    let _ = result_func(Ok(42));
-    let _ = f();
+fn err_immediate_return() -> Result<i32, i32> {
+    if let Err(err) = func_returning_result() {
+        return Err(err);
+    }
+    Ok(1)
 }
+
+fn err_immediate_return_and_do_something() -> Result<i32, i32> {
+    if let Err(err) = func_returning_result() {
+        return Err(err);
+    }
+    do_something();
+    Ok(1)
+}
+
+// No warning
+fn no_immediate_return() -> Result<i32, i32> {
+    if let Err(err) = func_returning_result() {
+        do_something();
+        return Err(err);
+    }
+    Ok(1)
+}
+
+// No warning
+fn mixed_result_and_option() -> Option<i32> {
+    if let Err(err) = func_returning_result() {
+        return Some(err);
+    }
+    None
+}
+
+// No warning
+fn else_if_check() -> Result<i32, i32> {
+    if true {
+        Ok(1)
+    } else if let Err(e) = func_returning_result() {
+        Err(e)
+    } else {
+        Err(-1)
+    }
+}
+
+// No warning
+#[allow(clippy::manual_map)]
+#[rustfmt::skip]
+fn option_map() -> Option<bool> {
+    if let Some(a) = Some(false) {
+        Some(!a)
+    } else {
+        None
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/question_mark.stderr b/tests/ui/question_mark.stderr
index 8d782b71dd6..1b6cd524b2f 100644
--- a/tests/ui/question_mark.stderr
+++ b/tests/ui/question_mark.stderr
@@ -1,5 +1,5 @@
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:6:5
+  --> $DIR/question_mark.rs:7:5
    |
 LL | /     if a.is_none() {
 LL | |         return None;
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::question-mark` implied by `-D warnings`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:51:9
+  --> $DIR/question_mark.rs:52:9
    |
 LL | /         if (self.opt).is_none() {
 LL | |             return None;
@@ -17,7 +17,7 @@ LL | |         }
    | |_________^ help: replace it with: `(self.opt)?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:55:9
+  --> $DIR/question_mark.rs:56:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None
@@ -25,7 +25,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:59:17
+  --> $DIR/question_mark.rs:60:17
    |
 LL |           let _ = if self.opt.is_none() {
    |  _________________^
@@ -35,8 +35,8 @@ LL | |             self.opt
 LL | |         };
    | |_________^ help: replace it with: `Some(self.opt?)`
 
-error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:65:17
+error: this block may be rewritten with the `?` operator
+  --> $DIR/question_mark.rs:66:17
    |
 LL |           let _ = if let Some(x) = self.opt {
    |  _________________^
@@ -47,7 +47,7 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:82:9
+  --> $DIR/question_mark.rs:83:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -55,7 +55,7 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:90:9
+  --> $DIR/question_mark.rs:91:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
@@ -63,15 +63,15 @@ LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:98:9
+  --> $DIR/question_mark.rs:99:9
    |
 LL | /         if self.opt.is_none() {
 LL | |             return None;
 LL | |         }
    | |_________^ help: replace it with: `self.opt.as_ref()?;`
 
-error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:105:26
+error: this block may be rewritten with the `?` operator
+  --> $DIR/question_mark.rs:106:26
    |
 LL |           let v: &Vec<_> = if let Some(ref v) = self.opt {
    |  __________________________^
@@ -81,8 +81,8 @@ LL | |             return None;
 LL | |         };
    | |_________^ help: replace it with: `self.opt.as_ref()?`
 
-error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:115:17
+error: this block may be rewritten with the `?` operator
+  --> $DIR/question_mark.rs:116:17
    |
 LL |           let v = if let Some(v) = self.opt {
    |  _________________^
@@ -93,26 +93,42 @@ LL | |         };
    | |_________^ help: replace it with: `self.opt?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:130:5
+  --> $DIR/question_mark.rs:131:5
    |
 LL | /     if f().is_none() {
 LL | |         return None;
 LL | |     }
    | |_____^ help: replace it with: `f()?;`
 
-error: this if-let-else may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:142:13
+error: this block may be rewritten with the `?` operator
+  --> $DIR/question_mark.rs:143:13
    |
 LL |     let _ = if let Ok(x) = x { x } else { return x };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
 
 error: this block may be rewritten with the `?` operator
-  --> $DIR/question_mark.rs:144:5
+  --> $DIR/question_mark.rs:145:5
    |
 LL | /     if x.is_err() {
 LL | |         return x;
 LL | |     }
    | |_____^ help: replace it with: `x?;`
 
-error: aborting due to 13 previous errors
+error: this block may be rewritten with the `?` operator
+  --> $DIR/question_mark.rs:193:5
+   |
+LL | /     if let Err(err) = func_returning_result() {
+LL | |         return Err(err);
+LL | |     }
+   | |_____^ help: replace it with: `func_returning_result()?;`
+
+error: this block may be rewritten with the `?` operator
+  --> $DIR/question_mark.rs:200:5
+   |
+LL | /     if let Err(err) = func_returning_result() {
+LL | |         return Err(err);
+LL | |     }
+   | |_____^ help: replace it with: `func_returning_result()?;`
+
+error: aborting due to 15 previous errors