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.
14 use syntax::codemap::Span;
15 use rustc_front::intravisit::{self, Visitor};
18 #[derive(Clone, Copy, PartialEq)]
23 #[derive(Copy, Clone)]
24 struct CheckLoopVisitor<'a> {
29 pub fn check_crate(sess: &Session, krate: &hir::Crate) {
30 krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal });
33 impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
34 fn visit_item(&mut self, i: &hir::Item) {
35 self.with_context(Normal, |v| intravisit::walk_item(v, i));
38 fn visit_expr(&mut self, e: &hir::Expr) {
40 hir::ExprWhile(ref e, ref b, _) => {
41 self.visit_expr(&**e);
42 self.with_context(Loop, |v| v.visit_block(&**b));
44 hir::ExprLoop(ref b, _) => {
45 self.with_context(Loop, |v| v.visit_block(&**b));
47 hir::ExprClosure(_, _, ref b) => {
48 self.with_context(Closure, |v| v.visit_block(&**b));
50 hir::ExprBreak(_) => self.require_loop("break", e.span),
51 hir::ExprAgain(_) => self.require_loop("continue", e.span),
52 _ => intravisit::walk_expr(self, e)
57 impl<'a> CheckLoopVisitor<'a> {
58 fn with_context<F>(&mut self, cx: Context, f: F) where
59 F: FnOnce(&mut CheckLoopVisitor<'a>),
67 fn require_loop(&self, name: &str, span: Span) {
71 span_err!(self.sess, span, E0267,
72 "`{}` inside of a closure", name);
75 span_err!(self.sess, span, E0268,
76 "`{}` outside of loop", name);