(index<- )        ./libsyntax/ast_map.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012-2013 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 abi;
  12  use ast::*;
  13  use ast_util;
  14  use codemap::Span;
  15  use fold::Folder;
  16  use fold;
  17  use parse::token;
  18  use print::pprust;
  19  use util::small_vector::SmallVector;
  20  
  21  use std::cell::RefCell;
  22  use std::fmt;
  23  use std::iter;
  24  use std::slice;
  25  use std::strbuf::StrBuf;
  26  
  27  #[deriving(Clone, Eq)]
  28  pub enum PathElem {
  29      PathMod(Name),
  30      PathName(Name)
  31  }
  32  
  33  impl PathElem {
  34      pub fn name(&self) -> Name {
  35          match *self {
  36              PathMod(name) | PathName(name) => name
  37          }
  38      }
  39  }
  40  
  41  impl fmt::Show for PathElem {
  42      fn fmt(&self, f&mut fmt::Formatter) -> fmt::Result {
  43          let slot = token::get_name(self.name());
  44          write!(f.buf, "{}", slot)
  45      }
  46  }
  47  
  48  #[deriving(Clone)]
  49  struct LinkedPathNode<'a> {
  50      node: PathElem,
  51      next: LinkedPath<'a>,
  52  }
  53  
  54  type LinkedPath<'a> = Option<&'a LinkedPathNode<'a>>;
  55  
  56  impl<'a> Iterator<PathElem> for LinkedPath<'a> {
  57      fn next(&mut self) -> Option<PathElem> {
  58          match *self {
  59              Some(node) => {
  60                  *self = node.next;
  61                  Some(node.node)
  62              }
  63              None => None
  64          }
  65      }
  66  }
  67  
  68  // HACK(eddyb) move this into libstd (value wrapper for slice::Items).
  69  #[deriving(Clone)]
  70  pub struct Values<'a, T>(pub slice::Items<'a, T>);
  71  
  72  impl<'a, T: Copy> Iterator<T> for Values<'a, T> {
  73      fn next(&mut self) -> Option<T> {
  74          let &Values(ref mut items) = self;
  75          items.next().map(|&x| x)
  76      }
  77  }
  78  
  79  /// The type of the iterator used by with_path.
  80  pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
  81  
  82  pub fn path_to_str<PI: Iterator<PathElem>>(mut pathPI) -> StrBuf {
  83      let itr = token::get_ident_interner();
  84  
  85      path.fold(StrBuf::new(), |mut s, e| {
  86          let e = itr.get(e.name());
  87          if !s.is_empty() {
  88              s.push_str("::");
  89          }
  90          s.push_str(e.as_slice());
  91          s
  92      }).to_strbuf()
  93  }
  94  
  95  #[deriving(Clone)]
  96  pub enum Node {
  97      NodeItem(@Item),
  98      NodeForeignItem(@ForeignItem),
  99      NodeTraitMethod(@TraitMethod),
 100      NodeMethod(@Method),
 101      NodeVariant(P<Variant>),
 102      NodeExpr(@Expr),
 103      NodeStmt(@Stmt),
 104      NodeArg(@Pat),
 105      NodeLocal(@Pat),
 106      NodeBlock(P<Block>),
 107  
 108      /// NodeStructCtor represents a tuple struct.
 109      NodeStructCtor(@StructDef),
 110  
 111      NodeLifetime(@Lifetime),
 112  }
 113  
 114  // The odd layout is to bring down the total size.
 115  #[deriving(Clone)]
 116  enum MapEntry {
 117      // Placeholder for holes in the map.
 118      NotPresent,
 119  
 120      // All the node types, with a parent ID.
 121      EntryItem(NodeId, @Item),
 122      EntryForeignItem(NodeId, @ForeignItem),
 123      EntryTraitMethod(NodeId, @TraitMethod),
 124      EntryMethod(NodeId, @Method),
 125      EntryVariant(NodeId, P<Variant>),
 126      EntryExpr(NodeId, @Expr),
 127      EntryStmt(NodeId, @Stmt),
 128      EntryArg(NodeId, @Pat),
 129      EntryLocal(NodeId, @Pat),
 130      EntryBlock(NodeId, P<Block>),
 131      EntryStructCtor(NodeId, @StructDef),
 132      EntryLifetime(NodeId, @Lifetime),
 133  
 134      // Roots for node trees.
 135      RootCrate,
 136      RootInlinedParent(P<InlinedParent>)
 137  }
 138  
 139  struct InlinedParent {
 140      path: Vec<PathElem> ,
 141      // Required by NodeTraitMethod and NodeMethod.
 142      def_id: DefId
 143  }
 144  
 145  impl MapEntry {
 146      fn parent(&self) -> Option<NodeId> {
 147          Some(match *self {
 148              EntryItem(id, _) => id,
 149              EntryForeignItem(id, _) => id,
 150              EntryTraitMethod(id, _) => id,
 151              EntryMethod(id, _) => id,
 152              EntryVariant(id, _) => id,
 153              EntryExpr(id, _) => id,
 154              EntryStmt(id, _) => id,
 155              EntryArg(id, _) => id,
 156              EntryLocal(id, _) => id,
 157              EntryBlock(id, _) => id,
 158              EntryStructCtor(id, _) => id,
 159              EntryLifetime(id, _) => id,
 160              _ => return None
 161          })
 162      }
 163  
 164      fn to_node(&self) -> Option<Node> {
 165          Some(match *self {
 166              EntryItem(_, p) => NodeItem(p),
 167              EntryForeignItem(_, p) => NodeForeignItem(p),
 168              EntryTraitMethod(_, p) => NodeTraitMethod(p),
 169              EntryMethod(_, p) => NodeMethod(p),
 170              EntryVariant(_, p) => NodeVariant(p),
 171              EntryExpr(_, p) => NodeExpr(p),
 172              EntryStmt(_, p) => NodeStmt(p),
 173              EntryArg(_, p) => NodeArg(p),
 174              EntryLocal(_, p) => NodeLocal(p),
 175              EntryBlock(_, p) => NodeBlock(p),
 176              EntryStructCtor(_, p) => NodeStructCtor(p),
 177              EntryLifetime(_, p) => NodeLifetime(p),
 178              _ => return None
 179          })
 180      }
 181  }
 182  
 183  pub struct Map {
 184      /// NodeIds are sequential integers from 0, so we can be
 185      /// super-compact by storing them in a vector. Not everything with
 186      /// a NodeId is in the map, but empirically the occupancy is about
 187      /// 75-80%, so there's not too much overhead (certainly less than
 188      /// a hashmap, since they (at the time of writing) have a maximum
 189      /// of 75% occupancy).
 190      ///
 191      /// Also, indexing is pretty quick when you've got a vector and
 192      /// plain old integers.
 193      map: RefCell<Vec<MapEntry> >
 194  }
 195  
 196  impl Map {
 197      fn find_entry(&self, idNodeId) -> Option<MapEntry> {
 198          let map = self.map.borrow();
 199          if map.len() > id as uint {
 200              Some(*map.get(id as uint))
 201          } else {
 202              None
 203          }
 204      }
 205  
 206      /// Retrieve the Node corresponding to `id`, failing if it cannot
 207      /// be found.
 208      pub fn get(&self, idNodeId) -> Node {
 209          match self.find(id) {
 210              Some(node) => node,
 211              None => fail!("couldn't find node id {} in the AST map", id)
 212          }
 213      }
 214  
 215      /// Retrieve the Node corresponding to `id`, returning None if
 216      /// cannot be found.
 217      pub fn find(&self, idNodeId) -> Option<Node> {
 218          self.find_entry(id).and_then(|x| x.to_node())
 219      }
 220  
 221      /// Retrieve the parent NodeId for `id`, or `id` itself if no
 222      /// parent is registered in this map.
 223      pub fn get_parent(&self, idNodeId) -> NodeId {
 224          self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
 225      }
 226  
 227      pub fn get_parent_did(&self, idNodeId) -> DefId {
 228          let parent = self.get_parent(id);
 229          match self.find_entry(parent) {
 230              Some(RootInlinedParent(data)) => data.def_id,
 231              _ => ast_util::local_def(parent)
 232          }
 233      }
 234  
 235      pub fn get_foreign_abi(&self, idNodeId) -> abi::Abi {
 236          let parent = self.get_parent(id);
 237          let abi = match self.find_entry(parent) {
 238              Some(EntryItem(_, i)) => match i.node {
 239                  ItemForeignMod(ref nm) => Some(nm.abi),
 240                  _ => None
 241              },
 242              // Wrong but OK, because the only inlined foreign items are intrinsics.
 243              Some(RootInlinedParent(_)) => Some(abi::RustIntrinsic),
 244              _ => None
 245          };
 246          match abi {
 247              Some(abi) => abi,
 248              None => fail!("expected foreign mod or inlined parent, found {}",
 249                            self.node_to_str(parent))
 250          }
 251      }
 252  
 253      pub fn get_foreign_vis(&self, idNodeId) -> Visibility {
 254          let vis = self.expect_foreign_item(id).vis;
 255          match self.find(self.get_parent(id)) {
 256              Some(NodeItem(i)) => vis.inherit_from(i.vis),
 257              _ => vis
 258          }
 259      }
 260  
 261      pub fn expect_item(&self, idNodeId) -> @Item {
 262          match self.find(id) {
 263              Some(NodeItem(item)) => item,
 264              _ => fail!("expected item, found {}", self.node_to_str(id))
 265          }
 266      }
 267  
 268      pub fn expect_struct(&self, idNodeId) -> @StructDef {
 269          match self.find(id) {
 270              Some(NodeItem(i)) => {
 271                  match i.node {
 272                      ItemStruct(struct_def, _) => struct_def,
 273                      _ => fail!("struct ID bound to non-struct")
 274                  }
 275              }
 276              Some(NodeVariant(ref variant)) => {
 277                  match (*variant).node.kind {
 278                      StructVariantKind(struct_def) => struct_def,
 279                      _ => fail!("struct ID bound to enum variant that isn't struct-like"),
 280                  }
 281              }
 282              _ => fail!(format!("expected struct, found {}", self.node_to_str(id))),
 283          }
 284      }
 285  
 286      pub fn expect_variant(&self, idNodeId) -> P<Variant> {
 287          match self.find(id) {
 288              Some(NodeVariant(variant)) => variant,
 289              _ => fail!(format!("expected variant, found {}", self.node_to_str(id))),
 290          }
 291      }
 292  
 293      pub fn expect_foreign_item(&self, idNodeId) -> @ForeignItem {
 294          match self.find(id) {
 295              Some(NodeForeignItem(item)) => item,
 296              _ => fail!("expected foreign item, found {}", self.node_to_str(id))
 297          }
 298      }
 299  
 300      pub fn get_path_elem(&self, idNodeId) -> PathElem {
 301          match self.get(id) {
 302              NodeItem(item) => {
 303                  match item.node {
 304                      ItemMod(_) | ItemForeignMod(_) => {
 305                          PathMod(item.ident.name)
 306                      }
 307                      _ => PathName(item.ident.name)
 308                  }
 309              }
 310              NodeForeignItem(i) => PathName(i.ident.name),
 311              NodeMethod(m) => PathName(m.ident.name),
 312              NodeTraitMethod(tm) => match *tm {
 313                  Required(ref m) => PathName(m.ident.name),
 314                  Provided(ref m) => PathName(m.ident.name)
 315              },
 316              NodeVariant(v) => PathName(v.node.name.name),
 317              node => fail!("no path elem for {:?}", node)
 318          }
 319      }
 320  
 321      pub fn with_path<T>(&self, idNodeId, f|PathElems-> T) -> T {
 322          self.with_path_next(id, None, f)
 323      }
 324  
 325      pub fn path_to_str(&self, idNodeId) -> StrBuf {
 326          self.with_path(id, |path| path_to_str(path))
 327      }
 328  
 329      fn path_to_str_with_ident(&self, idNodeId, iIdent) -> StrBuf {
 330          self.with_path(id, |path| {
 331              path_to_str(path.chain(Some(PathName(i.name)).move_iter()))
 332          })
 333      }
 334  
 335      fn with_path_next<T>(&self, idNodeId, nextLinkedPath, f|PathElems-> T) -> T {
 336          let parent = self.get_parent(id);
 337          let parent = match self.find_entry(id) {
 338              Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => {
 339                  // Anonymous extern items, enum variants and struct ctors
 340                  // go in the parent scope.
 341                  self.get_parent(parent)
 342              }
 343              // But tuple struct ctors don't have names, so use the path of its
 344              // parent, the struct item. Similarly with closure expressions.
 345              Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => {
 346                  return self.with_path_next(parent, next, f);
 347              }
 348              _ => parent
 349          };
 350          if parent == id {
 351              match self.find_entry(id) {
 352                  Some(RootInlinedParent(data)) => {
 353                      f(Values(data.path.iter()).chain(next))
 354                  }
 355                  _ => f(Values([].iter()).chain(next))
 356              }
 357          } else {
 358              self.with_path_next(parent, Some(&LinkedPathNode {
 359                  node: self.get_path_elem(id),
 360                  next: next
 361              }), f)
 362          }
 363      }
 364  
 365      pub fn with_attrs<T>(&self, idNodeId, f|Option<&[Attribute]>-> T) -> T {
 366          let node = self.get(id);
 367          let attrs = match node {
 368              NodeItem(ref i) => Some(i.attrs.as_slice()),
 369              NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()),
 370              NodeTraitMethod(ref tm) => match **tm {
 371                  Required(ref type_m) => Some(type_m.attrs.as_slice()),
 372                  Provided(ref m) => Some(m.attrs.as_slice())
 373              },
 374              NodeMethod(ref m) => Some(m.attrs.as_slice()),
 375              NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
 376              // unit/tuple structs take the attributes straight from
 377              // the struct definition.
 378              // FIXME(eddyb) make this work again (requires access to the map).
 379              NodeStructCtor(_) => {
 380                  return self.with_attrs(self.get_parent(id), f);
 381              }
 382              _ => None
 383          };
 384          f(attrs)
 385      }
 386  
 387      pub fn span(&self, idNodeId) -> Span {
 388          match self.find(id) {
 389              Some(NodeItem(item)) => item.span,
 390              Some(NodeForeignItem(foreign_item)) => foreign_item.span,
 391              Some(NodeTraitMethod(trait_method)) => {
 392                  match *trait_method {
 393                      Required(ref type_method) => type_method.span,
 394                      Provided(ref method) => method.span,
 395                  }
 396              }
 397              Some(NodeMethod(method)) => method.span,
 398              Some(NodeVariant(variant)) => variant.span,
 399              Some(NodeExpr(expr)) => expr.span,
 400              Some(NodeStmt(stmt)) => stmt.span,
 401              Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
 402              Some(NodeBlock(block)) => block.span,
 403              Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
 404              _ => fail!("node_span: could not find span for id {}", id),
 405          }
 406      }
 407  
 408      pub fn node_to_str(&self, idNodeId) -> StrBuf {
 409          node_id_to_str(self, id)
 410      }
 411  }
 412  
 413  pub trait FoldOps {
 414      fn new_id(&self, idNodeId) -> NodeId {
 415          id
 416      }
 417      fn new_span(&self, spanSpan) -> Span {
 418          span
 419      }
 420  }
 421  
 422  pub struct Ctx<'a, F> {
 423      map: &'a Map,
 424      // The node in which we are currently mapping (an item or a method).
 425      // When equal to DUMMY_NODE_ID, the next mapped node becomes the parent.
 426      parent: NodeId,
 427      fold_ops: F
 428  }
 429  
 430  impl<'a, F> Ctx<'a, F> {
 431      fn insert(&self, idNodeId, entryMapEntry) {
 432          (*self.map.map.borrow_mut()).grow_set(id as uint, &NotPresent, entry);
 433      }
 434  }
 435  
 436  impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
 437      fn new_id(&mut self, idNodeId) -> NodeId {
 438          let id = self.fold_ops.new_id(id);
 439          if self.parent == DUMMY_NODE_ID {
 440              self.parent = id;
 441          }
 442          id
 443      }
 444  
 445      fn new_span(&mut self, spanSpan) -> Span {
 446          self.fold_ops.new_span(span)
 447      }
 448  
 449      fn fold_item(&mut self, i@Item) -> SmallVector<@Item> {
 450          let parent = self.parent;
 451          self.parent = DUMMY_NODE_ID;
 452  
 453          let i = fold::noop_fold_item(i, self).expect_one("expected one item");
 454          assert_eq!(self.parent, i.id);
 455  
 456          match i.node {
 457              ItemImpl(_, _, _, ref ms) => {
 458                  for &m in ms.iter() {
 459                      self.insert(m.id, EntryMethod(self.parent, m));
 460                  }
 461              }
 462              ItemEnum(ref enum_definition, _) => {
 463                  for &v in enum_definition.variants.iter() {
 464                      self.insert(v.node.id, EntryVariant(self.parent, v));
 465                  }
 466              }
 467              ItemForeignMod(ref nm) => {
 468                  for &nitem in nm.items.iter() {
 469                      self.insert(nitem.id, EntryForeignItem(self.parent, nitem));
 470                  }
 471              }
 472              ItemStruct(struct_def, _) => {
 473                  // If this is a tuple-like struct, register the constructor.
 474                  match struct_def.ctor_id {
 475                      Some(ctor_id) => {
 476                          self.insert(ctor_id, EntryStructCtor(self.parent,
 477                                                               struct_def));
 478                      }
 479                      None => {}
 480                  }
 481              }
 482              ItemTrait(_, _, ref traits, ref methods) => {
 483                  for t in traits.iter() {
 484                      self.insert(t.ref_id, EntryItem(self.parent, i));
 485                  }
 486  
 487                  for tm in methods.iter() {
 488                      match *tm {
 489                          Required(ref m) => {
 490                              self.insert(m.id, EntryTraitMethod(self.parent,
 491                                                                 @(*tm).clone()));
 492                          }
 493                          Provided(m) => {
 494                              self.insert(m.id, EntryTraitMethod(self.parent,
 495                                                                 @Provided(m)));
 496                          }
 497                      }
 498                  }
 499              }
 500              _ => {}
 501          }
 502  
 503          self.parent = parent;
 504          self.insert(i.id, EntryItem(self.parent, i));
 505  
 506          SmallVector::one(i)
 507      }
 508  
 509      fn fold_pat(&mut self, pat@Pat) -> @Pat {
 510          let pat = fold::noop_fold_pat(pat, self);
 511          match pat.node {
 512              PatIdent(..) => {
 513                  // Note: this is at least *potentially* a pattern...
 514                  self.insert(pat.id, EntryLocal(self.parent, pat));
 515              }
 516              _ => {}
 517          }
 518  
 519          pat
 520      }
 521  
 522      fn fold_expr(&mut self, expr@Expr) -> @Expr {
 523          let expr = fold::noop_fold_expr(expr, self);
 524  
 525          self.insert(expr.id, EntryExpr(self.parent, expr));
 526  
 527          expr
 528      }
 529  
 530      fn fold_stmt(&mut self, stmt&Stmt) -> SmallVector<@Stmt> {
 531          let stmt = fold::noop_fold_stmt(stmt, self).expect_one("expected one statement");
 532          self.insert(ast_util::stmt_id(stmt), EntryStmt(self.parent, stmt));
 533          SmallVector::one(stmt)
 534      }
 535  
 536      fn fold_type_method(&mut self, m&TypeMethod) -> TypeMethod {
 537          let parent = self.parent;
 538          self.parent = DUMMY_NODE_ID;
 539          let m = fold::noop_fold_type_method(m, self);
 540          assert_eq!(self.parent, m.id);
 541          self.parent = parent;
 542          m
 543      }
 544  
 545      fn fold_method(&mut self, m@Method) -> @Method {
 546          let parent = self.parent;
 547          self.parent = DUMMY_NODE_ID;
 548          let m = fold::noop_fold_method(m, self);
 549          assert_eq!(self.parent, m.id);
 550          self.parent = parent;
 551          m
 552      }
 553  
 554      fn fold_fn_decl(&mut self, decl&FnDecl) -> P<FnDecl> {
 555          let decl = fold::noop_fold_fn_decl(decl, self);
 556          for a in decl.inputs.iter() {
 557              self.insert(a.id, EntryArg(self.parent, a.pat));
 558          }
 559          decl
 560      }
 561  
 562      fn fold_block(&mut self, blockP<Block>) -> P<Block> {
 563          let block = fold::noop_fold_block(block, self);
 564          self.insert(block.id, EntryBlock(self.parent, block));
 565          block
 566      }
 567  
 568      fn fold_lifetime(&mut self, lifetime&Lifetime) -> Lifetime {
 569          let lifetime = fold::noop_fold_lifetime(lifetime, self);
 570          self.insert(lifetime.id, EntryLifetime(self.parent, @lifetime));
 571          lifetime
 572      }
 573  }
 574  
 575  pub fn map_crate<F: FoldOps>(krateCrate, fold_opsF) -> (Crate, Map) {
 576      let map = Map { map: RefCell::new(Vec::new()) };
 577      let krate = {
 578          let mut cx = Ctx {
 579              map: &map,
 580              parent: CRATE_NODE_ID,
 581              fold_ops: fold_ops
 582          };
 583          cx.insert(CRATE_NODE_ID, RootCrate);
 584          cx.fold_crate(krate)
 585      };
 586  
 587      if log_enabled!(::log::DEBUG) {
 588          let map = map.map.borrow();
 589          // This only makes sense for ordered stores; note the
 590          // enumerate to count the number of entries.
 591          let (entries_less_1, _) = (*map).iter().filter(|&x| {
 592              match *x {
 593                  NotPresent => false,
 594                  _ => true
 595              }
 596          }).enumerate().last().expect("AST map was empty after folding?");
 597  
 598          let entries = entries_less_1 + 1;
 599          let vector_length = (*map).len();
 600          debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
 601                entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
 602      }
 603  
 604      (krate, map)
 605  }
 606  
 607  // Used for items loaded from external crate that are being inlined into this
 608  // crate.  The `path` should be the path to the item but should not include
 609  // the item itself.
 610  pub fn map_decoded_item<F: FoldOps>(map: &Map,
 611                                      pathVec<PathElem> ,
 612                                      fold_opsF,
 613                                      fold: |&mut Ctx<F>-> InlinedItem)
 614                                      -> InlinedItem {
 615      let mut cx = Ctx {
 616          map: map,
 617          parent: DUMMY_NODE_ID,
 618          fold_ops: fold_ops
 619      };
 620  
 621      // Generate a NodeId for the RootInlinedParent inserted below.
 622      cx.new_id(DUMMY_NODE_ID);
 623  
 624      // Methods get added to the AST map when their impl is visited.  Since we
 625      // don't decode and instantiate the impl, but just the method, we have to
 626      // add it to the table now. Likewise with foreign items.
 627      let mut def_id = DefId { krate: LOCAL_CRATE, node: DUMMY_NODE_ID };
 628      let ii = fold(&mut cx);
 629      match ii {
 630          IIItem(_) => {}
 631          IIMethod(impl_did, is_provided, m) => {
 632              let entry = if is_provided {
 633                  EntryTraitMethod(cx.parent, @Provided(m))
 634              } else {
 635                  EntryMethod(cx.parent, m)
 636              };
 637              cx.insert(m.id, entry);
 638              def_id = impl_did;
 639          }
 640          IIForeign(i) => {
 641              cx.insert(i.id, EntryForeignItem(cx.parent, i));
 642          }
 643      }
 644  
 645      cx.insert(cx.parent, RootInlinedParent(P(InlinedParent {
 646          path: path,
 647          def_id: def_id
 648      })));
 649  
 650      ii
 651  }
 652  
 653  fn node_id_to_str(map: &Map, idNodeId) -> StrBuf {
 654      match map.find(id) {
 655          Some(NodeItem(item)) => {
 656              let path_str = map.path_to_str_with_ident(id, item.ident);
 657              let item_str = match item.node {
 658                  ItemStatic(..) => "static",
 659                  ItemFn(..) => "fn",
 660                  ItemMod(..) => "mod",
 661                  ItemForeignMod(..) => "foreign mod",
 662                  ItemTy(..) => "ty",
 663                  ItemEnum(..) => "enum",
 664                  ItemStruct(..) => "struct",
 665                  ItemTrait(..) => "trait",
 666                  ItemImpl(..) => "impl",
 667                  ItemMac(..) => "macro"
 668              };
 669              (format!("{} {} (id={})", item_str, path_str, id)).to_strbuf()
 670          }
 671          Some(NodeForeignItem(item)) => {
 672              let path_str = map.path_to_str_with_ident(id, item.ident);
 673              (format!("foreign item {} (id={})", path_str, id)).to_strbuf()
 674          }
 675          Some(NodeMethod(m)) => {
 676              (format!("method {} in {} (id={})",
 677                      token::get_ident(m.ident),
 678                      map.path_to_str(id), id)).to_strbuf()
 679          }
 680          Some(NodeTraitMethod(ref tm)) => {
 681              let m = ast_util::trait_method_to_ty_method(&**tm);
 682              (format!("method {} in {} (id={})",
 683                      token::get_ident(m.ident),
 684                      map.path_to_str(id), id)).to_strbuf()
 685          }
 686          Some(NodeVariant(ref variant)) => {
 687              (format!("variant {} in {} (id={})",
 688                      token::get_ident(variant.node.name),
 689                      map.path_to_str(id), id)).to_strbuf()
 690          }
 691          Some(NodeExpr(expr)) => {
 692              (format!("expr {} (id={})",
 693                      pprust::expr_to_str(expr), id)).to_strbuf()
 694          }
 695          Some(NodeStmt(stmt)) => {
 696              (format!("stmt {} (id={})",
 697                      pprust::stmt_to_str(stmt), id)).to_strbuf()
 698          }
 699          Some(NodeArg(pat)) => {
 700              (format!("arg {} (id={})",
 701                      pprust::pat_to_str(pat), id)).to_strbuf()
 702          }
 703          Some(NodeLocal(pat)) => {
 704              (format!("local {} (id={})",
 705                      pprust::pat_to_str(pat), id)).to_strbuf()
 706          }
 707          Some(NodeBlock(block)) => {
 708              (format!("block {} (id={})",
 709                      pprust::block_to_str(block), id)).to_strbuf()
 710          }
 711          Some(NodeStructCtor(_)) => {
 712              (format!("struct_ctor {} (id={})",
 713                      map.path_to_str(id), id)).to_strbuf()
 714          }
 715          Some(NodeLifetime(ref l)) => {
 716              (format!("lifetime {} (id={})",
 717                      pprust::lifetime_to_str(*l), id)).to_strbuf()
 718          }
 719          None => {
 720              (format!("unknown node (id={})", id)).to_strbuf()
 721          }
 722      }
 723  }


libsyntax/ast_map.rs:182:1-182:1 -struct- definition:
pub struct Map {
    /// NodeIds are sequential integers from 0, so we can be
    /// super-compact by storing them in a vector. Not everything with
references:- 6
575: pub fn map_crate<F: FoldOps>(krate: Crate, fold_ops: F) -> (Crate, Map) {
576:     let map = Map { map: RefCell::new(Vec::new()) };
577:     let krate = {
--
653: fn node_id_to_str(map: &Map, id: NodeId) -> StrBuf {
654:     match map.find(id) {


libsyntax/ast_map.rs:115:19-115:19 -enum- definition:
enum MapEntry {
    // Placeholder for holes in the map.
    NotPresent,
references:- 6
430: impl<'a, F> Ctx<'a, F> {
431:     fn insert(&self, id: NodeId, entry: MapEntry) {
432:         (*self.map.map.borrow_mut()).grow_set(id as uint, &NotPresent, entry);


libsyntax/ast_map.rs:95:19-95:19 -enum- definition:
pub enum Node {
    NodeItem(@Item),
    NodeForeignItem(@ForeignItem),
references:- 5
207:     /// be found.
208:     pub fn get(&self, id: NodeId) -> Node {
209:         match self.find(id) {
--
216:     /// cannot be found.
217:     pub fn find(&self, id: NodeId) -> Option<Node> {
218:         self.find_entry(id).and_then(|x| x.to_node())


libsyntax/ast_map.rs:79:48-79:48 -NK_AS_STR_TODO- definition:
/// The type of the iterator used by with_path.
pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> StrBuf {
references:- 2
321:     pub fn with_path<T>(&self, id: NodeId, f: |PathElems| -> T) -> T {
322:         self.with_path_next(id, None, f)
--
335:     fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T {
336:         let parent = self.get_parent(id);


libsyntax/ast_map.rs:69:19-69:19 -struct- definition:
pub struct Values<'a, T>(pub slice::Items<'a, T>);
impl<'a, T: Copy> Iterator<T> for Values<'a, T> {
    fn next(&mut self) -> Option<T> {
references:- 4
79: /// The type of the iterator used by with_path.
80: pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;


libsyntax/ast_map.rs:27:23-27:23 -enum- definition:
pub enum PathElem {
    PathMod(Name),
    PathName(Name)
references:- 15
28: pub enum PathElem {
--
79: /// The type of the iterator used by with_path.
80: pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
--
139: struct InlinedParent {
140:     path: Vec<PathElem> ,
141:     // Required by NodeTraitMethod and NodeMethod.
--
300:     pub fn get_path_elem(&self, id: NodeId) -> PathElem {
301:         match self.get(id) {
--
610: pub fn map_decoded_item<F: FoldOps>(map: &Map,
611:                                     path: Vec<PathElem> ,
612:                                     fold_ops: F,


libsyntax/ast_map.rs:81:1-81:1 -fn- definition:
pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> StrBuf {
    let itr = token::get_ident_interner();
    path.fold(StrBuf::new(), |mut s, e| {
references:- 2
330:         self.with_path(id, |path| {
331:             path_to_str(path.chain(Some(PathName(i.name)).move_iter()))
332:         })


libsyntax/ast_map.rs:421:1-421:1 -struct- definition:
pub struct Ctx<'a, F> {
    map: &'a Map,
    // The node in which we are currently mapping (an item or a method).
references:- 5
577:     let krate = {
578:         let mut cx = Ctx {
579:             map: &map,
--
614:                                     -> InlinedItem {
615:     let mut cx = Ctx {
616:         map: map,


libsyntax/ast_map.rs:48:19-48:19 -struct- definition:
struct LinkedPathNode<'a> {
    node: PathElem,
    next: LinkedPath<'a>,
references:- 6
49: struct LinkedPathNode<'a> {
--
357:         } else {
358:             self.with_path_next(parent, Some(&LinkedPathNode {
359:                 node: self.get_path_elem(id),


libsyntax/ast_map.rs:53:1-53:1 -NK_AS_STR_TODO- definition:
type LinkedPath<'a> = Option<&'a LinkedPathNode<'a>>;
impl<'a> Iterator<PathElem> for LinkedPath<'a> {
    fn next(&mut self) -> Option<PathElem> {
references:- 4
335:     fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T {
336:         let parent = self.get_parent(id);


libsyntax/ast_map.rs:138:1-138:1 -struct- definition:
struct InlinedParent {
    path: Vec<PathElem> ,
    // Required by NodeTraitMethod and NodeMethod.
references:- 2
135:     RootCrate,
136:     RootInlinedParent(P<InlinedParent>)
137: }
--
645:     cx.insert(cx.parent, RootInlinedParent(P(InlinedParent {
646:         path: path,


libsyntax/ast_map.rs:412:1-412:1 -trait- definition:
pub trait FoldOps {
    fn new_id(&self, id: NodeId) -> NodeId {
        id
references:- 3
609: // the item itself.
610: pub fn map_decoded_item<F: FoldOps>(map: &Map,
611:                                     path: Vec<PathElem> ,