Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_ast_lowering: Stop lowering imports into multiple items #104963

Merged
merged 3 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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