about summary refs log tree commit diff
path: root/src/librustc/middle/check_loop.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc/middle/check_loop.rs')
-rw-r--r--src/librustc/middle/check_loop.rs86
1 files changed, 43 insertions, 43 deletions
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index a6aab151e5a..8a320f88649 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -8,68 +8,68 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use middle::ty;
 
-use syntax::ast::*;
-use syntax::visit;
+use syntax::ast;
+use syntax::codemap::Span;
 use syntax::visit::Visitor;
+use syntax::visit;
 
-#[deriving(Clone)]
-pub struct Context {
-    in_loop: bool,
-    can_ret: bool
+#[deriving(Clone, Eq)]
+enum Context {
+    Normal, Loop, Closure
 }
 
 struct CheckLoopVisitor {
     tcx: ty::ctxt,
 }
 
-pub fn check_crate(tcx: ty::ctxt, crate: &Crate) {
-    visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx },
-                      crate,
-                      Context { in_loop: false, can_ret: true });
+pub fn check_crate(tcx: ty::ctxt, crate: &ast::Crate) {
+    visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx }, crate, Normal)
 }
 
 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
-                                  });
+    fn visit_item(&mut self, i: @ast::item, _cx: Context) {
+        visit::walk_item(self, i, Normal);
     }
 
-    fn visit_expr(&mut self, e:@Expr, cx:Context) {
-
-            match e.node {
-              ExprWhile(e, ref b) => {
+    fn visit_expr(&mut self, e: @ast::Expr, cx:Context) {
+        match e.node {
+            ast::ExprWhile(e, ref b) => {
                 self.visit_expr(e, cx);
-                self.visit_block(b, Context { in_loop: true,.. cx });
-              }
-              ExprLoop(ref b, _) => {
-                self.visit_block(b, Context { in_loop: true,.. cx });
-              }
-              ExprFnBlock(_, ref b) | ExprProc(_, ref b) => {
-                self.visit_block(b, Context { in_loop: false, can_ret: false });
-              }
-              ExprBreak(_) => {
-                if !cx.in_loop {
-                    self.tcx.sess.span_err(e.span, "`break` outside of loop");
-                }
-              }
-              ExprAgain(_) => {
-                if !cx.in_loop {
-                    self.tcx.sess.span_err(e.span, "`loop` outside of loop");
-                }
-              }
-              ExprRet(oe) => {
-                if !cx.can_ret {
-                    self.tcx.sess.span_err(e.span, "`return` in block function");
+                self.visit_block(b, Loop);
+            }
+            ast::ExprLoop(ref b, _) => {
+                self.visit_block(b, Loop);
+            }
+            ast::ExprFnBlock(_, ref b) | ast::ExprProc(_, ref b) => {
+                self.visit_block(b, Closure);
+            }
+            ast::ExprBreak(_) => self.require_loop("break", cx, e.span),
+            ast::ExprAgain(_) => self.require_loop("continue", cx, e.span),
+            ast::ExprRet(oe) => {
+                if cx == Closure {
+                    self.tcx.sess.span_err(e.span, "`return` in a closure");
                 }
                 visit::walk_expr_opt(self, oe, cx);
-              }
-              _ => visit::walk_expr(self, e, cx)
             }
+            _ => visit::walk_expr(self, e, cx)
+        }
+    }
+}
 
+impl CheckLoopVisitor {
+    fn require_loop(&self, name: &str, cx: Context, span: Span) {
+        match cx {
+            Loop => {}
+            Closure => {
+                self.tcx.sess.span_err(span, format!("`{}` inside of a closure",
+                                                     name));
+            }
+            Normal => {
+                self.tcx.sess.span_err(span, format!("`{}` outside of loop",
+                                                     name));
+            }
+        }
     }
 }