about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-12-29 16:36:15 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-12-29 16:36:15 -0800
commit4dacf2780f90bd578606c4fd01de39b9c19b8573 (patch)
treeeddeee73fc9675d360ecfa6d2e17489bb1611353 /src
parent21f661a6ef813233aca16f0cbec939256640f021 (diff)
parentfbda51e27074b5cedce4c89091aee9adecb31ce0 (diff)
downloadrust-4dacf2780f90bd578606c4fd01de39b9c19b8573.tar.gz
rust-4dacf2780f90bd578606c4fd01de39b9c19b8573.zip
rollup merge of #20242: sanxiyn/break-from-fn
Fix #19331.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_resolve/lib.rs26
-rw-r--r--src/test/compile-fail/resolve-label.rs21
2 files changed, 45 insertions, 2 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 8e3eb4bf853..da67f461c4b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4008,6 +4008,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
+    /// Searches the current set of local scopes and
+    /// applies translations for closures.
     fn search_ribs(&self,
                    ribs: &[Rib],
                    name: Name,
@@ -4029,6 +4031,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         None
     }
 
+    /// Searches the current set of local scopes for labels.
+    /// Stops after meeting a closure.
+    fn search_label(&self, name: Name) -> Option<DefLike> {
+        for rib in self.label_ribs.iter().rev() {
+            match rib.kind {
+                NormalRibKind => {
+                    // Continue
+                }
+                _ => {
+                    // Do not resolve labels across function boundary
+                    return None
+                }
+            }
+            let result = rib.bindings.get(&name).cloned();
+            if result.is_some() {
+                return result
+            }
+        }
+        None
+    }
+
     fn resolve_crate(&mut self, krate: &ast::Crate) {
         debug!("(resolving crate) starting");
 
@@ -5835,8 +5858,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
                 let renamed = mtwt::resolve(label);
-                match self.search_ribs(self.label_ribs[],
-                                       renamed, expr.span) {
+                match self.search_label(renamed) {
                     None => {
                         self.resolve_error(
                             expr.span,
diff --git a/src/test/compile-fail/resolve-label.rs b/src/test/compile-fail/resolve-label.rs
new file mode 100644
index 00000000000..398b4f5859e
--- /dev/null
+++ b/src/test/compile-fail/resolve-label.rs
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+fn f() {
+    'l: loop {
+        fn g() {
+            loop {
+                break 'l; //~ ERROR use of undeclared label
+            }
+        }
+    }
+}
+
+fn main() {}