Skip to content

Commit 9004856

Browse files
committed
Auto merge of #153838 - oli-obk:use-tree-span, r=davidtwco
Use fine grained component-wise span tracking in use trees This often produces nicer spans and even doesn't need a Span field anymore (not that I expect the unused field to affect any perf, but still neat).
2 parents 033b925 + 033ccb0 commit 9004856

21 files changed

Lines changed: 115 additions & 75 deletions

File tree

compiler/rustc_ast/src/ast.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3338,7 +3338,7 @@ pub enum UseTreeKind {
33383338
/// ```
33393339
Nested { items: ThinVec<(UseTree, NodeId)>, span: Span },
33403340
/// `use prefix::*`
3341-
Glob,
3341+
Glob(Span),
33423342
}
33433343

33443344
/// A tree of paths sharing common prefixes.
@@ -3347,10 +3347,11 @@ pub enum UseTreeKind {
33473347
pub struct UseTree {
33483348
pub prefix: Path,
33493349
pub kind: UseTreeKind,
3350-
pub span: Span,
33513350
}
33523351

33533352
impl UseTree {
3353+
/// If the `UseTree` is just an identifier, return that.
3354+
/// Panics if it's a glob (`*`) or a nested use tree.
33543355
pub fn ident(&self) -> Ident {
33553356
match self.kind {
33563357
UseTreeKind::Simple(Some(rename)) => rename,
@@ -3360,6 +3361,27 @@ impl UseTree {
33603361
_ => panic!("`UseTree::ident` can only be used on a simple import"),
33613362
}
33623363
}
3364+
3365+
/// Returns the full span from the start of the path to the
3366+
/// closing `}` or nested spans, `*` of glob spans or the end of the
3367+
/// identifier of simple spans.
3368+
pub fn span(&self) -> Span {
3369+
self.prefix.span.to(self.hi_span())
3370+
}
3371+
3372+
/// Returns the trailing element's span. So for a nested
3373+
/// span you get the entire `{}`-block, for a glob you
3374+
/// get the span of the `*` itself, and for simple use trees
3375+
/// you get the identifier to rename the import to or the full
3376+
/// path if no rename is specified.
3377+
pub fn hi_span(&self) -> Span {
3378+
match self.kind {
3379+
UseTreeKind::Simple(None) => self.prefix.span,
3380+
UseTreeKind::Simple(Some(name)) => name.span,
3381+
UseTreeKind::Nested { span, .. } => span,
3382+
UseTreeKind::Glob(span) => span,
3383+
}
3384+
}
33633385
}
33643386

33653387
/// Distinguishes between `Attribute`s that decorate items and Attributes that

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
153153
self.lower_item_id_use_tree(nested, vec);
154154
}
155155
}
156-
UseTreeKind::Simple(..) | UseTreeKind::Glob => {}
156+
UseTreeKind::Simple(..) | UseTreeKind::Glob(_) => {}
157157
}
158158
}
159159

@@ -287,7 +287,11 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
287287
}
288288
ItemKind::Use(use_tree) => {
289289
// Start with an empty prefix.
290-
let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None };
290+
let prefix = Path {
291+
segments: ThinVec::new(),
292+
span: use_tree.prefix.span.shrink_to_lo(),
293+
tokens: None,
294+
};
291295

292296
self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
293297
}
@@ -659,7 +663,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
659663
let ident = self.lower_ident(ident);
660664
hir::ItemKind::Use(path, hir::UseKind::Single(ident))
661665
}
662-
UseTreeKind::Glob => {
666+
UseTreeKind::Glob(_) => {
663667
let res = self.expect_full_res(id);
664668
let res = self.lower_res(res);
665669
// Put the result in the appropriate namespace.
@@ -731,7 +735,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> {
731735
owner_id,
732736
kind,
733737
vis_span,
734-
span: this.lower_span(use_tree.span),
738+
span: this.lower_span(use_tree.span()),
735739
has_delayed_lints: !this.delayed_lints.is_empty(),
736740
eii: find_attr!(attrs, EiiImpls(..) | EiiDeclaration(..)),
737741
};

compiler/rustc_ast_pretty/src/pprust/state/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,7 @@ impl<'a> State<'a> {
867867
self.print_ident(rename);
868868
}
869869
}
870-
ast::UseTreeKind::Glob => {
870+
ast::UseTreeKind::Glob(_) => {
871871
if !tree.prefix.segments.is_empty() {
872872
self.print_path(&tree.prefix, false, 0);
873873
self.word("::");

compiler/rustc_builtin_macros/src/assert/context.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ impl<'cx, 'a> Context<'cx, 'a> {
102102
UseTree {
103103
prefix: this.cx.path(this.span, vec![Ident::with_dummy_span(sym)]),
104104
kind: UseTreeKind::Simple(None),
105-
span: this.span,
106105
},
107106
DUMMY_NODE_ID,
108107
)
@@ -121,7 +120,6 @@ impl<'cx, 'a> Context<'cx, 'a> {
121120
],
122121
span: self.span,
123122
},
124-
span: self.span,
125123
}),
126124
),
127125
)

compiler/rustc_builtin_macros/src/standard_library_imports.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ pub fn inject(
6868
thin_vec![cx.attr_word(sym::prelude_import, span)],
6969
ast::ItemKind::Use(ast::UseTree {
7070
prefix: cx.path(span, import_path),
71-
kind: ast::UseTreeKind::Glob,
72-
span,
71+
kind: ast::UseTreeKind::Glob(span),
7372
}),
7473
);
7574

compiler/rustc_expand/src/expand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,7 @@ impl InvocationCollectorNode for Box<ast::Item> {
14421442
if let ItemKind::Use(ut) = &self.kind {
14431443
fn collect_use_tree_leaves(ut: &ast::UseTree, idents: &mut Vec<Ident>) {
14441444
match &ut.kind {
1445-
ast::UseTreeKind::Glob => {}
1445+
ast::UseTreeKind::Glob(_) => {}
14461446
ast::UseTreeKind::Simple(_) => idents.push(ut.ident()),
14471447
ast::UseTreeKind::Nested { items, .. } => {
14481448
for (ut, _) in items {

compiler/rustc_lint/src/unused.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ impl UnusedImportBraces {
11781178
}
11791179
rename.unwrap_or(orig_ident).name
11801180
}
1181-
ast::UseTreeKind::Glob => sym::asterisk,
1181+
ast::UseTreeKind::Glob(_) => sym::asterisk,
11821182
ast::UseTreeKind::Nested { .. } => return,
11831183
};
11841184

compiler/rustc_parse/src/parser/item.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ impl<'a> Parser<'a> {
433433
let tree = self.parse_use_tree()?;
434434
if let Err(mut e) = self.expect_semi() {
435435
match tree.kind {
436-
UseTreeKind::Glob => {
436+
UseTreeKind::Glob(_) => {
437437
e.note("the wildcard token must be last on the path");
438438
}
439439
UseTreeKind::Nested { .. } => {
@@ -1328,13 +1328,13 @@ impl<'a> Parser<'a> {
13281328
}
13291329
};
13301330

1331-
Ok(UseTree { prefix, kind, span: lo.to(self.prev_token.span) })
1331+
Ok(UseTree { prefix, kind })
13321332
}
13331333

13341334
/// Parses `*` or `{...}`.
13351335
fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
13361336
Ok(if self.eat(exp!(Star)) {
1337-
UseTreeKind::Glob
1337+
UseTreeKind::Glob(self.prev_token.span)
13381338
} else {
13391339
let lo = self.token.span;
13401340
UseTreeKind::Nested {

compiler/rustc_resolve/src/build_reduced_graph.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -603,12 +603,15 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
603603
// so prefixes are prepended with crate root segment if necessary.
604604
// The root is prepended lazily, when the first non-empty prefix or terminating glob
605605
// appears, so imports in braced groups can have roots prepended independently.
606-
let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob);
607606
let crate_root = match prefix_iter.peek() {
608607
Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.is_rust_2015() => {
609608
Some(seg.ident.span.ctxt())
610609
}
611-
None if is_glob && use_tree.span.is_rust_2015() => Some(use_tree.span.ctxt()),
610+
None if let ast::UseTreeKind::Glob(span) = use_tree.kind
611+
&& span.is_rust_2015() =>
612+
{
613+
Some(span.ctxt())
614+
}
612615
_ => None,
613616
}
614617
.map(|ctxt| {
@@ -696,7 +699,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
696699
}
697700
// Deny `use ::{self};` after edition 2015
698701
kw::PathRoot if !self.r.path_root_is_crate_root(source.ident) => {
699-
self.r.dcx().span_err(use_tree.span, "extern prelude cannot be imported");
702+
self.r.dcx().span_err(use_tree.span(), "extern prelude cannot be imported");
700703
return;
701704
}
702705
_ => {}
@@ -727,20 +730,20 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
727730
id,
728731
};
729732

730-
self.add_import(module_path, kind, use_tree.span, item, root_span, item.id, vis);
733+
self.add_import(module_path, kind, use_tree.span(), item, root_span, item.id, vis);
731734
}
732-
ast::UseTreeKind::Glob => {
735+
ast::UseTreeKind::Glob(_) => {
733736
if !ast::attr::contains_name(&item.attrs, sym::prelude_import) {
734737
let kind = ImportKind::Glob { max_vis: CmCell::new(None), id };
735-
self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis);
738+
self.add_import(prefix, kind, use_tree.span(), item, root_span, item.id, vis);
736739
} else {
737740
// Resolve the prelude import early.
738741
let path_res =
739742
self.r.cm().maybe_resolve_path(&prefix, None, &self.parent_scope, None);
740743
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = path_res {
741744
self.r.prelude = Some(module);
742745
} else {
743-
self.r.dcx().span_err(use_tree.span, "cannot resolve a prelude import");
746+
self.r.dcx().span_err(use_tree.span(), "cannot resolve a prelude import");
744747
}
745748
}
746749
}
@@ -764,7 +767,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
764767
let tree = ast::UseTree {
765768
prefix: ast::Path::from_ident(Ident::new(kw::SelfLower, new_span)),
766769
kind: ast::UseTreeKind::Simple(Some(Ident::new(kw::Underscore, new_span))),
767-
span: use_tree.span,
768770
};
769771
self.build_reduced_graph_for_use_tree(
770772
// This particular use tree
@@ -835,7 +837,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
835837
// The whole `use` item
836838
item,
837839
vis,
838-
use_tree.span,
840+
use_tree.span(),
839841
);
840842
}
841843

compiler/rustc_resolve/src/check_unused.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -294,22 +294,25 @@ fn calc_unused_spans(
294294
) -> UnusedSpanResult {
295295
// The full span is the whole item's span if this current tree is not nested inside another
296296
// This tells rustfix to remove the whole item if all the imports are unused
297-
let full_span = if unused_import.use_tree.span == use_tree.span {
297+
let full_span = if unused_import.use_tree.span() == use_tree.span() {
298298
unused_import.item_span
299299
} else {
300-
use_tree.span
300+
use_tree.span()
301301
};
302302
match use_tree.kind {
303-
ast::UseTreeKind::Simple(..) | ast::UseTreeKind::Glob => {
303+
ast::UseTreeKind::Simple(..) | ast::UseTreeKind::Glob(_) => {
304304
if unused_import.unused.contains(&use_tree_id) {
305-
UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span }
305+
UnusedSpanResult::Unused { spans: vec![use_tree.span()], remove: full_span }
306306
} else {
307307
UnusedSpanResult::Used
308308
}
309309
}
310310
ast::UseTreeKind::Nested { items: ref nested, span: tree_span } => {
311311
if nested.is_empty() {
312-
return UnusedSpanResult::Unused { spans: vec![use_tree.span], remove: full_span };
312+
return UnusedSpanResult::Unused {
313+
spans: vec![use_tree.span()],
314+
remove: full_span,
315+
};
313316
}
314317

315318
let mut unused_spans = Vec::new();
@@ -340,10 +343,10 @@ fn calc_unused_spans(
340343
} else if pos == nested.len() - 1 || used_children > 0 {
341344
// Delete everything from the end of the last import, to delete the
342345
// previous comma
343-
nested[pos - 1].0.span.shrink_to_hi().to(use_tree.span)
346+
nested[pos - 1].0.hi_span().shrink_to_hi().to(use_tree.hi_span())
344347
} else {
345348
// Delete everything until the next import, to delete the trailing commas
346-
use_tree.span.to(nested[pos + 1].0.span.shrink_to_lo())
349+
use_tree.prefix.span.to(nested[pos + 1].0.prefix.span.shrink_to_lo())
347350
};
348351

349352
// Try to collapse adjacent spans into a single one. This prevents all cases of
@@ -379,11 +382,23 @@ fn calc_unused_spans(
379382
if used_children == 1 && !contains_self {
380383
// Left brace, from the start of the nested group to the first item.
381384
to_remove.push(
382-
tree_span.shrink_to_lo().to(nested.first().unwrap().0.span.shrink_to_lo()),
385+
tree_span.shrink_to_lo().to(nested
386+
.first()
387+
.unwrap()
388+
.0
389+
.prefix
390+
.span
391+
.shrink_to_lo()),
383392
);
384393
// Right brace, from the end of the last item to the end of the nested group.
385394
to_remove.push(
386-
nested.last().unwrap().0.span.shrink_to_hi().to(tree_span.shrink_to_hi()),
395+
nested
396+
.last()
397+
.unwrap()
398+
.0
399+
.hi_span()
400+
.shrink_to_hi()
401+
.to(tree_span.shrink_to_hi()),
387402
);
388403
}
389404

0 commit comments

Comments
 (0)