-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
refactor: create multiple HIR items for imports #51425
Changes from 3 commits
122b5b4
16cfa5c
02121f3
903e2c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -45,7 +45,7 @@ use hir; | |||
use hir::HirVec; | ||||
use hir::map::{DefKey, DefPathData, Definitions}; | ||||
use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}; | ||||
use hir::def::{Def, PathResolution}; | ||||
use hir::def::{Def, PathResolution, PerNS}; | ||||
use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES}; | ||||
use middle::cstore::CrateStore; | ||||
use rustc_data_structures::indexed_vec::IndexVec; | ||||
|
@@ -152,6 +152,9 @@ pub trait Resolver { | |||
/// Obtain the resolution for a node id | ||||
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>; | ||||
|
||||
/// Obtain the possible resolutions for the given `use` statement. | ||||
fn get_import(&mut self, id: NodeId) -> PerNS<Option<PathResolution>>; | ||||
|
||||
/// We must keep the set of definitions up to date as we add nodes that weren't in the AST. | ||||
/// This should only return `None` during testing. | ||||
fn definitions(&mut self) -> &mut Definitions; | ||||
|
@@ -571,6 +574,21 @@ impl<'a> LoweringContext<'a> { | |||
}) | ||||
} | ||||
|
||||
fn expect_full_def_from_use(&mut self, id: NodeId) -> Vec<Def> { | ||||
let mut ret = self.resolver.get_import(id).present_items().map(|pr| { | ||||
if pr.unresolved_segments() != 0 { | ||||
bug!("path not fully resolved: {:?}", pr); | ||||
} | ||||
pr.base_def() | ||||
}).collect::<Vec<_>>(); | ||||
|
||||
if ret.is_empty() { | ||||
ret.push(Def::Err); | ||||
} | ||||
|
||||
ret | ||||
} | ||||
|
||||
fn diagnostic(&self) -> &errors::Handler { | ||||
self.sess.diagnostic() | ||||
} | ||||
|
@@ -1532,13 +1550,13 @@ impl<'a> LoweringContext<'a> { | |||
|
||||
fn lower_path_extra( | ||||
&mut self, | ||||
id: NodeId, | ||||
def: Def, | ||||
p: &Path, | ||||
name: Option<Name>, | ||||
param_mode: ParamMode, | ||||
) -> hir::Path { | ||||
hir::Path { | ||||
def: self.expect_full_def(id), | ||||
def, | ||||
segments: p.segments | ||||
.iter() | ||||
.map(|segment| { | ||||
|
@@ -1558,7 +1576,8 @@ impl<'a> LoweringContext<'a> { | |||
} | ||||
|
||||
fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path { | ||||
self.lower_path_extra(id, p, None, param_mode) | ||||
let def = self.expect_full_def(id); | ||||
self.lower_path_extra(def, p, None, param_mode) | ||||
} | ||||
|
||||
fn lower_path_segment( | ||||
|
@@ -2363,7 +2382,7 @@ impl<'a> LoweringContext<'a> { | |||
let path = &tree.prefix; | ||||
|
||||
match tree.kind { | ||||
UseTreeKind::Simple(rename) => { | ||||
UseTreeKind::Simple(rename, id1, id2) => { | ||||
*name = tree.ident().name; | ||||
|
||||
// First apply the prefix to the path | ||||
|
@@ -2387,7 +2406,58 @@ impl<'a> LoweringContext<'a> { | |||
} | ||||
} | ||||
|
||||
let path = P(self.lower_path(id, &path, ParamMode::Explicit)); | ||||
let parent_def_index = self.current_hir_id_owner.last().unwrap().0; | ||||
let mut defs = self.expect_full_def_from_use(id).into_iter(); | ||||
// we want to return *something* from this function, so hang onto the first item | ||||
// for later | ||||
let mut ret_def = defs.next().unwrap_or(Def::Err); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use site duplication here |
||||
|
||||
for (def, &new_node_id) in defs.zip([id1, id2].iter()) { | ||||
let vis = vis.clone(); | ||||
let name = name.clone(); | ||||
let span = path.span; | ||||
self.resolver.definitions().create_def_with_parent( | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could now be possible to not create def ids here, but instead in rust/src/librustc/hir/map/def_collector.rs Line 131 in 538fea5
create_def method. I'm not sure if it's possible, because you'd already need to know how many definitions you are going to need
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm guessing it's problematic to create all the defs ahead of time and leave them potentially unused? Is there a way to pull them back out later (or mark them used in a way that won't affect anything)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's what I worry about, too. |
||||
parent_def_index, | ||||
new_node_id, | ||||
DefPathData::Misc, | ||||
DefIndexAddressSpace::High, | ||||
Mark::root(), | ||||
span); | ||||
self.allocate_hir_id_counter(new_node_id, &path); | ||||
|
||||
self.with_hir_id_owner(new_node_id, |this| { | ||||
let new_id = this.lower_node_id(new_node_id); | ||||
let path = this.lower_path_extra(def, &path, None, ParamMode::Explicit); | ||||
let item = hir::ItemUse(P(path), hir::UseKind::Single); | ||||
let vis = match vis { | ||||
hir::Visibility::Public => hir::Visibility::Public, | ||||
hir::Visibility::Crate(sugar) => hir::Visibility::Crate(sugar), | ||||
hir::Visibility::Inherited => hir::Visibility::Inherited, | ||||
hir::Visibility::Restricted { ref path, id: _ } => { | ||||
hir::Visibility::Restricted { | ||||
path: path.clone(), | ||||
// We are allocating a new NodeId here | ||||
id: this.next_id().node_id, | ||||
} | ||||
} | ||||
}; | ||||
|
||||
this.items.insert( | ||||
new_id.node_id, | ||||
hir::Item { | ||||
id: new_id.node_id, | ||||
hir_id: new_id.hir_id, | ||||
name: name, | ||||
attrs: attrs.clone(), | ||||
node: item, | ||||
vis, | ||||
span, | ||||
}, | ||||
); | ||||
}); | ||||
} | ||||
|
||||
let path = P(self.lower_path_extra(ret_def, &path, None, ParamMode::Explicit)); | ||||
hir::ItemUse(path, hir::UseKind::Single) | ||||
} | ||||
UseTreeKind::Glob => { | ||||
|
@@ -2654,7 +2724,7 @@ impl<'a> LoweringContext<'a> { | |||
match i.node { | ||||
ItemKind::Use(ref use_tree) => { | ||||
let mut vec = SmallVector::one(hir::ItemId { id: i.id }); | ||||
self.lower_item_id_use_tree(use_tree, &mut vec); | ||||
self.lower_item_id_use_tree(use_tree, i.id, &mut vec); | ||||
return vec; | ||||
} | ||||
ItemKind::MacroDef(..) => return SmallVector::new(), | ||||
|
@@ -2663,14 +2733,26 @@ impl<'a> LoweringContext<'a> { | |||
SmallVector::one(hir::ItemId { id: i.id }) | ||||
} | ||||
|
||||
fn lower_item_id_use_tree(&self, tree: &UseTree, vec: &mut SmallVector<hir::ItemId>) { | ||||
fn lower_item_id_use_tree(&mut self, | ||||
tree: &UseTree, | ||||
base_id: NodeId, | ||||
vec: &mut SmallVector<hir::ItemId>) | ||||
{ | ||||
match tree.kind { | ||||
UseTreeKind::Nested(ref nested_vec) => for &(ref nested, id) in nested_vec { | ||||
vec.push(hir::ItemId { id }); | ||||
self.lower_item_id_use_tree(nested, vec); | ||||
self.lower_item_id_use_tree(nested, id, vec); | ||||
}, | ||||
UseTreeKind::Glob => {} | ||||
UseTreeKind::Simple(..) => {} | ||||
UseTreeKind::Simple(_, id1, id2) => { | ||||
for (_, &id) in self.expect_full_def_from_use(base_id) | ||||
.into_iter() | ||||
.skip(1) | ||||
.zip([id1, id2].iter()) | ||||
{ | ||||
vec.push(hir::ItemId { id }); | ||||
} | ||||
}, | ||||
} | ||||
} | ||||
|
||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could return an
impl Iterator<Item=Def>
by not doing theis_empty
dance which is repeated at the use site of this function anyway.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it turns out i can! I was scarred because i tried doing that to a version of
lower_path
(which i wound up taking out when we moved to the AST modification) and wound up with exotic lifetime errors due to the introduction of a&ast::Path
with an unaccounted lifetime. But this one doesn't have to use anything external for its mapping, so it works out.