1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use driver::session::Session;
14 use syntax::codemap::Span;
15 use syntax::visit::Visitor;
18 #[deriving(Clone, PartialEq)]
23 struct CheckLoopVisitor<'a> {
28 pub fn check_crate(sess: &Session, krate: &ast::Crate) {
29 visit::walk_crate(&mut CheckLoopVisitor { sess: sess, cx: Normal }, krate)
32 impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
33 fn visit_item(&mut self, i: &ast::Item) {
34 self.with_context(Normal, |v| visit::walk_item(v, i));
37 fn visit_expr(&mut self, e: &ast::Expr) {
39 ast::ExprWhile(ref e, ref b, _) => {
40 self.visit_expr(&**e);
41 self.with_context(Loop, |v| v.visit_block(&**b));
43 ast::ExprLoop(ref b, _) => {
44 self.with_context(Loop, |v| v.visit_block(&**b));
46 ast::ExprForLoop(_, ref e, ref b, _) => {
47 self.visit_expr(&**e);
48 self.with_context(Loop, |v| v.visit_block(&**b));
50 ast::ExprFnBlock(_, _, ref b) |
51 ast::ExprProc(_, ref b) |
52 ast::ExprUnboxedFn(_, _, _, ref b) => {
53 self.with_context(Closure, |v| v.visit_block(&**b));
55 ast::ExprBreak(_) => self.require_loop("break", e.span),
56 ast::ExprAgain(_) => self.require_loop("continue", e.span),
57 _ => visit::walk_expr(self, e)
62 impl<'a> CheckLoopVisitor<'a> {
63 fn with_context(&mut self, cx: Context, f: |&mut CheckLoopVisitor<'a>|) {
70 fn require_loop(&self, name: &str, span: Span) {
74 self.sess.span_err(span,
75 format!("`{}` inside of a closure",
79 self.sess.span_err(span,
80 format!("`{}` outside of loop",