1
Fork 0

store the span of the nested part of the use tree in the ast

This commit is contained in:
Pietro Albini 2024-04-02 00:26:10 +02:00
parent 2ec337c193
commit 13f76235b3
No known key found for this signature in database
GPG key ID: 3E06ABE80BAAF19C
17 changed files with 45 additions and 36 deletions

View file

@ -2703,7 +2703,7 @@ pub enum UseTreeKind {
/// `use prefix` or `use prefix as rename` /// `use prefix` or `use prefix as rename`
Simple(Option<Ident>), Simple(Option<Ident>),
/// `use prefix::{...}` /// `use prefix::{...}`
Nested(ThinVec<(UseTree, NodeId)>), Nested { items: ThinVec<(UseTree, NodeId)>, span: Span },
/// `use prefix::*` /// `use prefix::*`
Glob, Glob,
} }

View file

@ -436,7 +436,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
vis.visit_path(prefix); vis.visit_path(prefix);
match kind { match kind {
UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)), UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
UseTreeKind::Nested(items) => { UseTreeKind::Nested { items, .. } => {
for (tree, id) in items { for (tree, id) in items {
vis.visit_use_tree(tree); vis.visit_use_tree(tree);
vis.visit_id(id); vis.visit_id(id);

View file

@ -488,8 +488,8 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
visit_opt!(visitor, visit_ident, rename); visit_opt!(visitor, visit_ident, rename);
} }
UseTreeKind::Glob => {} UseTreeKind::Glob => {}
UseTreeKind::Nested(ref use_trees) => { UseTreeKind::Nested { ref items, .. } => {
for &(ref nested_tree, nested_id) in use_trees { for &(ref nested_tree, nested_id) in items {
try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true)); try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
} }
} }

View file

@ -134,8 +134,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) { fn lower_item_id_use_tree(&mut self, tree: &UseTree, vec: &mut SmallVec<[hir::ItemId; 1]>) {
match &tree.kind { match &tree.kind {
UseTreeKind::Nested(nested_vec) => { UseTreeKind::Nested { items, .. } => {
for &(ref nested, id) in nested_vec { for &(ref nested, id) in items {
vec.push(hir::ItemId { vec.push(hir::ItemId {
owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
}); });
@ -517,7 +517,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let path = self.lower_use_path(res, &path, ParamMode::Explicit); let path = self.lower_use_path(res, &path, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::Glob) hir::ItemKind::Use(path, hir::UseKind::Glob)
} }
UseTreeKind::Nested(ref trees) => { UseTreeKind::Nested { items: ref trees, .. } => {
// Nested imports are desugared into simple imports. // Nested imports are desugared into simple imports.
// So, if we start with // So, if we start with
// //

View file

@ -712,7 +712,7 @@ impl<'a> State<'a> {
} }
self.word("*"); self.word("*");
} }
ast::UseTreeKind::Nested(items) => { ast::UseTreeKind::Nested { items, .. } => {
if !tree.prefix.segments.is_empty() { if !tree.prefix.segments.is_empty() {
self.print_path(&tree.prefix, false, 0); self.print_path(&tree.prefix, false, 0);
self.word("::"); self.word("::");
@ -731,7 +731,7 @@ impl<'a> State<'a> {
self.print_use_tree(&use_tree.0); self.print_use_tree(&use_tree.0);
if !is_last { if !is_last {
self.word(","); self.word(",");
if let ast::UseTreeKind::Nested(_) = use_tree.0.kind { if let ast::UseTreeKind::Nested { .. } = use_tree.0.kind {
self.hardbreak(); self.hardbreak();
} else { } else {
self.space(); self.space();

View file

@ -120,10 +120,13 @@ impl<'cx, 'a> Context<'cx, 'a> {
thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)], thin_vec![self.cx.attr_nested_word(sym::allow, sym::unused_imports, self.span)],
ItemKind::Use(UseTree { ItemKind::Use(UseTree {
prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])), prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
kind: UseTreeKind::Nested(thin_vec![ kind: UseTreeKind::Nested {
items: thin_vec![
nested_tree(self, sym::TryCaptureGeneric), nested_tree(self, sym::TryCaptureGeneric),
nested_tree(self, sym::TryCapturePrintable), nested_tree(self, sym::TryCapturePrintable),
]), ],
span: self.span,
},
span: self.span, span: self.span,
}), }),
), ),

View file

@ -1190,8 +1190,8 @@ impl InvocationCollectorNode for P<ast::Item> {
match &ut.kind { match &ut.kind {
ast::UseTreeKind::Glob => {} ast::UseTreeKind::Glob => {}
ast::UseTreeKind::Simple(_) => idents.push(ut.ident()), ast::UseTreeKind::Simple(_) => idents.push(ut.ident()),
ast::UseTreeKind::Nested(nested) => { ast::UseTreeKind::Nested { items, .. } => {
for (ut, _) in nested { for (ut, _) in items {
collect_use_tree_leaves(ut, idents); collect_use_tree_leaves(ut, idents);
} }
} }

View file

@ -1499,7 +1499,7 @@ declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
impl UnusedImportBraces { impl UnusedImportBraces {
fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) { fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
if let ast::UseTreeKind::Nested(ref items) = use_tree.kind { if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind {
// Recursively check nested UseTrees // Recursively check nested UseTrees
for (tree, _) in items { for (tree, _) in items {
self.check_use_tree(cx, tree, item); self.check_use_tree(cx, tree, item);
@ -1520,7 +1520,7 @@ impl UnusedImportBraces {
rename.unwrap_or(orig_ident).name rename.unwrap_or(orig_ident).name
} }
ast::UseTreeKind::Glob => Symbol::intern("*"), ast::UseTreeKind::Glob => Symbol::intern("*"),
ast::UseTreeKind::Nested(_) => return, ast::UseTreeKind::Nested { .. } => return,
}; };
cx.emit_span_lint( cx.emit_span_lint(

View file

@ -336,7 +336,7 @@ impl<'a> Parser<'a> {
UseTreeKind::Glob => { UseTreeKind::Glob => {
e.note("the wildcard token must be last on the path"); e.note("the wildcard token must be last on the path");
} }
UseTreeKind::Nested(..) => { UseTreeKind::Nested { .. } => {
e.note("glob-like brace syntax must be last on the path"); e.note("glob-like brace syntax must be last on the path");
} }
_ => (), _ => (),
@ -1056,7 +1056,11 @@ impl<'a> Parser<'a> {
Ok(if self.eat(&token::BinOp(token::Star)) { Ok(if self.eat(&token::BinOp(token::Star)) {
UseTreeKind::Glob UseTreeKind::Glob
} else { } else {
UseTreeKind::Nested(self.parse_use_tree_list()?) let lo = self.token.span;
UseTreeKind::Nested {
items: self.parse_use_tree_list()?,
span: lo.to(self.prev_token.span),
}
}) })
} }

View file

@ -565,7 +565,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis); self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis);
} }
ast::UseTreeKind::Nested(ref items) => { ast::UseTreeKind::Nested { ref items, .. } => {
// Ensure there is at most one `self` in the list // Ensure there is at most one `self` in the list
let self_spans = items let self_spans = items
.iter() .iter()

View file

@ -128,7 +128,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
self.unused_import(self.base_id).add(id); self.unused_import(self.base_id).add(id);
} }
} }
ast::UseTreeKind::Nested(ref items) => self.check_imports_as_underscore(items), ast::UseTreeKind::Nested { ref items, .. } => self.check_imports_as_underscore(items),
_ => {} _ => {}
} }
} }
@ -254,7 +254,7 @@ impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
return; return;
} }
if let ast::UseTreeKind::Nested(ref items) = use_tree.kind { if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind {
if items.is_empty() { if items.is_empty() {
self.unused_import(self.base_id).add(id); self.unused_import(self.base_id).add(id);
} }
@ -292,7 +292,7 @@ fn calc_unused_spans(
UnusedSpanResult::Used UnusedSpanResult::Used
} }
} }
ast::UseTreeKind::Nested(ref nested) => { ast::UseTreeKind::Nested { items: ref nested, .. } => {
if nested.is_empty() { if nested.is_empty() {
return UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span }; return UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span };
} }

View file

@ -2332,8 +2332,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
None => {} None => {}
} }
} }
} else if let UseTreeKind::Nested(use_trees) = &use_tree.kind { } else if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
for (use_tree, _) in use_trees { for (use_tree, _) in items {
self.future_proof_import(use_tree); self.future_proof_import(use_tree);
} }
} }
@ -2510,7 +2510,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
ItemKind::Use(ref use_tree) => { ItemKind::Use(ref use_tree) => {
let maybe_exported = match use_tree.kind { let maybe_exported = match use_tree.kind {
UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id), UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
UseTreeKind::Nested(_) => MaybeExported::NestedUse(&item.vis), UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis),
}; };
self.resolve_doc_links(&item.attrs, maybe_exported); self.resolve_doc_links(&item.attrs, maybe_exported);

View file

@ -201,8 +201,8 @@ impl SingleComponentPathImports {
if segments.is_empty() { if segments.is_empty() {
// keep track of `use {some_module, some_other_module};` usages // keep track of `use {some_module, some_other_module};` usages
if let UseTreeKind::Nested(trees) = &use_tree.kind { if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
for tree in trees { for tree in items {
let segments = &tree.0.prefix.segments; let segments = &tree.0.prefix.segments;
if segments.len() == 1 { if segments.len() == 1 {
if let UseTreeKind::Simple(None) = tree.0.kind { if let UseTreeKind::Simple(None) = tree.0.kind {
@ -229,8 +229,8 @@ impl SingleComponentPathImports {
} }
// nested case such as `use self::{module1::Struct1, module2::Struct2}` // nested case such as `use self::{module1::Struct1, module2::Struct2}`
if let UseTreeKind::Nested(trees) = &use_tree.kind { if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
for tree in trees { for tree in items {
let segments = &tree.0.prefix.segments; let segments = &tree.0.prefix.segments;
if !segments.is_empty() { if !segments.is_empty() {
imports_reused_with_self.push(segments[0].ident.name); imports_reused_with_self.push(segments[0].ident.name);

View file

@ -36,8 +36,8 @@ declare_lint_pass!(UnnecessarySelfImports => [UNNECESSARY_SELF_IMPORTS]);
impl EarlyLintPass for UnnecessarySelfImports { impl EarlyLintPass for UnnecessarySelfImports {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if let ItemKind::Use(use_tree) = &item.kind if let ItemKind::Use(use_tree) = &item.kind
&& let UseTreeKind::Nested(nodes) = &use_tree.kind && let UseTreeKind::Nested { items, .. } = &use_tree.kind
&& let [(self_tree, _)] = &**nodes && let [(self_tree, _)] = &**items
&& let [self_seg] = &*self_tree.prefix.segments && let [self_seg] = &*self_tree.prefix.segments
&& self_seg.ident.name == kw::SelfLower && self_seg.ident.name == kw::SelfLower
&& let Some(last_segment) = use_tree.prefix.segments.last() && let Some(last_segment) = use_tree.prefix.segments.last()

View file

@ -49,8 +49,8 @@ fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) {
unsafe_to_safe_check(old_name, new_name, cx, span); unsafe_to_safe_check(old_name, new_name, cx, span);
}, },
UseTreeKind::Simple(None) | UseTreeKind::Glob => {}, UseTreeKind::Simple(None) | UseTreeKind::Glob => {},
UseTreeKind::Nested(ref nested_use_tree) => { UseTreeKind::Nested { ref items, .. } => {
for (use_tree, _) in nested_use_tree { for (use_tree, _) in items {
check_use_tree(use_tree, cx, span); check_use_tree(use_tree, cx, span);
} }
}, },

View file

@ -637,7 +637,7 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool {
match (l, r) { match (l, r) {
(Glob, Glob) => true, (Glob, Glob) => true,
(Simple(l), Simple(r)) => both(l, r, |l, r| eq_id(*l, *r)), (Simple(l), Simple(r)) => both(l, r, |l, r| eq_id(*l, *r)),
(Nested(l), Nested(r)) => over(l, r, |(l, _), (r, _)| eq_use_tree(l, r)), (Nested { items: l, .. }, Nested { items: r, .. }) => over(l, r, |(l, _), (r, _)| eq_use_tree(l, r)),
_ => false, _ => false,
} }
} }

View file

@ -458,7 +458,9 @@ impl UseTree {
version, version,
}); });
} }
UseTreeKind::Nested(ref list) => { UseTreeKind::Nested {
items: ref list, ..
} => {
// Extract comments between nested use items. // Extract comments between nested use items.
// This needs to be done before sorting use items. // This needs to be done before sorting use items.
let items = itemize_list( let items = itemize_list(