]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_utils/src/ptr.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / src / tools / clippy / clippy_utils / src / ptr.rs
CommitLineData
f20569fa
XL
1use crate::{get_pat_name, match_var, snippet};
2use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
3use rustc_hir::{Body, BodyId, Expr, ExprKind, Param};
4use rustc_lint::LateContext;
5use rustc_middle::hir::map::Map;
6use rustc_span::{Span, Symbol};
7use std::borrow::Cow;
8
9pub fn get_spans(
10 cx: &LateContext<'_>,
11 opt_body_id: Option<BodyId>,
12 idx: usize,
13 replacements: &[(&'static str, &'static str)],
14) -> Option<Vec<(Span, Cow<'static, str>)>> {
15 if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) {
16 get_binding_name(&body.params[idx]).map_or_else(
17 || Some(vec![]),
18 |name| extract_clone_suggestions(cx, name, replacements, body),
19 )
20 } else {
21 Some(vec![])
22 }
23}
24
25fn extract_clone_suggestions<'tcx>(
26 cx: &LateContext<'tcx>,
27 name: Symbol,
28 replace: &[(&'static str, &'static str)],
29 body: &'tcx Body<'_>,
30) -> Option<Vec<(Span, Cow<'static, str>)>> {
31 let mut visitor = PtrCloneVisitor {
32 cx,
33 name,
34 replace,
35 spans: vec![],
36 abort: false,
37 };
38 visitor.visit_body(body);
39 if visitor.abort { None } else { Some(visitor.spans) }
40}
41
42struct PtrCloneVisitor<'a, 'tcx> {
43 cx: &'a LateContext<'tcx>,
44 name: Symbol,
45 replace: &'a [(&'static str, &'static str)],
46 spans: Vec<(Span, Cow<'static, str>)>,
47 abort: bool,
48}
49
50impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
51 type Map = Map<'tcx>;
52
53 fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
54 if self.abort {
55 return;
56 }
57 if let ExprKind::MethodCall(ref seg, _, ref args, _) = expr.kind {
58 if args.len() == 1 && match_var(&args[0], self.name) {
59 if seg.ident.name.as_str() == "capacity" {
60 self.abort = true;
61 return;
62 }
63 for &(fn_name, suffix) in self.replace {
64 if seg.ident.name.as_str() == fn_name {
65 self.spans
66 .push((expr.span, snippet(self.cx, args[0].span, "_") + suffix));
67 return;
68 }
69 }
70 }
71 }
72 walk_expr(self, expr);
73 }
74
75 fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
76 NestedVisitorMap::None
77 }
78}
79
80fn get_binding_name(arg: &Param<'_>) -> Option<Symbol> {
81 get_pat_name(&arg.pat)
82}