Skip to content

Commit e82faeb

Browse files
committed
Auto merge of #28742 - nikomatsakis:def-id-encapsulate, r=eddyb
As described in rust-lang/rfcs#1298, the idea here is to make DefIds independent of changes to the content of other items. They are also *mostly* independent from ordering, so e.g. reordering two functions will change the defids, but it will not change the paths that they expand into (but this is not the case for some things, such as impls). This is a major refactoring, so I did it in slices. The final commit is in some sense The Big One where most of the work is done. The earlier commits just pave the way by gradually refactoring accesses to the `node` field. This is a [breaking-change] for plugin authors. The things you need to do to migrate your code are as follows: 1. For local def-ids, rather than do `def_id.node`, call `tcx.map.as_local_node_id(def_id)`. 2. To construct a local def-id, call `tcx.map.local_def_id(node_id)`. 3. Note that you cannot make def-ids for any node, but only for "definitions" -- which include all items, as well as a number of other things, but not e.g. arbitrary expressions. 4. You can get the path to a def-id by calling `tcx.def_path(def_id)`. One thing that is NOT part of this PR, but which I plan do in a follow-up, is converting uses of the existing `with_path` API to use `def_path`, which is basically the same. r? @eddyb (or @nrc)
2 parents 24202c6 + f0dc7bd commit e82faeb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+2382
-1863
lines changed

src/librustc/front/map/collector.rs

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use super::*;
12+
use super::MapEntry::*;
13+
14+
use rustc_front::hir::*;
15+
use rustc_front::util;
16+
use rustc_front::visit::{self, Visitor};
17+
use middle::def_id::{CRATE_DEF_INDEX, DefIndex};
18+
use std::iter::repeat;
19+
use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
20+
use syntax::codemap::Span;
21+
22+
/// A Visitor that walks over an AST and collects Node's into an AST
23+
/// Map.
24+
pub struct NodeCollector<'ast> {
25+
pub map: Vec<MapEntry<'ast>>,
26+
pub definitions: Definitions,
27+
pub parent_node: NodeId,
28+
}
29+
30+
impl<'ast> NodeCollector<'ast> {
31+
pub fn root() -> NodeCollector<'ast> {
32+
let mut collector = NodeCollector {
33+
map: vec![],
34+
definitions: Definitions::new(),
35+
parent_node: CRATE_NODE_ID,
36+
};
37+
collector.insert_entry(CRATE_NODE_ID, RootCrate);
38+
39+
let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
40+
assert_eq!(result, CRATE_DEF_INDEX);
41+
42+
collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
43+
44+
collector
45+
}
46+
47+
pub fn extend(parent: &'ast InlinedParent,
48+
parent_node: NodeId,
49+
parent_def_path: DefPath,
50+
map: Vec<MapEntry<'ast>>,
51+
definitions: Definitions)
52+
-> NodeCollector<'ast> {
53+
let mut collector = NodeCollector {
54+
map: map,
55+
parent_node: parent_node,
56+
definitions: definitions,
57+
};
58+
59+
collector.insert_entry(parent_node, RootInlinedParent(parent));
60+
collector.create_def(parent_node, DefPathData::InlinedRoot(parent_def_path));
61+
62+
collector
63+
}
64+
65+
fn parent_def(&self) -> Option<DefIndex> {
66+
let mut parent_node = Some(self.parent_node);
67+
while let Some(p) = parent_node {
68+
if let Some(q) = self.definitions.opt_def_index(p) {
69+
return Some(q);
70+
}
71+
parent_node = self.map[p as usize].parent_node();
72+
}
73+
None
74+
}
75+
76+
fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
77+
let parent_def = self.parent_def();
78+
self.definitions.create_def_with_parent(parent_def, node_id, data)
79+
}
80+
81+
fn create_def_with_parent(&mut self,
82+
parent: Option<DefIndex>,
83+
node_id: NodeId,
84+
data: DefPathData)
85+
-> DefIndex {
86+
self.definitions.create_def_with_parent(parent, node_id, data)
87+
}
88+
89+
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
90+
debug!("ast_map: {:?} => {:?}", id, entry);
91+
let len = self.map.len();
92+
if id as usize >= len {
93+
self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
94+
}
95+
self.map[id as usize] = entry;
96+
}
97+
98+
fn insert_def(&mut self, id: NodeId, node: Node<'ast>, data: DefPathData) -> DefIndex {
99+
self.insert(id, node);
100+
self.create_def(id, data)
101+
}
102+
103+
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
104+
let entry = MapEntry::from_node(self.parent_node, node);
105+
self.insert_entry(id, entry);
106+
}
107+
108+
fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
109+
for a in &decl.inputs {
110+
self.insert(a.id, NodeArg(&*a.pat));
111+
}
112+
}
113+
}
114+
115+
impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
116+
fn visit_item(&mut self, i: &'ast Item) {
117+
// Pick the def data. This need not be unique, but the more
118+
// information we encapsulate into
119+
let def_data = match i.node {
120+
ItemDefaultImpl(..) | ItemImpl(..) => DefPathData::Impl,
121+
ItemEnum(..) | ItemStruct(..) | ItemTrait(..) => DefPathData::Type(i.name),
122+
ItemExternCrate(..) | ItemMod(..) => DefPathData::Mod(i.name),
123+
ItemStatic(..) | ItemConst(..) | ItemFn(..) => DefPathData::Value(i.name),
124+
_ => DefPathData::Misc,
125+
};
126+
127+
self.insert_def(i.id, NodeItem(i), def_data);
128+
129+
let parent_node = self.parent_node;
130+
self.parent_node = i.id;
131+
132+
match i.node {
133+
ItemImpl(..) => {}
134+
ItemEnum(ref enum_definition, _) => {
135+
for v in &enum_definition.variants {
136+
let variant_def_index =
137+
self.insert_def(v.node.id,
138+
NodeVariant(&**v),
139+
DefPathData::EnumVariant(v.node.name));
140+
141+
match v.node.kind {
142+
TupleVariantKind(ref args) => {
143+
for arg in args {
144+
self.create_def_with_parent(Some(variant_def_index),
145+
arg.id,
146+
DefPathData::PositionalField);
147+
}
148+
}
149+
StructVariantKind(ref def) => {
150+
for field in &def.fields {
151+
self.create_def_with_parent(
152+
Some(variant_def_index),
153+
field.node.id,
154+
DefPathData::Field(field.node.kind));
155+
}
156+
}
157+
}
158+
}
159+
}
160+
ItemForeignMod(..) => {
161+
}
162+
ItemStruct(ref struct_def, _) => {
163+
// If this is a tuple-like struct, register the constructor.
164+
if let Some(ctor_id) = struct_def.ctor_id {
165+
self.insert_def(ctor_id,
166+
NodeStructCtor(&**struct_def),
167+
DefPathData::StructCtor);
168+
}
169+
170+
for field in &struct_def.fields {
171+
self.create_def(field.node.id, DefPathData::Field(field.node.kind));
172+
}
173+
}
174+
ItemTrait(_, _, ref bounds, _) => {
175+
for b in bounds.iter() {
176+
if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
177+
self.insert(t.trait_ref.ref_id, NodeItem(i));
178+
}
179+
}
180+
}
181+
ItemUse(ref view_path) => {
182+
match view_path.node {
183+
ViewPathList(_, ref paths) => {
184+
for path in paths {
185+
self.insert(path.node.id(), NodeItem(i));
186+
}
187+
}
188+
_ => ()
189+
}
190+
}
191+
_ => {}
192+
}
193+
visit::walk_item(self, i);
194+
self.parent_node = parent_node;
195+
}
196+
197+
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
198+
self.insert_def(foreign_item.id,
199+
NodeForeignItem(foreign_item),
200+
DefPathData::Value(foreign_item.name));
201+
202+
let parent_node = self.parent_node;
203+
self.parent_node = foreign_item.id;
204+
visit::walk_foreign_item(self, foreign_item);
205+
self.parent_node = parent_node;
206+
}
207+
208+
fn visit_generics(&mut self, generics: &'ast Generics) {
209+
for ty_param in generics.ty_params.iter() {
210+
self.insert_def(ty_param.id,
211+
NodeTyParam(ty_param),
212+
DefPathData::TypeParam(ty_param.name));
213+
}
214+
215+
visit::walk_generics(self, generics);
216+
}
217+
218+
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
219+
let def_data = match ti.node {
220+
MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::Value(ti.name),
221+
TypeTraitItem(..) => DefPathData::Type(ti.name),
222+
};
223+
224+
self.insert(ti.id, NodeTraitItem(ti));
225+
self.create_def(ti.id, def_data);
226+
227+
let parent_node = self.parent_node;
228+
self.parent_node = ti.id;
229+
230+
match ti.node {
231+
ConstTraitItem(_, Some(ref expr)) => {
232+
self.create_def(expr.id, DefPathData::Initializer);
233+
}
234+
_ => { }
235+
}
236+
237+
visit::walk_trait_item(self, ti);
238+
239+
self.parent_node = parent_node;
240+
}
241+
242+
fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
243+
let def_data = match ii.node {
244+
MethodImplItem(..) | ConstImplItem(..) => DefPathData::Value(ii.name),
245+
TypeImplItem(..) => DefPathData::Type(ii.name),
246+
};
247+
248+
self.insert_def(ii.id, NodeImplItem(ii), def_data);
249+
250+
let parent_node = self.parent_node;
251+
self.parent_node = ii.id;
252+
253+
match ii.node {
254+
ConstImplItem(_, ref expr) => {
255+
self.create_def(expr.id, DefPathData::Initializer);
256+
}
257+
_ => { }
258+
}
259+
260+
visit::walk_impl_item(self, ii);
261+
262+
self.parent_node = parent_node;
263+
}
264+
265+
fn visit_pat(&mut self, pat: &'ast Pat) {
266+
let maybe_binding = match pat.node {
267+
PatIdent(_, id, _) => Some(id.node),
268+
_ => None
269+
};
270+
271+
if let Some(id) = maybe_binding {
272+
self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
273+
} else {
274+
self.insert(pat.id, NodePat(pat));
275+
}
276+
277+
let parent_node = self.parent_node;
278+
self.parent_node = pat.id;
279+
visit::walk_pat(self, pat);
280+
self.parent_node = parent_node;
281+
}
282+
283+
fn visit_expr(&mut self, expr: &'ast Expr) {
284+
self.insert(expr.id, NodeExpr(expr));
285+
286+
match expr.node {
287+
ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
288+
_ => { }
289+
}
290+
291+
let parent_node = self.parent_node;
292+
self.parent_node = expr.id;
293+
visit::walk_expr(self, expr);
294+
self.parent_node = parent_node;
295+
}
296+
297+
fn visit_stmt(&mut self, stmt: &'ast Stmt) {
298+
let id = util::stmt_id(stmt);
299+
self.insert(id, NodeStmt(stmt));
300+
let parent_node = self.parent_node;
301+
self.parent_node = id;
302+
visit::walk_stmt(self, stmt);
303+
self.parent_node = parent_node;
304+
}
305+
306+
fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
307+
b: &'ast Block, s: Span, id: NodeId) {
308+
assert_eq!(self.parent_node, id);
309+
self.visit_fn_decl(fd);
310+
visit::walk_fn(self, fk, fd, b, s);
311+
}
312+
313+
fn visit_ty(&mut self, ty: &'ast Ty) {
314+
match ty.node {
315+
TyBareFn(ref fd) => {
316+
self.visit_fn_decl(&*fd.decl);
317+
}
318+
_ => {}
319+
}
320+
visit::walk_ty(self, ty);
321+
}
322+
323+
fn visit_block(&mut self, block: &'ast Block) {
324+
self.insert(block.id, NodeBlock(block));
325+
let parent_node = self.parent_node;
326+
self.parent_node = block.id;
327+
visit::walk_block(self, block);
328+
self.parent_node = parent_node;
329+
}
330+
331+
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
332+
self.insert(lifetime.id, NodeLifetime(lifetime));
333+
}
334+
335+
fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
336+
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
337+
self.visit_lifetime(&def.lifetime);
338+
}
339+
340+
fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
341+
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
342+
}
343+
}
344+

0 commit comments

Comments
 (0)