1
Fork 0

non_local_defs: be more precise about what needs to be moved

This commit is contained in:
Urgau 2024-05-15 14:08:28 +02:00
parent 402580bcd5
commit d3dfe14b53
13 changed files with 171 additions and 232 deletions

View file

@ -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);

View file

@ -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.
///