- // Extract inner expr type from match argument generated by
- // question mark operator
- let inner_expr = &args[0];
-
- // if the inner expr is inside macro but the outer one is not, do not lint (#6921)
- if differing_macro_contexts(expr.span, inner_expr.span) {
- return None;
- }
-
- let inner_ty = cx.typeck_results().expr_ty(inner_expr);
- let outer_ty = cx.typeck_results().expr_ty(expr);
-
- // Check if outer and inner type are Option
- let outer_is_some = is_type_diagnostic_item(cx, outer_ty, sym::option_type);
- let inner_is_some = is_type_diagnostic_item(cx, inner_ty, sym::option_type);
-
- // Check for Option MSRV
- let meets_option_msrv = meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_OPTION_MSRV);
- if outer_is_some && inner_is_some && meets_option_msrv {
- return Some(SomeOkCall::SomeCall(expr, inner_expr));
- }
-
- // Check if outer and inner type are Result
- let outer_is_result = is_type_diagnostic_item(cx, outer_ty, sym::result_type);
- let inner_is_result = is_type_diagnostic_item(cx, inner_ty, sym::result_type);
-
- // Additional check: if the error type of the Result can be converted
- // via the From trait, then don't match
- let does_not_call_from = !has_implicit_error_from(cx, expr, inner_expr);
-
- // Must meet Result MSRV
- let meets_result_msrv = meets_msrv(nqml.msrv.as_ref(), &NEEDLESS_QUESTION_MARK_RESULT_MSRV);
- if outer_is_result && inner_is_result && does_not_call_from && meets_result_msrv {
- return Some(SomeOkCall::OkCall(expr, inner_expr));
- }
+ span_lint_and_sugg(
+ cx,
+ NEEDLESS_QUESTION_MARK,
+ expr.span,
+ "question mark operator is useless here",
+ &format!("try removing question mark and `{sugg_remove}`"),
+ format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
+ Applicability::MachineApplicable,
+ );