non_local_defs: be more precise about what needs to be moved
This commit is contained in:
parent
402580bcd5
commit
d3dfe14b53
13 changed files with 171 additions and 232 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue