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

Keep resolved defs in path prefixes and emit them in save-analysis #54145

Merged
merged 10 commits into from
Oct 26, 2018
17 changes: 15 additions & 2 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ pub trait Visitor<'v> : Sized {
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: NodeId) {
walk_fn(self, fk, fd, b, s, id)
}
fn visit_use(&mut self, path: &'v Path, id: NodeId, hir_id: HirId) {
walk_use(self, path, id, hir_id)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and walk_use are unused.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are used because it means the visitor walks down into the paths and path segments in a use statement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

visit_use is used in walk_item

fn visit_trait_item(&mut self, ti: &'v TraitItem) {
walk_trait_item(self, ti)
}
Expand Down Expand Up @@ -471,8 +474,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
}
}
ItemKind::Use(ref path, _) => {
visitor.visit_id(item.id);
visitor.visit_path(path, item.hir_id);
visitor.visit_use(path, item.id, item.hir_id);
}
ItemKind::Static(ref typ, _, body) |
ItemKind::Const(ref typ, body) => {
Expand Down Expand Up @@ -554,6 +556,14 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
walk_list!(visitor, visit_attribute, &item.attrs);
}

pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V,
path: &'v Path,
item_id: NodeId,
hir_id: HirId) {
visitor.visit_id(item_id);
visitor.visit_path(path, hir_id);
}

pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
enum_definition: &'v EnumDef,
generics: &'v Generics,
Expand Down Expand Up @@ -652,6 +662,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
path_span: Span,
segment: &'v PathSegment) {
visitor.visit_ident(segment.ident);
if let Some(id) = segment.id {
visitor.visit_id(id);
}
if let Some(ref args) = segment.args {
visitor.visit_generic_args(path_span, args);
}
Expand Down
122 changes: 89 additions & 33 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,12 @@ pub struct LoweringContext<'a> {
}

pub trait Resolver {
/// Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);
/// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc.
fn resolve_hir_path(
&mut self,
path: &ast::Path,
is_value: bool,
) -> hir::Path;

/// Obtain the resolution for a node id
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
Expand All @@ -163,7 +167,6 @@ pub trait Resolver {
span: Span,
crate_root: Option<&str>,
components: &[&str],
params: Option<P<hir::GenericArgs>>,
is_value: bool,
) -> hir::Path;
}
Expand Down Expand Up @@ -1064,6 +1067,9 @@ impl<'a> LoweringContext<'a> {
}

fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
// Note that we explicitly do not walk the path. Since we don't really
// lower attributes (we use the AST version) there is nowhere to keep
// the HirIds. We don't actually need HIR version of attributes anyway.
Attribute {
id: attr.id,
style: attr.style,
Expand Down Expand Up @@ -1677,6 +1683,7 @@ impl<'a> LoweringContext<'a> {
num_lifetimes,
parenthesized_generic_args,
itctx.reborrow(),
None,
)
})
.collect(),
Expand Down Expand Up @@ -1720,6 +1727,7 @@ impl<'a> LoweringContext<'a> {
0,
ParenthesizedGenericArgs::Warn,
itctx.reborrow(),
None,
));
let qpath = hir::QPath::TypeRelative(ty, segment);

Expand Down Expand Up @@ -1748,6 +1756,7 @@ impl<'a> LoweringContext<'a> {
p: &Path,
ident: Option<Ident>,
param_mode: ParamMode,
explicit_owner: Option<NodeId>,
) -> hir::Path {
hir::Path {
def,
Expand All @@ -1761,6 +1770,7 @@ impl<'a> LoweringContext<'a> {
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
explicit_owner,
)
})
.chain(ident.map(|ident| hir::PathSegment::from_ident(ident)))
Expand All @@ -1771,7 +1781,7 @@ impl<'a> LoweringContext<'a> {

fn lower_path(&mut self, id: NodeId, p: &Path, param_mode: ParamMode) -> hir::Path {
let def = self.expect_full_def(id);
self.lower_path_extra(def, p, None, param_mode)
self.lower_path_extra(def, p, None, param_mode, None)
}

fn lower_path_segment(
Expand All @@ -1782,6 +1792,7 @@ impl<'a> LoweringContext<'a> {
expected_lifetimes: usize,
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext<'_>,
explicit_owner: Option<NodeId>,
) -> hir::PathSegment {
let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
let msg = "parenthesized parameters may only be used with a trait";
Expand Down Expand Up @@ -1852,8 +1863,17 @@ impl<'a> LoweringContext<'a> {
}
}

let def = self.expect_full_def(segment.id);
let id = if let Some(owner) = explicit_owner {
self.lower_node_id_with_owner(segment.id, owner)
} else {
self.lower_node_id(segment.id)
};

hir::PathSegment::new(
segment.ident,
Some(id.node_id),
Some(def),
generic_args,
infer_types,
)
Expand Down Expand Up @@ -2936,19 +2956,20 @@ impl<'a> LoweringContext<'a> {
attrs: &hir::HirVec<Attribute>,
) -> hir::ItemKind {
let path = &tree.prefix;
let segments = prefix
.segments
.iter()
.chain(path.segments.iter())
.cloned()
.collect();

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

// First apply the prefix to the path
let mut path = Path {
segments: prefix
.segments
.iter()
.chain(path.segments.iter())
.cloned()
.collect(),
segments,
span: path.span,
};

Expand All @@ -2968,9 +2989,18 @@ impl<'a> LoweringContext<'a> {
// for later
let ret_def = defs.next().unwrap_or(Def::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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's strange, macro imports still need to be checked for stability/deprecation later on.
Save-analysis based IDEs should be able to jump from use xxx::my_macro; to the definition of my_macro as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But perhaps the comment is incorrect?
id1 and id2 were introduced in #51425 as extra ids in addition to the primary id kept elsewhere (in the item or in UseTreeKind::Nested), so the import still desugars into three namespaces.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Save-analysis based IDEs should be able to jump ...

They should but we don't support this yet.

as extra ids in addition to the primary id

When I was debugging, one of the ids was always equal to the primary id (I think that we don't look at the primary id here at all, just these two). I don't understand the stability/deprecation issue, I just added a comment because this seemed pretty non-obvious and took me a while to work out.

// Essentially a single `use` which imports two names is desugared into
// two imports.
for (def, &new_node_id) in defs.zip([id1, id2].iter()) {
let vis = vis.clone();
let name = name.clone();
let mut path = path.clone();
for seg in &mut path.segments {
seg.id = self.sess.next_node_id();
}
let span = path.span;
self.resolver.definitions().create_def_with_parent(
parent_def_index,
Expand All @@ -2983,7 +3013,8 @@ impl<'a> LoweringContext<'a> {

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 path =
this.lower_path_extra(def, &path, None, ParamMode::Explicit, None);
let item = hir::ItemKind::Use(P(path), hir::UseKind::Single);
let vis_kind = match vis.node {
hir::VisibilityKind::Public => hir::VisibilityKind::Public,
Expand All @@ -2993,7 +3024,6 @@ impl<'a> LoweringContext<'a> {
let id = this.next_id();
hir::VisibilityKind::Restricted {
path: path.clone(),
// We are allocating a new NodeId here
id: id.node_id,
hir_id: id.hir_id,
}
Expand All @@ -3016,50 +3046,60 @@ impl<'a> LoweringContext<'a> {
});
}

let path = P(self.lower_path_extra(ret_def, &path, None, ParamMode::Explicit));
let path =
P(self.lower_path_extra(ret_def, &path, None, ParamMode::Explicit, None));
hir::ItemKind::Use(path, hir::UseKind::Single)
}
UseTreeKind::Glob => {
let path = P(self.lower_path(
id,
&Path {
segments: prefix
.segments
.iter()
.chain(path.segments.iter())
.cloned()
.collect(),
segments,
span: path.span,
},
ParamMode::Explicit,
));
hir::ItemKind::Use(path, hir::UseKind::Glob)
}
UseTreeKind::Nested(ref trees) => {
// Nested imports are desugared into simple imports.

let prefix = Path {
segments: prefix
.segments
.iter()
.chain(path.segments.iter())
.cloned()
.collect(),
segments,
span: prefix.span.to(path.span),
};

// Add all the nested PathListItems in the HIR
// Add all the nested PathListItems to the HIR.
for &(ref use_tree, id) in trees {
self.allocate_hir_id_counter(id, &use_tree);

let LoweredNodeId {
node_id: new_id,
hir_id: new_hir_id,
} = self.lower_node_id(id);

let mut vis = vis.clone();
let mut name = name.clone();
let item =
self.lower_use_tree(use_tree, &prefix, new_id, &mut vis, &mut name, &attrs);
let mut prefix = prefix.clone();

// Give the segments new ids since they are being cloned.
for seg in &mut prefix.segments {
seg.id = self.sess.next_node_id();
}

// Each `use` import is an item and thus are owners of the
// names in the path. Up to this point the nested import is
// the current owner, since we want each desugared import to
// own its own names, we have to adjust the owner before
// lowering the rest of the import.
self.with_hir_id_owner(new_id, |this| {
let item = this.lower_use_tree(use_tree,
&prefix,
new_id,
&mut vis,
&mut name,
attrs);

let vis_kind = match vis.node {
hir::VisibilityKind::Public => hir::VisibilityKind::Public,
hir::VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
Expand All @@ -3068,7 +3108,6 @@ impl<'a> LoweringContext<'a> {
let id = this.next_id();
hir::VisibilityKind::Restricted {
path: path.clone(),
// We are allocating a new NodeId here
id: id.node_id,
hir_id: id.hir_id,
}
Expand All @@ -3081,7 +3120,7 @@ impl<'a> LoweringContext<'a> {
hir::Item {
id: new_id,
hir_id: new_hir_id,
name: name,
name,
attrs: attrs.clone(),
node: item,
vis,
Expand Down Expand Up @@ -3645,6 +3684,7 @@ impl<'a> LoweringContext<'a> {
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
None,
);
let args = args.iter().map(|x| self.lower_expr(x)).collect();
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args)
Expand Down Expand Up @@ -4498,8 +4538,15 @@ impl<'a> LoweringContext<'a> {
} else {
self.lower_node_id(id)
};
let def = self.expect_full_def(id);
hir::VisibilityKind::Restricted {
path: P(self.lower_path(id, path, ParamMode::Explicit)),
path: P(self.lower_path_extra(
def,
path,
None,
ParamMode::Explicit,
explicit_owner,
)),
id: lowered_id.node_id,
hir_id: lowered_id.hir_id,
}
Expand Down Expand Up @@ -4806,8 +4853,17 @@ impl<'a> LoweringContext<'a> {
params: Option<P<hir::GenericArgs>>,
is_value: bool
) -> hir::Path {
self.resolver
.resolve_str_path(span, self.crate_root, components, params, is_value)
let mut path = self.resolver
.resolve_str_path(span, self.crate_root, components, is_value);
path.segments.last_mut().unwrap().args = params;


for seg in path.segments.iter_mut() {
if let Some(id) = seg.id {
seg.id = Some(self.lower_node_id(id).node_id);
}
}
path
}

fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> hir::Ty {
Expand Down
22 changes: 17 additions & 5 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,17 +210,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
None => format!("{:?}", node)
};

if hir_id == ::hir::DUMMY_HIR_ID {
debug!("Maybe you forgot to lower the node id {:?}?", id);
}
let forgot_str = if hir_id == ::hir::DUMMY_HIR_ID {
format!("\nMaybe you forgot to lower the node id {:?}?", id)
} else {
String::new()
};

bug!("inconsistent DepNode for `{}`: \
current_dep_node_owner={}, hir_id.owner={}",
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}) {}",
node_str,
self.definitions
.def_path(self.current_dep_node_owner)
.to_string_no_crate(),
self.definitions.def_path(hir_id.owner).to_string_no_crate())
self.current_dep_node_owner,
self.definitions.def_path(hir_id.owner).to_string_no_crate(),
hir_id.owner,
forgot_str)
}
}

Expand Down Expand Up @@ -392,6 +397,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}

fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment) {
if let Some(id) = path_segment.id {
self.insert(id, Node::PathSegment(path_segment));
}
intravisit::walk_path_segment(self, path_span, path_segment);
}

fn visit_ty(&mut self, ty: &'hir Ty) {
self.insert(ty.id, Node::Ty(ty));

Expand Down
Loading