diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 9e832c19a16..96ccb2999ae 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -299,7 +299,7 @@ struct Context {
     // Others operate directly on @ast::item structures (or similar). Finally,
     // others still are added to the Session object via `add_lint`, and these
     // are all passed with the lint_session visitor.
-    visitors: ~[visit::vt<()>],
+    visitors: ~[visit::vt<@mut Context>],
 }
 
 impl Context {
@@ -416,20 +416,20 @@ impl Context {
         }
     }
 
-    fn add_lint(&mut self, v: visit::vt<()>) {
+    fn add_lint(&mut self, v: visit::vt<@mut Context>) {
         self.visitors.push(item_stopping_visitor(v));
     }
 
-    fn process(&self, n: AttributedNode) {
+    fn process(@mut self, n: AttributedNode) {
         match n {
             Item(it) => {
                 for self.visitors.each |v| {
-                    visit::visit_item(it, (), *v);
+                    visit::visit_item(it, self, *v);
                 }
             }
             Crate(c) => {
                 for self.visitors.each |v| {
-                    visit::visit_crate(c, (), *v);
+                    visit::visit_crate(c, self, *v);
                 }
             }
             // Can't use visit::visit_method_helper because the
@@ -439,7 +439,7 @@ impl Context {
                 let fk = visit::fk_method(copy m.ident, &m.generics, m);
                 for self.visitors.each |v| {
                     visit::visit_fn(&fk, &m.decl, &m.body, m.span, m.id,
-                                    (), *v);
+                                    self, *v);
                 }
             }
         }
@@ -499,9 +499,9 @@ fn ty_stopping_visitor<E>(v: visit::vt<E>) -> visit::vt<E> {
     visit::mk_vt(@visit::Visitor {visit_ty: |_t, _e, _v| { },.. **v})
 }
 
-fn lint_while_true(cx: @mut Context) -> visit::vt<()> {
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_expr: |e: @ast::expr| {
+fn lint_while_true() -> visit::vt<@mut Context> {
+    visit::mk_vt(@visit::Visitor {
+        visit_expr: |e, cx: @mut Context, vt| {
             match e.node {
                 ast::expr_while(cond, _) => {
                     match cond.node {
@@ -517,12 +517,13 @@ fn lint_while_true(cx: @mut Context) -> visit::vt<()> {
                 }
                 _ => ()
             }
+            visit::visit_expr(e, cx, vt);
         },
-        .. *visit::default_simple_visitor()
+        .. *visit::default_visitor()
     })
 }
 
-fn lint_type_limits(cx: @mut Context) -> visit::vt<()> {
+fn lint_type_limits() -> visit::vt<@mut Context> {
     fn is_valid<T:cmp::Ord>(binop: ast::binop, v: T,
             min: T, max: T) -> bool {
         match binop {
@@ -568,7 +569,7 @@ fn lint_type_limits(cx: @mut Context) -> visit::vt<()> {
         }
     }
 
-    fn check_limits(cx: @mut Context, binop: ast::binop, l: &ast::expr,
+    fn check_limits(cx: &Context, binop: ast::binop, l: &ast::expr,
                     r: &ast::expr) -> bool {
         let (lit, expr, swap) = match (&l.node, &r.node) {
             (&ast::expr_lit(_), _) => (l, r, true),
@@ -621,26 +622,26 @@ fn lint_type_limits(cx: @mut Context) -> visit::vt<()> {
         }
     }
 
-    let visit_expr: @fn(@ast::expr) = |e| {
-        match e.node {
-            ast::expr_binary(ref binop, @ref l, @ref r) => {
-                if is_comparison(*binop)
-                    && !check_limits(cx, *binop, l, r) {
-                    cx.span_lint(type_limits, e.span,
-                                 "comparison is useless due to type limits");
+    visit::mk_vt(@visit::Visitor {
+        visit_expr: |e, cx: @mut Context, vt| {
+            match e.node {
+                ast::expr_binary(ref binop, @ref l, @ref r) => {
+                    if is_comparison(*binop)
+                        && !check_limits(cx, *binop, l, r) {
+                        cx.span_lint(type_limits, e.span,
+                                     "comparison is useless due to type limits");
+                    }
                 }
+                _ => ()
             }
-            _ => ()
-        }
-    };
+            visit::visit_expr(e, cx, vt);
+        },
 
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_expr: visit_expr,
-        .. *visit::default_simple_visitor()
+        .. *visit::default_visitor()
     })
 }
 
-fn check_item_default_methods(cx: @mut Context, item: @ast::item) {
+fn check_item_default_methods(cx: &Context, item: @ast::item) {
     match item.node {
         ast::item_trait(_, _, ref methods) => {
             for methods.each |method| {
@@ -657,9 +658,9 @@ fn check_item_default_methods(cx: @mut Context, item: @ast::item) {
     }
 }
 
-fn check_item_ctypes(cx: @mut Context, it: @ast::item) {
+fn check_item_ctypes(cx: &Context, it: @ast::item) {
 
-    fn check_foreign_fn(cx: @mut Context, decl: &ast::fn_decl) {
+    fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) {
         let tys = vec::map(decl.inputs, |a| a.ty );
         for vec::each(vec::append_one(tys, decl.output)) |ty| {
             match ty.node {
@@ -699,7 +700,7 @@ fn check_item_ctypes(cx: @mut Context, it: @ast::item) {
     }
 }
 
-fn check_type_for_lint(cx: @mut Context, lint: lint, span: span, ty: ty::t) {
+fn check_type_for_lint(cx: &Context, lint: lint, span: span, ty: ty::t) {
     if cx.get_level(lint) == allow { return }
 
     let mut n_box = 0;
@@ -726,13 +727,13 @@ fn check_type_for_lint(cx: @mut Context, lint: lint, span: span, ty: ty::t) {
     }
 }
 
-fn check_type(cx: @mut Context, span: span, ty: ty::t) {
+fn check_type(cx: &Context, span: span, ty: ty::t) {
     for [managed_heap_memory, owned_heap_memory, heap_memory].each |lint| {
         check_type_for_lint(cx, *lint, span, ty);
     }
 }
 
-fn check_item_heap(cx: @mut Context, it: @ast::item) {
+fn check_item_heap(cx: &Context, it: @ast::item) {
     match it.node {
       ast::item_fn(*) |
       ast::item_ty(*) |
@@ -756,19 +757,20 @@ fn check_item_heap(cx: @mut Context, it: @ast::item) {
     }
 }
 
-fn lint_heap(cx: @mut Context) -> visit::vt<()> {
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_expr: |e| {
+fn lint_heap() -> visit::vt<@mut Context> {
+    visit::mk_vt(@visit::Visitor {
+        visit_expr: |e, cx: @mut Context, vt| {
             let ty = ty::expr_ty(cx.tcx, e);
             check_type(cx, e.span, ty);
+            visit::visit_expr(e, cx, vt);
         },
-        .. *visit::default_simple_visitor()
+        .. *visit::default_visitor()
     })
 }
 
-fn lint_path_statement(cx: @mut Context) -> visit::vt<()> {
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_stmt: |s| {
+fn lint_path_statement() -> visit::vt<@mut Context> {
+    visit::mk_vt(@visit::Visitor {
+        visit_stmt: |s, cx: @mut Context, vt| {
             match s.node {
                 ast::stmt_semi(
                     @ast::expr { node: ast::expr_path(_), _ },
@@ -779,12 +781,13 @@ fn lint_path_statement(cx: @mut Context) -> visit::vt<()> {
                 }
                 _ => ()
             }
+            visit::visit_stmt(s, cx, vt);
         },
-        .. *visit::default_simple_visitor()
+        .. *visit::default_visitor()
     })
 }
 
-fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) {
+fn check_item_non_camel_case_types(cx: &Context, it: @ast::item) {
     fn is_camel_case(cx: ty::ctxt, ident: ast::ident) -> bool {
         let ident = cx.sess.str_of(ident);
         assert!(!ident.is_empty());
@@ -808,7 +811,7 @@ fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) {
         }
     }
 
-    fn check_case(cx: @mut Context, ident: ast::ident, span: span) {
+    fn check_case(cx: &Context, ident: ast::ident, span: span) {
         if !is_camel_case(cx.tcx, ident) {
             cx.span_lint(non_camel_case_types, span,
                          "type, variant, or trait should have \
@@ -831,27 +834,26 @@ fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) {
     }
 }
 
-fn lint_unused_unsafe(cx: @mut Context) -> visit::vt<()> {
-    let visit_expr: @fn(@ast::expr) = |e| {
-        match e.node {
-            ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => {
-                if !cx.tcx.used_unsafe.contains(&blk.node.id) {
-                    cx.span_lint(unused_unsafe, blk.span,
-                                 "unnecessary `unsafe` block");
+fn lint_unused_unsafe() -> visit::vt<@mut Context> {
+    visit::mk_vt(@visit::Visitor {
+        visit_expr: |e, cx: @mut Context, vt| {
+            match e.node {
+                ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => {
+                    if !cx.tcx.used_unsafe.contains(&blk.node.id) {
+                        cx.span_lint(unused_unsafe, blk.span,
+                                     "unnecessary `unsafe` block");
+                    }
                 }
+                _ => ()
             }
-            _ => ()
-        }
-    };
-
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_expr: visit_expr,
-        .. *visit::default_simple_visitor()
+            visit::visit_expr(e, cx, vt);
+        },
+        .. *visit::default_visitor()
     })
 }
 
-fn lint_unused_mut(cx: @mut Context) -> visit::vt<()> {
-    let check_pat: @fn(@ast::pat) = |p| {
+fn lint_unused_mut() -> visit::vt<@mut Context> {
+    fn check_pat(cx: &Context, p: @ast::pat) {
         let mut used = false;
         let mut bindings = 0;
         do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| {
@@ -866,37 +868,48 @@ fn lint_unused_mut(cx: @mut Context) -> visit::vt<()> {
             };
             cx.span_lint(unused_mut, p.span, msg);
         }
-    };
+    }
 
-    let visit_fn_decl: @fn(&ast::fn_decl) = |fd| {
+    fn visit_fn_decl(cx: &Context, fd: &ast::fn_decl) {
         for fd.inputs.each |arg| {
             if arg.is_mutbl {
-                check_pat(arg.pat);
+                check_pat(cx, arg.pat);
             }
         }
-    };
+    }
 
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_local: |l| {
+    visit::mk_vt(@visit::Visitor {
+        visit_local: |l, cx: @mut Context, vt| {
             if l.node.is_mutbl {
-                check_pat(l.node.pat);
+                check_pat(cx, l.node.pat);
             }
+            visit::visit_local(l, cx, vt);
         },
-        visit_fn: |_, fd, _, _, _| visit_fn_decl(fd),
-        visit_ty_method: |tm| visit_fn_decl(&tm.decl),
-        visit_struct_method: |sm| visit_fn_decl(&sm.decl),
-        visit_trait_method: |tm| {
+        visit_fn: |a, fd, b, c, d, cx, vt| {
+            visit_fn_decl(cx, fd);
+            visit::visit_fn(a, fd, b, c, d, cx, vt);
+        },
+        visit_ty_method: |tm, cx, vt| {
+            visit_fn_decl(cx, &tm.decl);
+            visit::visit_ty_method(tm, cx, vt);
+        },
+        visit_struct_method: |sm, cx, vt| {
+            visit_fn_decl(cx, &sm.decl);
+            visit::visit_struct_method(sm, cx, vt);
+        },
+        visit_trait_method: |tm, cx, vt| {
             match *tm {
-                ast::required(ref tm) => visit_fn_decl(&tm.decl),
-                ast::provided(m) => visit_fn_decl(&m.decl),
+                ast::required(ref tm) => visit_fn_decl(cx, &tm.decl),
+                ast::provided(m) => visit_fn_decl(cx, &m.decl)
             }
+            visit::visit_trait_method(tm, cx, vt);
         },
-        .. *visit::default_simple_visitor()
+        .. *visit::default_visitor()
     })
 }
 
-fn lint_session(cx: @mut Context) -> visit::vt<()> {
-    ast_util::id_visitor(|id| {
+fn lint_session() -> visit::vt<@mut Context> {
+    ast_util::id_visitor(|id, cx: @mut Context| {
         match cx.tcx.sess.lints.pop(&id) {
             None => {},
             Some(l) => {
@@ -908,10 +921,10 @@ fn lint_session(cx: @mut Context) -> visit::vt<()> {
     })
 }
 
-fn lint_unnecessary_allocations(cx: @mut Context) -> visit::vt<()> {
+fn lint_unnecessary_allocations() -> visit::vt<@mut Context> {
     // Warn if string and vector literals with sigils are immediately borrowed.
     // Those can have the sigil removed.
-    fn check(cx: @mut Context, e: @ast::expr) {
+    fn check(cx: &Context, e: @ast::expr) {
         match e.node {
             ast::expr_vstore(e2, ast::expr_vstore_uniq) |
             ast::expr_vstore(e2, ast::expr_vstore_box) => {
@@ -938,19 +951,18 @@ fn lint_unnecessary_allocations(cx: @mut Context) -> visit::vt<()> {
         }
     }
 
-    let visit_expr: @fn(@ast::expr) = |e| {
-        check(cx, e);
-    };
-
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_expr: visit_expr,
-        .. *visit::default_simple_visitor()
+    visit::mk_vt(@visit::Visitor {
+        visit_expr: |e, cx: @mut Context, vt| {
+            check(cx, e);
+            visit::visit_expr(e, cx, vt);
+        },
+        .. *visit::default_visitor()
     })
 }
 
-fn lint_missing_struct_doc(cx: @mut Context) -> visit::vt<()> {
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_struct_field: |field| {
+fn lint_missing_struct_doc() -> visit::vt<@mut Context> {
+    visit::mk_vt(@visit::Visitor {
+        visit_struct_field: |field, cx: @mut Context, vt| {
             let relevant = match field.node.kind {
                 ast::named_field(_, vis) => vis != ast::private,
                 ast::unnamed_field => false,
@@ -969,14 +981,16 @@ fn lint_missing_struct_doc(cx: @mut Context) -> visit::vt<()> {
                                                                   for a field.");
                 }
             }
+
+            visit::visit_struct_field(field, cx, vt);
         },
-        .. *visit::default_simple_visitor()
+        .. *visit::default_visitor()
     })
 }
 
-fn lint_missing_trait_doc(cx: @mut Context) -> visit::vt<()> {
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_trait_method: |method| {
+fn lint_missing_trait_doc() -> visit::vt<@mut Context> {
+    visit::mk_vt(@visit::Visitor {
+        visit_trait_method: |method, cx: @mut Context, vt| {
             let mut has_doc = false;
             let span = match copy *method {
                 ast::required(m) => {
@@ -1006,8 +1020,9 @@ fn lint_missing_trait_doc(cx: @mut Context) -> visit::vt<()> {
                 cx.span_lint(missing_trait_doc, span, "missing documentation \
                                                        for a method.");
             }
+            visit::visit_trait_method(method, cx, vt);
         },
-        .. *visit::default_simple_visitor()
+        .. *visit::default_visitor()
     })
 }
 
@@ -1031,39 +1046,33 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
     }
 
     // Register each of the lint passes with the context
-    cx.add_lint(lint_while_true(cx));
-    cx.add_lint(lint_path_statement(cx));
-    cx.add_lint(lint_heap(cx));
-    cx.add_lint(lint_type_limits(cx));
-    cx.add_lint(lint_unused_unsafe(cx));
-    cx.add_lint(lint_unused_mut(cx));
-    cx.add_lint(lint_session(cx));
-    cx.add_lint(lint_unnecessary_allocations(cx));
-    cx.add_lint(lint_missing_struct_doc(cx));
-    cx.add_lint(lint_missing_trait_doc(cx));
-
-    // type inference doesn't like this being declared below, we need to tell it
-    // what the type of this first function is...
-    let visit_item:
-        @fn(@ast::item, @mut Context, visit::vt<@mut Context>) =
-    |it, cx, vt| {
-        do cx.with_lint_attrs(it.attrs) {
-            check_item_ctypes(cx, it);
-            check_item_non_camel_case_types(cx, it);
-            check_item_default_methods(cx, it);
-            check_item_heap(cx, it);
-
-            cx.process(Item(it));
-            visit::visit_item(it, cx, vt);
-        }
-    };
+    cx.add_lint(lint_while_true());
+    cx.add_lint(lint_path_statement());
+    cx.add_lint(lint_heap());
+    cx.add_lint(lint_type_limits());
+    cx.add_lint(lint_unused_unsafe());
+    cx.add_lint(lint_unused_mut());
+    cx.add_lint(lint_session());
+    cx.add_lint(lint_unnecessary_allocations());
+    cx.add_lint(lint_missing_struct_doc());
+    cx.add_lint(lint_missing_trait_doc());
 
     // Actually perform the lint checks (iterating the ast)
     do cx.with_lint_attrs(crate.node.attrs) {
         cx.process(Crate(crate));
 
         visit::visit_crate(crate, cx, visit::mk_vt(@visit::Visitor {
-            visit_item: visit_item,
+            visit_item: |it, cx: @mut Context, vt| {
+                do cx.with_lint_attrs(it.attrs) {
+                    check_item_ctypes(cx, it);
+                    check_item_non_camel_case_types(cx, it);
+                    check_item_default_methods(cx, it);
+                    check_item_heap(cx, it);
+
+                    cx.process(Item(it));
+                    visit::visit_item(it, cx, vt);
+                }
+            },
             visit_fn: |fk, decl, body, span, id, cx, vt| {
                 match *fk {
                     visit::fk_method(_, _, m) => {
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 59743b6e892..8d5af682d62 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -386,82 +386,103 @@ pub impl id_range {
     }
 }
 
-pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> {
-    let visit_generics: @fn(&Generics) = |generics| {
+pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
+    let visit_generics: @fn(&Generics, T) = |generics, t| {
         for generics.ty_params.each |p| {
-            vfn(p.id);
+            vfn(p.id, t);
         }
         for generics.lifetimes.each |p| {
-            vfn(p.id);
+            vfn(p.id, t);
         }
     };
-    visit::mk_simple_visitor(@visit::SimpleVisitor {
-        visit_mod: |_m, _sp, id| vfn(id),
+    visit::mk_vt(@visit::Visitor {
+        visit_mod: |m, sp, id, t, vt| {
+            vfn(id, t);
+            visit::visit_mod(m, sp, id, t, vt);
+        },
 
-        visit_view_item: |vi| {
+        visit_view_item: |vi, t, vt| {
             match vi.node {
-              view_item_extern_mod(_, _, id) => vfn(id),
+              view_item_extern_mod(_, _, id) => vfn(id, t),
               view_item_use(ref vps) => {
                   for vps.each |vp| {
                       match vp.node {
-                          view_path_simple(_, _, id) => vfn(id),
-                          view_path_glob(_, id) => vfn(id),
+                          view_path_simple(_, _, id) => vfn(id, t),
+                          view_path_glob(_, id) => vfn(id, t),
                           view_path_list(_, ref paths, id) => {
-                              vfn(id);
+                              vfn(id, t);
                               for paths.each |p| {
-                                  vfn(p.node.id);
+                                  vfn(p.node.id, t);
                               }
                           }
                       }
                   }
               }
             }
+            visit::visit_view_item(vi, t, vt);
         },
 
-        visit_foreign_item: |ni| vfn(ni.id),
+        visit_foreign_item: |ni, t, vt| {
+            vfn(ni.id, t);
+            visit::visit_foreign_item(ni, t, vt);
+        },
 
-        visit_item: |i| {
-            vfn(i.id);
+        visit_item: |i, t, vt| {
+            vfn(i.id, t);
             match i.node {
               item_enum(ref enum_definition, _) =>
-                for (*enum_definition).variants.each |v| { vfn(v.node.id); },
+                for (*enum_definition).variants.each |v| { vfn(v.node.id, t); },
               _ => ()
             }
+            visit::visit_item(i, t, vt);
         },
 
-        visit_local: |l| vfn(l.node.id),
-        visit_block: |b| vfn(b.node.id),
-        visit_stmt: |s| vfn(ast_util::stmt_id(s)),
-        visit_arm: |_| {},
-        visit_pat: |p| vfn(p.id),
-        visit_decl: |_| {},
-
-        visit_expr: |e| {
-            vfn(e.callee_id);
-            vfn(e.id);
+        visit_local: |l, t, vt| {
+            vfn(l.node.id, t);
+            visit::visit_local(l, t, vt);
+        },
+        visit_block: |b, t, vt| {
+            vfn(b.node.id, t);
+            visit::visit_block(b, t, vt);
+        },
+        visit_stmt: |s, t, vt| {
+            vfn(ast_util::stmt_id(s), t);
+            visit::visit_stmt(s, t, vt);
+        },
+        visit_pat: |p, t, vt| {
+            vfn(p.id, t);
+            visit::visit_pat(p, t, vt);
         },
 
-        visit_expr_post: |_| {},
+        visit_expr: |e, t, vt| {
+            vfn(e.callee_id, t);
+            vfn(e.id, t);
+            visit::visit_expr(e, t, vt);
+        },
 
-        visit_ty: |t| {
-            match t.node {
-              ty_path(_, id) => vfn(id),
+        visit_ty: |ty, t, vt| {
+            match ty.node {
+              ty_path(_, id) => vfn(id, t),
               _ => { /* fall through */ }
             }
+            visit::visit_ty(ty, t, vt);
         },
 
-        visit_generics: visit_generics,
+        visit_generics: |generics, t, vt| {
+            visit_generics(generics, t);
+            visit::visit_generics(generics, t, vt);
+        },
 
-        visit_fn: |fk, d, _, _, id| {
-            vfn(id);
+        visit_fn: |fk, d, a, b, id, t, vt| {
+            vfn(id, t);
 
             match *fk {
                 visit::fk_item_fn(_, generics, _, _) => {
-                    visit_generics(generics);
+                    visit_generics(generics, t);
                 }
                 visit::fk_method(_, generics, m) => {
-                    vfn(m.self_id);
-                    visit_generics(generics);
+                    vfn(m.self_id, t);
+                    visit_generics(generics, t);
                 }
                 visit::fk_anon(_) |
                 visit::fk_fn_block => {
@@ -469,20 +490,22 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> {
             }
 
             for d.inputs.each |arg| {
-                vfn(arg.id)
+                vfn(arg.id, t)
             }
+            visit::visit_fn(fk, d, a, b, id, t, vt);
         },
 
-        visit_ty_method: |_| {},
-        visit_trait_method: |_| {},
-        visit_struct_def: |_, _, _, _| {},
-        visit_struct_field: |f| vfn(f.node.id),
-        visit_struct_method: |_| {}
+        visit_struct_field: |f, t, vt| {
+            vfn(f.node.id, t);
+            visit::visit_struct_field(f, t, vt);
+        },
+
+        .. *visit::default_visitor()
     })
 }
 
 pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(node_id)) {
-    item.accept((), id_visitor(vfn));
+    item.accept((), id_visitor(|id, ()| vfn(id)));
 }
 
 pub fn compute_id_range(visit_ids_fn: &fn(@fn(node_id))) -> id_range {