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.
15 use syntax::codemap::Span;
16 use syntax::visit::Visitor;
19 #[derive(Clone, Copy, PartialEq)]
25 struct CheckLoopVisitor<'a> {
30 pub fn check_crate(sess: &Session, krate: &ast::Crate) {
31 visit::walk_crate(&mut CheckLoopVisitor { sess: sess, cx: Normal }, krate)
34 impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
35 fn visit_item(&mut self, i: &ast::Item) {
36 self.with_context(Normal, |v| visit::walk_item(v, i));
39 fn visit_expr(&mut self, e: &ast::Expr) {
41 ast::ExprWhile(ref e, ref b, _) => {
42 self.visit_expr(&**e);
43 self.with_context(Loop, |v| v.visit_block(&**b));
45 ast::ExprLoop(ref b, _) => {
46 self.with_context(Loop, |v| v.visit_block(&**b));
48 ast::ExprForLoop(_, ref e, ref b, _) => {
49 self.visit_expr(&**e);
50 self.with_context(Loop, |v| v.visit_block(&**b));
52 ast::ExprClosure(_, _, _, 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<F>(&mut self, cx: Context, f: F) where
64 F: FnOnce(&mut CheckLoopVisitor<'a>),
72 fn require_loop(&self, name: &str, span: Span) {
76 self.sess.span_err(span,
77 format!("`{}` inside of a closure", name)[]);
80 self.sess.span_err(span,
81 format!("`{}` outside of loop", name)[]);