]> git.proxmox.com Git - rustc.git/blame - src/librustc_passes/loops.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / librustc_passes / loops.rs
CommitLineData
1a4d82fc 1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
223e47cc
LB
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
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.
1a4d82fc 10use self::Context::*;
223e47cc 11
7453a54e 12use rustc::session::Session;
223e47cc 13
7453a54e 14use rustc::dep_graph::DepNode;
54a0048b
SL
15use rustc::hir::map::Map;
16use rustc::hir::intravisit::{self, Visitor};
17use rustc::hir;
7453a54e 18use syntax::codemap::Span;
223e47cc 19
1a4d82fc
JJ
20#[derive(Clone, Copy, PartialEq)]
21enum Context {
22 Normal, Loop, Closure
23}
24
c34b1796 25#[derive(Copy, Clone)]
1a4d82fc
JJ
26struct CheckLoopVisitor<'a> {
27 sess: &'a Session,
28 cx: Context
29}
30
7453a54e
SL
31pub fn check_crate(sess: &Session, map: &Map) {
32 let _task = map.dep_graph.in_task(DepNode::CheckLoops);
33 let krate = map.krate();
92a42be0 34 krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal });
1a4d82fc
JJ
35}
36
37impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
e9174d1e 38 fn visit_item(&mut self, i: &hir::Item) {
92a42be0 39 self.with_context(Normal, |v| intravisit::walk_item(v, i));
1a4d82fc
JJ
40 }
41
e9174d1e 42 fn visit_expr(&mut self, e: &hir::Expr) {
1a4d82fc 43 match e.node {
e9174d1e 44 hir::ExprWhile(ref e, ref b, _) => {
7453a54e
SL
45 self.visit_expr(&e);
46 self.with_context(Loop, |v| v.visit_block(&b));
1a4d82fc 47 }
e9174d1e 48 hir::ExprLoop(ref b, _) => {
7453a54e 49 self.with_context(Loop, |v| v.visit_block(&b));
1a4d82fc 50 }
e9174d1e 51 hir::ExprClosure(_, _, ref b) => {
7453a54e 52 self.with_context(Closure, |v| v.visit_block(&b));
1a4d82fc 53 }
e9174d1e
SL
54 hir::ExprBreak(_) => self.require_loop("break", e.span),
55 hir::ExprAgain(_) => self.require_loop("continue", e.span),
92a42be0 56 _ => intravisit::walk_expr(self, e)
1a4d82fc
JJ
57 }
58 }
223e47cc
LB
59}
60
1a4d82fc
JJ
61impl<'a> CheckLoopVisitor<'a> {
62 fn with_context<F>(&mut self, cx: Context, f: F) where
63 F: FnOnce(&mut CheckLoopVisitor<'a>),
64 {
65 let old_cx = self.cx;
66 self.cx = cx;
67 f(self);
68 self.cx = old_cx;
69 }
70
71 fn require_loop(&self, name: &str, span: Span) {
72 match self.cx {
73 Loop => {}
74 Closure => {
85aaf69f
SL
75 span_err!(self.sess, span, E0267,
76 "`{}` inside of a closure", name);
1a4d82fc
JJ
77 }
78 Normal => {
85aaf69f
SL
79 span_err!(self.sess, span, E0268,
80 "`{}` outside of loop", name);
223e47cc 81 }
1a4d82fc
JJ
82 }
83 }
223e47cc 84}