blob: e4e5fa54201051b4bfa999ac96b170d6683e82eb [file] [edit]
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_expr_identity_function;
use clippy_utils::res::MaybeDef;
use clippy_utils::source::snippet_with_context;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_span::Span;
use rustc_span::symbol::sym;
use super::MAP_OR_IDENTITY;
/// lint use of `_.map_or(err, |n| n)` for `Result`s and `Option`s.
pub(super) fn check(
cx: &LateContext<'_>,
expr: &Expr<'_>,
recv: &Expr<'_>,
call_span: Span,
def_arg: &Expr<'_>,
map_arg: &Expr<'_>,
) {
// lint if the caller of `map_or()` is a `Result` or an `Option`
// and if the mapping function is the identity function
if let Some(symbol @ (sym::Result | sym::Option)) = cx.typeck_results().expr_ty_adjusted(recv).opt_diag_name(cx)
&& is_expr_identity_function(cx, map_arg)
{
let msg = format!("expression can be simplified using `{symbol}::unwrap_or()`");
span_lint_and_then(cx, MAP_OR_IDENTITY, expr.span, msg, |diag| {
let mut applicability = Applicability::MachineApplicable;
let (err_snippet, _) = snippet_with_context(cx, def_arg.span, expr.span.ctxt(), "..", &mut applicability);
let sugg = format!("unwrap_or({err_snippet})");
diag.span_suggestion_verbose(call_span, "consider using `unwrap_or`", sugg, applicability);
});
}
}