1 use crate::source::snippet;
2 use crate::{path_to_local_id, strip_pat_refs};
3 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
4 use rustc_hir::{Body, BodyId, Expr, ExprKind, HirId, PatKind};
5 use rustc_lint::LateContext;
6 use rustc_middle::hir::map::Map;
12 opt_body_id: Option<BodyId>,
14 replacements: &[(&'static str, &'static str)],
15 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
16 if let Some(body) = opt_body_id.map(|id| cx.tcx.hir().body(id)) {
17 if let PatKind::Binding(_, binding_id, _, _) = strip_pat_refs(body.params[idx].pat).kind {
18 extract_clone_suggestions(cx, binding_id, replacements, body)
27 fn extract_clone_suggestions<'tcx>(
28 cx: &LateContext<'tcx>,
30 replace: &[(&'static str, &'static str)],
32 ) -> Option<Vec<(Span, Cow<'static, str>)>> {
33 let mut visitor = PtrCloneVisitor {
40 visitor.visit_body(body);
41 if visitor.abort { None } else { Some(visitor.spans) }
44 struct PtrCloneVisitor<'a, 'tcx> {
45 cx: &'a LateContext<'tcx>,
47 replace: &'a [(&'static str, &'static str)],
48 spans: Vec<(Span, Cow<'static, str>)>,
52 impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
55 fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
59 if let ExprKind::MethodCall(seg, _, [recv], _) = expr.kind {
60 if path_to_local_id(recv, self.id) {
61 if seg.ident.name.as_str() == "capacity" {
65 for &(fn_name, suffix) in self.replace {
66 if seg.ident.name.as_str() == fn_name {
67 self.spans.push((expr.span, snippet(self.cx, recv.span, "_") + suffix));
73 walk_expr(self, expr);
76 fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
77 NestedVisitorMap::None