1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet;
3 use clippy_utils::ty::is_type_diagnostic_item;
4 use clippy_utils::{match_qpath, paths};
5 use rustc_errors::Applicability;
7 use rustc_lint::LateContext;
8 use rustc_span::symbol::sym;
10 use super::OPTION_MAP_OR_NONE;
11 use super::RESULT_MAP_OR_INTO_OPTION;
13 /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s
14 pub(super) fn check<'tcx>(
15 cx: &LateContext<'tcx>,
16 expr: &'tcx hir::Expr<'_>,
17 recv: &'tcx hir::Expr<'_>,
18 def_arg: &'tcx hir::Expr<'_>,
19 map_arg: &'tcx hir::Expr<'_>,
21 let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type);
22 let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type);
24 // There are two variants of this `map_or` lint:
25 // (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>`
26 // (2) using `map_or` as a combinator instead of `and_then`
28 // (For this lint) we don't care if any other type calls `map_or`
29 if !is_option && !is_result {
33 let (lint_name, msg, instead, hint) = {
34 let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind {
35 match_qpath(qpath, &paths::OPTION_NONE)
40 if !default_arg_is_none {
45 let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind {
46 match_qpath(qpath, &paths::OPTION_SOME)
52 let self_snippet = snippet(cx, recv.span, "..");
53 let func_snippet = snippet(cx, map_arg.span, "..");
54 let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
55 `and_then(..)` instead";
59 "try using `and_then` instead",
60 format!("{0}.and_then({1})", self_snippet, func_snippet),
62 } else if f_arg_is_some {
63 let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \
65 let self_snippet = snippet(cx, recv.span, "..");
67 RESULT_MAP_OR_INTO_OPTION,
69 "try using `ok` instead",
70 format!("{0}.ok()", self_snippet),
85 Applicability::MachineApplicable,