mem_replace_with_default: use diagnostic items intead of paths

This commit is contained in:
Mateusz Gacek 2021-03-12 12:00:08 -08:00
parent c86ba7f92d
commit 41be515062
3 changed files with 35 additions and 24 deletions

View file

@ -4,6 +4,7 @@ use crate::utils::{
};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@ -12,6 +13,8 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
use clippy_utils::is_diagnostic_assoc_item;
declare_clippy_lint! {
/// **What it does:** Checks for `mem::replace()` on an `Option` with
/// `None`.
@ -194,27 +197,43 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
}
}
/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent"
/// constructor from the std library
fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool {
let std_types_symbols = &[
sym::string_type,
sym::vec_type,
sym::vecdeque_type,
sym::LinkedList,
sym::hashmap_type,
sym::BTreeMap,
sym::hashset_type,
sym::BTreeSet,
sym::BinaryHeap,
];
if std_types_symbols
.iter()
.any(|symbol| is_diagnostic_assoc_item(cx, def_id, *symbol))
{
if let QPath::TypeRelative(_, ref method) = path {
if method.ident.name == sym::new {
return true;
}
}
}
false
}
fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
if let ExprKind::Call(ref repl_func, _) = src.kind {
if_chain! {
if !in_external_macro(cx.tcx.sess, expr_span);
if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
let defaults = &[
paths::DEFAULT_TRAIT_METHOD.as_ref(),
paths::STRING_NEW.as_ref(),
paths::VEC_NEW.as_ref(),
paths::VEC_DEQUE_NEW.as_ref(),
paths::LINKED_LIST_NEW.as_ref(),
paths::HASHMAP_NEW.as_ref(),
paths::BTREEMAP_NEW.as_ref(),
paths::HASHSET_NEW.as_ref(),
paths::BTREESET_NEW.as_ref(),
paths::BINARY_HEAP_NEW.as_ref(),
];
if defaults.iter().any(|x| match_def_path(cx, repl_def_id, &x));
if is_diagnostic_assoc_item(cx, repl_def_id, sym::Default)
|| is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
then {
span_lint_and_then(