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:
commit
d80cd3d9bc
@ -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,
|
||||
|
@ -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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user