From b2213498c4654d60af7e40ff8f59b14a9a3a18a9 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 25 Jun 2015 23:13:03 -0700 Subject: [PATCH] Resolve lifetime parameters for foreign functions. Pretty straightforward; just need to make sure to explicitly handle the generic parameters of each ast::ForeignItemFn. Fixes #26587. --- src/librustc/middle/resolve_lifetime.rs | 25 ++++++++++++++++++- .../compile-fail/generic-extern-lifetime.rs | 25 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/generic-extern-lifetime.rs 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 or the MIT license +// , 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() {}