Skip to content

Commit 1768b10

Browse files
committed
Auto merge of #26688 - nrc:map-parent-2, r=manishearth
r? @Manishearth
2 parents d2cf9f9 + 8261599 commit 1768b10

File tree

2 files changed

+138
-37
lines changed

2 files changed

+138
-37
lines changed

src/librustc/ast_map/mod.rs

Lines changed: 130 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub enum Node<'ast> {
121121
NodeLifetime(&'ast Lifetime),
122122
}
123123

124-
/// Represents an entry and its parent Node ID
124+
/// Represents an entry and its parent NodeID.
125125
/// The odd layout is to bring down the total size.
126126
#[derive(Copy, Debug)]
127127
enum MapEntry<'ast> {
@@ -179,7 +179,7 @@ impl<'ast> MapEntry<'ast> {
179179
}
180180
}
181181

182-
fn parent(self) -> Option<NodeId> {
182+
fn parent_node(self) -> Option<NodeId> {
183183
Some(match self {
184184
EntryItem(id, _) => id,
185185
EntryForeignItem(id, _) => id,
@@ -283,10 +283,88 @@ impl<'ast> Map<'ast> {
283283
self.find_entry(id).and_then(|x| x.to_node())
284284
}
285285

286-
/// Retrieve the parent NodeId for `id`, or `id` itself if no
287-
/// parent is registered in this map.
286+
/// Similar to get_parent, returns the parent node id or id if there is no
287+
/// parent.
288+
/// This function returns the immediate parent in the AST, whereas get_parent
289+
/// returns the enclosing item. Note that this might not be the actual parent
290+
/// node in the AST - some kinds of nodes are not in the map and these will
291+
/// never appear as the parent_node. So you can always walk the parent_nodes
292+
/// from a node to the root of the ast (unless you get the same id back here
293+
/// that can happen if the id is not in the map itself or is just weird).
294+
pub fn get_parent_node(&self, id: NodeId) -> NodeId {
295+
self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
296+
}
297+
298+
/// If there is some error when walking the parents (e.g., a node does not
299+
/// have a parent in the map or a node can't be found), then we return the
300+
/// last good node id we found. Note that reaching the crate root (id == 0),
301+
/// is not an error, since items in the crate module have the crate root as
302+
/// parent.
303+
fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
304+
where F: Fn(&Node<'ast>) -> bool
305+
{
306+
let mut id = start_id;
307+
loop {
308+
let parent_node = self.get_parent_node(id);
309+
if parent_node == 0 {
310+
return Ok(0);
311+
}
312+
if parent_node == id {
313+
return Err(id);
314+
}
315+
316+
let node = self.find_entry(parent_node);
317+
if node.is_none() {
318+
return Err(id);
319+
}
320+
let node = node.unwrap().to_node();
321+
match node {
322+
Some(ref node) => {
323+
if found(node) {
324+
return Ok(parent_node);
325+
}
326+
}
327+
None => {
328+
return Err(parent_node);
329+
}
330+
}
331+
id = parent_node;
332+
}
333+
}
334+
335+
/// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
336+
/// parent item is in this map. The "parent item" is the closest parent node
337+
/// in the AST which is recorded by the map and is an item, either an item
338+
/// in a module, trait, or impl.
288339
pub fn get_parent(&self, id: NodeId) -> NodeId {
289-
self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
340+
match self.walk_parent_nodes(id, |node| match *node {
341+
NodeItem(_) |
342+
NodeForeignItem(_) |
343+
NodeTraitItem(_) |
344+
NodeImplItem(_) => true,
345+
_ => false,
346+
}) {
347+
Ok(id) => id,
348+
Err(id) => id,
349+
}
350+
}
351+
352+
/// Returns the nearest enclosing scope. A scope is an item or block.
353+
/// FIXME it is not clear to me that all items qualify as scopes - statics
354+
/// and associated types probably shouldn't, for example. Behaviour in this
355+
/// regard should be expected to be highly unstable.
356+
pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
357+
match self.walk_parent_nodes(id, |node| match *node {
358+
NodeItem(_) |
359+
NodeForeignItem(_) |
360+
NodeTraitItem(_) |
361+
NodeImplItem(_) |
362+
NodeBlock(_) => true,
363+
_ => false,
364+
}) {
365+
Ok(id) => Some(id),
366+
Err(_) => None,
367+
}
290368
}
291369

292370
pub fn get_parent_did(&self, id: NodeId) -> DefId {
@@ -590,15 +668,15 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
590668
return None;
591669
}
592670
self.idx += 1;
593-
let (p, name) = match self.map.find_entry(idx) {
594-
Some(EntryItem(p, n)) => (p, n.name()),
595-
Some(EntryForeignItem(p, n))=> (p, n.name()),
596-
Some(EntryTraitItem(p, n)) => (p, n.name()),
597-
Some(EntryImplItem(p, n)) => (p, n.name()),
598-
Some(EntryVariant(p, n)) => (p, n.name()),
671+
let name = match self.map.find_entry(idx) {
672+
Some(EntryItem(_, n)) => n.name(),
673+
Some(EntryForeignItem(_, n))=> n.name(),
674+
Some(EntryTraitItem(_, n)) => n.name(),
675+
Some(EntryImplItem(_, n)) => n.name(),
676+
Some(EntryVariant(_, n)) => n.name(),
599677
_ => continue,
600678
};
601-
if self.matches_names(p, name) {
679+
if self.matches_names(self.map.get_parent(idx), name) {
602680
return Some(idx)
603681
}
604682
}
@@ -647,8 +725,7 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
647725
/// A Visitor that walks over an AST and collects Node's into an AST Map.
648726
struct NodeCollector<'ast> {
649727
map: Vec<MapEntry<'ast>>,
650-
/// The node in which we are currently mapping (an item or a method).
651-
parent: NodeId
728+
parent_node: NodeId,
652729
}
653730

654731
impl<'ast> NodeCollector<'ast> {
@@ -662,7 +739,7 @@ impl<'ast> NodeCollector<'ast> {
662739
}
663740

664741
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
665-
let entry = MapEntry::from_node(self.parent, node);
742+
let entry = MapEntry::from_node(self.parent_node, node);
666743
self.insert_entry(id, entry);
667744
}
668745

@@ -676,8 +753,10 @@ impl<'ast> NodeCollector<'ast> {
676753
impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
677754
fn visit_item(&mut self, i: &'ast Item) {
678755
self.insert(i.id, NodeItem(i));
679-
let parent = self.parent;
680-
self.parent = i.id;
756+
757+
let parent_node = self.parent_node;
758+
self.parent_node = i.id;
759+
681760
match i.node {
682761
ItemImpl(_, _, _, _, _, ref impl_items) => {
683762
for ii in impl_items {
@@ -727,21 +806,23 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
727806
_ => {}
728807
}
729808
visit::walk_item(self, i);
730-
self.parent = parent;
809+
self.parent_node = parent_node;
731810
}
732811

733812
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
734-
let parent = self.parent;
735-
self.parent = ti.id;
813+
let parent_node = self.parent_node;
814+
self.parent_node = ti.id;
736815
visit::walk_trait_item(self, ti);
737-
self.parent = parent;
816+
self.parent_node = parent_node;
738817
}
739818

740819
fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
741-
let parent = self.parent;
742-
self.parent = ii.id;
820+
let parent_node = self.parent_node;
821+
self.parent_node = ii.id;
822+
743823
visit::walk_impl_item(self, ii);
744-
self.parent = parent;
824+
825+
self.parent_node = parent_node;
745826
}
746827

747828
fn visit_pat(&mut self, pat: &'ast Pat) {
@@ -750,38 +831,58 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
750831
PatIdent(..) => NodeLocal(pat),
751832
_ => NodePat(pat)
752833
});
834+
835+
let parent_node = self.parent_node;
836+
self.parent_node = pat.id;
753837
visit::walk_pat(self, pat);
838+
self.parent_node = parent_node;
754839
}
755840

756841
fn visit_expr(&mut self, expr: &'ast Expr) {
757842
self.insert(expr.id, NodeExpr(expr));
843+
let parent_node = self.parent_node;
844+
self.parent_node = expr.id;
758845
visit::walk_expr(self, expr);
846+
self.parent_node = parent_node;
759847
}
760848

761849
fn visit_stmt(&mut self, stmt: &'ast Stmt) {
762-
self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
850+
let id = ast_util::stmt_id(stmt);
851+
self.insert(id, NodeStmt(stmt));
852+
let parent_node = self.parent_node;
853+
self.parent_node = id;
763854
visit::walk_stmt(self, stmt);
855+
self.parent_node = parent_node;
764856
}
765857

766858
fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
767-
b: &'ast Block, s: Span, _: NodeId) {
859+
b: &'ast Block, s: Span, id: NodeId) {
860+
let parent_node = self.parent_node;
861+
self.parent_node = id;
768862
self.visit_fn_decl(fd);
769863
visit::walk_fn(self, fk, fd, b, s);
864+
self.parent_node = parent_node;
770865
}
771866

772867
fn visit_ty(&mut self, ty: &'ast Ty) {
868+
let parent_node = self.parent_node;
869+
self.parent_node = ty.id;
773870
match ty.node {
774871
TyBareFn(ref fd) => {
775872
self.visit_fn_decl(&*fd.decl);
776873
}
777874
_ => {}
778875
}
779876
visit::walk_ty(self, ty);
877+
self.parent_node = parent_node;
780878
}
781879

782880
fn visit_block(&mut self, block: &'ast Block) {
783881
self.insert(block.id, NodeBlock(block));
882+
let parent_node = self.parent_node;
883+
self.parent_node = block.id;
784884
visit::walk_block(self, block);
885+
self.parent_node = parent_node;
785886
}
786887

787888
fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) {
@@ -809,7 +910,7 @@ pub fn map_crate<'ast, F: FoldOps>(forest: &'ast mut Forest, fold_ops: F) -> Map
809910

810911
let mut collector = NodeCollector {
811912
map: vec![],
812-
parent: CRATE_NODE_ID
913+
parent_node: CRATE_NODE_ID,
813914
};
814915
collector.insert_entry(CRATE_NODE_ID, RootCrate);
815916
visit::walk_crate(&mut collector, &forest.krate);
@@ -864,11 +965,11 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
864965
ii: ii
865966
});
866967

968+
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
867969
let mut collector = NodeCollector {
868970
map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
869-
parent: fld.new_id(DUMMY_NODE_ID)
971+
parent_node: ii_parent_id,
870972
};
871-
let ii_parent_id = collector.parent;
872973
collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
873974
visit::walk_inlined_item(&mut collector, &ii_parent.ii);
874975

src/librustc_trans/save/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
172172
qualname: qualname,
173173
declaration: None,
174174
span: sub_span.unwrap(),
175-
scope: self.tcx.map.get_parent(item.id),
175+
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
176176
})
177177
}
178178
ast::ItemStatic(ref typ, mt, ref expr) => {
@@ -191,7 +191,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
191191
name: get_ident(item.ident).to_string(),
192192
qualname: qualname,
193193
span: sub_span.unwrap(),
194-
scope: self.tcx.map.get_parent(item.id),
194+
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
195195
value: value,
196196
type_value: ty_to_string(&typ),
197197
})
@@ -205,7 +205,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
205205
name: get_ident(item.ident).to_string(),
206206
qualname: qualname,
207207
span: sub_span.unwrap(),
208-
scope: self.tcx.map.get_parent(item.id),
208+
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
209209
value: self.span_utils.snippet(expr.span),
210210
type_value: ty_to_string(&typ),
211211
})
@@ -223,7 +223,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
223223
name: get_ident(item.ident).to_string(),
224224
qualname: qualname,
225225
span: sub_span.unwrap(),
226-
scope: self.tcx.map.get_parent(item.id),
226+
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
227227
filename: filename,
228228
})
229229
},
@@ -237,14 +237,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
237237
value: val,
238238
span: sub_span.unwrap(),
239239
qualname: enum_name,
240-
scope: self.tcx.map.get_parent(item.id),
240+
scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0),
241241
})
242242
},
243243
ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => {
244244
let mut type_data = None;
245245
let sub_span;
246246

247-
let parent = self.tcx.map.get_parent(item.id);
247+
let parent = self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0);
248248

249249
match typ.node {
250250
// Common case impl for a struct or something basic.
@@ -337,7 +337,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
337337
return Some(Data::VariableRefData(VariableRefData {
338338
name: get_ident(ident.node).to_string(),
339339
span: sub_span.unwrap(),
340-
scope: self.tcx.map.get_parent(expr.id),
340+
scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
341341
ref_id: f.id,
342342
}));
343343
}
@@ -360,7 +360,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
360360
let sub_span = self.span_utils.span_for_last_ident(path.span);
361361
Some(Data::TypeRefData(TypeRefData {
362362
span: sub_span.unwrap(),
363-
scope: self.tcx.map.get_parent(expr.id),
363+
scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0),
364364
ref_id: def_id,
365365
}))
366366
}

0 commit comments

Comments
 (0)