2021-03-15 19:55:45 -05:00
|
|
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
2021-03-16 11:06:34 -05:00
|
|
|
use clippy_utils::paths;
|
2021-03-14 18:17:44 -05:00
|
|
|
use clippy_utils::source::snippet_with_macro_callsite;
|
2021-03-13 17:01:03 -06:00
|
|
|
use clippy_utils::ty::{is_type_diagnostic_item, match_type};
|
2021-03-04 09:16:43 -06:00
|
|
|
use rustc_errors::Applicability;
|
|
|
|
use rustc_hir as hir;
|
|
|
|
use rustc_lint::LateContext;
|
|
|
|
use rustc_middle::ty;
|
2021-03-16 22:34:37 -05:00
|
|
|
use rustc_span::symbol::{sym, Symbol};
|
2021-03-04 09:16:43 -06:00
|
|
|
|
|
|
|
use super::CLONE_ON_REF_PTR;
|
|
|
|
|
2021-03-16 22:34:37 -05:00
|
|
|
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol, args: &[hir::Expr<'_>]) {
|
|
|
|
if !(args.len() == 1 && method_name == sym::clone) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let arg = &args[0];
|
2021-03-04 09:16:43 -06:00
|
|
|
let obj_ty = cx.typeck_results().expr_ty(arg).peel_refs();
|
|
|
|
|
|
|
|
if let ty::Adt(_, subst) = obj_ty.kind() {
|
|
|
|
let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) {
|
|
|
|
"Rc"
|
|
|
|
} else if is_type_diagnostic_item(cx, obj_ty, sym::Arc) {
|
|
|
|
"Arc"
|
|
|
|
} else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) {
|
|
|
|
"Weak"
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
let snippet = snippet_with_macro_callsite(cx, arg.span, "..");
|
|
|
|
|
|
|
|
span_lint_and_sugg(
|
|
|
|
cx,
|
|
|
|
CLONE_ON_REF_PTR,
|
|
|
|
expr.span,
|
|
|
|
"using `.clone()` on a ref-counted pointer",
|
|
|
|
"try this",
|
|
|
|
format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet),
|
|
|
|
Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|