Skip to content

Commit bb18a8a

Browse files
committed
Auto merge of #161349 - oli-obk:unflatten-use, r=<try>
Unflatten `use` statements in HIR
2 parents 407371f + ab9b7ef commit bb18a8a

67 files changed

Lines changed: 942 additions & 782 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎compiler/rustc_ast/src/ast.rs‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHashe
2929
use rustc_data_structures::tagged_ptr::Tag;
3030
use rustc_macros::{Decodable, Encodable, StableHash, Walkable};
3131
pub use rustc_span::AttrId;
32-
use rustc_span::def_id::LocalDefId;
3332
use rustc_span::{
3433
ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan,
3534
sym,
@@ -4410,9 +4409,6 @@ pub type ForeignItem = Item<ForeignItemKind>;
44104409
pub enum AstOwner {
44114410
/// This definition does not correspond to a HIR owner.
44124411
NonOwner,
4413-
/// This definition corresponds to a nested `use` tree.
4414-
/// The `LocalDefId` points to its HIR owner.
4415-
NestedUseTree(LocalDefId),
44164412
Crate(Box<Crate>),
44174413
Item(Box<Item>),
44184414
TraitItem(Box<AssocItem>),

‎compiler/rustc_ast_lowering/src/index.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
152152
self.visit_body(body);
153153
}
154154

155+
fn visit_use(&mut self, tree: &'hir UseTree<'hir>, hir_id: HirId) {
156+
if !hir_id.is_owner() {
157+
self.insert(tree.prefix.span, hir_id, Node::NestedUseTree(tree));
158+
}
159+
intravisit::walk_use(self, tree, hir_id);
160+
}
161+
155162
fn visit_param(&mut self, param: &'hir Param<'hir>) {
156163
let node = Node::Param(param);
157164
self.insert(param.pat.span, param.hir_id, node);

‎compiler/rustc_ast_lowering/src/item.rs‎

Lines changed: 21 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@ use rustc_ast::visit::AssocCtxt;
33
use rustc_ast::*;
44
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
55
use rustc_hir::attrs::{AttributeKind, EiiImplResolution};
6-
use rustc_hir::def::{DefKind, PerNS, Res};
6+
use rustc_hir::def::{DefKind, Res};
77
use rustc_hir::{
88
self as hir, CRATE_OWNER_ID, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target,
99
find_attr,
1010
};
11-
use rustc_middle::span_bug;
1211
use rustc_middle::ty::data_structures::IndexMap;
1312
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
1413
use rustc_span::def_id::{DefId, LocalDefId};
@@ -244,11 +243,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
244243
hir::ItemKind::ExternCrate(*orig_name, ident)
245244
}
246245
ItemKind::Use(use_tree) => {
247-
// Start with an empty prefix.
248-
let prefix =
249-
Path { segments: ThinVec::new(), span: use_tree.prefix.span.shrink_to_lo() };
250-
251-
self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs)
246+
hir::ItemKind::Use(self.lower_use_tree(use_tree, id, vis_span, attrs))
252247
}
253248
ItemKind::Static(ast::StaticItem {
254249
ident,
@@ -591,13 +586,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
591586
fn lower_use_tree(
592587
&mut self,
593588
tree: &UseTree,
594-
prefix: &Path,
595589
id: NodeId,
596590
vis_span: Span,
597591
attrs: &'hir [hir::Attribute],
598-
) -> hir::ItemKind<'hir> {
592+
) -> hir::UseTree<'hir> {
599593
let path = &tree.prefix;
600-
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
594+
let segments = path.segments.iter().cloned().collect();
601595

602596
match tree.kind {
603597
UseTreeKind::Simple(rename) => {
@@ -619,104 +613,35 @@ impl<'hir> LoweringContext<'_, 'hir> {
619613
let res = self.lower_import_res(id, path.span);
620614
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
621615
let ident = self.lower_ident(ident);
622-
hir::ItemKind::Use(path, hir::UseKind::Single(ident))
616+
hir::UseTree { prefix: path, kind: hir::UseKind::Single(ident) }
623617
}
624618
UseTreeKind::Glob(_) => {
625619
let res = self.expect_full_res(id);
626620
let res = self.lower_res(res);
627621
// Put the result in the appropriate namespace.
628-
let res = match res {
629-
Res::Def(DefKind::Mod | DefKind::Trait, _) => {
630-
PerNS { type_ns: Some(res), value_ns: None, macro_ns: None }
631-
}
632-
Res::Def(DefKind::Enum, _) => {
633-
PerNS { type_ns: None, value_ns: Some(res), macro_ns: None }
634-
}
635-
Res::Err => {
636-
// Propagate the error to all namespaces, just to be sure.
637-
let err = Some(Res::Err);
638-
PerNS { type_ns: err, value_ns: err, macro_ns: err }
639-
}
640-
_ => span_bug!(path.span, "bad glob res {:?}", res),
641-
};
622+
let res = res.in_namespace();
642623
let path = Path { segments, span: path.span };
643624
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
644-
hir::ItemKind::Use(path, hir::UseKind::Glob)
625+
hir::UseTree { prefix: path, kind: hir::UseKind::Glob }
645626
}
646627
UseTreeKind::Nested { items: ref trees, .. } => {
647-
// Nested imports are desugared into simple imports.
648-
// So, if we start with
649-
//
650-
// ```
651-
// pub(x) use foo::{a, b};
652-
// ```
653-
//
654-
// we will create three items:
655-
//
656-
// ```
657-
// pub(x) use foo::a;
658-
// pub(x) use foo::b;
659-
// pub(x) use foo::{}; // <-- this is called the `ListStem`
660-
// ```
661-
//
662-
// The first two are produced by recursively invoking
663-
// `lower_use_tree` (and indeed there may be things
664-
// like `use foo::{a::{b, c}}` and so forth). They
665-
// wind up being directly added to
666-
// `self.items`. However, the structure of this
667-
// function also requires us to return one item, and
668-
// for that we return the `{}` import (called the
669-
// `ListStem`).
670-
671-
let span = prefix.span.to(path.span);
672-
let prefix = Path { segments, span };
628+
let res = self.expect_full_res(id);
629+
let res = self.lower_res(res);
630+
// Put the result in the appropriate namespace.
631+
let res = res.in_namespace();
632+
let prefix = self.lower_use_path(res, &path, ParamMode::Explicit);
673633

674634
// Add all the nested `PathListItem`s to the HIR.
675-
for &(ref use_tree, id) in trees {
676-
let owner_id = self.owner_id(id);
677-
678-
// Each `use` import is an item and thus are owners of the
679-
// names in the path. Up to this point the nested import is
680-
// the current owner, since we want each desugared import to
681-
// own its own names, we have to adjust the owner before
682-
// lowering the rest of the import.
683-
self.with_hir_id_owner(id, |this| {
684-
// `prefix` is lowered multiple times, but in different HIR owners.
685-
// So each segment gets renewed `HirId` with the same
686-
// `ItemLocalId` and the new owner. (See `lower_node_id`)
687-
let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, attrs);
688-
if !attrs.is_empty() {
689-
this.attrs.insert(hir::ItemLocalId::ZERO, attrs);
690-
}
691-
692-
let item = hir::Item {
693-
owner_id,
694-
kind,
695-
vis_span,
696-
span: this.lower_span(use_tree.span()),
697-
eii: find_attr!(attrs, EiiImpl(..) | EiiDeclaration(..)),
698-
};
699-
hir::OwnerNode::Item(this.arena.alloc(item))
700-
});
701-
}
635+
let items = self.arena.alloc_from_iter(trees.iter().map(|&(ref use_tree, id)| {
636+
let hir_id = self.lower_node_id(id);
637+
let def_id = self.owner.node_id_to_def_id[&id];
638+
if !attrs.is_empty() {
639+
self.attrs.insert(hir_id.local_id, attrs);
640+
}
641+
(self.lower_use_tree(use_tree, id, vis_span, attrs), hir_id, def_id)
642+
}));
702643

703-
// Condition should match `build_reduced_graph_for_use_tree`.
704-
let path = if trees.is_empty()
705-
&& !(prefix.segments.is_empty()
706-
|| prefix.segments.len() == 1
707-
&& prefix.segments[0].ident.name == kw::PathRoot)
708-
{
709-
// For empty lists we need to lower the prefix so it is checked for things
710-
// like stability later.
711-
let res = self.lower_import_res(id, span);
712-
self.lower_use_path(res, &prefix, ParamMode::Explicit)
713-
} else {
714-
// For non-empty lists we can just drop all the data, the prefix is already
715-
// present in HIR as a part of nested imports.
716-
let span = self.lower_span(span);
717-
self.arena.alloc(hir::UsePath { res: PerNS::default(), segments: &[], span })
718-
};
719-
hir::ItemKind::Use(path, hir::UseKind::ListStem)
644+
hir::UseTree { prefix, kind: hir::UseKind::Nested { items } }
720645
}
721646
}
722647
}

0 commit comments

Comments
 (0)