1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::is_lang_ctor;
3 use clippy_utils::source::snippet;
4 use clippy_utils::ty::is_type_diagnostic_item;
5 use rustc_errors::Applicability;
7 use rustc_hir::LangItem::{OptionNone, OptionSome};
8 use rustc_lint::LateContext;
9 use rustc_span::symbol::sym;
11 use super::OPTION_MAP_OR_NONE;
12 use super::RESULT_MAP_OR_INTO_OPTION;
14 /// lint use of `_.map_or(None, _)` for `Option`s and `Result`s
15 pub(super) fn check<'tcx>(
16 cx: &LateContext<'tcx>,
17 expr: &'tcx hir::Expr<'_>,
18 recv: &'tcx hir::Expr<'_>,
19 def_arg: &'tcx hir::Expr<'_>,
20 map_arg: &'tcx hir::Expr<'_>,
22 let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type);
23 let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::result_type);
25 // There are two variants of this `map_or` lint:
26 // (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>`
27 // (2) using `map_or` as a combinator instead of `and_then`
29 // (For this lint) we don't care if any other type calls `map_or`
30 if !is_option && !is_result {
34 let (lint_name, msg, instead, hint) = {
35 let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind {
36 is_lang_ctor(cx, qpath, OptionNone)
41 if !default_arg_is_none {
46 let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind {
47 is_lang_ctor(cx, qpath, OptionSome)
53 let self_snippet = snippet(cx, recv.span, "..");
54 let func_snippet = snippet(cx, map_arg.span, "..");
55 let msg = "called `map_or(None, ..)` on an `Option` value. This can be done more directly by calling \
56 `and_then(..)` instead";
60 "try using `and_then` instead",
61 format!("{0}.and_then({1})", self_snippet, func_snippet),
63 } else if f_arg_is_some {
64 let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \
66 let self_snippet = snippet(cx, recv.span, "..");
68 RESULT_MAP_OR_INTO_OPTION,
70 "try using `ok` instead",
71 format!("{0}.ok()", self_snippet),
86 Applicability::MachineApplicable,