about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-19 06:52:03 -0700
committerbors <bors@rust-lang.org>2013-08-19 06:52:03 -0700
commitd597f54fc2b864bcdf110fecb120758dc2feb5f6 (patch)
tree0057844029534e30b244723bdebd67ef61ba71a6 /src
parent81a78161b5354c9cfecd8c659cc1dc3711d347d6 (diff)
parent6c15f21bd76d0658866d2db431c4bb4bc6b2932e (diff)
downloadrust-d597f54fc2b864bcdf110fecb120758dc2feb5f6.tar.gz
rust-d597f54fc2b864bcdf110fecb120758dc2feb5f6.zip
auto merge of #8539 : pnkfelix/rust/fsk-visitor-vpar-defaults-step2, r=graydon,nikomatsakis
r? @nikomatsakis

Follow up to #8527 (which was step 1 of 5).  See that for overall description 

Part of #7081
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/check_const.rs96
-rw-r--r--src/librustc/middle/check_loop.rs54
-rw-r--r--src/librustc/middle/check_match.rs54
-rw-r--r--src/librustc/middle/const_eval.rs19
-rw-r--r--src/librustc/middle/effect.rs115
-rw-r--r--src/librustc/middle/privacy.rs279
-rw-r--r--src/librustc/middle/reachable.rs207
-rw-r--r--src/librustc/middle/region.rs224
8 files changed, 602 insertions, 446 deletions
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 160cc23bd19..0530ffd30b4 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -17,7 +17,30 @@ use util::ppaux;
 
 use syntax::ast::*;
 use syntax::codemap;
-use syntax::{oldvisit, ast_util, ast_map};
+use syntax::{ast_util, ast_map};
+use syntax::visit::Visitor;
+use syntax::visit;
+
+struct CheckCrateVisitor {
+    sess: Session,
+    ast_map: ast_map::map,
+    def_map: resolve::DefMap,
+    method_map: typeck::method_map,
+    tcx: ty::ctxt,
+}
+
+impl Visitor<bool> for CheckCrateVisitor {
+    fn visit_item(&mut self, i:@item, env:bool) {
+        check_item(self, self.sess, self.ast_map, self.def_map, i, env);
+    }
+    fn visit_pat(&mut self, p:@pat, env:bool) {
+        check_pat(self, p, env);
+    }
+    fn visit_expr(&mut self, ex:@expr, env:bool) {
+        check_expr(self, self.sess, self.def_map, self.method_map,
+                   self.tcx, ex, env);
+    }
+}
 
 pub fn check_crate(sess: Session,
                    crate: &Crate,
@@ -25,39 +48,40 @@ pub fn check_crate(sess: Session,
                    def_map: resolve::DefMap,
                    method_map: typeck::method_map,
                    tcx: ty::ctxt) {
-    oldvisit::visit_crate(crate, (false, oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_item: |a,b| check_item(sess, ast_map, def_map, a, b),
-        visit_pat: check_pat,
-        visit_expr: |a,b|
-            check_expr(sess, def_map, method_map, tcx, a, b),
-        .. *oldvisit::default_visitor()
-    })));
+    let mut v = CheckCrateVisitor {
+        sess: sess,
+        ast_map: ast_map,
+        def_map: def_map,
+        method_map: method_map,
+        tcx: tcx,
+    };
+    visit::walk_crate(&mut v, crate, false);
     sess.abort_if_errors();
 }
 
-pub fn check_item(sess: Session,
+pub fn check_item(v: &mut CheckCrateVisitor,
+                  sess: Session,
                   ast_map: ast_map::map,
                   def_map: resolve::DefMap,
                   it: @item,
-                  (_is_const, v): (bool,
-                                   oldvisit::vt<bool>)) {
+                  _is_const: bool) {
     match it.node {
       item_static(_, _, ex) => {
-        (v.visit_expr)(ex, (true, v));
+        v.visit_expr(ex, true);
         check_item_recursion(sess, ast_map, def_map, it);
       }
       item_enum(ref enum_definition, _) => {
         for var in (*enum_definition).variants.iter() {
             for ex in var.node.disr_expr.iter() {
-                (v.visit_expr)(*ex, (true, v));
+                v.visit_expr(*ex, true);
             }
         }
       }
-      _ => oldvisit::visit_item(it, (false, v))
+      _ => visit::walk_item(v, it, false)
     }
 }
 
-pub fn check_pat(p: @pat, (_is_const, v): (bool, oldvisit::vt<bool>)) {
+pub fn check_pat(v: &mut CheckCrateVisitor, p: @pat, _is_const: bool) {
     fn is_str(e: @expr) -> bool {
         match e.node {
             expr_vstore(
@@ -72,22 +96,22 @@ pub fn check_pat(p: @pat, (_is_const, v): (bool, oldvisit::vt<bool>)) {
     }
     match p.node {
       // Let through plain ~-string literals here
-      pat_lit(a) => if !is_str(a) { (v.visit_expr)(a, (true, v)); },
+      pat_lit(a) => if !is_str(a) { v.visit_expr(a, true); },
       pat_range(a, b) => {
-        if !is_str(a) { (v.visit_expr)(a, (true, v)); }
-        if !is_str(b) { (v.visit_expr)(b, (true, v)); }
+        if !is_str(a) { v.visit_expr(a, true); }
+        if !is_str(b) { v.visit_expr(b, true); }
       }
-      _ => oldvisit::visit_pat(p, (false, v))
+      _ => visit::walk_pat(v, p, false)
     }
 }
 
-pub fn check_expr(sess: Session,
+pub fn check_expr(v: &mut CheckCrateVisitor,
+                  sess: Session,
                   def_map: resolve::DefMap,
                   method_map: typeck::method_map,
                   tcx: ty::ctxt,
                   e: @expr,
-                  (is_const, v): (bool,
-                                  oldvisit::vt<bool>)) {
+                  is_const: bool) {
     if is_const {
         match e.node {
           expr_unary(_, deref, _) => { }
@@ -152,8 +176,8 @@ pub fn check_expr(sess: Session,
                 }
             }
           }
-          expr_paren(e) => { check_expr(sess, def_map, method_map,
-                                         tcx, e, (is_const, v)); }
+          expr_paren(e) => { check_expr(v, sess, def_map, method_map,
+                                        tcx, e, is_const); }
           expr_vstore(_, expr_vstore_slice) |
           expr_vec(_, m_imm) |
           expr_addr_of(m_imm, _) |
@@ -192,7 +216,7 @@ pub fn check_expr(sess: Session,
       }
       _ => ()
     }
-    oldvisit::visit_expr(e, (is_const, v));
+    visit::walk_expr(v, e, is_const);
 }
 
 #[deriving(Clone)]
@@ -204,6 +228,8 @@ struct env {
     idstack: @mut ~[NodeId]
 }
 
+struct CheckItemRecursionVisitor;
+
 // Make sure a const item doesn't recursively refer to itself
 // FIXME: Should use the dependency graph when it's available (#1356)
 pub fn check_item_recursion(sess: Session,
@@ -218,29 +244,27 @@ pub fn check_item_recursion(sess: Session,
         idstack: @mut ~[]
     };
 
-    let visitor = oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_item: visit_item,
-        visit_expr: visit_expr,
-        .. *oldvisit::default_visitor()
-    });
-    (visitor.visit_item)(it, (env, visitor));
+    let mut visitor = CheckItemRecursionVisitor;
+    visitor.visit_item(it, env);
+}
 
-    fn visit_item(it: @item, (env, v): (env, oldvisit::vt<env>)) {
+impl Visitor<env> for CheckItemRecursionVisitor {
+    fn visit_item(&mut self, it: @item, env: env) {
         if env.idstack.iter().any(|x| x == &(it.id)) {
             env.sess.span_fatal(env.root_it.span, "recursive constant");
         }
         env.idstack.push(it.id);
-        oldvisit::visit_item(it, (env, v));
+        visit::walk_item(self, it, env);
         env.idstack.pop();
     }
 
-    fn visit_expr(e: @expr, (env, v): (env, oldvisit::vt<env>)) {
+    fn visit_expr(&mut self, e: @expr, env: env) {
         match e.node {
             expr_path(*) => match env.def_map.find(&e.id) {
                 Some(&def_static(def_id, _)) if ast_util::is_local(def_id) =>
                     match env.ast_map.get_copy(&def_id.node) {
                         ast_map::node_item(it, _) => {
-                            (v.visit_item)(it, (env, v));
+                            self.visit_item(it, env);
                         }
                         _ => fail!("const not bound to an item")
                     },
@@ -248,6 +272,6 @@ pub fn check_item_recursion(sess: Session,
             },
             _ => ()
         }
-        oldvisit::visit_expr(e, (env, v));
+        visit::walk_expr(self, e, env);
     }
 }
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index cbd1d3cd9ad..35705dff6ef 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -12,7 +12,8 @@
 use middle::ty;
 
 use syntax::ast::*;
-use syntax::oldvisit;
+use syntax::visit;
+use syntax::visit::Visitor;
 
 #[deriving(Clone)]
 pub struct Context {
@@ -20,50 +21,55 @@ pub struct Context {
     can_ret: bool
 }
 
+struct CheckLoopVisitor {
+    tcx: ty::ctxt,
+}
+
 pub fn check_crate(tcx: ty::ctxt, crate: &Crate) {
-    oldvisit::visit_crate(crate,
-                          (Context { in_loop: false, can_ret: true },
-                          oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_item: |i, (_cx, v)| {
-            oldvisit::visit_item(i, (Context {
+    visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx },
+                      crate,
+                      Context { in_loop: false, can_ret: true });
+}
+
+impl Visitor<Context> for CheckLoopVisitor {
+    fn visit_item(&mut self, i:@item, _cx:Context) {
+        visit::walk_item(self, i, Context {
                                     in_loop: false,
                                     can_ret: true
-                                 }, v));
-        },
-        visit_expr: |e: @expr, (cx, v): (Context, oldvisit::vt<Context>)| {
+                                  });
+    }
+
+    fn visit_expr(&mut self, e:@expr, cx:Context) {
+
             match e.node {
               expr_while(e, ref b) => {
-                (v.visit_expr)(e, (cx, v));
-                (v.visit_block)(b, (Context { in_loop: true,.. cx }, v));
+                self.visit_expr(e, cx);
+                self.visit_block(b, Context { in_loop: true,.. cx });
               }
               expr_loop(ref b, _) => {
-                (v.visit_block)(b, (Context { in_loop: true,.. cx }, v));
+                self.visit_block(b, Context { in_loop: true,.. cx });
               }
               expr_fn_block(_, ref b) => {
-                (v.visit_block)(b, (Context {
-                                         in_loop: false,
-                                         can_ret: false
-                                      }, v));
+                self.visit_block(b, Context { in_loop: false, can_ret: false });
               }
               expr_break(_) => {
                 if !cx.in_loop {
-                    tcx.sess.span_err(e.span, "`break` outside of loop");
+                    self.tcx.sess.span_err(e.span, "`break` outside of loop");
                 }
               }
               expr_again(_) => {
                 if !cx.in_loop {
-                    tcx.sess.span_err(e.span, "`loop` outside of loop");
+                    self.tcx.sess.span_err(e.span, "`loop` outside of loop");
                 }
               }
               expr_ret(oe) => {
                 if !cx.can_ret {
-                    tcx.sess.span_err(e.span, "`return` in block function");
+                    self.tcx.sess.span_err(e.span, "`return` in block function");
                 }
-                oldvisit::visit_expr_opt(oe, (cx, v));
+                visit::walk_expr_opt(self, oe, cx);
               }
-              _ => oldvisit::visit_expr(e, (cx, v))
+              _ => visit::walk_expr(self, e, cx)
             }
-        },
-        .. *oldvisit::default_visitor()
-    })));
+
+    }
 }
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 9719460bbd3..3f321fcfcd2 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -25,7 +25,8 @@ use extra::sort;
 use syntax::ast::*;
 use syntax::ast_util::{unguarded_pat, walk_pat};
 use syntax::codemap::{span, dummy_sp, spanned};
-use syntax::oldvisit;
+use syntax::visit;
+use syntax::visit::{Visitor,fn_kind};
 
 pub struct MatchCheckCtxt {
     tcx: ty::ctxt,
@@ -33,6 +34,22 @@ pub struct MatchCheckCtxt {
     moves_map: moves::MovesMap
 }
 
+struct CheckMatchVisitor {
+    cx: @MatchCheckCtxt
+}
+
+impl Visitor<()> for CheckMatchVisitor {
+    fn visit_expr(&mut self, ex:@expr, e:()) {
+        check_expr(self, self.cx, ex, e);
+    }
+    fn visit_local(&mut self, l:@Local, e:()) {
+        check_local(self, self.cx, l, e);
+    }
+    fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl, b:&Block, s:span, n:NodeId, e:()) {
+        check_fn(self, self.cx, fk, fd, b, s, n, e);
+    }
+}
+
 pub fn check_crate(tcx: ty::ctxt,
                    method_map: method_map,
                    moves_map: moves::MovesMap,
@@ -40,20 +57,18 @@ pub fn check_crate(tcx: ty::ctxt,
     let cx = @MatchCheckCtxt {tcx: tcx,
                               method_map: method_map,
                               moves_map: moves_map};
-    oldvisit::visit_crate(crate, ((), oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_expr: |a,b| check_expr(cx, a, b),
-        visit_local: |a,b| check_local(cx, a, b),
-        visit_fn: |kind, decl, body, sp, id, (e, v)|
-            check_fn(cx, kind, decl, body, sp, id, (e, v)),
-        .. *oldvisit::default_visitor::<()>()
-    })));
+    let mut v = CheckMatchVisitor { cx: cx };
+
+    visit::walk_crate(&mut v, crate, ());
+
     tcx.sess.abort_if_errors();
 }
 
-pub fn check_expr(cx: @MatchCheckCtxt,
+pub fn check_expr(v: &mut CheckMatchVisitor,
+                  cx: @MatchCheckCtxt,
                   ex: @expr,
-                  (s, v): ((), oldvisit::vt<()>)) {
-    oldvisit::visit_expr(ex, (s, v));
+                  s: ()) {
+    visit::walk_expr(v, ex, s);
     match ex.node {
       expr_match(scrut, ref arms) => {
         // First, check legality of move bindings.
@@ -787,10 +802,11 @@ pub fn default(cx: &MatchCheckCtxt, r: &[@pat]) -> Option<~[@pat]> {
     else { None }
 }
 
-pub fn check_local(cx: &MatchCheckCtxt,
+pub fn check_local(v: &mut CheckMatchVisitor,
+                   cx: &MatchCheckCtxt,
                    loc: @Local,
-                   (s, v): ((), oldvisit::vt<()>)) {
-    oldvisit::visit_local(loc, (s, v));
+                   s: ()) {
+    visit::walk_local(v, loc, s);
     if is_refutable(cx, loc.pat) {
         cx.tcx.sess.span_err(loc.pat.span,
                              "refutable pattern in local binding");
@@ -800,15 +816,15 @@ pub fn check_local(cx: &MatchCheckCtxt,
     check_legality_of_move_bindings(cx, false, [ loc.pat ]);
 }
 
-pub fn check_fn(cx: &MatchCheckCtxt,
-                kind: &oldvisit::fn_kind,
+pub fn check_fn(v: &mut CheckMatchVisitor,
+                cx: &MatchCheckCtxt,
+                kind: &visit::fn_kind,
                 decl: &fn_decl,
                 body: &Block,
                 sp: span,
                 id: NodeId,
-                (s, v): ((),
-                         oldvisit::vt<()>)) {
-    oldvisit::visit_fn(kind, decl, body, sp, id, (s, v));
+                s: ()) {
+    visit::walk_fn(v, kind, decl, body, sp, id, s);
     for input in decl.inputs.iter() {
         if is_refutable(cx, input.pat) {
             cx.tcx.sess.span_err(input.pat.span,
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 68e3dfd63be..2e8d0d351d9 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -14,7 +14,9 @@ use middle::astencode;
 use middle::ty;
 use middle;
 
-use syntax::{ast, ast_map, ast_util, oldvisit};
+use syntax::{ast, ast_map, ast_util};
+use syntax::visit;
+use syntax::visit::Visitor;
 use syntax::ast::*;
 
 use std::float;
@@ -267,13 +269,18 @@ pub fn lookup_constness(tcx: ty::ctxt, e: &expr) -> constness {
     }
 }
 
+struct ConstEvalVisitor { tcx: ty::ctxt }
+
+impl Visitor<()> for ConstEvalVisitor {
+    fn visit_expr_post(&mut self, e:@expr, _:()) {
+        classify(e, self.tcx);
+    }
+}
+
 pub fn process_crate(crate: &ast::Crate,
                      tcx: ty::ctxt) {
-    let v = oldvisit::mk_simple_visitor(@oldvisit::SimpleVisitor {
-        visit_expr_post: |e| { classify(e, tcx); },
-        .. *oldvisit::default_simple_visitor()
-    });
-    oldvisit::visit_crate(crate, ((), v));
+    let mut v = ConstEvalVisitor { tcx: tcx };
+    visit::walk_crate(&mut v, crate, ());
     tcx.sess.abort_if_errors();
 }
 
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 651ce292d28..de0be2a0bc5 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -20,8 +20,10 @@ use syntax::ast::{deref, expr_call, expr_inline_asm, expr_method_call};
 use syntax::ast::{expr_unary, unsafe_fn, expr_path};
 use syntax::ast;
 use syntax::codemap::span;
-use syntax::oldvisit::{fk_item_fn, fk_method};
-use syntax::oldvisit;
+use syntax::visit::{fk_item_fn, fk_method};
+use syntax::visit;
+use syntax::visit::{Visitor,fn_kind};
+use syntax::ast::{fn_decl,Block,NodeId,expr};
 
 #[deriving(Eq)]
 enum UnsafeContext {
@@ -45,108 +47,110 @@ fn type_is_unsafe_function(ty: ty::t) -> bool {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
-                   method_map: method_map,
-                   crate: &ast::Crate) {
-    let context = @mut Context {
-        method_map: method_map,
-        unsafe_context: SafeContext,
-    };
+struct EffectCheckVisitor {
+    tcx: ty::ctxt,
+    context: @mut Context,
+}
 
-    let require_unsafe: @fn(span: span,
-                            description: &str) = |span, description| {
-        match context.unsafe_context {
+impl EffectCheckVisitor {
+    fn require_unsafe(&mut self, span: span, description: &str) {
+        match self.context.unsafe_context {
             SafeContext => {
                 // Report an error.
-                tcx.sess.span_err(span,
+                self.tcx.sess.span_err(span,
                                   fmt!("%s requires unsafe function or block",
                                        description))
             }
             UnsafeBlock(block_id) => {
                 // OK, but record this.
                 debug!("effect: recording unsafe block as used: %?", block_id);
-                let _ = tcx.used_unsafe.insert(block_id);
+                let _ = self.tcx.used_unsafe.insert(block_id);
             }
             UnsafeFn => {}
         }
-    };
+    }
+}
+
+impl Visitor<()> for EffectCheckVisitor {
+    fn visit_fn(&mut self, fn_kind:&fn_kind, fn_decl:&fn_decl,
+                block:&Block, span:span, node_id:NodeId, _:()) {
 
-    let visitor = oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_fn: |fn_kind, fn_decl, block, span, node_id, (_, visitor)| {
             let (is_item_fn, is_unsafe_fn) = match *fn_kind {
                 fk_item_fn(_, _, purity, _) => (true, purity == unsafe_fn),
                 fk_method(_, _, method) => (true, method.purity == unsafe_fn),
                 _ => (false, false),
             };
 
-            let old_unsafe_context = context.unsafe_context;
+            let old_unsafe_context = self.context.unsafe_context;
             if is_unsafe_fn {
-                context.unsafe_context = UnsafeFn
+                self.context.unsafe_context = UnsafeFn
             } else if is_item_fn {
-                context.unsafe_context = SafeContext
+                self.context.unsafe_context = SafeContext
             }
 
-            oldvisit::visit_fn(fn_kind,
+            visit::walk_fn(self,
+                           fn_kind,
                             fn_decl,
                             block,
                             span,
                             node_id,
-                            ((),
-                             visitor));
+                            ());
+
+            self.context.unsafe_context = old_unsafe_context
+    }
 
-            context.unsafe_context = old_unsafe_context
-        },
+    fn visit_block(&mut self, block:&Block, _:()) {
 
-        visit_block: |block, (_, visitor)| {
-            let old_unsafe_context = context.unsafe_context;
+            let old_unsafe_context = self.context.unsafe_context;
             if block.rules == ast::UnsafeBlock &&
-                    context.unsafe_context == SafeContext {
-                context.unsafe_context = UnsafeBlock(block.id)
+                    self.context.unsafe_context == SafeContext {
+                self.context.unsafe_context = UnsafeBlock(block.id)
             }
 
-            oldvisit::visit_block(block, ((), visitor));
+            visit::walk_block(self, block, ());
 
-            context.unsafe_context = old_unsafe_context
-        },
+            self.context.unsafe_context = old_unsafe_context
+    }
+
+    fn visit_expr(&mut self, expr:@expr, _:()) {
 
-        visit_expr: |expr, (_, visitor)| {
             match expr.node {
                 expr_method_call(callee_id, _, _, _, _, _) => {
-                    let base_type = ty::node_id_to_type(tcx, callee_id);
+                    let base_type = ty::node_id_to_type(self.tcx, callee_id);
                     debug!("effect: method call case, base type is %s",
-                           ppaux::ty_to_str(tcx, base_type));
+                           ppaux::ty_to_str(self.tcx, base_type));
                     if type_is_unsafe_function(base_type) {
-                        require_unsafe(expr.span,
+                        self.require_unsafe(expr.span,
                                        "invocation of unsafe method")
                     }
                 }
                 expr_call(base, _, _) => {
-                    let base_type = ty::node_id_to_type(tcx, base.id);
+                    let base_type = ty::node_id_to_type(self.tcx, base.id);
                     debug!("effect: call case, base type is %s",
-                           ppaux::ty_to_str(tcx, base_type));
+                           ppaux::ty_to_str(self.tcx, base_type));
                     if type_is_unsafe_function(base_type) {
-                        require_unsafe(expr.span, "call to unsafe function")
+                        self.require_unsafe(expr.span, "call to unsafe function")
                     }
                 }
                 expr_unary(_, deref, base) => {
-                    let base_type = ty::node_id_to_type(tcx, base.id);
+                    let base_type = ty::node_id_to_type(self.tcx, base.id);
                     debug!("effect: unary case, base type is %s",
-                           ppaux::ty_to_str(tcx, base_type));
+                           ppaux::ty_to_str(self.tcx, base_type));
                     match ty::get(base_type).sty {
                         ty_ptr(_) => {
-                            require_unsafe(expr.span,
+                            self.require_unsafe(expr.span,
                                            "dereference of unsafe pointer")
                         }
                         _ => {}
                     }
                 }
                 expr_inline_asm(*) => {
-                    require_unsafe(expr.span, "use of inline assembly")
+                    self.require_unsafe(expr.span, "use of inline assembly")
                 }
                 expr_path(*) => {
-                    match ty::resolve_expr(tcx, expr) {
+                    match ty::resolve_expr(self.tcx, expr) {
                         ast::def_static(_, true) => {
-                            require_unsafe(expr.span, "use of mutable static")
+                            self.require_unsafe(expr.span, "use of mutable static")
                         }
                         _ => {}
                     }
@@ -154,11 +158,22 @@ pub fn check_crate(tcx: ty::ctxt,
                 _ => {}
             }
 
-            oldvisit::visit_expr(expr, ((), visitor))
-        },
+            visit::walk_expr(self, expr, ());
+    }
+}
 
-        .. *oldvisit::default_visitor()
-    });
+pub fn check_crate(tcx: ty::ctxt,
+                   method_map: method_map,
+                   crate: &ast::Crate) {
+    let context = @mut Context {
+        method_map: method_map,
+        unsafe_context: SafeContext,
+    };
+
+    let mut visitor = EffectCheckVisitor {
+        tcx: tcx,
+        context: context,
+    };
 
-    oldvisit::visit_crate(crate, ((), visitor))
+    visit::walk_crate(&mut visitor, crate, ());
 }
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 54e7c79e97c..6a566f10f1e 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -34,54 +34,57 @@ use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy};
 use syntax::attr;
 use syntax::codemap::span;
 use syntax::parse::token;
-use syntax::oldvisit;
+use syntax::visit;
+use syntax::visit::Visitor;
+use syntax::ast::{_mod,expr,item,Block,pat};
 
-pub fn check_crate<'mm>(tcx: ty::ctxt,
-                   method_map: &'mm method_map,
-                   crate: &ast::Crate) {
-    let privileged_items = @mut ~[];
+struct PrivacyVisitor {
+    tcx: ty::ctxt,
+    privileged_items: @mut ~[NodeId],
+}
 
+impl PrivacyVisitor {
     // Adds an item to its scope.
-    let add_privileged_item: @fn(@ast::item, &mut uint) = |item, count| {
+    fn add_privileged_item(&mut self, item: @ast::item, count: &mut uint) {
         match item.node {
             item_struct(*) | item_trait(*) | item_enum(*) |
             item_fn(*) => {
-                privileged_items.push(item.id);
+                self.privileged_items.push(item.id);
                 *count += 1;
             }
             item_impl(_, _, _, ref methods) => {
                 for method in methods.iter() {
-                    privileged_items.push(method.id);
+                    self.privileged_items.push(method.id);
                     *count += 1;
                 }
-                privileged_items.push(item.id);
+                self.privileged_items.push(item.id);
                 *count += 1;
             }
             item_foreign_mod(ref foreign_mod) => {
                 for foreign_item in foreign_mod.items.iter() {
-                    privileged_items.push(foreign_item.id);
+                    self.privileged_items.push(foreign_item.id);
                     *count += 1;
                 }
             }
             _ => {}
         }
-    };
+    }
 
     // Adds items that are privileged to this scope.
-    let add_privileged_items: @fn(&[@ast::item]) -> uint = |items| {
+    fn add_privileged_items(&mut self, items: &[@ast::item]) -> uint {
         let mut count = 0;
         for &item in items.iter() {
-            add_privileged_item(item, &mut count);
+            self.add_privileged_item(item, &mut count);
         }
         count
-    };
+    }
 
     // Checks that an enum variant is in scope
-    let check_variant: @fn(span: span, enum_id: ast::def_id) =
-            |span, enum_id| {
-        let variant_info = ty::enum_variants(tcx, enum_id)[0];
+    fn check_variant(&mut self, span: span, enum_id: ast::def_id) {
+        let variant_info = ty::enum_variants(self.tcx, enum_id)[0];
         let parental_privacy = if is_local(enum_id) {
-            let parent_vis = ast_map::node_item_query(tcx.items, enum_id.node,
+            let parent_vis = ast_map::node_item_query(self.tcx.items,
+                                                      enum_id.node,
                                    |it| { it.vis },
                                    ~"unbound enum parent when checking \
                                     dereference of enum type");
@@ -99,15 +102,14 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
         if variant_visibility_to_privacy(variant_info.vis,
                                          parental_privacy == Public)
                                          == Private {
-            tcx.sess.span_err(span,
+            self.tcx.sess.span_err(span,
                 "can only dereference enums \
                  with a single, public variant");
         }
-    };
+    }
 
     // Returns true if a crate-local method is private and false otherwise.
-    let method_is_private: @fn(span: span, method_id: NodeId) -> bool =
-            |span, method_id| {
+    fn method_is_private(&mut self, span: span, method_id: NodeId) -> bool {
         let check = |vis: visibility, container_id: def_id| {
             let mut is_private = false;
             if vis == private {
@@ -117,12 +119,12 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
             } else {
                 // Look up the enclosing impl.
                 if container_id.crate != LOCAL_CRATE {
-                    tcx.sess.span_bug(span,
+                    self.tcx.sess.span_bug(span,
                                       "local method isn't in local \
                                        impl?!");
                 }
 
-                match tcx.items.find(&container_id.node) {
+                match self.tcx.items.find(&container_id.node) {
                     Some(&node_item(item, _)) => {
                         match item.node {
                             item_impl(_, None, _, _)
@@ -133,10 +135,10 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                         }
                     }
                     Some(_) => {
-                        tcx.sess.span_bug(span, "impl wasn't an item?!");
+                        self.tcx.sess.span_bug(span, "impl wasn't an item?!");
                     }
                     None => {
-                        tcx.sess.span_bug(span, "impl wasn't in AST map?!");
+                        self.tcx.sess.span_bug(span, "impl wasn't in AST map?!");
                     }
                 }
             }
@@ -144,7 +146,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
             is_private
         };
 
-        match tcx.items.find(&method_id) {
+        match self.tcx.items.find(&method_id) {
             Some(&node_method(method, impl_id, _)) => {
                 check(method.vis, impl_id)
             }
@@ -155,26 +157,25 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                 }
             }
             Some(_) => {
-                tcx.sess.span_bug(span,
+                self.tcx.sess.span_bug(span,
                                   fmt!("method_is_private: method was a %s?!",
                                        ast_map::node_id_to_str(
-                                            tcx.items,
+                                            self.tcx.items,
                                             method_id,
                                            token::get_ident_interner())));
             }
             None => {
-                tcx.sess.span_bug(span, "method not found in \
+                self.tcx.sess.span_bug(span, "method not found in \
                                          AST map?!");
             }
         }
-    };
+    }
 
     // Returns true if the given local item is private and false otherwise.
-    let local_item_is_private: @fn(span: span, item_id: NodeId) -> bool =
-            |span, item_id| {
+    fn local_item_is_private(&mut self, span: span, item_id: NodeId) -> bool {
         let mut f: &fn(NodeId) -> bool = |_| false;
         f = |item_id| {
-            match tcx.items.find(&item_id) {
+            match self.tcx.items.find(&item_id) {
                 Some(&node_item(item, _)) => item.vis != public,
                 Some(&node_foreign_item(*)) => false,
                 Some(&node_method(method, impl_did, _)) => {
@@ -186,104 +187,96 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                 }
                 Some(&node_trait_method(_, trait_did, _)) => f(trait_did.node),
                 Some(_) => {
-                    tcx.sess.span_bug(span,
+                    self.tcx.sess.span_bug(span,
                                       fmt!("local_item_is_private: item was \
                                             a %s?!",
                                            ast_map::node_id_to_str(
-                                                tcx.items,
+                                                self.tcx.items,
                                                 item_id,
                                                token::get_ident_interner())));
                 }
                 None => {
-                    tcx.sess.span_bug(span, "item not found in AST map?!");
+                    self.tcx.sess.span_bug(span, "item not found in AST map?!");
                 }
             }
         };
         f(item_id)
-    };
+    }
 
     // Checks that a private field is in scope.
-    let check_field: @fn(span: span, id: ast::def_id, ident: ast::ident) =
-            |span, id, ident| {
-        let fields = ty::lookup_struct_fields(tcx, id);
+    fn check_field(&mut self, span: span, id: ast::def_id, ident: ast::ident) {
+        let fields = ty::lookup_struct_fields(self.tcx, id);
         for field in fields.iter() {
             if field.ident != ident { loop; }
             if field.vis == private {
-                tcx.sess.span_err(span, fmt!("field `%s` is private",
+                self.tcx.sess.span_err(span, fmt!("field `%s` is private",
                                              token::ident_to_str(&ident)));
             }
             break;
         }
-    };
+    }
 
     // Given the ID of a method, checks to ensure it's in scope.
-    let check_method_common: @fn(span: span,
-                                 method_id: def_id,
-                                 name: &ident) =
-            |span, method_id, name| {
+    fn check_method_common(&mut self, span: span, method_id: def_id, name: &ident) {
         // If the method is a default method, we need to use the def_id of
         // the default implementation.
         // Having to do this this is really unfortunate.
-        let method_id = ty::method(tcx, method_id).provided_source
+        let method_id = ty::method(self.tcx, method_id).provided_source
             .unwrap_or_default(method_id);
 
         if method_id.crate == LOCAL_CRATE {
-            let is_private = method_is_private(span, method_id.node);
-            let container_id = ty::method(tcx, method_id).container_id;
+            let is_private = self.method_is_private(span, method_id.node);
+            let container_id = ty::method(self.tcx, method_id).container_id;
             if is_private &&
                     (container_id.crate != LOCAL_CRATE ||
-                     !privileged_items.iter().any(|x| x == &(container_id.node))) {
-                tcx.sess.span_err(span,
+                     !self.privileged_items.iter().any(|x| x == &(container_id.node))) {
+                self.tcx.sess.span_err(span,
                                   fmt!("method `%s` is private",
                                        token::ident_to_str(name)));
             }
         } else {
             let visibility =
-                csearch::get_item_visibility(tcx.sess.cstore, method_id);
+                csearch::get_item_visibility(self.tcx.sess.cstore, method_id);
             if visibility != public {
-                tcx.sess.span_err(span,
+                self.tcx.sess.span_err(span,
                                   fmt!("method `%s` is private",
                                        token::ident_to_str(name)));
             }
         }
-    };
+    }
 
     // Checks that a private path is in scope.
-    let check_path: @fn(span: span, def: def, path: &Path) =
-            |span, def, path| {
+    fn check_path(&mut self, span: span, def: def, path: &Path) {
         debug!("checking path");
         match def {
             def_static_method(method_id, _, _) => {
                 debug!("found static method def, checking it");
-                check_method_common(span, method_id, path.idents.last())
+                self.check_method_common(span, method_id, path.idents.last())
             }
             def_fn(def_id, _) => {
                 if def_id.crate == LOCAL_CRATE {
-                    if local_item_is_private(span, def_id.node) &&
-                            !privileged_items.iter().any(|x| x == &def_id.node) {
-                        tcx.sess.span_err(span,
+                    if self.local_item_is_private(span, def_id.node) &&
+                            !self.privileged_items.iter().any(|x| x == &def_id.node) {
+                        self.tcx.sess.span_err(span,
                                           fmt!("function `%s` is private",
                                                token::ident_to_str(path.idents.last())));
                     }
-                } else if csearch::get_item_visibility(tcx.sess.cstore,
+                } else if csearch::get_item_visibility(self.tcx.sess.cstore,
                                                        def_id) != public {
-                    tcx.sess.span_err(span,
+                    self.tcx.sess.span_err(span,
                                       fmt!("function `%s` is private",
                                            token::ident_to_str(path.idents.last())));
                 }
             }
             _ => {}
         }
-    };
+    }
 
     // Checks that a private method is in scope.
-    let check_method: @fn(span: span,
-                          origin: &method_origin,
-                          ident: ast::ident) =
-            |span, origin, ident| {
+    fn check_method(&mut self, span: span, origin: &method_origin, ident: ast::ident) {
         match *origin {
             method_static(method_id) => {
-                check_method_common(span, method_id, &ident)
+                self.check_method_common(span, method_id, &ident)
             }
             method_param(method_param {
                 trait_id: trait_id,
@@ -292,19 +285,20 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
             }) |
             method_trait(trait_id, method_num) => {
                 if trait_id.crate == LOCAL_CRATE {
-                    match tcx.items.find(&trait_id.node) {
+                    match self.tcx.items.find(&trait_id.node) {
                         Some(&node_item(item, _)) => {
                             match item.node {
                                 item_trait(_, _, ref methods) => {
                                     if method_num >= (*methods).len() {
-                                        tcx.sess.span_bug(span, "method number out of range?!");
+                                        self.tcx.sess.span_bug(span,
+                                                               "method number out of range?!");
                                     }
                                     match (*methods)[method_num] {
                                         provided(method)
                                              if method.vis == private &&
-                                             !privileged_items.iter()
+                                             !self.privileged_items.iter()
                                              .any(|x| x == &(trait_id.node)) => {
-                                            tcx.sess.span_err(span,
+                                            self.tcx.sess.span_err(span,
                                                               fmt!("method `%s` is private",
                                                                    token::ident_to_str(&method
                                                                                         .ident)));
@@ -316,15 +310,16 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                                     }
                                 }
                                 _ => {
-                                    tcx.sess.span_bug(span, "trait wasn't actually a trait?!");
+                                    self.tcx.sess.span_bug(span, "trait wasn't actually a trait?!");
                                 }
                             }
                         }
                         Some(_) => {
-                            tcx.sess.span_bug(span, "trait wasn't an item?!");
+                            self.tcx.sess.span_bug(span, "trait wasn't an item?!");
                         }
                         None => {
-                            tcx.sess.span_bug(span, "trait item wasn't found in the AST map?!");
+                            self.tcx.sess.span_bug(span,
+                                                   "trait item wasn't found in the AST map?!");
                         }
                     }
                 } else {
@@ -332,30 +327,35 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                 }
             }
         }
-    };
+    }
+}
+
+impl<'self> Visitor<&'self method_map> for PrivacyVisitor {
 
-    let visitor = oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_mod: |the_module, span, node_id, (method_map, visitor)| {
-            let n_added = add_privileged_items(the_module.items);
+    fn visit_mod<'mm>(&mut self, the_module:&_mod, _:span, _:NodeId,
+                      method_map:&'mm method_map) {
 
-            oldvisit::visit_mod(the_module,
-                                span,
-                                node_id,
-                                (method_map, visitor));
+            let n_added = self.add_privileged_items(the_module.items);
+
+            visit::walk_mod(self, the_module, method_map);
 
             do n_added.times {
-                ignore(privileged_items.pop());
+                ignore(self.privileged_items.pop());
             }
-        },
-        visit_item: |item, (method_map, visitor)| {
+    }
+
+    fn visit_item<'mm>(&mut self, item:@item, method_map:&'mm method_map) {
+
             // Do not check privacy inside items with the resolve_unexported
             // attribute. This is used for the test runner.
             if !attr::contains_name(item.attrs, "!resolve_unexported") {
-                check_sane_privacy(tcx, item);
-                oldvisit::visit_item(item, (method_map, visitor));
+                check_sane_privacy(self.tcx, item);
+                visit::walk_item(self, item, method_map);
             }
-        },
-        visit_block: |block, (method_map, visitor)| {
+    }
+
+    fn visit_block<'mm>(&mut self, block:&Block, method_map:&'mm method_map) {
+
             // Gather up all the privileged items.
             let mut n_added = 0;
             for stmt in block.stmts.iter() {
@@ -363,7 +363,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                     stmt_decl(decl, _) => {
                         match decl.node {
                             decl_item(item) => {
-                                add_privileged_item(item, &mut n_added);
+                                self.add_privileged_item(item, &mut n_added);
                             }
                             _ => {}
                         }
@@ -372,15 +372,16 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                 }
             }
 
-            oldvisit::visit_block(block, (method_map, visitor));
+            visit::walk_block(self, block, method_map);
 
             do n_added.times {
-                ignore(privileged_items.pop());
+                ignore(self.privileged_items.pop());
             }
-        },
-        visit_expr: |expr,
-                     (method_map, visitor):
-                        (&'mm method_map, oldvisit::vt<&'mm method_map>)| {
+
+    }
+
+    fn visit_expr<'mm>(&mut self, expr:@expr, method_map:&'mm method_map) {
+
             match expr.node {
                 expr_field(base, ident, _) => {
                     // Method calls are now a special syntactic form,
@@ -389,35 +390,35 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
 
                     // With type_autoderef, make sure we don't
                     // allow pointers to violate privacy
-                    match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
+                    match ty::get(ty::type_autoderef(self.tcx, ty::expr_ty(self.tcx,
                                                           base))).sty {
                         ty_struct(id, _)
-                        if id.crate != LOCAL_CRATE || !privileged_items.iter()
+                        if id.crate != LOCAL_CRATE || !self.privileged_items.iter()
                                 .any(|x| x == &(id.node)) => {
                             debug!("(privacy checking) checking field access");
-                            check_field(expr.span, id, ident);
+                            self.check_field(expr.span, id, ident);
                         }
                         _ => {}
                     }
                 }
                 expr_method_call(_, base, ident, _, _, _) => {
                     // Ditto
-                    match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
+                    match ty::get(ty::type_autoderef(self.tcx, ty::expr_ty(self.tcx,
                                                           base))).sty {
                         ty_enum(id, _) |
                         ty_struct(id, _)
                         if id.crate != LOCAL_CRATE ||
-                           !privileged_items.iter().any(|x| x == &(id.node)) => {
+                           !self.privileged_items.iter().any(|x| x == &(id.node)) => {
                             match method_map.find(&expr.id) {
                                 None => {
-                                    tcx.sess.span_bug(expr.span,
+                                    self.tcx.sess.span_bug(expr.span,
                                                       "method call not in \
                                                        method map");
                                 }
                                 Some(ref entry) => {
                                     debug!("(privacy checking) checking \
                                             impl method");
-                                    check_method(expr.span, &entry.origin, ident);
+                                    self.check_method(expr.span, &entry.origin, ident);
                                 }
                             }
                         }
@@ -425,35 +426,35 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                     }
                 }
                 expr_path(ref path) => {
-                    check_path(expr.span, tcx.def_map.get_copy(&expr.id), path);
+                    self.check_path(expr.span, self.tcx.def_map.get_copy(&expr.id), path);
                 }
                 expr_struct(_, ref fields, _) => {
-                    match ty::get(ty::expr_ty(tcx, expr)).sty {
+                    match ty::get(ty::expr_ty(self.tcx, expr)).sty {
                         ty_struct(id, _) => {
                             if id.crate != LOCAL_CRATE ||
-                                    !privileged_items.iter().any(|x| x == &(id.node)) {
+                                    !self.privileged_items.iter().any(|x| x == &(id.node)) {
                                 for field in (*fields).iter() {
                                         debug!("(privacy checking) checking \
                                                 field in struct literal");
-                                    check_field(expr.span, id, field.ident);
+                                    self.check_field(expr.span, id, field.ident);
                                 }
                             }
                         }
                         ty_enum(id, _) => {
                             if id.crate != LOCAL_CRATE ||
-                                    !privileged_items.iter().any(|x| x == &(id.node)) {
-                                match tcx.def_map.get_copy(&expr.id) {
+                                    !self.privileged_items.iter().any(|x| x == &(id.node)) {
+                                match self.tcx.def_map.get_copy(&expr.id) {
                                     def_variant(_, variant_id) => {
                                         for field in (*fields).iter() {
                                                 debug!("(privacy checking) \
                                                         checking field in \
                                                         struct variant \
                                                         literal");
-                                            check_field(expr.span, variant_id, field.ident);
+                                            self.check_field(expr.span, variant_id, field.ident);
                                         }
                                     }
                                     _ => {
-                                        tcx.sess.span_bug(expr.span,
+                                        self.tcx.sess.span_bug(expr.span,
                                                           "resolve didn't \
                                                            map enum struct \
                                                            constructor to a \
@@ -463,7 +464,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                             }
                         }
                         _ => {
-                            tcx.sess.span_bug(expr.span, "struct expr \
+                            self.tcx.sess.span_bug(expr.span, "struct expr \
                                                           didn't have \
                                                           struct type?!");
                         }
@@ -474,11 +475,11 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                     // enum type t, then t's first variant is public or
                     // privileged. (We can assume it has only one variant
                     // since typeck already happened.)
-                    match ty::get(ty::expr_ty(tcx, operand)).sty {
+                    match ty::get(ty::expr_ty(self.tcx, operand)).sty {
                         ty_enum(id, _) => {
                             if id.crate != LOCAL_CRATE ||
-                                !privileged_items.iter().any(|x| x == &(id.node)) {
-                                check_variant(expr.span, id);
+                                !self.privileged_items.iter().any(|x| x == &(id.node)) {
+                                self.check_variant(expr.span, id);
                             }
                         }
                         _ => { /* No check needed */ }
@@ -487,36 +488,39 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                 _ => {}
             }
 
-            oldvisit::visit_expr(expr, (method_map, visitor));
-        },
-        visit_pat: |pattern, (method_map, visitor)| {
+            visit::walk_expr(self, expr, method_map);
+
+    }
+
+    fn visit_pat<'mm>(&mut self, pattern:@pat, method_map:&'mm method_map) {
+
             match pattern.node {
                 pat_struct(_, ref fields, _) => {
-                    match ty::get(ty::pat_ty(tcx, pattern)).sty {
+                    match ty::get(ty::pat_ty(self.tcx, pattern)).sty {
                         ty_struct(id, _) => {
                             if id.crate != LOCAL_CRATE ||
-                                    !privileged_items.iter().any(|x| x == &(id.node)) {
+                                    !self.privileged_items.iter().any(|x| x == &(id.node)) {
                                 for field in fields.iter() {
                                         debug!("(privacy checking) checking \
                                                 struct pattern");
-                                    check_field(pattern.span, id, field.ident);
+                                    self.check_field(pattern.span, id, field.ident);
                                 }
                             }
                         }
                         ty_enum(enum_id, _) => {
                             if enum_id.crate != LOCAL_CRATE ||
-                                    !privileged_items.iter().any(|x| x == &enum_id.node) {
-                                match tcx.def_map.find(&pattern.id) {
+                                    !self.privileged_items.iter().any(|x| x == &enum_id.node) {
+                                match self.tcx.def_map.find(&pattern.id) {
                                     Some(&def_variant(_, variant_id)) => {
                                         for field in fields.iter() {
                                             debug!("(privacy checking) \
                                                     checking field in \
                                                     struct variant pattern");
-                                            check_field(pattern.span, variant_id, field.ident);
+                                            self.check_field(pattern.span, variant_id, field.ident);
                                         }
                                     }
                                     _ => {
-                                        tcx.sess.span_bug(pattern.span,
+                                        self.tcx.sess.span_bug(pattern.span,
                                                           "resolve didn't \
                                                            map enum struct \
                                                            pattern to a \
@@ -526,7 +530,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                             }
                         }
                         _ => {
-                            tcx.sess.span_bug(pattern.span,
+                            self.tcx.sess.span_bug(pattern.span,
                                               "struct pattern didn't have \
                                                struct type?!");
                         }
@@ -535,11 +539,20 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                 _ => {}
             }
 
-            oldvisit::visit_pat(pattern, (method_map, visitor));
-        },
-        .. *oldvisit::default_visitor()
-    });
-    oldvisit::visit_crate(crate, (method_map, visitor));
+            visit::walk_pat(self, pattern, method_map);
+    }
+}
+
+pub fn check_crate<'mm>(tcx: ty::ctxt,
+                        method_map: &'mm method_map,
+                        crate: &ast::Crate) {
+    let privileged_items = @mut ~[];
+
+    let mut visitor = PrivacyVisitor {
+        tcx: tcx,
+        privileged_items: privileged_items,
+    };
+    visit::walk_crate(&mut visitor, crate, method_map);
 }
 
 /// Validates all of the visibility qualifers placed on the item given. This
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 33a8960baee..b6a4ac49391 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -24,8 +24,8 @@ use syntax::ast_map;
 use syntax::ast_util::def_id_of_def;
 use syntax::attr;
 use syntax::parse::token;
-use syntax::oldvisit::Visitor;
-use syntax::oldvisit;
+use syntax::visit::Visitor;
+use syntax::visit;
 
 // Returns true if the given set of attributes contains the `#[inline]`
 // attribute.
@@ -94,40 +94,29 @@ struct ReachableContext {
     worklist: @mut ~[NodeId],
 }
 
-impl ReachableContext {
-    // Creates a new reachability computation context.
-    fn new(tcx: ty::ctxt, method_map: typeck::method_map)
-           -> ReachableContext {
-        ReachableContext {
-            tcx: tcx,
-            method_map: method_map,
-            reachable_symbols: @mut HashSet::new(),
-            worklist: @mut ~[],
-        }
-    }
+struct ReachableVisitor {
+    reachable_symbols: @mut HashSet<NodeId>,
+    worklist: @mut ~[NodeId],
+}
+
+impl Visitor<PrivacyContext> for ReachableVisitor {
+
+    fn visit_item(&mut self, item:@item, privacy_context:PrivacyContext) {
 
-    // Step 1: Mark all public symbols, and add all public symbols that might
-    // be inlined to a worklist.
-    fn mark_public_symbols(&self, crate: @Crate) {
-        let reachable_symbols = self.reachable_symbols;
-        let worklist = self.worklist;
-        let visitor = oldvisit::mk_vt(@Visitor {
-            visit_item: |item, (privacy_context, visitor):
-                    (PrivacyContext, oldvisit::vt<PrivacyContext>)| {
                 match item.node {
                     item_fn(*) => {
                         if privacy_context == PublicContext {
-                            reachable_symbols.insert(item.id);
+                            self.reachable_symbols.insert(item.id);
                         }
                         if item_might_be_inlined(item) {
-                            worklist.push(item.id)
+                            self.worklist.push(item.id)
                         }
                     }
                     item_struct(ref struct_def, _) => {
                         match struct_def.ctor_id {
                             Some(ctor_id) if
                                     privacy_context == PublicContext => {
-                                reachable_symbols.insert(ctor_id);
+                                self.reachable_symbols.insert(ctor_id);
                             }
                             Some(_) | None => {}
                         }
@@ -135,7 +124,7 @@ impl ReachableContext {
                     item_enum(ref enum_def, _) => {
                         if privacy_context == PublicContext {
                             for variant in enum_def.variants.iter() {
-                                reachable_symbols.insert(variant.node.id);
+                                self.reachable_symbols.insert(variant.node.id);
                             }
                         }
                     }
@@ -155,7 +144,7 @@ impl ReachableContext {
                         // Mark all public methods as reachable.
                         for &method in methods.iter() {
                             if should_be_considered_public(method) {
-                                reachable_symbols.insert(method.id);
+                                self.reachable_symbols.insert(method.id);
                             }
                         }
 
@@ -164,7 +153,7 @@ impl ReachableContext {
                             // symbols to the worklist.
                             for &method in methods.iter() {
                                 if should_be_considered_public(method) {
-                                    worklist.push(method.id)
+                                    self.worklist.push(method.id)
                                 }
                             }
                         } else {
@@ -176,7 +165,7 @@ impl ReachableContext {
                                 if generics_require_inlining(generics) ||
                                         attributes_specify_inlining(*attrs) ||
                                         should_be_considered_public(*method) {
-                                    worklist.push(method.id)
+                                    self.worklist.push(method.id)
                                 }
                             }
                         }
@@ -187,8 +176,8 @@ impl ReachableContext {
                             for trait_method in trait_methods.iter() {
                                 match *trait_method {
                                     provided(method) => {
-                                        reachable_symbols.insert(method.id);
-                                        worklist.push(method.id)
+                                        self.reachable_symbols.insert(method.id);
+                                        self.worklist.push(method.id)
                                     }
                                     required(_) => {}
                                 }
@@ -199,15 +188,97 @@ impl ReachableContext {
                 }
 
                 if item.vis == public && privacy_context == PublicContext {
-                    oldvisit::visit_item(item, (PublicContext, visitor))
+                    visit::walk_item(self, item, PublicContext)
                 } else {
-                    oldvisit::visit_item(item, (PrivateContext, visitor))
+                    visit::walk_item(self, item, PrivateContext)
                 }
-            },
-            .. *oldvisit::default_visitor()
-        });
+    }
+
+}
+
+struct MarkSymbolVisitor {
+    worklist: @mut ~[NodeId],
+    method_map: typeck::method_map,
+    tcx: ty::ctxt,
+    reachable_symbols: @mut HashSet<NodeId>,
+}
+
+impl Visitor<()> for MarkSymbolVisitor {
 
-        oldvisit::visit_crate(crate, (PublicContext, visitor))
+    fn visit_expr(&mut self, expr:@expr, _:()) {
+
+                match expr.node {
+                    expr_path(_) => {
+                        let def = match self.tcx.def_map.find(&expr.id) {
+                            Some(&def) => def,
+                            None => {
+                                self.tcx.sess.span_bug(expr.span,
+                                                  "def ID not in def map?!")
+                            }
+                        };
+
+                        let def_id = def_id_of_def(def);
+                        if ReachableContext::
+                                def_id_represents_local_inlined_item(self.tcx,
+                                                                     def_id) {
+                            self.worklist.push(def_id.node)
+                        }
+                        self.reachable_symbols.insert(def_id.node);
+                    }
+                    expr_method_call(*) => {
+                        match self.method_map.find(&expr.id) {
+                            Some(&typeck::method_map_entry {
+                                origin: typeck::method_static(def_id),
+                                _
+                            }) => {
+                                if ReachableContext::
+                                    def_id_represents_local_inlined_item(
+                                        self.tcx,
+                                        def_id) {
+                                    self.worklist.push(def_id.node)
+                                }
+                                self.reachable_symbols.insert(def_id.node);
+                            }
+                            Some(_) => {}
+                            None => {
+                                self.tcx.sess.span_bug(expr.span,
+                                                  "method call expression \
+                                                   not in method map?!")
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+
+                visit::walk_expr(self, expr, ())
+    }
+}
+
+impl ReachableContext {
+    // Creates a new reachability computation context.
+    fn new(tcx: ty::ctxt, method_map: typeck::method_map)
+           -> ReachableContext {
+        ReachableContext {
+            tcx: tcx,
+            method_map: method_map,
+            reachable_symbols: @mut HashSet::new(),
+            worklist: @mut ~[],
+        }
+    }
+
+    // Step 1: Mark all public symbols, and add all public symbols that might
+    // be inlined to a worklist.
+    fn mark_public_symbols(&self, crate: @Crate) {
+        let reachable_symbols = self.reachable_symbols;
+        let worklist = self.worklist;
+
+        let mut visitor = ReachableVisitor {
+            reachable_symbols: reachable_symbols,
+            worklist: worklist,
+        };
+
+
+        visit::walk_crate(&mut visitor, crate, PublicContext);
     }
 
     // Returns true if the given def ID represents a local item that is
@@ -269,63 +340,21 @@ impl ReachableContext {
     }
 
     // Helper function to set up a visitor for `propagate()` below.
-    fn init_visitor(&self) -> oldvisit::vt<()> {
+    fn init_visitor(&self) -> MarkSymbolVisitor {
         let (worklist, method_map) = (self.worklist, self.method_map);
         let (tcx, reachable_symbols) = (self.tcx, self.reachable_symbols);
-        oldvisit::mk_vt(@oldvisit::Visitor {
-            visit_expr: |expr, (_, visitor)| {
-                match expr.node {
-                    expr_path(_) => {
-                        let def = match tcx.def_map.find(&expr.id) {
-                            Some(&def) => def,
-                            None => {
-                                tcx.sess.span_bug(expr.span,
-                                                  "def ID not in def map?!")
-                            }
-                        };
-
-                        let def_id = def_id_of_def(def);
-                        if ReachableContext::
-                                def_id_represents_local_inlined_item(tcx,
-                                                                     def_id) {
-                            worklist.push(def_id.node)
-                        }
-                        reachable_symbols.insert(def_id.node);
-                    }
-                    expr_method_call(*) => {
-                        match method_map.find(&expr.id) {
-                            Some(&typeck::method_map_entry {
-                                origin: typeck::method_static(def_id),
-                                _
-                            }) => {
-                                if ReachableContext::
-                                    def_id_represents_local_inlined_item(
-                                        tcx,
-                                        def_id) {
-                                    worklist.push(def_id.node)
-                                }
-                                reachable_symbols.insert(def_id.node);
-                            }
-                            Some(_) => {}
-                            None => {
-                                tcx.sess.span_bug(expr.span,
-                                                  "method call expression \
-                                                   not in method map?!")
-                            }
-                        }
-                    }
-                    _ => {}
-                }
 
-                oldvisit::visit_expr(expr, ((), visitor))
-            },
-            ..*oldvisit::default_visitor()
-        })
+        MarkSymbolVisitor {
+            worklist: worklist,
+            method_map: method_map,
+            tcx: tcx,
+            reachable_symbols: reachable_symbols,
+        }
     }
 
     // Step 2: Mark all symbols that the symbols on the worklist touch.
     fn propagate(&self) {
-        let visitor = self.init_visitor();
+        let mut visitor = self.init_visitor();
         let mut scanned = HashSet::new();
         while self.worklist.len() > 0 {
             let search_item = self.worklist.pop();
@@ -342,7 +371,7 @@ impl ReachableContext {
                 Some(&ast_map::node_item(item, _)) => {
                     match item.node {
                         item_fn(_, _, _, _, ref search_block) => {
-                            oldvisit::visit_block(search_block, ((), visitor))
+                            visit::walk_block(&mut visitor, search_block, ())
                         }
                         _ => {
                             self.tcx.sess.span_bug(item.span,
@@ -359,12 +388,12 @@ impl ReachableContext {
                                                     worklist?!")
                         }
                         provided(ref method) => {
-                            oldvisit::visit_block(&method.body, ((), visitor))
+                            visit::walk_block(&mut visitor, &method.body, ())
                         }
                     }
                 }
                 Some(&ast_map::node_method(ref method, _, _)) => {
-                    oldvisit::visit_block(&method.body, ((), visitor))
+                    visit::walk_block(&mut visitor, &method.body, ())
                 }
                 Some(_) => {
                     let ident_interner = token::get_ident_interner();
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 4da22be4428..ddd22a0add4 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -34,7 +34,10 @@ use syntax::codemap::span;
 use syntax::print::pprust;
 use syntax::parse::token;
 use syntax::parse::token::special_idents;
-use syntax::{ast, oldvisit};
+use syntax::{ast, visit};
+use syntax::visit::{Visitor,fn_kind};
+use syntax::ast::{Block,item,fn_decl,NodeId,arm,pat,stmt,expr,Local};
+use syntax::ast::{Ty,TypeMethod,struct_field};
 
 /**
 The region maps encode information about region relationships.
@@ -323,8 +326,9 @@ fn parent_to_expr(cx: Context, child_id: ast::NodeId, sp: span) {
     }
 }
 
-fn resolve_block(blk: &ast::Block,
-                 (cx, visitor): (Context, oldvisit::vt<Context>)) {
+fn resolve_block(visitor: &mut RegionResolutionVisitor,
+                 blk: &ast::Block,
+                 cx: Context) {
     // Record the parent of this block.
     parent_to_expr(cx, blk.id, blk.span);
 
@@ -332,39 +336,43 @@ fn resolve_block(blk: &ast::Block,
     let new_cx = Context {var_parent: Some(blk.id),
                           parent: Some(blk.id),
                           ..cx};
-    oldvisit::visit_block(blk, (new_cx, visitor));
+    visit::walk_block(visitor, blk, new_cx);
 }
 
-fn resolve_arm(arm: &ast::arm,
-               (cx, visitor): (Context, oldvisit::vt<Context>)) {
-    oldvisit::visit_arm(arm, (cx, visitor));
+fn resolve_arm(visitor: &mut RegionResolutionVisitor,
+               arm: &ast::arm,
+               cx: Context) {
+    visit::walk_arm(visitor, arm, cx);
 }
 
-fn resolve_pat(pat: @ast::pat,
-               (cx, visitor): (Context, oldvisit::vt<Context>)) {
+fn resolve_pat(visitor: &mut RegionResolutionVisitor,
+               pat: @ast::pat,
+               cx: Context) {
     assert_eq!(cx.var_parent, cx.parent);
     parent_to_expr(cx, pat.id, pat.span);
-    oldvisit::visit_pat(pat, (cx, visitor));
+    visit::walk_pat(visitor, pat, cx);
 }
 
-fn resolve_stmt(stmt: @ast::stmt,
-                (cx, visitor): (Context, oldvisit::vt<Context>)) {
+fn resolve_stmt(visitor: &mut RegionResolutionVisitor,
+                stmt: @ast::stmt,
+                cx: Context) {
     match stmt.node {
         ast::stmt_decl(*) => {
-            oldvisit::visit_stmt(stmt, (cx, visitor));
+            visit::walk_stmt(visitor, stmt, cx);
         }
         ast::stmt_expr(_, stmt_id) |
         ast::stmt_semi(_, stmt_id) => {
             parent_to_expr(cx, stmt_id, stmt.span);
             let expr_cx = Context {parent: Some(stmt_id), ..cx};
-            oldvisit::visit_stmt(stmt, (expr_cx, visitor));
+            visit::walk_stmt(visitor, stmt, expr_cx);
         }
         ast::stmt_mac(*) => cx.sess.bug("unexpanded macro")
     }
 }
 
-fn resolve_expr(expr: @ast::expr,
-                (cx, visitor): (Context, oldvisit::vt<Context>)) {
+fn resolve_expr(visitor: &mut RegionResolutionVisitor,
+                expr: @ast::expr,
+                cx: Context) {
     parent_to_expr(cx, expr.id, expr.span);
 
     let mut new_cx = cx;
@@ -400,30 +408,32 @@ fn resolve_expr(expr: @ast::expr,
     };
 
 
-    oldvisit::visit_expr(expr, (new_cx, visitor));
+    visit::walk_expr(visitor, expr, new_cx);
 }
 
-fn resolve_local(local: @ast::Local,
-                 (cx, visitor): (Context, oldvisit::vt<Context>)) {
+fn resolve_local(visitor: &mut RegionResolutionVisitor,
+                 local: @ast::Local,
+                 cx: Context) {
     assert_eq!(cx.var_parent, cx.parent);
     parent_to_expr(cx, local.id, local.span);
-    oldvisit::visit_local(local, (cx, visitor));
+    visit::walk_local(visitor, local, cx);
 }
 
-fn resolve_item(item: @ast::item,
-                (cx, visitor): (Context, oldvisit::vt<Context>)) {
+fn resolve_item(visitor: &mut RegionResolutionVisitor,
+                item: @ast::item,
+                cx: Context) {
     // Items create a new outer block scope as far as we're concerned.
     let new_cx = Context {var_parent: None, parent: None, ..cx};
-    oldvisit::visit_item(item, (new_cx, visitor));
+    visit::walk_item(visitor, item, new_cx);
 }
 
-fn resolve_fn(fk: &oldvisit::fn_kind,
+fn resolve_fn(visitor: &mut RegionResolutionVisitor,
+              fk: &visit::fn_kind,
               decl: &ast::fn_decl,
               body: &ast::Block,
               sp: span,
               id: ast::NodeId,
-              (cx, visitor): (Context,
-                              oldvisit::vt<Context>)) {
+              cx: Context) {
     debug!("region::resolve_fn(id=%?, \
                                span=%?, \
                                body.id=%?, \
@@ -438,26 +448,58 @@ fn resolve_fn(fk: &oldvisit::fn_kind,
                            var_parent: Some(body.id),
                            ..cx};
     match *fk {
-        oldvisit::fk_method(_, _, method) => {
+        visit::fk_method(_, _, method) => {
             cx.region_maps.record_parent(method.self_id, body.id);
         }
         _ => {}
     }
-    oldvisit::visit_fn_decl(decl, (decl_cx, visitor));
+    visit::walk_fn_decl(visitor, decl, decl_cx);
 
     // The body of the fn itself is either a root scope (top-level fn)
     // or it continues with the inherited scope (closures).
     let body_cx = match *fk {
-        oldvisit::fk_item_fn(*) |
-        oldvisit::fk_method(*) => {
+        visit::fk_item_fn(*) |
+        visit::fk_method(*) => {
             Context {parent: None, var_parent: None, ..cx}
         }
-        oldvisit::fk_anon(*) |
-        oldvisit::fk_fn_block(*) => {
+        visit::fk_anon(*) |
+        visit::fk_fn_block(*) => {
             cx
         }
     };
-    (visitor.visit_block)(body, (body_cx, visitor));
+    visitor.visit_block(body, body_cx);
+}
+
+struct RegionResolutionVisitor;
+
+impl Visitor<Context> for RegionResolutionVisitor {
+
+    fn visit_block(&mut self, b:&Block, cx:Context) {
+        resolve_block(self, b, cx);
+    }
+
+    fn visit_item(&mut self, i:@item, cx:Context) {
+        resolve_item(self, i, cx);
+    }
+
+    fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl, b:&Block, s:span, n:NodeId, cx:Context) {
+        resolve_fn(self, fk, fd, b, s, n, cx);
+    }
+    fn visit_arm(&mut self, a:&arm, cx:Context) {
+        resolve_arm(self, a, cx);
+    }
+    fn visit_pat(&mut self, p:@pat, cx:Context) {
+        resolve_pat(self, p, cx);
+    }
+    fn visit_stmt(&mut self, s:@stmt, cx:Context) {
+        resolve_stmt(self, s, cx);
+    }
+    fn visit_expr(&mut self, ex:@expr, cx:Context) {
+        resolve_expr(self, ex, cx);
+    }
+    fn visit_local(&mut self, l:@Local, cx:Context) {
+        resolve_local(self, l, cx);
+    }
 }
 
 pub fn resolve_crate(sess: Session,
@@ -474,18 +516,8 @@ pub fn resolve_crate(sess: Session,
                       region_maps: region_maps,
                       parent: None,
                       var_parent: None};
-    let visitor = oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_block: resolve_block,
-        visit_item: resolve_item,
-        visit_fn: resolve_fn,
-        visit_arm: resolve_arm,
-        visit_pat: resolve_pat,
-        visit_stmt: resolve_stmt,
-        visit_expr: resolve_expr,
-        visit_local: resolve_local,
-        .. *oldvisit::default_visitor()
-    });
-    oldvisit::visit_crate(crate, (cx, visitor));
+    let mut visitor = RegionResolutionVisitor;
+    visit::walk_crate(&mut visitor, crate, cx);
     return region_maps;
 }
 
@@ -700,46 +732,45 @@ impl DetermineRpCtxt {
     }
 }
 
-fn determine_rp_in_item(item: @ast::item,
-                        (cx, visitor): (@mut DetermineRpCtxt,
-                                        oldvisit::vt<@mut DetermineRpCtxt>)) {
+fn determine_rp_in_item(visitor: &mut DetermineRpVisitor,
+                        item: @ast::item,
+                        cx: @mut DetermineRpCtxt) {
     do cx.with(item.id, true) {
-        oldvisit::visit_item(item, (cx, visitor));
+        visit::walk_item(visitor, item, cx);
     }
 }
 
-fn determine_rp_in_fn(fk: &oldvisit::fn_kind,
+fn determine_rp_in_fn(visitor: &mut DetermineRpVisitor,
+                      fk: &visit::fn_kind,
                       decl: &ast::fn_decl,
                       body: &ast::Block,
                       _: span,
                       _: ast::NodeId,
-                      (cx, visitor): (@mut DetermineRpCtxt,
-                                      oldvisit::vt<@mut DetermineRpCtxt>)) {
+                      cx: @mut DetermineRpCtxt) {
     do cx.with(cx.item_id, false) {
         do cx.with_ambient_variance(rv_contravariant) {
             for a in decl.inputs.iter() {
-                (visitor.visit_ty)(&a.ty, (cx, visitor));
+                visitor.visit_ty(&a.ty, cx);
             }
         }
-        (visitor.visit_ty)(&decl.output, (cx, visitor));
-        let generics = oldvisit::generics_of_fn(fk);
-        (visitor.visit_generics)(&generics, (cx, visitor));
-        (visitor.visit_block)(body, (cx, visitor));
+        visitor.visit_ty(&decl.output, cx);
+        let generics = visit::generics_of_fn(fk);
+        visitor.visit_generics(&generics, cx);
+        visitor.visit_block(body, cx);
     }
 }
 
-fn determine_rp_in_ty_method(ty_m: &ast::TypeMethod,
-                             (cx, visitor):
-                             (@mut DetermineRpCtxt,
-                              oldvisit::vt<@mut DetermineRpCtxt>)) {
+fn determine_rp_in_ty_method(visitor: &mut DetermineRpVisitor,
+                             ty_m: &ast::TypeMethod,
+                             cx: @mut DetermineRpCtxt) {
     do cx.with(cx.item_id, false) {
-        oldvisit::visit_ty_method(ty_m, (cx, visitor));
+        visit::walk_ty_method(visitor, ty_m, cx);
     }
 }
 
-fn determine_rp_in_ty(ty: &ast::Ty,
-                      (cx, visitor): (@mut DetermineRpCtxt,
-                                      oldvisit::vt<@mut DetermineRpCtxt>)) {
+fn determine_rp_in_ty(visitor: &mut DetermineRpVisitor,
+                      ty: &ast::Ty,
+                      cx: @mut DetermineRpCtxt) {
     // we are only interested in types that will require an item to
     // be region-parameterized.  if cx.item_id is zero, then this type
     // is not a member of a type defn nor is it a constitutent of an
@@ -823,14 +854,14 @@ fn determine_rp_in_ty(ty: &ast::Ty,
     match ty.node {
       ast::ty_box(ref mt) | ast::ty_uniq(ref mt) | ast::ty_vec(ref mt) |
       ast::ty_rptr(_, ref mt) | ast::ty_ptr(ref mt) => {
-        visit_mt(mt, (cx, visitor));
+        visit_mt(visitor, mt, cx);
       }
 
       ast::ty_path(ref path, _, _) => {
         // type parameters are---for now, anyway---always invariant
         do cx.with_ambient_variance(rv_invariant) {
             for tp in path.types.iter() {
-                (visitor.visit_ty)(tp, (cx, visitor));
+                visitor.visit_ty(tp, cx);
             }
         }
       }
@@ -843,37 +874,59 @@ fn determine_rp_in_ty(ty: &ast::Ty,
             // parameters are contravariant
             do cx.with_ambient_variance(rv_contravariant) {
                 for a in decl.inputs.iter() {
-                    (visitor.visit_ty)(&a.ty, (cx, visitor));
+                    visitor.visit_ty(&a.ty, cx);
                 }
             }
-            (visitor.visit_ty)(&decl.output, (cx, visitor));
+            visitor.visit_ty(&decl.output, cx);
         }
       }
 
       _ => {
-        oldvisit::visit_ty(ty, (cx, visitor));
+        visit::walk_ty(visitor, ty, cx);
       }
     }
 
-    fn visit_mt(mt: &ast::mt,
-                (cx, visitor): (@mut DetermineRpCtxt,
-                                oldvisit::vt<@mut DetermineRpCtxt>)) {
+    fn visit_mt(visitor: &mut DetermineRpVisitor,
+                mt: &ast::mt,
+                cx: @mut DetermineRpCtxt) {
         // mutability is invariant
         if mt.mutbl == ast::m_mutbl {
             do cx.with_ambient_variance(rv_invariant) {
-                (visitor.visit_ty)(mt.ty, (cx, visitor));
+                visitor.visit_ty(mt.ty, cx);
             }
         } else {
-            (visitor.visit_ty)(mt.ty, (cx, visitor));
+            visitor.visit_ty(mt.ty, cx);
         }
     }
 }
 
-fn determine_rp_in_struct_field(
-        cm: @ast::struct_field,
-        (cx, visitor): (@mut DetermineRpCtxt,
-                        oldvisit::vt<@mut DetermineRpCtxt>)) {
-    oldvisit::visit_struct_field(cm, (cx, visitor));
+fn determine_rp_in_struct_field(visitor: &mut DetermineRpVisitor,
+                                cm: @ast::struct_field,
+                                cx: @mut DetermineRpCtxt) {
+    visit::walk_struct_field(visitor, cm, cx);
+}
+
+struct DetermineRpVisitor;
+
+impl Visitor<@mut DetermineRpCtxt> for DetermineRpVisitor {
+
+    fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl,
+                b:&Block, s:span, n:NodeId, e:@mut DetermineRpCtxt) {
+        determine_rp_in_fn(self, fk, fd, b, s, n, e);
+    }
+    fn visit_item(&mut self, i:@item, e:@mut DetermineRpCtxt) {
+        determine_rp_in_item(self, i, e);
+    }
+    fn visit_ty(&mut self, t:&Ty, e:@mut DetermineRpCtxt) {
+        determine_rp_in_ty(self, t, e);
+    }
+    fn visit_ty_method(&mut self, t:&TypeMethod, e:@mut DetermineRpCtxt) {
+        determine_rp_in_ty_method(self, t, e);
+    }
+    fn visit_struct_field(&mut self, s:@struct_field, e:@mut DetermineRpCtxt) {
+        determine_rp_in_struct_field(self, s, e);
+    }
+
 }
 
 pub fn determine_rp_in_crate(sess: Session,
@@ -894,15 +947,8 @@ pub fn determine_rp_in_crate(sess: Session,
     };
 
     // Gather up the base set, worklist and dep_map
-    let visitor = oldvisit::mk_vt(@oldvisit::Visitor {
-        visit_fn: determine_rp_in_fn,
-        visit_item: determine_rp_in_item,
-        visit_ty: determine_rp_in_ty,
-        visit_ty_method: determine_rp_in_ty_method,
-        visit_struct_field: determine_rp_in_struct_field,
-        .. *oldvisit::default_visitor()
-    });
-    oldvisit::visit_crate(crate, (cx, visitor));
+    let mut visitor = DetermineRpVisitor;
+    visit::walk_crate(&mut visitor, crate, cx);
 
     // Propagate indirect dependencies
     //