-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathclone_on_ref_ptr.rs
50 lines (47 loc) · 1.52 KB
/
clone_on_ref_ptr.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_with_context;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_span::symbol::{Symbol, sym};
use super::CLONE_ON_REF_PTR;
pub(super) fn check(
cx: &LateContext<'_>,
expr: &hir::Expr<'_>,
method_name: Symbol,
receiver: &hir::Expr<'_>,
args: &[hir::Expr<'_>],
) {
if !(args.is_empty() && method_name == sym::clone) {
return;
}
let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
if let ty::Adt(adt, subst) = obj_ty.kind()
&& let Some(name) = cx.tcx.get_diagnostic_name(adt.did())
{
let caller_type = match name {
sym::Rc => "Rc",
sym::Arc => "Arc",
sym::RcWeak | sym::ArcWeak => "Weak",
_ => return,
};
span_lint_and_then(
cx,
CLONE_ON_REF_PTR,
expr.span,
"using `.clone()` on a ref-counted pointer",
|diag| {
// Sometimes unnecessary ::<_> after Rc/Arc/Weak
let mut app = Applicability::Unspecified;
let snippet = snippet_with_context(cx, receiver.span, expr.span.ctxt(), "..", &mut app).0;
diag.span_suggestion(
expr.span,
"try",
format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
app,
);
},
);
}
}