auto merge of #17028 : pcwalton/rust/higher-rank-trait-lifetimes, r=pnkfelix

They will ICE during typechecking if used, because they depend on trait
reform.

This is part of unboxed closures.

r? @nikomatsakis
This commit is contained in:
bors 2014-09-23 14:30:40 +00:00
commit d80cd3d9bc
10 changed files with 128 additions and 10 deletions

View File

@ -21,6 +21,7 @@ use driver::session::Session;
use middle::subst;
use syntax::ast;
use syntax::codemap::Span;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::print::pprust::{lifetime_to_string};
@ -98,8 +99,22 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
ast::ItemTy(_, ref generics) |
ast::ItemEnum(_, ref generics) |
ast::ItemStruct(_, ref generics) |
ast::ItemImpl(ref generics, _, _, _) |
ast::ItemTrait(ref generics, _, _, _) => &generics.lifetimes
ast::ItemTrait(ref generics, _, _, _) => {
self.with(|scope, f| {
f(EarlyScope(subst::TypeSpace,
&generics.lifetimes,
scope))
}, |v| v.check_lifetime_defs(&generics.lifetimes));
&generics.lifetimes
}
ast::ItemImpl(ref generics, _, _, _) => {
self.with(|scope, f| {
f(EarlyScope(subst::TypeSpace,
&generics.lifetimes,
scope))
}, |v| v.check_lifetime_defs(&generics.lifetimes));
&generics.lifetimes
}
};
self.with(|_, f| f(EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE)), |v| {
@ -155,6 +170,20 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
}
self.resolve_lifetime_ref(lifetime_ref);
}
fn visit_generics(&mut self, generics: &ast::Generics) {
for ty_param in generics.ty_params.iter() {
self.visit_ty_param_bounds(&ty_param.bounds);
match ty_param.default {
Some(ref ty) => self.visit_ty(&**ty),
None => {}
}
}
for predicate in generics.where_clause.predicates.iter() {
self.visit_ident(predicate.span, predicate.ident);
self.visit_ty_param_bounds(&predicate.bounds);
}
}
}
impl<'a> LifetimeContext<'a> {
@ -167,6 +196,47 @@ impl<'a> LifetimeContext<'a> {
}))
}
fn visit_ty_param_bounds(&mut self,
bounds: &OwnedSlice<ast::TyParamBound>) {
for bound in bounds.iter() {
match *bound {
ast::TraitTyParamBound(ref trait_ref) => {
self.visit_trait_ref(trait_ref);
}
ast::UnboxedFnTyParamBound(ref fn_decl) => {
self.visit_unboxed_fn_ty_param_bound(&**fn_decl);
}
ast::RegionTyParamBound(ref lifetime) => {
self.visit_lifetime_ref(lifetime);
}
}
}
}
fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
self.with(|scope, f| {
f(LateScope(trait_ref.ref_id, &trait_ref.lifetimes, scope))
}, |v| {
v.check_lifetime_defs(&trait_ref.lifetimes);
for lifetime in trait_ref.lifetimes.iter() {
v.visit_lifetime_decl(lifetime);
}
v.visit_path(&trait_ref.path, trait_ref.ref_id);
})
}
fn visit_unboxed_fn_ty_param_bound(&mut self,
bound: &ast::UnboxedFnBound) {
self.with(|scope, f| {
f(LateScope(bound.ref_id, &bound.lifetimes, scope))
}, |v| {
for argument in bound.decl.inputs.iter() {
v.visit_ty(&*argument.ty);
}
v.visit_ty(&*bound.decl.output);
})
}
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
fn visit_fn_decl(&mut self,
n: ast::NodeId,

View File

@ -1110,6 +1110,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
ast::TraitTyParamBound(ast::TraitRef {
path: new_path,
ref_id: tr.ref_id,
lifetimes: tr.lifetimes.clone(),
})
}
}

View File

@ -223,6 +223,7 @@ pub type TyParamBounds = OwnedSlice<TyParamBound>;
pub struct UnboxedFnBound {
pub path: Path,
pub decl: P<FnDecl>,
pub lifetimes: Vec<LifetimeDef>,
pub ref_id: NodeId,
}
@ -1219,6 +1220,7 @@ pub struct Attribute_ {
pub struct TraitRef {
pub path: Path,
pub ref_id: NodeId,
pub lifetimes: Vec<LifetimeDef>,
}
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]

View File

@ -435,7 +435,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
ast::TraitRef {
path: path,
ref_id: ast::DUMMY_NODE_ID
ref_id: ast::DUMMY_NODE_ID,
lifetimes: Vec::new(),
}
}

View File

@ -668,11 +668,13 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
UnboxedFnBound {
ref path,
ref decl,
ref lifetimes,
ref_id
} => {
UnboxedFnTyParamBound(P(UnboxedFnBound {
path: fld.fold_path(path.clone()),
decl: fld.fold_fn_decl(decl.clone()),
lifetimes: fld.fold_lifetime_defs(lifetimes.clone()),
ref_id: fld.new_id(ref_id),
}))
}
@ -808,10 +810,17 @@ pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) ->
})
}
pub fn noop_fold_trait_ref<T: Folder>(TraitRef {ref_id, path}: TraitRef, fld: &mut T) -> TraitRef {
TraitRef {
ref_id: fld.new_id(ref_id),
pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
let id = fld.new_id(p.ref_id);
let TraitRef {
path,
lifetimes,
..
} = p;
ast::TraitRef {
path: fld.fold_path(path),
ref_id: id,
lifetimes: fld.fold_lifetime_defs(lifetimes),
}
}

View File

@ -34,7 +34,8 @@ use ast::{FnOnceUnboxedClosureKind};
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, Lit, Lit_};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
use ast::{LifetimeDef, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary};
use ast::{LitNil, LitStr, LitInt, Local, LocalLet};
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal};
@ -3791,8 +3792,21 @@ impl<'a> Parser<'a> {
{
let mut result = vec!();
loop {
let lifetime_defs = if self.eat(&token::LT) {
let lifetime_defs = self.parse_lifetime_defs();
self.expect_gt();
lifetime_defs
} else {
Vec::new()
};
match self.token {
token::LIFETIME(lifetime) => {
if lifetime_defs.len() > 0 {
let span = self.last_span;
self.span_err(span, "lifetime declarations are not \
allowed here")
}
result.push(RegionTyParamBound(ast::Lifetime {
id: ast::DUMMY_NODE_ID,
span: self.span,
@ -3818,12 +3832,14 @@ impl<'a> Parser<'a> {
cf: return_style,
variadic: false,
}),
lifetimes: lifetime_defs,
ref_id: ast::DUMMY_NODE_ID,
})));
} else {
result.push(TraitTyParamBound(ast::TraitRef {
path: path,
ref_id: ast::DUMMY_NODE_ID,
lifetimes: lifetime_defs,
}))
}
}
@ -3852,6 +3868,7 @@ impl<'a> Parser<'a> {
ast::TraitRef {
path: path,
ref_id: ast::DUMMY_NODE_ID,
lifetimes: Vec::new(),
}
}
@ -4482,8 +4499,11 @@ impl<'a> Parser<'a> {
// New-style trait. Reinterpret the type as a trait.
let opt_trait_ref = match ty.node {
TyPath(ref path, None, node_id) => {
Some(TraitRef { path: (*path).clone(),
ref_id: node_id })
Some(TraitRef {
path: (*path).clone(),
ref_id: node_id,
lifetimes: Vec::new(),
})
}
TyPath(_, Some(_), _) => {
self.span_err(ty.span,

View File

@ -900,6 +900,16 @@ impl<'a> State<'a> {
}
fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
if t.lifetimes.len() > 0 {
try!(self.print_generics(&ast::Generics {
lifetimes: t.lifetimes.clone(),
ty_params: OwnedSlice::empty(),
where_clause: ast::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: Vec::new(),
},
}));
}
self.print_path(&t.path, false)
}

View File

@ -202,7 +202,9 @@ pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
/// Like with walk_method_helper this doesn't correspond to a method
/// in Visitor, and so it gets a _helper suffix.
pub fn walk_trait_ref_helper<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef) {
pub fn walk_trait_ref_helper<'v,V>(visitor: &mut V, trait_ref: &'v TraitRef)
where V: Visitor<'v> {
walk_lifetime_decls(visitor, &trait_ref.lifetimes);
visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
}
@ -495,6 +497,7 @@ pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V,
visitor.visit_ty(&*argument.ty)
}
visitor.visit_ty(&*function_declaration.decl.output);
walk_lifetime_decls(visitor, &function_declaration.lifetimes);
}
RegionTyParamBound(ref lifetime) => {
visitor.visit_lifetime_ref(lifetime);

View File

@ -9,6 +9,7 @@
// except according to those terms.
struct Foo<'a, 'a> { //~ ERROR lifetime name `'a` declared twice
//~^ ERROR lifetime name `'a` declared twice
x: &'a int
}

View File

@ -9,6 +9,7 @@
// except according to those terms.
struct Foo<'static> { //~ ERROR illegal lifetime parameter name: `'static`
//~^ ERROR illegal lifetime parameter name: `'static`
x: &'static int
}