]> git.lizzy.rs Git - rust.git/commitdiff
Refactor the HIR so that items are stored in a map in the `Crate`,
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 17 Nov 2015 22:32:12 +0000 (17:32 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 19 Nov 2015 00:22:18 +0000 (19:22 -0500)
rather being stored inline. Refactor (and rename) the visitor so that
(by default) it only visits the interior content of an item not nested
items.

This is a [breaking-change] for anyone who uses the HIR visitor. Besides
changing `visit::` to `intravisit::`, you need to refactor your visitor
in one of two ways, depending on what it requires:

1. If you just want to visit all items (most common), you should call
   `krate.visit_all_items(&mut visitor)`.

2. If you need to visit nested items in the middle of the parent items,
   you should override `visit_nested_item` with something like:
   `self.visit_item(self.tcx.map.expect_item(item.id))`, presuming you
   have access to a tcx (or at least a HIR map).

mk/crates.mk
src/librustc_front/fold.rs
src/librustc_front/hir.rs
src/librustc_front/intravisit.rs [new file with mode: 0644]
src/librustc_front/lib.rs
src/librustc_front/lowering.rs
src/librustc_front/print/pprust.rs
src/librustc_front/util.rs
src/librustc_front/visit.rs [deleted file]

index 89a836eb7cb31355d5d98c91f01e0c7b5e5436aa..d77d99a4a1a0cb038a57708080b0d991c1aac636 100644 (file)
@@ -96,7 +96,7 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo
                      rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
                             rustc_trans rustc_privacy rustc_lint rustc_front
 
-DEPS_rustc_front := std syntax log serialize
+DEPS_rustc_front := std syntax log serialize rustc_data_structures
 DEPS_rustc_lint := rustc log syntax
 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
 DEPS_rustc_mir := rustc rustc_front syntax
index b963aba9c07eb262f56ca4b139cfc4589e27e75f..7ec4e1ba33121d99f67fa8de3b78c1c8397ba6b9 100644 (file)
@@ -77,10 +77,14 @@ fn fold_foreign_item(&mut self, ni: P<ForeignItem>) -> P<ForeignItem> {
         noop_fold_foreign_item(ni, self)
     }
 
-    fn fold_item(&mut self, i: P<Item>) -> P<Item> {
+    fn fold_item(&mut self, i: Item) -> Item {
         noop_fold_item(i, self)
     }
 
+    fn fold_item_id(&mut self, i: ItemId) -> ItemId {
+        noop_fold_item_id(i, self)
+    }
+
     fn fold_struct_field(&mut self, sf: StructField) -> StructField {
         noop_fold_struct_field(sf, self)
     }
@@ -271,10 +275,16 @@ fn fold_where_predicate(&mut self, where_predicate: WherePredicate) -> WherePred
         noop_fold_where_predicate(where_predicate, self)
     }
 
+    /// called for the `id` on each declaration
     fn new_id(&mut self, i: NodeId) -> NodeId {
         i
     }
 
+    /// called for ids that are references (e.g., ItemDef)
+    fn map_id(&mut self, i: NodeId) -> NodeId {
+        i
+    }
+
     fn new_span(&mut self, sp: Span) -> Span {
         sp
     }
@@ -342,7 +352,7 @@ pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> P<Decl> {
                 span: fld.new_span(span),
             },
             DeclItem(it) => Spanned {
-                node: DeclItem(fld.fold_item(it)),
+                node: DeclItem(fld.fold_item_id(it)),
                 span: fld.new_span(span),
             },
         }
@@ -879,34 +889,40 @@ pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T) -> P<ImplI
     })
 }
 
-pub fn noop_fold_mod<T: Folder>(Mod { inner, items }: Mod, folder: &mut T) -> Mod {
+pub fn noop_fold_mod<T: Folder>(Mod { inner, item_ids }: Mod, folder: &mut T) -> Mod {
     Mod {
         inner: folder.new_span(inner),
-        items: items.into_iter().map(|x| folder.fold_item(x)).collect(),
+        item_ids: item_ids.into_iter().map(|x| folder.fold_item_id(x)).collect(),
     }
 }
 
-pub fn noop_fold_crate<T: Folder>(Crate { module, attrs, config, span, exported_macros }: Crate,
+pub fn noop_fold_crate<T: Folder>(Crate { module, attrs, config, span,
+                                          exported_macros, items }: Crate,
                                   folder: &mut T)
                                   -> Crate {
     let config = folder.fold_meta_items(config);
 
-    let crate_mod = folder.fold_item(P(hir::Item {
+    let crate_mod = folder.fold_item(hir::Item {
         name: token::special_idents::invalid.name,
         attrs: attrs,
         id: DUMMY_NODE_ID,
         vis: hir::Public,
         span: span,
         node: hir::ItemMod(module),
-    }));
+    });
 
-    let (module, attrs, span) =
-        crate_mod.and_then(|hir::Item { attrs, span, node, .. }| {
+    let (module, attrs, span) = match crate_mod {
+        hir::Item { attrs, span, node, .. } => {
             match node {
                 hir::ItemMod(m) => (m, attrs, span),
                 _ => panic!("fold converted a module to not a module"),
             }
-        });
+        }
+    };
+
+    let items = items.into_iter()
+                     .map(|(id, item)| (id, folder.fold_item(item)))
+                     .collect();
 
     Crate {
         module: module,
@@ -914,31 +930,37 @@ pub fn noop_fold_crate<T: Folder>(Crate { module, attrs, config, span, exported_
         config: config,
         span: span,
         exported_macros: exported_macros,
+        items: items,
     }
 }
 
-pub fn noop_fold_item<T: Folder>(item: P<Item>, folder: &mut T) -> P<Item> {
-    item.map(|Item { id, name, attrs, node, vis, span }| {
-        let id = folder.new_id(id);
-        let node = folder.fold_item_underscore(node);
-        // FIXME: we should update the impl_pretty_name, but it uses pretty printing.
-        // let ident = match node {
-        //     // The node may have changed, recompute the "pretty" impl name.
-        //     ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
-        //         impl_pretty_name(maybe_trait, Some(&**ty))
-        //     }
-        //     _ => ident
-        // };
-
-        Item {
-            id: id,
-            name: folder.fold_name(name),
-            attrs: fold_attrs(attrs, folder),
-            node: node,
-            vis: vis,
-            span: folder.new_span(span),
-        }
-    })
+pub fn noop_fold_item_id<T: Folder>(i: ItemId, folder: &mut T) -> ItemId {
+    let id = folder.map_id(i.id);
+    ItemId { id: id }
+}
+
+// fold one item into one item
+pub fn noop_fold_item<T: Folder>(item: Item, folder: &mut T) -> Item {
+    let Item { id, name, attrs, node, vis, span } = item;
+    let id = folder.new_id(id);
+    let node = folder.fold_item_underscore(node);
+    // FIXME: we should update the impl_pretty_name, but it uses pretty printing.
+    // let ident = match node {
+    //     // The node may have changed, recompute the "pretty" impl name.
+    //     ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
+    //         impl_pretty_name(maybe_trait, Some(&**ty))
+    //     }
+    //     _ => ident
+    // };
+
+    Item {
+        id: id,
+        name: folder.fold_name(name),
+        attrs: fold_attrs(attrs, folder),
+        node: node,
+        vis: vis,
+        span: folder.new_span(span),
+    }
 }
 
 pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) -> P<ForeignItem> {
index 1fa7c9d301c0de5ece11ce0287ac530d1d88e3d8..4232254327cdec14221f85577018cc2c17603016 100644 (file)
@@ -35,6 +35,8 @@
 pub use self::Visibility::*;
 pub use self::PathParameters::*;
 
+use intravisit::Visitor;
+use rustc_data_structures::fnv::FnvHashMap;
 use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId};
 use syntax::abi::Abi;
 use syntax::ast::{Name, Ident, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
@@ -320,13 +322,42 @@ pub struct WhereEqPredicate {
     pub ty: P<Ty>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate {
     pub module: Mod,
     pub attrs: Vec<Attribute>,
     pub config: CrateConfig,
     pub span: Span,
     pub exported_macros: Vec<MacroDef>,
+    pub items: FnvHashMap<NodeId, Item>,
+}
+
+impl Crate {
+    pub fn item(&self, id: NodeId) -> &Item {
+        &self.items[&id]
+    }
+
+    /// Visits all items in the crate in some determinstic (but
+    /// unspecified) order. If you just need to process every item,
+    /// but don't care about nesting, this method is the best choice.
+    ///
+    /// If you do care about nesting -- usually because your algorithm
+    /// follows lexical scoping rules -- then you want a different
+    /// approach. You should override `visit_nested_item` in your
+    /// visitor and then call `intravisit::walk_crate` instead.
+    pub fn visit_all_items<'hir, V:Visitor<'hir>>(&'hir self, visitor: &mut V) {
+        // In principle, we could just iterate over the hashmap, but
+        // in practice that makes the order of error reporting vary
+        // with small changes in the input etc etc, which makes the
+        // test base hard to maintain. So instead we sort by node-id
+        // so as to get reproducible results.
+        let mut pairs: Vec<_> = self.items.iter().collect();
+        pairs.sort_by(|&(id1, _), &(id2, _)| id1.cmp(id2));
+
+        for (_, item) in pairs {
+            visitor.visit_item(item);
+        }
+    }
 }
 
 /// A macro definition, in this crate or imported from another.
@@ -537,7 +568,7 @@ pub enum Decl_ {
     /// A local (let) binding:
     DeclLocal(P<Local>),
     /// An item binding:
-    DeclItem(P<Item>),
+    DeclItem(ItemId),
 }
 
 /// represents one arm of a 'match'
@@ -992,7 +1023,7 @@ pub struct Mod {
     /// For `mod foo;`, the inner span ranges from the first token
     /// to the last token in the external file.
     pub inner: Span,
-    pub items: Vec<P<Item>>,
+    pub item_ids: Vec<ItemId>,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -1205,7 +1236,13 @@ pub fn is_unit(&self) -> bool {
     }
 }
 
-
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct ItemId {
+    pub id: NodeId,
+}
 
 //  FIXME (#3300): Should allow items to be anonymous. Right now
 //  we just use dummy names for anon items.
diff --git a/src/librustc_front/intravisit.rs b/src/librustc_front/intravisit.rs
new file mode 100644 (file)
index 0000000..9c923ea
--- /dev/null
@@ -0,0 +1,816 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! HIR walker. Each overridden visit method has full control over what
+//! happens with its node, it can do its own traversal of the node's children,
+//! call `visit::walk_*` to apply the default traversal algorithm, or prevent
+//! deeper traversal by doing nothing.
+//!
+//! Note: it is an important invariant that the default visitor walks the body
+//! of a function in "execution order" (more concretely, reverse post-order
+//! with respect to the CFG implied by the AST), meaning that if AST node A may
+//! execute before AST node B, then A is visited first.  The borrow checker in
+//! particular relies on this property.
+//!
+//! Note: walking an AST before macro expansion is probably a bad idea. For
+//! instance, a walker looking for item names in a module will miss all of
+//! those that are created by the expansion of a macro.
+
+use syntax::abi::Abi;
+use syntax::ast::{Ident, NodeId, CRATE_NODE_ID, Name, Attribute};
+use syntax::codemap::Span;
+use hir::*;
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub enum FnKind<'a> {
+    /// fn foo() or extern "Abi" fn foo()
+    ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, Visibility),
+
+    /// fn foo(&self)
+    Method(Name, &'a MethodSig, Option<Visibility>),
+
+    /// |x, y| {}
+    Closure,
+}
+
+/// Each method of the Visitor trait is a hook to be potentially
+/// overridden.  Each method's default implementation recursively visits
+/// the substructure of the input via the corresponding `walk` method;
+/// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
+///
+/// Note that this visitor does NOT visit nested items by default. If
+/// you simply want to visit all items in the crate in some order, you
+/// should call `Crate::visit_all_items`. Otherwise, see the comment
+/// on `visit_nested_item` for details on how to visit nested items.
+///
+/// If you want to ensure that your code handles every variant
+/// explicitly, you need to override each method.  (And you also need
+/// to monitor future changes to `Visitor` in case a new method with a
+/// new default implementation gets introduced.)
+pub trait Visitor<'v> : Sized {
+    ///////////////////////////////////////////////////////////////////////////
+    // Nested items.
+
+    /// Invoked when a nested item is encountered. By default, does
+    /// nothing. If you want a deep walk, you need to override to
+    /// fetch the item contents. But most of the time, it is easier
+    /// (and better) to invoke `Crate::visit_all_items`, which visits
+    /// all items in the crate in some order (but doesn't respect
+    /// nesting).
+    #[allow(unused_variables)]
+    fn visit_nested_item(&mut self, id: ItemId) {
+    }
+
+    /// Visit the top-level item and (optionally) nested items. See
+    /// `visit_nested_item` for details.
+    fn visit_item(&mut self, i: &'v Item) {
+        walk_item(self, i)
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    fn visit_name(&mut self, _span: Span, _name: Name) {
+        // Nothing to do.
+    }
+    fn visit_ident(&mut self, span: Span, ident: Ident) {
+        walk_ident(self, span, ident);
+    }
+    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) {
+        walk_mod(self, m)
+    }
+    fn visit_foreign_item(&mut self, i: &'v ForeignItem) {
+        walk_foreign_item(self, i)
+    }
+    fn visit_local(&mut self, l: &'v Local) {
+        walk_local(self, l)
+    }
+    fn visit_block(&mut self, b: &'v Block) {
+        walk_block(self, b)
+    }
+    fn visit_stmt(&mut self, s: &'v Stmt) {
+        walk_stmt(self, s)
+    }
+    fn visit_arm(&mut self, a: &'v Arm) {
+        walk_arm(self, a)
+    }
+    fn visit_pat(&mut self, p: &'v Pat) {
+        walk_pat(self, p)
+    }
+    fn visit_decl(&mut self, d: &'v Decl) {
+        walk_decl(self, d)
+    }
+    fn visit_expr(&mut self, ex: &'v Expr) {
+        walk_expr(self, ex)
+    }
+    fn visit_expr_post(&mut self, _ex: &'v Expr) {
+    }
+    fn visit_ty(&mut self, t: &'v Ty) {
+        walk_ty(self, t)
+    }
+    fn visit_generics(&mut self, g: &'v Generics) {
+        walk_generics(self, g)
+    }
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
+        walk_fn(self, fk, fd, b, s)
+    }
+    fn visit_trait_item(&mut self, ti: &'v TraitItem) {
+        walk_trait_item(self, ti)
+    }
+    fn visit_impl_item(&mut self, ii: &'v ImplItem) {
+        walk_impl_item(self, ii)
+    }
+    fn visit_trait_ref(&mut self, t: &'v TraitRef) {
+        walk_trait_ref(self, t)
+    }
+    fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
+        walk_ty_param_bound(self, bounds)
+    }
+    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
+        walk_poly_trait_ref(self, t, m)
+    }
+    fn visit_variant_data(&mut self,
+                          s: &'v VariantData,
+                          _: Name,
+                          _: &'v Generics,
+                          _: NodeId,
+                          _: Span) {
+        walk_struct_def(self, s)
+    }
+    fn visit_struct_field(&mut self, s: &'v StructField) {
+        walk_struct_field(self, s)
+    }
+    fn visit_enum_def(&mut self,
+                      enum_definition: &'v EnumDef,
+                      generics: &'v Generics,
+                      item_id: NodeId,
+                      _: Span) {
+        walk_enum_def(self, enum_definition, generics, item_id)
+    }
+    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
+        walk_variant(self, v, g, item_id)
+    }
+    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
+        walk_lifetime(self, lifetime)
+    }
+    fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
+        walk_lifetime_def(self, lifetime)
+    }
+    fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
+        walk_explicit_self(self, es)
+    }
+    fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
+        walk_path(self, path)
+    }
+    fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
+        walk_path_list_item(self, prefix, item)
+    }
+    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
+        walk_path_segment(self, path_span, path_segment)
+    }
+    fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
+        walk_path_parameters(self, path_span, path_parameters)
+    }
+    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
+        walk_assoc_type_binding(self, type_binding)
+    }
+    fn visit_attribute(&mut self, _attr: &'v Attribute) {
+    }
+    fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
+        walk_macro_def(self, macro_def)
+    }
+}
+
+pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
+    for name in opt_name {
+        visitor.visit_name(span, name);
+    }
+}
+
+pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
+    for ident in opt_ident {
+        visitor.visit_ident(span, ident);
+    }
+}
+
+pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
+    visitor.visit_name(span, ident.name);
+}
+
+/// Walks the contents of a crate. See also `Crate::visit_all_items`.
+pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
+    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
+    walk_list!(visitor, visit_attribute, &krate.attrs);
+    walk_list!(visitor, visit_macro_def, &krate.exported_macros);
+}
+
+pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
+    visitor.visit_name(macro_def.span, macro_def.name);
+    walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
+    walk_list!(visitor, visit_attribute, &macro_def.attrs);
+}
+
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
+    for &item_id in &module.item_ids {
+        visitor.visit_nested_item(item_id);
+    }
+}
+
+pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
+    visitor.visit_pat(&local.pat);
+    walk_list!(visitor, visit_ty, &local.ty);
+    walk_list!(visitor, visit_expr, &local.init);
+}
+
+pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
+    visitor.visit_name(lifetime.span, lifetime.name);
+}
+
+pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {
+    visitor.visit_lifetime(&lifetime_def.lifetime);
+    walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
+}
+
+pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, explicit_self: &'v ExplicitSelf) {
+    match explicit_self.node {
+        SelfStatic => {}
+        SelfValue(name) => {
+            visitor.visit_name(explicit_self.span, name)
+        }
+        SelfRegion(ref opt_lifetime, _, name) => {
+            visitor.visit_name(explicit_self.span, name);
+            walk_list!(visitor, visit_lifetime, opt_lifetime);
+        }
+        SelfExplicit(ref typ, name) => {
+            visitor.visit_name(explicit_self.span, name);
+            visitor.visit_ty(typ)
+        }
+    }
+}
+
+pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
+                                  trait_ref: &'v PolyTraitRef,
+                                  _modifier: &'v TraitBoundModifier)
+    where V: Visitor<'v>
+{
+    walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
+    visitor.visit_trait_ref(&trait_ref.trait_ref);
+}
+
+pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
+    where V: Visitor<'v>
+{
+    visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
+}
+
+pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
+    visitor.visit_name(item.span, item.name);
+    match item.node {
+        ItemExternCrate(opt_name) => {
+            walk_opt_name(visitor, item.span, opt_name)
+        }
+        ItemUse(ref vp) => {
+            match vp.node {
+                ViewPathSimple(name, ref path) => {
+                    visitor.visit_name(vp.span, name);
+                    visitor.visit_path(path, item.id);
+                }
+                ViewPathGlob(ref path) => {
+                    visitor.visit_path(path, item.id);
+                }
+                ViewPathList(ref prefix, ref list) => {
+                    if !list.is_empty() {
+                        for item in list {
+                            visitor.visit_path_list_item(prefix, item)
+                        }
+                    } else {
+                        visitor.visit_path(prefix, item.id);
+                    }
+                }
+            }
+        }
+        ItemStatic(ref typ, _, ref expr) |
+        ItemConst(ref typ, ref expr) => {
+            visitor.visit_ty(typ);
+            visitor.visit_expr(expr);
+        }
+        ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
+            visitor.visit_fn(FnKind::ItemFn(item.name,
+                                            generics,
+                                            unsafety,
+                                            constness,
+                                            abi,
+                                            item.vis),
+                             declaration,
+                             body,
+                             item.span,
+                             item.id)
+        }
+        ItemMod(ref module) => {
+            visitor.visit_mod(module, item.span, item.id)
+        }
+        ItemForeignMod(ref foreign_module) => {
+            walk_list!(visitor, visit_foreign_item, &foreign_module.items);
+        }
+        ItemTy(ref typ, ref type_parameters) => {
+            visitor.visit_ty(typ);
+            visitor.visit_generics(type_parameters)
+        }
+        ItemEnum(ref enum_definition, ref type_parameters) => {
+            visitor.visit_generics(type_parameters);
+            visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
+        }
+        ItemDefaultImpl(_, ref trait_ref) => {
+            visitor.visit_trait_ref(trait_ref)
+        }
+        ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
+            visitor.visit_generics(type_parameters);
+            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
+            visitor.visit_ty(typ);
+            walk_list!(visitor, visit_impl_item, impl_items);
+        }
+        ItemStruct(ref struct_definition, ref generics) => {
+            visitor.visit_generics(generics);
+            visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
+        }
+        ItemTrait(_, ref generics, ref bounds, ref methods) => {
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_trait_item, methods);
+        }
+    }
+    walk_list!(visitor, visit_attribute, &item.attrs);
+}
+
+pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
+                                         enum_definition: &'v EnumDef,
+                                         generics: &'v Generics,
+                                         item_id: NodeId) {
+    walk_list!(visitor,
+               visit_variant,
+               &enum_definition.variants,
+               generics,
+               item_id);
+}
+
+pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
+                                        variant: &'v Variant,
+                                        generics: &'v Generics,
+                                        item_id: NodeId) {
+    visitor.visit_name(variant.span, variant.node.name);
+    visitor.visit_variant_data(&variant.node.data,
+                               variant.node.name,
+                               generics,
+                               item_id,
+                               variant.span);
+    walk_list!(visitor, visit_expr, &variant.node.disr_expr);
+    walk_list!(visitor, visit_attribute, &variant.node.attrs);
+}
+
+pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
+    match typ.node {
+        TyVec(ref ty) => {
+            visitor.visit_ty(ty)
+        }
+        TyPtr(ref mutable_type) => {
+            visitor.visit_ty(&mutable_type.ty)
+        }
+        TyRptr(ref opt_lifetime, ref mutable_type) => {
+            walk_list!(visitor, visit_lifetime, opt_lifetime);
+            visitor.visit_ty(&mutable_type.ty)
+        }
+        TyTup(ref tuple_element_types) => {
+            walk_list!(visitor, visit_ty, tuple_element_types);
+        }
+        TyBareFn(ref function_declaration) => {
+            walk_fn_decl(visitor, &function_declaration.decl);
+            walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
+        }
+        TyPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            visitor.visit_path(path, typ.id);
+        }
+        TyObjectSum(ref ty, ref bounds) => {
+            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+        }
+        TyFixedLengthVec(ref ty, ref expression) => {
+            visitor.visit_ty(ty);
+            visitor.visit_expr(expression)
+        }
+        TyPolyTraitRef(ref bounds) => {
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+        }
+        TyTypeof(ref expression) => {
+            visitor.visit_expr(expression)
+        }
+        TyInfer => {}
+    }
+}
+
+pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
+    for segment in &path.segments {
+        visitor.visit_path_segment(path.span, segment);
+    }
+}
+
+pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
+                                               prefix: &'v Path,
+                                               item: &'v PathListItem) {
+    for segment in &prefix.segments {
+        visitor.visit_path_segment(prefix.span, segment);
+    }
+
+    walk_opt_name(visitor, item.span, item.node.name());
+    walk_opt_name(visitor, item.span, item.node.rename());
+}
+
+pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
+                                             path_span: Span,
+                                             segment: &'v PathSegment) {
+    visitor.visit_ident(path_span, segment.identifier);
+    visitor.visit_path_parameters(path_span, &segment.parameters);
+}
+
+pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                _path_span: Span,
+                                                path_parameters: &'v PathParameters) {
+    match *path_parameters {
+        AngleBracketedParameters(ref data) => {
+            walk_list!(visitor, visit_ty, &data.types);
+            walk_list!(visitor, visit_lifetime, &data.lifetimes);
+            walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
+        }
+        ParenthesizedParameters(ref data) => {
+            walk_list!(visitor, visit_ty, &data.inputs);
+            walk_list!(visitor, visit_ty, &data.output);
+        }
+    }
+}
+
+pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                   type_binding: &'v TypeBinding) {
+    visitor.visit_name(type_binding.span, type_binding.name);
+    visitor.visit_ty(&type_binding.ty);
+}
+
+pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
+    match pattern.node {
+        PatEnum(ref path, ref opt_children) => {
+            visitor.visit_path(path, pattern.id);
+            if let Some(ref children) = *opt_children {
+                walk_list!(visitor, visit_pat, children);
+            }
+        }
+        PatQPath(ref qself, ref path) => {
+            visitor.visit_ty(&qself.ty);
+            visitor.visit_path(path, pattern.id)
+        }
+        PatStruct(ref path, ref fields, _) => {
+            visitor.visit_path(path, pattern.id);
+            for field in fields {
+                visitor.visit_name(field.span, field.node.name);
+                visitor.visit_pat(&field.node.pat)
+            }
+        }
+        PatTup(ref tuple_elements) => {
+            walk_list!(visitor, visit_pat, tuple_elements);
+        }
+        PatBox(ref subpattern) |
+        PatRegion(ref subpattern, _) => {
+            visitor.visit_pat(subpattern)
+        }
+        PatIdent(_, ref pth1, ref optional_subpattern) => {
+            visitor.visit_ident(pth1.span, pth1.node);
+            walk_list!(visitor, visit_pat, optional_subpattern);
+        }
+        PatLit(ref expression) => visitor.visit_expr(expression),
+        PatRange(ref lower_bound, ref upper_bound) => {
+            visitor.visit_expr(lower_bound);
+            visitor.visit_expr(upper_bound)
+        }
+        PatWild => (),
+        PatVec(ref prepatterns, ref slice_pattern, ref postpatterns) => {
+            walk_list!(visitor, visit_pat, prepatterns);
+            walk_list!(visitor, visit_pat, slice_pattern);
+            walk_list!(visitor, visit_pat, postpatterns);
+        }
+    }
+}
+
+pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
+    visitor.visit_name(foreign_item.span, foreign_item.name);
+
+    match foreign_item.node {
+        ForeignItemFn(ref function_declaration, ref generics) => {
+            walk_fn_decl(visitor, function_declaration);
+            visitor.visit_generics(generics)
+        }
+        ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
+    }
+
+    walk_list!(visitor, visit_attribute, &foreign_item.attrs);
+}
+
+pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
+    match *bound {
+        TraitTyParamBound(ref typ, ref modifier) => {
+            visitor.visit_poly_trait_ref(typ, modifier);
+        }
+        RegionTyParamBound(ref lifetime) => {
+            visitor.visit_lifetime(lifetime);
+        }
+    }
+}
+
+pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
+    for param in &generics.ty_params {
+        visitor.visit_name(param.span, param.name);
+        walk_list!(visitor, visit_ty_param_bound, &param.bounds);
+        walk_list!(visitor, visit_ty, &param.default);
+    }
+    walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
+    for predicate in &generics.where_clause.predicates {
+        match predicate {
+            &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
+                                                                          ref bounds,
+                                                                          ref bound_lifetimes,
+                                                                          ..}) => {
+                visitor.visit_ty(bounded_ty);
+                walk_list!(visitor, visit_ty_param_bound, bounds);
+                walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
+            }
+            &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
+                                                                            ref bounds,
+                                                                            ..}) => {
+                visitor.visit_lifetime(lifetime);
+                walk_list!(visitor, visit_lifetime, bounds);
+            }
+            &WherePredicate::EqPredicate(WhereEqPredicate{id,
+                                                                    ref path,
+                                                                    ref ty,
+                                                                    ..}) => {
+                visitor.visit_path(path, id);
+                visitor.visit_ty(ty);
+            }
+        }
+    }
+}
+
+pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
+    if let Return(ref output_ty) = *ret_ty {
+        visitor.visit_ty(output_ty)
+    }
+}
+
+pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
+    for argument in &function_declaration.inputs {
+        visitor.visit_pat(&argument.pat);
+        visitor.visit_ty(&argument.ty)
+    }
+    walk_fn_ret_ty(visitor, &function_declaration.output)
+}
+
+pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
+    for argument in &function_declaration.inputs {
+        visitor.visit_ty(&argument.ty)
+    }
+    walk_fn_ret_ty(visitor, &function_declaration.output)
+}
+
+pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
+    match function_kind {
+        FnKind::ItemFn(_, generics, _, _, _, _) => {
+            visitor.visit_generics(generics);
+        }
+        FnKind::Method(_, sig, _) => {
+            visitor.visit_generics(&sig.generics);
+            visitor.visit_explicit_self(&sig.explicit_self);
+        }
+        FnKind::Closure => {}
+    }
+}
+
+pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
+                                   function_kind: FnKind<'v>,
+                                   function_declaration: &'v FnDecl,
+                                   function_body: &'v Block,
+                                   _span: Span) {
+    walk_fn_decl(visitor, function_declaration);
+    walk_fn_kind(visitor, function_kind);
+    visitor.visit_block(function_body)
+}
+
+pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
+    visitor.visit_name(trait_item.span, trait_item.name);
+    walk_list!(visitor, visit_attribute, &trait_item.attrs);
+    match trait_item.node {
+        ConstTraitItem(ref ty, ref default) => {
+            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_expr, default);
+        }
+        MethodTraitItem(ref sig, None) => {
+            visitor.visit_explicit_self(&sig.explicit_self);
+            visitor.visit_generics(&sig.generics);
+            walk_fn_decl(visitor, &sig.decl);
+        }
+        MethodTraitItem(ref sig, Some(ref body)) => {
+            visitor.visit_fn(FnKind::Method(trait_item.name, sig, None),
+                             &sig.decl,
+                             body,
+                             trait_item.span,
+                             trait_item.id);
+        }
+        TypeTraitItem(ref bounds, ref default) => {
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_ty, default);
+        }
+    }
+}
+
+pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
+    visitor.visit_name(impl_item.span, impl_item.name);
+    walk_list!(visitor, visit_attribute, &impl_item.attrs);
+    match impl_item.node {
+        ImplItemKind::Const(ref ty, ref expr) => {
+            visitor.visit_ty(ty);
+            visitor.visit_expr(expr);
+        }
+        ImplItemKind::Method(ref sig, ref body) => {
+            visitor.visit_fn(FnKind::Method(impl_item.name, sig, Some(impl_item.vis)),
+                             &sig.decl,
+                             body,
+                             impl_item.span,
+                             impl_item.id);
+        }
+        ImplItemKind::Type(ref ty) => {
+            visitor.visit_ty(ty);
+        }
+    }
+}
+
+pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
+    walk_list!(visitor, visit_struct_field, struct_definition.fields());
+}
+
+pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
+    walk_opt_name(visitor, struct_field.span, struct_field.node.name());
+    visitor.visit_ty(&struct_field.node.ty);
+    walk_list!(visitor, visit_attribute, &struct_field.node.attrs);
+}
+
+pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
+    walk_list!(visitor, visit_stmt, &block.stmts);
+    walk_list!(visitor, visit_expr, &block.expr);
+}
+
+pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
+    match statement.node {
+        StmtDecl(ref declaration, _) => visitor.visit_decl(declaration),
+        StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
+            visitor.visit_expr(expression)
+        }
+    }
+}
+
+pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
+    match declaration.node {
+        DeclLocal(ref local) => visitor.visit_local(local),
+        DeclItem(item) => visitor.visit_nested_item(item),
+    }
+}
+
+pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
+    match expression.node {
+        ExprBox(ref subexpression) => {
+            visitor.visit_expr(subexpression)
+        }
+        ExprVec(ref subexpressions) => {
+            walk_list!(visitor, visit_expr, subexpressions);
+        }
+        ExprRepeat(ref element, ref count) => {
+            visitor.visit_expr(element);
+            visitor.visit_expr(count)
+        }
+        ExprStruct(ref path, ref fields, ref optional_base) => {
+            visitor.visit_path(path, expression.id);
+            for field in fields {
+                visitor.visit_name(field.name.span, field.name.node);
+                visitor.visit_expr(&field.expr)
+            }
+            walk_list!(visitor, visit_expr, optional_base);
+        }
+        ExprTup(ref subexpressions) => {
+            walk_list!(visitor, visit_expr, subexpressions);
+        }
+        ExprCall(ref callee_expression, ref arguments) => {
+            walk_list!(visitor, visit_expr, arguments);
+            visitor.visit_expr(callee_expression)
+        }
+        ExprMethodCall(ref name, ref types, ref arguments) => {
+            visitor.visit_name(name.span, name.node);
+            walk_list!(visitor, visit_expr, arguments);
+            walk_list!(visitor, visit_ty, types);
+        }
+        ExprBinary(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(left_expression);
+            visitor.visit_expr(right_expression)
+        }
+        ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
+            visitor.visit_expr(subexpression)
+        }
+        ExprLit(_) => {}
+        ExprCast(ref subexpression, ref typ) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_ty(typ)
+        }
+        ExprIf(ref head_expression, ref if_block, ref optional_else) => {
+            visitor.visit_expr(head_expression);
+            visitor.visit_block(if_block);
+            walk_list!(visitor, visit_expr, optional_else);
+        }
+        ExprWhile(ref subexpression, ref block, opt_ident) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
+        }
+        ExprLoop(ref block, opt_ident) => {
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
+        }
+        ExprMatch(ref subexpression, ref arms, _) => {
+            visitor.visit_expr(subexpression);
+            walk_list!(visitor, visit_arm, arms);
+        }
+        ExprClosure(_, ref function_declaration, ref body) => {
+            visitor.visit_fn(FnKind::Closure,
+                             function_declaration,
+                             body,
+                             expression.span,
+                             expression.id)
+        }
+        ExprBlock(ref block) => visitor.visit_block(block),
+        ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
+            visitor.visit_expr(right_hand_expression);
+            visitor.visit_expr(left_hand_expression)
+        }
+        ExprAssignOp(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(right_expression);
+            visitor.visit_expr(left_expression)
+        }
+        ExprField(ref subexpression, ref name) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_name(name.span, name.node);
+        }
+        ExprTupField(ref subexpression, _) => {
+            visitor.visit_expr(subexpression);
+        }
+        ExprIndex(ref main_expression, ref index_expression) => {
+            visitor.visit_expr(main_expression);
+            visitor.visit_expr(index_expression)
+        }
+        ExprRange(ref start, ref end) => {
+            walk_list!(visitor, visit_expr, start);
+            walk_list!(visitor, visit_expr, end);
+        }
+        ExprPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            visitor.visit_path(path, expression.id)
+        }
+        ExprBreak(ref opt_sp_ident) | ExprAgain(ref opt_sp_ident) => {
+            for sp_ident in opt_sp_ident {
+                visitor.visit_ident(sp_ident.span, sp_ident.node);
+            }
+        }
+        ExprRet(ref optional_expression) => {
+            walk_list!(visitor, visit_expr, optional_expression);
+        }
+        ExprInlineAsm(ref ia) => {
+            for &(_, ref input) in &ia.inputs {
+                visitor.visit_expr(&input)
+            }
+            for &(_, ref output, _) in &ia.outputs {
+                visitor.visit_expr(&output)
+            }
+        }
+    }
+
+    visitor.visit_expr_post(expression)
+}
+
+pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
+    walk_list!(visitor, visit_pat, &arm.pats);
+    walk_list!(visitor, visit_expr, &arm.guard);
+    visitor.visit_expr(&arm.body);
+    walk_list!(visitor, visit_attribute, &arm.attrs);
+}
index 022744cbc3a14e430ff010ae1c60a8660739e208..d8c5eac1feb5ab2bab278590528b9a638fd63507 100644 (file)
 #[macro_use]
 #[no_link]
 extern crate rustc_bitflags;
+extern crate rustc_data_structures;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
 pub mod hir;
 pub mod lowering;
 pub mod fold;
-pub mod visit;
+pub mod intravisit;
 pub mod util;
 
 pub mod print {
index 250379d2d7efc3d2df58f6b4d421b8bece9c75a9..ad081598c1124a479221b9fe97d1914716aa9652 100644 (file)
@@ -71,6 +71,8 @@
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::{self, str_to_ident};
 use syntax::std_inject;
+use syntax::visit::{self, Visitor};
+use rustc_data_structures::fnv::FnvHashMap;
 
 use std::cell::{Cell, RefCell};
 
@@ -191,7 +193,7 @@ pub fn lower_decl(lctx: &LoweringContext, d: &Decl) -> P<hir::Decl> {
             span: d.span,
         }),
         DeclItem(ref it) => P(Spanned {
-            node: hir::DeclItem(lower_item(lctx, it)),
+            node: hir::DeclItem(lower_item_id(lctx, it)),
             span: d.span,
         }),
     }
@@ -693,17 +695,36 @@ pub fn lower_impl_item(lctx: &LoweringContext, i: &ImplItem) -> P<hir::ImplItem>
 pub fn lower_mod(lctx: &LoweringContext, m: &Mod) -> hir::Mod {
     hir::Mod {
         inner: m.inner,
-        items: m.items.iter().map(|x| lower_item(lctx, x)).collect(),
+        item_ids: m.items.iter().map(|x| lower_item_id(lctx, x)).collect(),
+    }
+}
+
+struct ItemLowerer<'lcx, 'interner: 'lcx> {
+    items: FnvHashMap<NodeId, hir::Item>,
+    lctx: &'lcx LoweringContext<'interner>,
+}
+
+impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
+    fn visit_item(&mut self, item: &'lcx Item) {
+        self.items.insert(item.id, lower_item(self.lctx, item));
+        visit::walk_item(self, item);
     }
 }
 
 pub fn lower_crate(lctx: &LoweringContext, c: &Crate) -> hir::Crate {
+    let items = {
+        let mut item_lowerer = ItemLowerer { items: FnvHashMap(), lctx: lctx };
+        visit::walk_crate(&mut item_lowerer, c);
+        item_lowerer.items
+    };
+
     hir::Crate {
         module: lower_mod(lctx, &c.module),
         attrs: c.attrs.clone(),
         config: c.config.clone(),
         span: c.span,
         exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(lctx, m)).collect(),
+        items: items,
     }
 }
 
@@ -721,13 +742,11 @@ pub fn lower_macro_def(_lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef {
     }
 }
 
-// fold one item into possibly many items
-pub fn lower_item(lctx: &LoweringContext, i: &Item) -> P<hir::Item> {
-    P(lower_item_simple(lctx, i))
+pub fn lower_item_id(_lctx: &LoweringContext, i: &Item) -> hir::ItemId {
+    hir::ItemId { id: i.id }
 }
 
-// fold one item into exactly one item
-pub fn lower_item_simple(lctx: &LoweringContext, i: &Item) -> hir::Item {
+pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item {
     let node = lower_item_underscore(lctx, &i.node);
 
     hir::Item {
index 09c814449a9bc5ba289978029c4cf47a72e1278b..f29ef0e821752e29fab8c56ba4f653c3b6fd839a 100644 (file)
@@ -25,7 +25,7 @@
 use syntax::ptr::P;
 
 use hir;
-use hir::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
+use hir::{Crate, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 
 use std::io::{self, Write, Read};
 
@@ -54,6 +54,7 @@ impl PpAnn for NoAnn {}
 
 
 pub struct State<'a> {
+    krate: Option<&'a Crate>,
     pub s: pp::Printer<'a>,
     cm: Option<&'a CodeMap>,
     comments: Option<Vec<comments::Comment>>,
@@ -85,13 +86,14 @@ fn literals(&self) -> &Option<Vec<comments::Literal>> {
     }
 }
 
-pub fn rust_printer<'a>(writer: Box<Write + 'a>) -> State<'a> {
+pub fn rust_printer<'a>(writer: Box<Write + 'a>, krate: Option<&'a Crate>) -> State<'a> {
     static NO_ANN: NoAnn = NoAnn;
-    rust_printer_annotated(writer, &NO_ANN)
+    rust_printer_annotated(writer, &NO_ANN, krate)
 }
 
-pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>, ann: &'a PpAnn) -> State<'a> {
+pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>, ann: &'a PpAnn, krate: Option<&'a Crate>) -> State<'a> {
     State {
+        krate: krate,
         s: pp::mk_printer(writer, default_columns),
         cm: None,
         comments: None,
@@ -124,7 +126,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                        ann: &'a PpAnn,
                        is_expanded: bool)
                        -> io::Result<()> {
-    let mut s = State::new_from_input(cm, span_diagnostic, filename, input, out, ann, is_expanded);
+    let mut s = State::new_from_input(cm, span_diagnostic, filename, input, out, ann, is_expanded, Some(krate));
 
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
@@ -141,7 +143,8 @@ pub fn new_from_input(cm: &'a CodeMap,
                           input: &mut Read,
                           out: Box<Write + 'a>,
                           ann: &'a PpAnn,
-                          is_expanded: bool)
+                          is_expanded: bool,
+                          krate: Option<&'a Crate>)
                           -> State<'a> {
         let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic,
                                                                    filename,
@@ -158,16 +161,19 @@ pub fn new_from_input(cm: &'a CodeMap,
                        None
                    } else {
                        Some(lits)
-                   })
+                   },
+                   krate)
     }
 
     pub fn new(cm: &'a CodeMap,
                out: Box<Write + 'a>,
                ann: &'a PpAnn,
                comments: Option<Vec<comments::Comment>>,
-               literals: Option<Vec<comments::Literal>>)
+               literals: Option<Vec<comments::Literal>>,
+               krate: Option<&'a Crate>)
                -> State<'a> {
         State {
+            krate: krate,
             s: pp::mk_printer(out, default_columns),
             cm: Some(cm),
             comments: comments.clone(),
@@ -187,7 +193,7 @@ pub fn to_string<F>(f: F) -> String
 {
     let mut wr = Vec::new();
     {
-        let mut printer = rust_printer(Box::new(&mut wr));
+        let mut printer = rust_printer(Box::new(&mut wr), None);
         f(&mut printer).unwrap();
         eof(&mut printer.s).unwrap();
     }
@@ -451,8 +457,8 @@ pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<hir::Expr>]) -> io::Resul
 
     pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
         try!(self.print_inner_attributes(attrs));
-        for item in &_mod.items {
-            try!(self.print_item(&**item));
+        for item_id in &_mod.item_ids {
+            try!(self.print_item_id(item_id));
         }
         Ok(())
     }
@@ -620,6 +626,16 @@ fn print_associated_type(&mut self,
         word(&mut self.s, ";")
     }
 
+    pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> {
+        if let Some(krate) = self.krate {
+            // skip nested items if krate context was not provided
+            let item = &krate.items[&item_id.id];
+            self.print_item(item)
+        } else {
+            Ok(())
+        }
+    }
+
     /// Pretty-print an item
     pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
         try!(self.hardbreak_if_not_bol());
@@ -1566,7 +1582,9 @@ pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
                 }
                 self.end()
             }
-            hir::DeclItem(ref item) => self.print_item(&**item),
+            hir::DeclItem(ref item) => {
+                self.print_item_id(item)
+            }
         }
     }
 
index a2c52b274d55fb1dd2878597d7b51f21babc6623..97b25dafb6decddf74c0b7d494652a7edc29ee82 100644 (file)
@@ -10,7 +10,7 @@
 
 use hir;
 use hir::*;
-use visit::{self, Visitor, FnKind};
+use intravisit::{self, Visitor, FnKind};
 use syntax::ast_util;
 use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID};
 use syntax::codemap::Span;
@@ -145,12 +145,26 @@ pub fn unop_to_string(op: UnOp) -> &'static str {
 }
 
 pub struct IdVisitor<'a, O: 'a> {
-    pub operation: &'a mut O,
-    pub pass_through_items: bool,
-    pub visited_outermost: bool,
+    operation: &'a mut O,
+
+    // In general, the id visitor visits the contents of an item, but
+    // not including nested trait/impl items, nor other nested items.
+    // The base visitor itself always skips nested items, but not
+    // trait/impl items. This means in particular that if you start by
+    // visiting a trait or an impl, you should not visit the
+    // trait/impl items respectively.  This is handled by setting
+    // `skip_members` to true when `visit_item` is on the stack. This
+    // way, if the user begins by calling `visit_trait_item`, we will
+    // visit the trait item, but if they begin with `visit_item`, we
+    // won't visit the (nested) trait items.
+    skip_members: bool,
 }
 
 impl<'a, O: ast_util::IdVisitingOperation> IdVisitor<'a, O> {
+    pub fn new(operation: &'a mut O) -> IdVisitor<'a, O> {
+        IdVisitor { operation: operation, skip_members: false }
+    }
+
     fn visit_generics_helper(&mut self, generics: &Generics) {
         for type_parameter in generics.ty_params.iter() {
             self.operation.visit_id(type_parameter.id)
@@ -164,22 +178,17 @@ fn visit_generics_helper(&mut self, generics: &Generics) {
 impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
     fn visit_mod(&mut self, module: &Mod, _: Span, node_id: NodeId) {
         self.operation.visit_id(node_id);
-        visit::walk_mod(self, module)
+        intravisit::walk_mod(self, module)
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
         self.operation.visit_id(foreign_item.id);
-        visit::walk_foreign_item(self, foreign_item)
+        intravisit::walk_foreign_item(self, foreign_item)
     }
 
     fn visit_item(&mut self, item: &Item) {
-        if !self.pass_through_items {
-            if self.visited_outermost {
-                return;
-            } else {
-                self.visited_outermost = true
-            }
-        }
+        assert!(!self.skip_members);
+        self.skip_members = true;
 
         self.operation.visit_id(item.id);
         match item.node {
@@ -196,45 +205,44 @@ fn visit_item(&mut self, item: &Item) {
             }
             _ => {}
         }
+        intravisit::walk_item(self, item);
 
-        visit::walk_item(self, item);
-
-        self.visited_outermost = false
+        self.skip_members = false;
     }
 
     fn visit_local(&mut self, local: &Local) {
         self.operation.visit_id(local.id);
-        visit::walk_local(self, local)
+        intravisit::walk_local(self, local)
     }
 
     fn visit_block(&mut self, block: &Block) {
         self.operation.visit_id(block.id);
-        visit::walk_block(self, block)
+        intravisit::walk_block(self, block)
     }
 
     fn visit_stmt(&mut self, statement: &Stmt) {
         self.operation.visit_id(stmt_id(statement));
-        visit::walk_stmt(self, statement)
+        intravisit::walk_stmt(self, statement)
     }
 
     fn visit_pat(&mut self, pattern: &Pat) {
         self.operation.visit_id(pattern.id);
-        visit::walk_pat(self, pattern)
+        intravisit::walk_pat(self, pattern)
     }
 
     fn visit_expr(&mut self, expression: &Expr) {
         self.operation.visit_id(expression.id);
-        visit::walk_expr(self, expression)
+        intravisit::walk_expr(self, expression)
     }
 
     fn visit_ty(&mut self, typ: &Ty) {
         self.operation.visit_id(typ.id);
-        visit::walk_ty(self, typ)
+        intravisit::walk_ty(self, typ)
     }
 
     fn visit_generics(&mut self, generics: &Generics) {
         self.visit_generics_helper(generics);
-        visit::walk_generics(self, generics)
+        intravisit::walk_generics(self, generics)
     }
 
     fn visit_fn(&mut self,
@@ -243,14 +251,6 @@ fn visit_fn(&mut self,
                 block: &'v Block,
                 span: Span,
                 node_id: NodeId) {
-        if !self.pass_through_items {
-            match function_kind {
-                FnKind::Method(..) if self.visited_outermost => return,
-                FnKind::Method(..) => self.visited_outermost = true,
-                _ => {}
-            }
-        }
-
         self.operation.visit_id(node_id);
 
         match function_kind {
@@ -267,18 +267,12 @@ fn visit_fn(&mut self,
             self.operation.visit_id(argument.id)
         }
 
-        visit::walk_fn(self, function_kind, function_declaration, block, span);
-
-        if !self.pass_through_items {
-            if let FnKind::Method(..) = function_kind {
-                self.visited_outermost = false;
-            }
-        }
+        intravisit::walk_fn(self, function_kind, function_declaration, block, span);
     }
 
     fn visit_struct_field(&mut self, struct_field: &StructField) {
         self.operation.visit_id(struct_field.node.id);
-        visit::walk_struct_field(self, struct_field)
+        intravisit::walk_struct_field(self, struct_field)
     }
 
     fn visit_variant_data(&mut self,
@@ -288,17 +282,21 @@ fn visit_variant_data(&mut self,
                           _: NodeId,
                           _: Span) {
         self.operation.visit_id(struct_def.id());
-        visit::walk_struct_def(self, struct_def);
+        intravisit::walk_struct_def(self, struct_def);
     }
 
     fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
-        self.operation.visit_id(ti.id);
-        visit::walk_trait_item(self, ti);
+        if !self.skip_members {
+            self.operation.visit_id(ti.id);
+            intravisit::walk_trait_item(self, ti);
+        }
     }
 
     fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
-        self.operation.visit_id(ii.id);
-        visit::walk_impl_item(self, ii);
+        if !self.skip_members {
+            self.operation.visit_id(ii.id);
+            intravisit::walk_impl_item(self, ii);
+        }
     }
 
     fn visit_lifetime(&mut self, lifetime: &Lifetime) {
@@ -311,7 +309,7 @@ fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
 
     fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
         self.operation.visit_id(trait_ref.ref_id);
-        visit::walk_trait_ref(self, trait_ref);
+        intravisit::walk_trait_ref(self, trait_ref);
     }
 }
 
@@ -323,11 +321,7 @@ pub fn compute_id_range_for_fn_body(fk: FnKind,
                                     id: NodeId)
                                     -> ast_util::IdRange {
     let mut visitor = ast_util::IdRangeComputingVisitor { result: ast_util::IdRange::max() };
-    let mut id_visitor = IdVisitor {
-        operation: &mut visitor,
-        pass_through_items: false,
-        visited_outermost: false,
-    };
+    let mut id_visitor = IdVisitor::new(&mut visitor);
     id_visitor.visit_fn(fk, decl, body, sp, id);
     id_visitor.operation.result
 }
diff --git a/src/librustc_front/visit.rs b/src/librustc_front/visit.rs
deleted file mode 100644 (file)
index ec58f31..0000000
+++ /dev/null
@@ -1,790 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! HIR walker. Each overridden visit method has full control over what
-//! happens with its node, it can do its own traversal of the node's children,
-//! call `visit::walk_*` to apply the default traversal algorithm, or prevent
-//! deeper traversal by doing nothing.
-//!
-//! Note: it is an important invariant that the default visitor walks the body
-//! of a function in "execution order" (more concretely, reverse post-order
-//! with respect to the CFG implied by the AST), meaning that if AST node A may
-//! execute before AST node B, then A is visited first.  The borrow checker in
-//! particular relies on this property.
-//!
-//! Note: walking an AST before macro expansion is probably a bad idea. For
-//! instance, a walker looking for item names in a module will miss all of
-//! those that are created by the expansion of a macro.
-
-use syntax::abi::Abi;
-use syntax::ast::{Ident, NodeId, CRATE_NODE_ID, Name, Attribute};
-use syntax::codemap::Span;
-use hir::*;
-
-#[derive(Copy, Clone, PartialEq, Eq)]
-pub enum FnKind<'a> {
-    /// fn foo() or extern "Abi" fn foo()
-    ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, Visibility),
-
-    /// fn foo(&self)
-    Method(Name, &'a MethodSig, Option<Visibility>),
-
-    /// |x, y| {}
-    Closure,
-}
-
-/// Each method of the Visitor trait is a hook to be potentially
-/// overridden.  Each method's default implementation recursively visits
-/// the substructure of the input via the corresponding `walk` method;
-/// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
-///
-/// If you want to ensure that your code handles every variant
-/// explicitly, you need to override each method.  (And you also need
-/// to monitor future changes to `Visitor` in case a new method with a
-/// new default implementation gets introduced.)
-pub trait Visitor<'v> : Sized {
-    fn visit_name(&mut self, _span: Span, _name: Name) {
-        // Nothing to do.
-    }
-    fn visit_ident(&mut self, span: Span, ident: Ident) {
-        walk_ident(self, span, ident);
-    }
-    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) {
-        walk_mod(self, m)
-    }
-    fn visit_foreign_item(&mut self, i: &'v ForeignItem) {
-        walk_foreign_item(self, i)
-    }
-    fn visit_item(&mut self, i: &'v Item) {
-        walk_item(self, i)
-    }
-    fn visit_local(&mut self, l: &'v Local) {
-        walk_local(self, l)
-    }
-    fn visit_block(&mut self, b: &'v Block) {
-        walk_block(self, b)
-    }
-    fn visit_stmt(&mut self, s: &'v Stmt) {
-        walk_stmt(self, s)
-    }
-    fn visit_arm(&mut self, a: &'v Arm) {
-        walk_arm(self, a)
-    }
-    fn visit_pat(&mut self, p: &'v Pat) {
-        walk_pat(self, p)
-    }
-    fn visit_decl(&mut self, d: &'v Decl) {
-        walk_decl(self, d)
-    }
-    fn visit_expr(&mut self, ex: &'v Expr) {
-        walk_expr(self, ex)
-    }
-    fn visit_expr_post(&mut self, _ex: &'v Expr) {
-    }
-    fn visit_ty(&mut self, t: &'v Ty) {
-        walk_ty(self, t)
-    }
-    fn visit_generics(&mut self, g: &'v Generics) {
-        walk_generics(self, g)
-    }
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
-        walk_fn(self, fk, fd, b, s)
-    }
-    fn visit_trait_item(&mut self, ti: &'v TraitItem) {
-        walk_trait_item(self, ti)
-    }
-    fn visit_impl_item(&mut self, ii: &'v ImplItem) {
-        walk_impl_item(self, ii)
-    }
-    fn visit_trait_ref(&mut self, t: &'v TraitRef) {
-        walk_trait_ref(self, t)
-    }
-    fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
-        walk_ty_param_bound(self, bounds)
-    }
-    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
-        walk_poly_trait_ref(self, t, m)
-    }
-    fn visit_variant_data(&mut self,
-                          s: &'v VariantData,
-                          _: Name,
-                          _: &'v Generics,
-                          _: NodeId,
-                          _: Span) {
-        walk_struct_def(self, s)
-    }
-    fn visit_struct_field(&mut self, s: &'v StructField) {
-        walk_struct_field(self, s)
-    }
-    fn visit_enum_def(&mut self,
-                      enum_definition: &'v EnumDef,
-                      generics: &'v Generics,
-                      item_id: NodeId,
-                      _: Span) {
-        walk_enum_def(self, enum_definition, generics, item_id)
-    }
-    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
-        walk_variant(self, v, g, item_id)
-    }
-    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
-        walk_lifetime(self, lifetime)
-    }
-    fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
-        walk_lifetime_def(self, lifetime)
-    }
-    fn visit_explicit_self(&mut self, es: &'v ExplicitSelf) {
-        walk_explicit_self(self, es)
-    }
-    fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
-        walk_path(self, path)
-    }
-    fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
-        walk_path_list_item(self, prefix, item)
-    }
-    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
-        walk_path_segment(self, path_span, path_segment)
-    }
-    fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
-        walk_path_parameters(self, path_span, path_parameters)
-    }
-    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
-        walk_assoc_type_binding(self, type_binding)
-    }
-    fn visit_attribute(&mut self, _attr: &'v Attribute) {
-    }
-    fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
-        walk_macro_def(self, macro_def)
-    }
-}
-
-pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
-    for name in opt_name {
-        visitor.visit_name(span, name);
-    }
-}
-
-pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
-    for ident in opt_ident {
-        visitor.visit_ident(span, ident);
-    }
-}
-
-pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
-    visitor.visit_name(span, ident.name);
-}
-
-pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
-    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
-    walk_list!(visitor, visit_attribute, &krate.attrs);
-    walk_list!(visitor, visit_macro_def, &krate.exported_macros);
-}
-
-pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
-    visitor.visit_name(macro_def.span, macro_def.name);
-    walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
-    walk_list!(visitor, visit_attribute, &macro_def.attrs);
-}
-
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
-    walk_list!(visitor, visit_item, &module.items);
-}
-
-pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
-    visitor.visit_pat(&local.pat);
-    walk_list!(visitor, visit_ty, &local.ty);
-    walk_list!(visitor, visit_expr, &local.init);
-}
-
-pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
-    visitor.visit_name(lifetime.span, lifetime.name);
-}
-
-pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {
-    visitor.visit_lifetime(&lifetime_def.lifetime);
-    walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
-}
-
-pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, explicit_self: &'v ExplicitSelf) {
-    match explicit_self.node {
-        SelfStatic => {}
-        SelfValue(name) => {
-            visitor.visit_name(explicit_self.span, name)
-        }
-        SelfRegion(ref opt_lifetime, _, name) => {
-            visitor.visit_name(explicit_self.span, name);
-            walk_list!(visitor, visit_lifetime, opt_lifetime);
-        }
-        SelfExplicit(ref typ, name) => {
-            visitor.visit_name(explicit_self.span, name);
-            visitor.visit_ty(typ)
-        }
-    }
-}
-
-pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
-                                  trait_ref: &'v PolyTraitRef,
-                                  _modifier: &'v TraitBoundModifier)
-    where V: Visitor<'v>
-{
-    walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
-    visitor.visit_trait_ref(&trait_ref.trait_ref);
-}
-
-pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
-    where V: Visitor<'v>
-{
-    visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
-}
-
-pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
-    visitor.visit_name(item.span, item.name);
-    match item.node {
-        ItemExternCrate(opt_name) => {
-            walk_opt_name(visitor, item.span, opt_name)
-        }
-        ItemUse(ref vp) => {
-            match vp.node {
-                ViewPathSimple(name, ref path) => {
-                    visitor.visit_name(vp.span, name);
-                    visitor.visit_path(path, item.id);
-                }
-                ViewPathGlob(ref path) => {
-                    visitor.visit_path(path, item.id);
-                }
-                ViewPathList(ref prefix, ref list) => {
-                    if !list.is_empty() {
-                        for item in list {
-                            visitor.visit_path_list_item(prefix, item)
-                        }
-                    } else {
-                        visitor.visit_path(prefix, item.id);
-                    }
-                }
-            }
-        }
-        ItemStatic(ref typ, _, ref expr) |
-        ItemConst(ref typ, ref expr) => {
-            visitor.visit_ty(typ);
-            visitor.visit_expr(expr);
-        }
-        ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
-            visitor.visit_fn(FnKind::ItemFn(item.name,
-                                            generics,
-                                            unsafety,
-                                            constness,
-                                            abi,
-                                            item.vis),
-                             declaration,
-                             body,
-                             item.span,
-                             item.id)
-        }
-        ItemMod(ref module) => {
-            visitor.visit_mod(module, item.span, item.id)
-        }
-        ItemForeignMod(ref foreign_module) => {
-            walk_list!(visitor, visit_foreign_item, &foreign_module.items);
-        }
-        ItemTy(ref typ, ref type_parameters) => {
-            visitor.visit_ty(typ);
-            visitor.visit_generics(type_parameters)
-        }
-        ItemEnum(ref enum_definition, ref type_parameters) => {
-            visitor.visit_generics(type_parameters);
-            visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
-        }
-        ItemDefaultImpl(_, ref trait_ref) => {
-            visitor.visit_trait_ref(trait_ref)
-        }
-        ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
-            visitor.visit_generics(type_parameters);
-            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
-            visitor.visit_ty(typ);
-            walk_list!(visitor, visit_impl_item, impl_items);
-        }
-        ItemStruct(ref struct_definition, ref generics) => {
-            visitor.visit_generics(generics);
-            visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
-        }
-        ItemTrait(_, ref generics, ref bounds, ref methods) => {
-            visitor.visit_generics(generics);
-            walk_list!(visitor, visit_ty_param_bound, bounds);
-            walk_list!(visitor, visit_trait_item, methods);
-        }
-    }
-    walk_list!(visitor, visit_attribute, &item.attrs);
-}
-
-pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
-                                         enum_definition: &'v EnumDef,
-                                         generics: &'v Generics,
-                                         item_id: NodeId) {
-    walk_list!(visitor,
-               visit_variant,
-               &enum_definition.variants,
-               generics,
-               item_id);
-}
-
-pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
-                                        variant: &'v Variant,
-                                        generics: &'v Generics,
-                                        item_id: NodeId) {
-    visitor.visit_name(variant.span, variant.node.name);
-    visitor.visit_variant_data(&variant.node.data,
-                               variant.node.name,
-                               generics,
-                               item_id,
-                               variant.span);
-    walk_list!(visitor, visit_expr, &variant.node.disr_expr);
-    walk_list!(visitor, visit_attribute, &variant.node.attrs);
-}
-
-pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
-    match typ.node {
-        TyVec(ref ty) => {
-            visitor.visit_ty(ty)
-        }
-        TyPtr(ref mutable_type) => {
-            visitor.visit_ty(&mutable_type.ty)
-        }
-        TyRptr(ref opt_lifetime, ref mutable_type) => {
-            walk_list!(visitor, visit_lifetime, opt_lifetime);
-            visitor.visit_ty(&mutable_type.ty)
-        }
-        TyTup(ref tuple_element_types) => {
-            walk_list!(visitor, visit_ty, tuple_element_types);
-        }
-        TyBareFn(ref function_declaration) => {
-            walk_fn_decl(visitor, &function_declaration.decl);
-            walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
-        }
-        TyPath(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, typ.id);
-        }
-        TyObjectSum(ref ty, ref bounds) => {
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_ty_param_bound, bounds);
-        }
-        TyFixedLengthVec(ref ty, ref expression) => {
-            visitor.visit_ty(ty);
-            visitor.visit_expr(expression)
-        }
-        TyPolyTraitRef(ref bounds) => {
-            walk_list!(visitor, visit_ty_param_bound, bounds);
-        }
-        TyTypeof(ref expression) => {
-            visitor.visit_expr(expression)
-        }
-        TyInfer => {}
-    }
-}
-
-pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
-    for segment in &path.segments {
-        visitor.visit_path_segment(path.span, segment);
-    }
-}
-
-pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
-                                               prefix: &'v Path,
-                                               item: &'v PathListItem) {
-    for segment in &prefix.segments {
-        visitor.visit_path_segment(prefix.span, segment);
-    }
-
-    walk_opt_name(visitor, item.span, item.node.name());
-    walk_opt_name(visitor, item.span, item.node.rename());
-}
-
-pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
-                                             path_span: Span,
-                                             segment: &'v PathSegment) {
-    visitor.visit_ident(path_span, segment.identifier);
-    visitor.visit_path_parameters(path_span, &segment.parameters);
-}
-
-pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
-                                                _path_span: Span,
-                                                path_parameters: &'v PathParameters) {
-    match *path_parameters {
-        AngleBracketedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.types);
-            walk_list!(visitor, visit_lifetime, &data.lifetimes);
-            walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
-        }
-        ParenthesizedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.inputs);
-            walk_list!(visitor, visit_ty, &data.output);
-        }
-    }
-}
-
-pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
-                                                   type_binding: &'v TypeBinding) {
-    visitor.visit_name(type_binding.span, type_binding.name);
-    visitor.visit_ty(&type_binding.ty);
-}
-
-pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
-    match pattern.node {
-        PatEnum(ref path, ref opt_children) => {
-            visitor.visit_path(path, pattern.id);
-            if let Some(ref children) = *opt_children {
-                walk_list!(visitor, visit_pat, children);
-            }
-        }
-        PatQPath(ref qself, ref path) => {
-            visitor.visit_ty(&qself.ty);
-            visitor.visit_path(path, pattern.id)
-        }
-        PatStruct(ref path, ref fields, _) => {
-            visitor.visit_path(path, pattern.id);
-            for field in fields {
-                visitor.visit_name(field.span, field.node.name);
-                visitor.visit_pat(&field.node.pat)
-            }
-        }
-        PatTup(ref tuple_elements) => {
-            walk_list!(visitor, visit_pat, tuple_elements);
-        }
-        PatBox(ref subpattern) |
-        PatRegion(ref subpattern, _) => {
-            visitor.visit_pat(subpattern)
-        }
-        PatIdent(_, ref pth1, ref optional_subpattern) => {
-            visitor.visit_ident(pth1.span, pth1.node);
-            walk_list!(visitor, visit_pat, optional_subpattern);
-        }
-        PatLit(ref expression) => visitor.visit_expr(expression),
-        PatRange(ref lower_bound, ref upper_bound) => {
-            visitor.visit_expr(lower_bound);
-            visitor.visit_expr(upper_bound)
-        }
-        PatWild => (),
-        PatVec(ref prepatterns, ref slice_pattern, ref postpatterns) => {
-            walk_list!(visitor, visit_pat, prepatterns);
-            walk_list!(visitor, visit_pat, slice_pattern);
-            walk_list!(visitor, visit_pat, postpatterns);
-        }
-    }
-}
-
-pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
-    visitor.visit_name(foreign_item.span, foreign_item.name);
-
-    match foreign_item.node {
-        ForeignItemFn(ref function_declaration, ref generics) => {
-            walk_fn_decl(visitor, function_declaration);
-            visitor.visit_generics(generics)
-        }
-        ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
-    }
-
-    walk_list!(visitor, visit_attribute, &foreign_item.attrs);
-}
-
-pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
-    match *bound {
-        TraitTyParamBound(ref typ, ref modifier) => {
-            visitor.visit_poly_trait_ref(typ, modifier);
-        }
-        RegionTyParamBound(ref lifetime) => {
-            visitor.visit_lifetime(lifetime);
-        }
-    }
-}
-
-pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
-    for param in &generics.ty_params {
-        visitor.visit_name(param.span, param.name);
-        walk_list!(visitor, visit_ty_param_bound, &param.bounds);
-        walk_list!(visitor, visit_ty, &param.default);
-    }
-    walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
-    for predicate in &generics.where_clause.predicates {
-        match predicate {
-            &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
-                                                                          ref bounds,
-                                                                          ref bound_lifetimes,
-                                                                          ..}) => {
-                visitor.visit_ty(bounded_ty);
-                walk_list!(visitor, visit_ty_param_bound, bounds);
-                walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
-            }
-            &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
-                                                                            ref bounds,
-                                                                            ..}) => {
-                visitor.visit_lifetime(lifetime);
-                walk_list!(visitor, visit_lifetime, bounds);
-            }
-            &WherePredicate::EqPredicate(WhereEqPredicate{id,
-                                                                    ref path,
-                                                                    ref ty,
-                                                                    ..}) => {
-                visitor.visit_path(path, id);
-                visitor.visit_ty(ty);
-            }
-        }
-    }
-}
-
-pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
-    if let Return(ref output_ty) = *ret_ty {
-        visitor.visit_ty(output_ty)
-    }
-}
-
-pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
-    for argument in &function_declaration.inputs {
-        visitor.visit_pat(&argument.pat);
-        visitor.visit_ty(&argument.ty)
-    }
-    walk_fn_ret_ty(visitor, &function_declaration.output)
-}
-
-pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
-    for argument in &function_declaration.inputs {
-        visitor.visit_ty(&argument.ty)
-    }
-    walk_fn_ret_ty(visitor, &function_declaration.output)
-}
-
-pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
-    match function_kind {
-        FnKind::ItemFn(_, generics, _, _, _, _) => {
-            visitor.visit_generics(generics);
-        }
-        FnKind::Method(_, sig, _) => {
-            visitor.visit_generics(&sig.generics);
-            visitor.visit_explicit_self(&sig.explicit_self);
-        }
-        FnKind::Closure => {}
-    }
-}
-
-pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
-                                   function_kind: FnKind<'v>,
-                                   function_declaration: &'v FnDecl,
-                                   function_body: &'v Block,
-                                   _span: Span) {
-    walk_fn_decl(visitor, function_declaration);
-    walk_fn_kind(visitor, function_kind);
-    visitor.visit_block(function_body)
-}
-
-pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
-    visitor.visit_name(trait_item.span, trait_item.name);
-    walk_list!(visitor, visit_attribute, &trait_item.attrs);
-    match trait_item.node {
-        ConstTraitItem(ref ty, ref default) => {
-            visitor.visit_ty(ty);
-            walk_list!(visitor, visit_expr, default);
-        }
-        MethodTraitItem(ref sig, None) => {
-            visitor.visit_explicit_self(&sig.explicit_self);
-            visitor.visit_generics(&sig.generics);
-            walk_fn_decl(visitor, &sig.decl);
-        }
-        MethodTraitItem(ref sig, Some(ref body)) => {
-            visitor.visit_fn(FnKind::Method(trait_item.name, sig, None),
-                             &sig.decl,
-                             body,
-                             trait_item.span,
-                             trait_item.id);
-        }
-        TypeTraitItem(ref bounds, ref default) => {
-            walk_list!(visitor, visit_ty_param_bound, bounds);
-            walk_list!(visitor, visit_ty, default);
-        }
-    }
-}
-
-pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
-    visitor.visit_name(impl_item.span, impl_item.name);
-    walk_list!(visitor, visit_attribute, &impl_item.attrs);
-    match impl_item.node {
-        ImplItemKind::Const(ref ty, ref expr) => {
-            visitor.visit_ty(ty);
-            visitor.visit_expr(expr);
-        }
-        ImplItemKind::Method(ref sig, ref body) => {
-            visitor.visit_fn(FnKind::Method(impl_item.name, sig, Some(impl_item.vis)),
-                             &sig.decl,
-                             body,
-                             impl_item.span,
-                             impl_item.id);
-        }
-        ImplItemKind::Type(ref ty) => {
-            visitor.visit_ty(ty);
-        }
-    }
-}
-
-pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
-    walk_list!(visitor, visit_struct_field, struct_definition.fields());
-}
-
-pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
-    walk_opt_name(visitor, struct_field.span, struct_field.node.name());
-    visitor.visit_ty(&struct_field.node.ty);
-    walk_list!(visitor, visit_attribute, &struct_field.node.attrs);
-}
-
-pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
-    walk_list!(visitor, visit_stmt, &block.stmts);
-    walk_list!(visitor, visit_expr, &block.expr);
-}
-
-pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
-    match statement.node {
-        StmtDecl(ref declaration, _) => visitor.visit_decl(declaration),
-        StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
-            visitor.visit_expr(expression)
-        }
-    }
-}
-
-pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
-    match declaration.node {
-        DeclLocal(ref local) => visitor.visit_local(local),
-        DeclItem(ref item) => visitor.visit_item(item),
-    }
-}
-
-pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
-    match expression.node {
-        ExprBox(ref subexpression) => {
-            visitor.visit_expr(subexpression)
-        }
-        ExprVec(ref subexpressions) => {
-            walk_list!(visitor, visit_expr, subexpressions);
-        }
-        ExprRepeat(ref element, ref count) => {
-            visitor.visit_expr(element);
-            visitor.visit_expr(count)
-        }
-        ExprStruct(ref path, ref fields, ref optional_base) => {
-            visitor.visit_path(path, expression.id);
-            for field in fields {
-                visitor.visit_name(field.name.span, field.name.node);
-                visitor.visit_expr(&field.expr)
-            }
-            walk_list!(visitor, visit_expr, optional_base);
-        }
-        ExprTup(ref subexpressions) => {
-            walk_list!(visitor, visit_expr, subexpressions);
-        }
-        ExprCall(ref callee_expression, ref arguments) => {
-            walk_list!(visitor, visit_expr, arguments);
-            visitor.visit_expr(callee_expression)
-        }
-        ExprMethodCall(ref name, ref types, ref arguments) => {
-            visitor.visit_name(name.span, name.node);
-            walk_list!(visitor, visit_expr, arguments);
-            walk_list!(visitor, visit_ty, types);
-        }
-        ExprBinary(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(left_expression);
-            visitor.visit_expr(right_expression)
-        }
-        ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
-            visitor.visit_expr(subexpression)
-        }
-        ExprLit(_) => {}
-        ExprCast(ref subexpression, ref typ) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_ty(typ)
-        }
-        ExprIf(ref head_expression, ref if_block, ref optional_else) => {
-            visitor.visit_expr(head_expression);
-            visitor.visit_block(if_block);
-            walk_list!(visitor, visit_expr, optional_else);
-        }
-        ExprWhile(ref subexpression, ref block, opt_ident) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_block(block);
-            walk_opt_ident(visitor, expression.span, opt_ident)
-        }
-        ExprLoop(ref block, opt_ident) => {
-            visitor.visit_block(block);
-            walk_opt_ident(visitor, expression.span, opt_ident)
-        }
-        ExprMatch(ref subexpression, ref arms, _) => {
-            visitor.visit_expr(subexpression);
-            walk_list!(visitor, visit_arm, arms);
-        }
-        ExprClosure(_, ref function_declaration, ref body) => {
-            visitor.visit_fn(FnKind::Closure,
-                             function_declaration,
-                             body,
-                             expression.span,
-                             expression.id)
-        }
-        ExprBlock(ref block) => visitor.visit_block(block),
-        ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
-            visitor.visit_expr(right_hand_expression);
-            visitor.visit_expr(left_hand_expression)
-        }
-        ExprAssignOp(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(right_expression);
-            visitor.visit_expr(left_expression)
-        }
-        ExprField(ref subexpression, ref name) => {
-            visitor.visit_expr(subexpression);
-            visitor.visit_name(name.span, name.node);
-        }
-        ExprTupField(ref subexpression, _) => {
-            visitor.visit_expr(subexpression);
-        }
-        ExprIndex(ref main_expression, ref index_expression) => {
-            visitor.visit_expr(main_expression);
-            visitor.visit_expr(index_expression)
-        }
-        ExprRange(ref start, ref end) => {
-            walk_list!(visitor, visit_expr, start);
-            walk_list!(visitor, visit_expr, end);
-        }
-        ExprPath(ref maybe_qself, ref path) => {
-            if let Some(ref qself) = *maybe_qself {
-                visitor.visit_ty(&qself.ty);
-            }
-            visitor.visit_path(path, expression.id)
-        }
-        ExprBreak(ref opt_sp_ident) | ExprAgain(ref opt_sp_ident) => {
-            for sp_ident in opt_sp_ident {
-                visitor.visit_ident(sp_ident.span, sp_ident.node);
-            }
-        }
-        ExprRet(ref optional_expression) => {
-            walk_list!(visitor, visit_expr, optional_expression);
-        }
-        ExprInlineAsm(ref ia) => {
-            for &(_, ref input) in &ia.inputs {
-                visitor.visit_expr(&input)
-            }
-            for &(_, ref output, _) in &ia.outputs {
-                visitor.visit_expr(&output)
-            }
-        }
-    }
-
-    visitor.visit_expr_post(expression)
-}
-
-pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
-    walk_list!(visitor, visit_pat, &arm.pats);
-    walk_list!(visitor, visit_expr, &arm.guard);
-    visitor.visit_expr(&arm.body);
-    walk_list!(visitor, visit_attribute, &arm.attrs);
-}