]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_passes/loops.rs
Rollup merge of #41249 - GuillaumeGomez:rustdoc-render, r=steveklabnik,frewsxcv
[rust.git] / src / librustc_passes / loops.rs
index 5f9acc0430a817b099f0c120eaf4d61d08b21f98..2ea235af103788b0f9de6e09b5f3a36b139ffbdd 100644 (file)
@@ -11,7 +11,6 @@
 
 use rustc::session::Session;
 
-use rustc::dep_graph::DepNode;
 use rustc::hir::map::Map;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
@@ -50,7 +49,6 @@ struct CheckLoopVisitor<'a, 'hir: 'a> {
 }
 
 pub fn check_crate(sess: &Session, map: &Map) {
-    let _task = map.dep_graph.in_task(DepNode::CheckLoops);
     let krate = map.krate();
     krate.visit_all_item_likes(&mut CheckLoopVisitor {
         sess: sess,
@@ -87,11 +85,26 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
                 self.with_context(Closure, |v| v.visit_nested_body(b));
             }
             hir::ExprBreak(label, ref opt_expr) => {
+                let loop_id = match label.target_id {
+                    hir::ScopeTarget::Block(_) => return,
+                    hir::ScopeTarget::Loop(loop_res) => {
+                        match loop_res.into() {
+                            Ok(loop_id) => loop_id,
+                            Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
+                            Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
+                                self.emit_unlabled_cf_in_while_condition(e.span, "break");
+                                ast::DUMMY_NODE_ID
+                            },
+                            Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
+                        }
+                    }
+                };
+
                 if opt_expr.is_some() {
-                    let loop_kind = if label.loop_id == ast::DUMMY_NODE_ID {
+                    let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
                         None
                     } else {
-                        Some(match self.hir_map.expect_expr(label.loop_id).node {
+                        Some(match self.hir_map.expect_expr(loop_id).node {
                             hir::ExprWhile(..) => LoopKind::WhileLoop,
                             hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
                             ref r => span_bug!(e.span,
@@ -110,9 +123,17 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
                         }
                     }
                 }
+
                 self.require_loop("break", e.span);
             }
-            hir::ExprAgain(_) => self.require_loop("continue", e.span),
+            hir::ExprAgain(label) => {
+                if let hir::ScopeTarget::Loop(
+                    hir::LoopIdResult::Err(
+                        hir::LoopIdError::UnlabeledCfInWhileCondition)) = label.target_id {
+                    self.emit_unlabled_cf_in_while_condition(e.span, "continue");
+                }
+                self.require_loop("continue", e.span)
+            },
             _ => intravisit::walk_expr(self, e),
         }
     }
@@ -143,4 +164,12 @@ fn require_loop(&self, name: &str, span: Span) {
             }
         }
     }
+
+    fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
+        struct_span_err!(self.sess, span, E0590,
+                         "`break` or `continue` with no label in the condition of a `while` loop")
+            .span_label(span,
+                        &format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
+            .emit();
+    }
 }