Ported check_loop from oldvisit to <V:Visit> trait API.

This commit is contained in:
Felix S. Klock II 2013-08-13 02:49:30 +02:00
parent 4127c67406
commit 356341192f

View File

@ -12,7 +12,8 @@
use middle::ty; use middle::ty;
use syntax::ast::*; use syntax::ast::*;
use syntax::oldvisit; use syntax::visit;
use syntax::visit::Visitor;
#[deriving(Clone)] #[deriving(Clone)]
pub struct Context { pub struct Context {
@ -20,50 +21,55 @@ pub struct Context {
can_ret: bool can_ret: bool
} }
struct CheckLoopVisitor {
tcx: ty::ctxt,
}
pub fn check_crate(tcx: ty::ctxt, crate: &Crate) { pub fn check_crate(tcx: ty::ctxt, crate: &Crate) {
oldvisit::visit_crate(crate, visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx },
(Context { in_loop: false, can_ret: true }, crate,
oldvisit::mk_vt(@oldvisit::Visitor { Context { in_loop: false, can_ret: true });
visit_item: |i, (_cx, v)| { }
oldvisit::visit_item(i, (Context {
impl Visitor<Context> for CheckLoopVisitor {
fn visit_item(&mut self, i:@item, _cx:Context) {
visit::walk_item(self, i, Context {
in_loop: false, in_loop: false,
can_ret: true 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 { match e.node {
expr_while(e, ref b) => { expr_while(e, ref b) => {
(v.visit_expr)(e, (cx, v)); self.visit_expr(e, cx);
(v.visit_block)(b, (Context { in_loop: true,.. cx }, v)); self.visit_block(b, Context { in_loop: true,.. cx });
} }
expr_loop(ref b, _) => { 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) => { expr_fn_block(_, ref b) => {
(v.visit_block)(b, (Context { self.visit_block(b, Context { in_loop: false, can_ret: false });
in_loop: false,
can_ret: false
}, v));
} }
expr_break(_) => { expr_break(_) => {
if !cx.in_loop { 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(_) => { expr_again(_) => {
if !cx.in_loop { 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) => { expr_ret(oe) => {
if !cx.can_ret { 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() }
})));
} }