rust/clippy_lints/src/methods/unwrap_or_else_default.rs
Piotr Mikulski 4b3a87f886 clippy
2021-12-23 21:47:31 -08:00

59 lines
1.9 KiB
Rust

//! Lint for `some_result_or_option.unwrap_or_else(Default::default)`
use super::UNWRAP_OR_ELSE_DEFAULT;
use clippy_utils::{
diagnostics::span_lint_and_sugg, is_default_equivalent_ctor, is_diag_trait_item, is_trait_item,
source::snippet_with_applicability, ty::is_type_diagnostic_item,
};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::sym;
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx hir::Expr<'_>,
recv: &'tcx hir::Expr<'_>,
u_arg: &'tcx hir::Expr<'_>,
) {
// something.unwrap_or_else(Default::default)
// ^^^^^^^^^- recv ^^^^^^^^^^^^^^^^- u_arg
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- expr
let recv_ty = cx.typeck_results().expr_ty(recv);
let is_option = is_type_diagnostic_item(cx, recv_ty, sym::Option);
let is_result = is_type_diagnostic_item(cx, recv_ty, sym::Result);
let is_default_eq = match &u_arg.kind {
hir::ExprKind::Path(qpath) => {
if let Some(repl_def_id) = cx.qpath_res(qpath, u_arg.hir_id).opt_def_id() {
is_diag_trait_item(cx, repl_def_id, sym::Default)
|| is_default_equivalent_ctor(cx, repl_def_id, qpath)
} else {
false
}
},
_ => false,
};
if_chain! {
if is_option || is_result;
if is_trait_item(cx, u_arg, sym::Default) || is_default_eq;
then {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
UNWRAP_OR_ELSE_DEFAULT,
expr.span,
"use of `.unwrap_or_else(..)` to construct default value",
"try",
format!(
"{}.unwrap_or_default()",
snippet_with_applicability(cx, recv.span, "..", &mut applicability)
),
applicability,
);
}
}
}