about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2024-05-15 14:08:28 +0200
committerUrgau <urgau@numericable.fr>2024-05-27 23:59:18 +0200
commitd3dfe14b53e2211138e3a4eae5915351ff62f5bc (patch)
treed752a9c0edf2426125a44e543c3df50ca07bc8a1 /compiler
parent402580bcd5ade168a3a7edd0713821fa7d06dc2c (diff)
downloadrust-d3dfe14b53e2211138e3a4eae5915351ff62f5bc.tar.gz
rust-d3dfe14b53e2211138e3a4eae5915351ff62f5bc.zip
non_local_defs: be more precise about what needs to be moved
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_lint/src/lints.rs12
-rw-r--r--compiler/rustc_lint/src/non_local_def.rs40
2 files changed, 43 insertions, 9 deletions
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 800cd398adb..ad6e7b958c7 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1337,8 +1337,7 @@ pub enum NonLocalDefinitionsDiag {
         cargo_update: Option<NonLocalDefinitionsCargoUpdateNote>,
         const_anon: Option<Option<Span>>,
         move_help: Span,
-        self_ty: Span,
-        of_trait: Option<Span>,
+        may_move: Vec<Span>,
         has_trait: bool,
     },
     MacroRules {
@@ -1361,8 +1360,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
                 cargo_update,
                 const_anon,
                 move_help,
-                self_ty,
-                of_trait,
+                may_move,
                 has_trait,
             } => {
                 diag.primary_message(fluent::lint_non_local_definitions_impl);
@@ -1376,10 +1374,10 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
                 } else {
                     diag.note(fluent::lint_without_trait);
                 }
+
                 let mut ms = MultiSpan::from_span(move_help);
-                ms.push_span_label(self_ty, fluent::lint_non_local_definitions_may_move);
-                if let Some(of_trait) = of_trait {
-                    ms.push_span_label(of_trait, fluent::lint_non_local_definitions_may_move);
+                for sp in may_move {
+                    ms.push_span_label(sp, fluent::lint_non_local_definitions_may_move);
                 }
                 diag.span_help(ms, fluent::lint_help);
 
diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs
index 6b75e546a66..0805c2e2766 100644
--- a/compiler/rustc_lint/src/non_local_def.rs
+++ b/compiler/rustc_lint/src/non_local_def.rs
@@ -1,3 +1,5 @@
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::HirId;
 use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, TyKind};
 use rustc_hir::{Path, QPath};
 use rustc_infer::infer::InferCtxt;
@@ -214,6 +216,29 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                     None
                 };
 
+                let mut collector = PathCollector { paths: Vec::new() };
+                collector.visit_ty(&impl_.self_ty);
+                if let Some(of_trait) = &impl_.of_trait {
+                    collector.visit_trait_ref(of_trait);
+                }
+                collector.visit_generics(&impl_.generics);
+
+                let may_move: Vec<Span> = collector
+                    .paths
+                    .into_iter()
+                    .filter_map(|path| {
+                        if path_has_local_parent(&path, cx, parent, parent_parent) {
+                            if let Some(args) = &path.segments.last().unwrap().args {
+                                Some(path.span.until(args.span_ext))
+                            } else {
+                                Some(path.span)
+                            }
+                        } else {
+                            None
+                        }
+                    })
+                    .collect();
+
                 let const_anon = matches!(parent_def_kind, DefKind::Const | DefKind::Static { .. })
                     .then_some(span_for_const_anon_suggestion);
 
@@ -223,14 +248,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
                     NonLocalDefinitionsDiag::Impl {
                         depth: self.body_depth,
                         move_help: item.span,
-                        self_ty: impl_.self_ty.span,
-                        of_trait: impl_.of_trait.map(|t| t.path.span),
                         body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent),
                         body_name: parent_opt_item_name
                             .map(|s| s.to_ident_string())
                             .unwrap_or_else(|| "<unnameable>".to_string()),
                         cargo_update: cargo_update(),
                         const_anon,
+                        may_move,
                         has_trait: impl_.of_trait.is_some(),
                     },
                 )
@@ -348,6 +372,18 @@ impl<'a, 'tcx, F: FnMut(DefId) -> bool> TypeFolder<TyCtxt<'tcx>>
     }
 }
 
+/// Simple hir::Path collector
+struct PathCollector<'tcx> {
+    paths: Vec<Path<'tcx>>,
+}
+
+impl<'tcx> Visitor<'tcx> for PathCollector<'tcx> {
+    fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
+        self.paths.push(path.clone()); // need to clone, bc of the restricted lifetime
+        intravisit::walk_path(self, path)
+    }
+}
+
 /// Given a path and a parent impl def id, this checks if the if parent resolution
 /// def id correspond to the def id of the parent impl definition.
 ///