Skip to content

Commit

Permalink
Auto merge of #104963 - petrochenkov:noaddids2, r=cjgillot
Browse files Browse the repository at this point in the history
rustc_ast_lowering: Stop lowering imports into multiple items

Lower them into a single item with multiple resolutions instead.
This also allows to remove additional `NodId`s and `DefId`s related to those additional items.
  • Loading branch information
bors committed Dec 2, 2022
2 parents 56c241c + b32a4ed commit 11663b1
Show file tree
Hide file tree
Showing 56 changed files with 227 additions and 324 deletions.
9 changes: 3 additions & 6 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2517,10 +2517,7 @@ pub struct Variant {
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum UseTreeKind {
/// `use prefix` or `use prefix as rename`
///
/// The extra `NodeId`s are for HIR lowering, when additional statements are created for each
/// namespace.
Simple(Option<Ident>, NodeId, NodeId),
Simple(Option<Ident>),
/// `use prefix::{...}`
Nested(Vec<(UseTree, NodeId)>),
/// `use prefix::*`
Expand All @@ -2539,8 +2536,8 @@ pub struct UseTree {
impl UseTree {
pub fn ident(&self) -> Ident {
match self.kind {
UseTreeKind::Simple(Some(rename), ..) => rename,
UseTreeKind::Simple(None, ..) => {
UseTreeKind::Simple(Some(rename)) => rename,
UseTreeKind::Simple(None) => {
self.prefix.segments.last().expect("empty prefix in a simple import").ident
}
_ => panic!("`UseTree::ident` can only be used on a simple import"),
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
let UseTree { prefix, kind, span } = use_tree;
vis.visit_path(prefix);
match kind {
UseTreeKind::Simple(rename, id1, id2) => {
visit_opt(rename, |rename| vis.visit_ident(rename));
vis.visit_id(id1);
vis.visit_id(id2);
}
UseTreeKind::Simple(rename) => visit_opt(rename, |rename| vis.visit_ident(rename)),
UseTreeKind::Nested(items) => {
for (tree, id) in items {
vis.visit_use_tree(tree);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) {
pub fn walk_use_tree<'a, V: Visitor<'a>>(visitor: &mut V, use_tree: &'a UseTree, id: NodeId) {
visitor.visit_path(&use_tree.prefix, id);
match &use_tree.kind {
UseTreeKind::Simple(rename, ..) => {
UseTreeKind::Simple(rename) => {
// The extra IDs are handled during HIR lowering.
if let &Some(rename) = rename {
visitor.visit_ident(rename);
Expand Down
95 changes: 15 additions & 80 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{Span, Symbol};
use rustc_target::spec::abi;
use smallvec::{smallvec, SmallVec};
use std::iter;
use thin_vec::ThinVec;

pub(super) struct ItemLowerer<'a, 'hir> {
Expand Down Expand Up @@ -179,36 +178,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
let mut node_ids =
smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
if let ItemKind::Use(use_tree) = &i.kind {
self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
self.lower_item_id_use_tree(use_tree, &mut node_ids);
}
node_ids
}

fn lower_item_id_use_tree(
&mut self,
tree: &UseTree,
base_id: NodeId,
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 {
UseTreeKind::Nested(nested_vec) => {
for &(ref nested, id) in nested_vec {
vec.push(hir::ItemId {
owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
});
self.lower_item_id_use_tree(nested, id, vec);
}
}
UseTreeKind::Glob => {}
UseTreeKind::Simple(_, id1, id2) => {
for (_, id) in
iter::zip(self.expect_full_res_from_use(base_id).skip(1), [*id1, *id2])
{
vec.push(hir::ItemId {
owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
});
self.lower_item_id_use_tree(nested, vec);
}
}
UseTreeKind::Simple(..) | UseTreeKind::Glob => {}
}
}

Expand Down Expand Up @@ -489,7 +474,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();

match tree.kind {
UseTreeKind::Simple(rename, id1, id2) => {
UseTreeKind::Simple(rename) => {
*ident = tree.ident();

// First, apply the prefix to the path.
Expand All @@ -505,66 +490,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

let mut resolutions = self.expect_full_res_from_use(id).fuse();
// We want to return *something* from this function, so hold onto the first item
// for later.
let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err));

// Here, we are looping over namespaces, if they exist for the definition
// being imported. We only handle type and value namespaces because we
// won't be dealing with macros in the rest of the compiler.
// Essentially a single `use` which imports two names is desugared into
// two imports.
for new_node_id in [id1, id2] {
let new_id = self.local_def_id(new_node_id);
let Some(res) = resolutions.next() else {
debug_assert!(self.children.iter().find(|(id, _)| id == &new_id).is_none());
// Associate an HirId to both ids even if there is no resolution.
self.children.push((
new_id,
hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id))),
);
continue;
};
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
// Give the cloned segment the same resolution information
// as the old one (this is needed for stability checking).
let new_id = self.next_node_id();
self.resolver.clone_res(seg.id, new_id);
seg.id = new_id;
}
let span = path.span;

self.with_hir_id_owner(new_node_id, |this| {
let res = this.lower_res(res);
let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
if let Some(attrs) = attrs {
this.attrs.insert(hir::ItemLocalId::new(0), attrs);
}

let item = hir::Item {
owner_id: hir::OwnerId { def_id: new_id },
ident: this.lower_ident(ident),
kind,
vis_span,
span: this.lower_span(span),
};
hir::OwnerNode::Item(this.arena.alloc(item))
});
}

let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit);
let res =
self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect();
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::Single)
}
UseTreeKind::Glob => {
let path = self.lower_path(
id,
&Path { segments, span: path.span, tokens: None },
ParamMode::Explicit,
);
let res = self.expect_full_res(id);
let res = smallvec![self.lower_res(res)];
let path = Path { segments, span: path.span, tokens: None };
let path = self.lower_use_path(res, &path, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::Glob)
}
UseTreeKind::Nested(ref trees) => {
Expand Down Expand Up @@ -634,9 +569,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
});
}

let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
let res = self.lower_res(res);
let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit);
let res =
self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect();
let path = self.lower_use_path(res, &prefix, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::ListStem)
}
}
Expand Down
21 changes: 5 additions & 16 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_hir::GenericArg;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{BytePos, Span, DUMMY_SP};

use smallvec::smallvec;
use smallvec::{smallvec, SmallVec};

impl<'a, 'hir> LoweringContext<'a, 'hir> {
#[instrument(level = "trace", skip(self))]
Expand Down Expand Up @@ -144,13 +144,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
);
}

pub(crate) fn lower_path_extra(
pub(crate) fn lower_use_path(
&mut self,
res: Res,
res: SmallVec<[Res; 3]>,
p: &Path,
param_mode: ParamMode,
) -> &'hir hir::Path<'hir> {
self.arena.alloc(hir::Path {
) -> &'hir hir::UsePath<'hir> {
self.arena.alloc(hir::UsePath {
res,
segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
self.lower_path_segment(
Expand All @@ -165,17 +165,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
})
}

pub(crate) fn lower_path(
&mut self,
id: NodeId,
p: &Path,
param_mode: ParamMode,
) -> &'hir hir::Path<'hir> {
let res = self.expect_full_res(id);
let res = self.lower_res(res);
self.lower_path_extra(res, p, param_mode)
}

pub(crate) fn lower_path_segment(
&mut self,
path_span: Span,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ impl<'a> State<'a> {

fn print_use_tree(&mut self, tree: &ast::UseTree) {
match &tree.kind {
ast::UseTreeKind::Simple(rename, ..) => {
ast::UseTreeKind::Simple(rename) => {
self.print_path(&tree.prefix, false, 0);
if let &Some(rename) = rename {
self.nbsp();
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/assert/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
(
UseTree {
prefix: this.cx.path(this.span, vec![Ident::with_dummy_span(sym)]),
kind: UseTreeKind::Simple(None, DUMMY_NODE_ID, DUMMY_NODE_ID),
kind: UseTreeKind::Simple(None),
span: this.span,
},
DUMMY_NODE_ID,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/stable_hasher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ where
}
}

impl<A, CTX> HashStable<CTX> for SmallVec<[A; 1]>
impl<A, const N: usize, CTX> HashStable<CTX> for SmallVec<[A; N]>
where
A: HashStable<CTX>,
{
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ macro_rules! arena_types {
[] param: rustc_hir::Param<'tcx>,
[] pat: rustc_hir::Pat<'tcx>,
[] path: rustc_hir::Path<'tcx>,
[] use_path: rustc_hir::UsePath<'tcx>,
[] path_segment: rustc_hir::PathSegment<'tcx>,
[] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>,
[] qpath: rustc_hir::QPath<'tcx>,
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,17 @@ impl Lifetime {
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
/// along with a bunch of supporting information.
#[derive(Debug, HashStable_Generic)]
pub struct Path<'hir> {
pub struct Path<'hir, R = Res> {
pub span: Span,
/// The resolution for the path.
pub res: Res,
pub res: R,
/// The segments in the path: the things separated by `::`.
pub segments: &'hir [PathSegment<'hir>],
}

/// Up to three resolutions for type, value and macro namespaces.
pub type UsePath<'hir> = Path<'hir, SmallVec<[Res; 3]>>;

impl Path<'_> {
pub fn is_global(&self) -> bool {
!self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
Expand Down Expand Up @@ -3068,7 +3071,7 @@ pub enum ItemKind<'hir> {
/// or just
///
/// `use foo::bar::baz;` (with `as baz` implicitly on the right).
Use(&'hir Path<'hir>, UseKind),
Use(&'hir UsePath<'hir>, UseKind),

/// A `static` item.
Static(&'hir Ty<'hir>, Mutability, BodyId),
Expand Down
13 changes: 8 additions & 5 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ pub trait Visitor<'v>: Sized {
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, _: Span, id: HirId) {
walk_fn(self, fk, fd, b, id)
}
fn visit_use(&mut self, path: &'v Path<'v>, hir_id: HirId) {
fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) {
walk_use(self, path, hir_id)
}
fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) {
Expand Down Expand Up @@ -422,7 +422,7 @@ pub trait Visitor<'v>: Sized {
fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) {
walk_qpath(self, qpath, id)
}
fn visit_path(&mut self, path: &'v Path<'v>, _id: HirId) {
fn visit_path(&mut self, path: &Path<'v>, _id: HirId) {
walk_path(self, path)
}
fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) {
Expand Down Expand Up @@ -938,9 +938,12 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'
}
}

pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) {
pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v UsePath<'v>, hir_id: HirId) {
visitor.visit_id(hir_id);
visitor.visit_path(path, hir_id);
let UsePath { segments, ref res, span } = *path;
for &res in res {
visitor.visit_path(&Path { segments, res, span }, hir_id);
}
}

pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
Expand Down Expand Up @@ -1126,7 +1129,7 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath<'v>, id:
}
}

pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>) {
pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &Path<'v>) {
for segment in path.segments {
visitor.visit_path_segment(segment);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}

fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, _: hir::HirId) {
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
if let Some(ref args) = segment.args {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1591,7 +1591,7 @@ impl<'a> State<'a> {
self.print_ident(Ident::with_dummy_span(name))
}

pub fn print_path(&mut self, path: &hir::Path<'_>, colons_before_params: bool) {
pub fn print_path<R>(&mut self, path: &hir::Path<'_, R>, colons_before_params: bool) {
self.maybe_print_comment(path.span.lo());

for (i, segment) in path.segments.iter().enumerate() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
fn check_path(
&mut self,
cx: &LateContext<'tcx>,
path: &'tcx rustc_hir::Path<'tcx>,
path: &rustc_hir::Path<'tcx>,
_: rustc_hir::HirId,
) {
if let Some(segment) = path.segments.iter().nth_back(1)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
hir_visit::walk_lifetime(self, lt);
}

fn visit_path(&mut self, p: &'tcx hir::Path<'tcx>, id: hir::HirId) {
fn visit_path(&mut self, p: &hir::Path<'tcx>, id: hir::HirId) {
lint_callback!(self, check_path, p, id);
hir_visit::walk_path(self, p);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ macro_rules! late_lint_methods {
fn check_struct_def(a: &$hir hir::VariantData<$hir>);
fn check_field_def(a: &$hir hir::FieldDef<$hir>);
fn check_variant(a: &$hir hir::Variant<$hir>);
fn check_path(a: &$hir hir::Path<$hir>, b: hir::HirId);
fn check_path(a: &hir::Path<$hir>, b: hir::HirId);
fn check_attribute(a: &$hir ast::Attribute);

/// Called when entering a syntax node that can have lint attributes such
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,7 @@ impl UnusedImportBraces {

// Trigger the lint if the nested item is a non-self single item
let node_name = match items[0].0.kind {
ast::UseTreeKind::Simple(rename, ..) => {
ast::UseTreeKind::Simple(rename) => {
let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
if orig_ident.name == kw::SelfLower {
return;
Expand Down
Loading

0 comments on commit 11663b1

Please sign in to comment.