about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-07-23 09:16:08 +0000
committerbors <bors@rust-lang.org>2015-07-23 09:16:08 +0000
commitd6a617863761a4023b437bd70288abc77ac20554 (patch)
treeb41ed19cea5e6a16ed013553afae2d24e9edd653
parent8d91bbd90afeaf2e4b262cd48db7d29e9b8d1f49 (diff)
parentb2213498c4654d60af7e40ff8f59b14a9a3a18a9 (diff)
downloadrust-d6a617863761a4023b437bd70288abc77ac20554.tar.gz
rust-d6a617863761a4023b437bd70288abc77ac20554.zip
Auto merge of #26588 - eefriedman:foreign-lifetime, r=nrc
Pretty straightforward; just need to make sure to explicitly handle
the generic parameters of each ast::ForeignItemFn.

Fixes #26587.
-rw-r--r--src/librustc/middle/resolve_lifetime.rs25
-rw-r--r--src/test/compile-fail/generic-extern-lifetime.rs25
2 files changed, 49 insertions, 1 deletions
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 510f1a2a2c9..76edc8c9b20 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -109,7 +109,7 @@ pub fn krate(sess: &Session, krate: &ast::Crate, def_map: &DefMap) -> NamedRegio
 
 impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
     fn visit_item(&mut self, item: &ast::Item) {
-        // Items save/restore the set of labels. This way innner items
+        // Items save/restore the set of labels. This way inner items
         // can freely reuse names, be they loop labels or lifetimes.
         let saved = replace(&mut self.labels_in_fn, vec![]);
 
@@ -151,6 +151,29 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         replace(&mut self.labels_in_fn, saved);
     }
 
+    fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
+        // Items save/restore the set of labels. This way inner items
+        // can freely reuse names, be they loop labels or lifetimes.
+        let saved = replace(&mut self.labels_in_fn, vec![]);
+
+        // Items always introduce a new root scope
+        self.with(RootScope, |_, this| {
+            match item.node {
+                ast::ForeignItemFn(_, ref generics) => {
+                    this.visit_early_late(subst::FnSpace, generics, |this| {
+                        visit::walk_foreign_item(this, item);
+                    })
+                }
+                ast::ForeignItemStatic(..) => {
+                    visit::walk_foreign_item(this, item);
+                }
+            }
+        });
+
+        // Done traversing the item; restore saved set of labels.
+        replace(&mut self.labels_in_fn, saved);
+    }
+
     fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
                 b: &'v ast::Block, s: Span, _: ast::NodeId) {
         match fk {
diff --git a/src/test/compile-fail/generic-extern-lifetime.rs b/src/test/compile-fail/generic-extern-lifetime.rs
new file mode 100644
index 00000000000..fa2d4743937
--- /dev/null
+++ b/src/test/compile-fail/generic-extern-lifetime.rs
@@ -0,0 +1,25 @@
+// Copyright 2015 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.
+
+// Test to make sure the names of the lifetimes are correctly resolved
+// in extern blocks.
+
+extern {
+   pub fn life<'a>(x:&'a i32);
+   pub fn life2<'b>(x:&'a i32, y:&'b i32); //~ ERROR use of undeclared lifetime name `'a`
+   pub fn life3<'a>(x:&'a i32, y:&i32) -> &'a i32;
+   pub fn life4<'b>(x: for<'c> fn(&'a i32)); //~ ERROR use of undeclared lifetime name `'a`
+   pub fn life5<'b>(x: for<'c> fn(&'b i32));
+   pub fn life6<'b>(x: for<'c> fn(&'c i32));
+   pub fn life7<'b>() -> for<'c> fn(&'a i32); //~ ERROR use of undeclared lifetime name `'a`
+   pub fn life8<'b>() -> for<'c> fn(&'b i32);
+   pub fn life9<'b>() -> for<'c> fn(&'c i32);
+}
+fn main() {}