about summary refs log tree commit diff
diff options
context:
space:
mode:
authorest31 <MTest31@outlook.com>2018-05-12 10:18:21 +0200
committerest31 <MTest31@outlook.com>2018-05-16 13:56:25 +0200
commitf8c2598dfc45f929ec85e9d1c542f1dbb6a9982c (patch)
treeef1088064a8761e49b850fddb6264abaf162fb74
parent50f063c75b4d05976a1c132afd213c75913c7605 (diff)
downloadrust-f8c2598dfc45f929ec85e9d1c542f1dbb6a9982c.tar.gz
rust-f8c2598dfc45f929ec85e9d1c542f1dbb6a9982c.zip
Add E0696 for continue pointing to a labeled block
-rw-r--r--src/librustc_passes/diagnostics.rs1
-rw-r--r--src/librustc_passes/loops.rs18
-rw-r--r--src/test/ui/label_break_value_continue.rs34
-rw-r--r--src/test/ui/label_break_value_continue.stderr30
4 files changed, 81 insertions, 2 deletions
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 4434def85ba..5dd11617b8b 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -308,4 +308,5 @@ register_diagnostics! {
     E0642, // patterns aren't allowed in methods without bodies
     E0666, // nested `impl Trait` is illegal
     E0667, // `impl Trait` in projections
+    E0696, // `continue` pointing to a labeled block
 }
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index bd43cd71e41..eb8d416a8dd 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -152,8 +152,22 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
             hir::ExprAgain(label) => {
                 self.require_label_in_labeled_block(e.span, &label, "continue");
 
-                if let Err(hir::LoopIdError::UnlabeledCfInWhileCondition) = label.target_id {
-                    self.emit_unlabled_cf_in_while_condition(e.span, "continue");
+                match label.target_id {
+                    Ok(loop_id) => {
+                        if let hir::map::NodeBlock(block) = self.hir_map.find(loop_id).unwrap() {
+                            struct_span_err!(self.sess, e.span, E0696,
+                                            "`continue` pointing to a labeled block")
+                                .span_label(e.span,
+                                            "labeled blocks cannot be `continue`'d")
+                                .span_note(block.span,
+                                            "labeled block the continue points to")
+                                .emit();
+                        }
+                    }
+                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
+                        self.emit_unlabled_cf_in_while_condition(e.span, "continue");
+                    }
+                    _ => {}
                 }
                 self.require_break_cx("continue", e.span)
             },
diff --git a/src/test/ui/label_break_value_continue.rs b/src/test/ui/label_break_value_continue.rs
new file mode 100644
index 00000000000..10557d4bcd6
--- /dev/null
+++ b/src/test/ui/label_break_value_continue.rs
@@ -0,0 +1,34 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Simple continue pointing to an unlabeled break should yield in an error
+fn continue_simple() {
+    'b: {
+        continue; //~ ERROR unlabeled `continue` inside of a labeled block
+    }
+}
+
+// Labeled continue pointing to an unlabeled break should yield in an error
+fn continue_labeled() {
+    'b: {
+        continue 'b; //~ ERROR `continue` pointing to a labeled block
+    }
+}
+
+// Simple continue that would cross a labeled block should yield in an error
+fn continue_crossing() {
+    loop {
+        'b: {
+            continue; //~ ERROR unlabeled `continue` inside of a labeled block
+        }
+    }
+}
+
+pub fn main() {}
diff --git a/src/test/ui/label_break_value_continue.stderr b/src/test/ui/label_break_value_continue.stderr
new file mode 100644
index 00000000000..cf707f1b960
--- /dev/null
+++ b/src/test/ui/label_break_value_continue.stderr
@@ -0,0 +1,30 @@
+error[E0695]: unlabeled `continue` inside of a labeled block
+  --> $DIR/label_break_value_continue.rs:14:9
+   |
+LL |         continue; //~ ERROR unlabeled `continue` inside of a labeled block
+   |         ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label
+
+error[E0696]: `continue` pointing to a labeled block
+  --> $DIR/label_break_value_continue.rs:21:9
+   |
+LL |         continue 'b; //~ ERROR `continue` pointing to a labeled block
+   |         ^^^^^^^^^^^ labeled blocks cannot be `continue`'d
+   |
+note: labeled block the continue points to
+  --> $DIR/label_break_value_continue.rs:20:5
+   |
+LL | /     'b: {
+LL | |         continue 'b; //~ ERROR `continue` pointing to a labeled block
+LL | |     }
+   | |_____^
+
+error[E0695]: unlabeled `continue` inside of a labeled block
+  --> $DIR/label_break_value_continue.rs:29:13
+   |
+LL |             continue; //~ ERROR unlabeled `continue` inside of a labeled block
+   |             ^^^^^^^^ `continue` statements that would diverge to or through a labeled block need to bear a label
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0695, E0696.
+For more information about an error, try `rustc --explain E0695`.