Temporary bootstrapping hack: introduce syntax for r egion bounds like 'b:'a
,
meaning `'b outlives 'a`. Syntax currently does nothing but is needed for full fix to #5763. To use this syntax, the issue_5763_bootstrap feature guard is required.
This commit is contained in:
parent
1a53c00117
commit
fcab98038c
19 changed files with 241 additions and 81 deletions
|
@ -576,7 +576,7 @@ impl<'a> Visitor<()> for Context<'a> {
|
||||||
run_lints!(self, check_lifetime_ref, lt);
|
run_lints!(self, check_lifetime_ref, lt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lifetime_decl(&mut self, lt: &ast::Lifetime, _: ()) {
|
fn visit_lifetime_decl(&mut self, lt: &ast::LifetimeDef, _: ()) {
|
||||||
run_lints!(self, check_lifetime_decl, lt);
|
run_lints!(self, check_lifetime_decl, lt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ pub trait LintPass {
|
||||||
fn check_variant(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { }
|
fn check_variant(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { }
|
||||||
fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option<ast::Lifetime>) { }
|
fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option<ast::Lifetime>) { }
|
||||||
fn check_lifetime_ref(&mut self, _: &Context, _: &ast::Lifetime) { }
|
fn check_lifetime_ref(&mut self, _: &Context, _: &ast::Lifetime) { }
|
||||||
fn check_lifetime_decl(&mut self, _: &Context, _: &ast::Lifetime) { }
|
fn check_lifetime_decl(&mut self, _: &Context, _: &ast::LifetimeDef) { }
|
||||||
fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { }
|
fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { }
|
||||||
fn check_mac(&mut self, _: &Context, _: &ast::Mac) { }
|
fn check_mac(&mut self, _: &Context, _: &ast::Mac) { }
|
||||||
fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { }
|
fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { }
|
||||||
|
|
|
@ -59,10 +59,10 @@ struct LifetimeContext<'a> {
|
||||||
enum ScopeChain<'a> {
|
enum ScopeChain<'a> {
|
||||||
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
|
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
|
||||||
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
|
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
|
||||||
EarlyScope(subst::ParamSpace, &'a Vec<ast::Lifetime>, Scope<'a>),
|
EarlyScope(subst::ParamSpace, &'a Vec<ast::LifetimeDef>, Scope<'a>),
|
||||||
/// LateScope(binder_id, ['a, 'b, ...], s) extends s with late-bound
|
/// LateScope(binder_id, ['a, 'b, ...], s) extends s with late-bound
|
||||||
/// lifetimes introduced by the declaration binder_id.
|
/// lifetimes introduced by the declaration binder_id.
|
||||||
LateScope(ast::NodeId, &'a Vec<ast::Lifetime>, Scope<'a>),
|
LateScope(ast::NodeId, &'a Vec<ast::LifetimeDef>, Scope<'a>),
|
||||||
/// lifetimes introduced by items within a code block are scoped
|
/// lifetimes introduced by items within a code block are scoped
|
||||||
/// to that block.
|
/// to that block.
|
||||||
BlockScope(ast::NodeId, Scope<'a>),
|
BlockScope(ast::NodeId, Scope<'a>),
|
||||||
|
@ -136,7 +136,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
|
||||||
fn push_fn_scope(this: &mut LifetimeContext,
|
fn push_fn_scope(this: &mut LifetimeContext,
|
||||||
ty: &ast::Ty,
|
ty: &ast::Ty,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
lifetimes: &Vec<ast::Lifetime>) {
|
lifetimes: &Vec<ast::LifetimeDef>) {
|
||||||
let scope1 = LateScope(ty.id, lifetimes, scope);
|
let scope1 = LateScope(ty.id, lifetimes, scope);
|
||||||
this.check_lifetime_names(lifetimes);
|
this.check_lifetime_names(lifetimes);
|
||||||
debug!("pushing fn scope id={} due to type", ty.id);
|
debug!("pushing fn scope id={} due to type", ty.id);
|
||||||
|
@ -216,7 +216,7 @@ impl<'a> LifetimeContext<'a> {
|
||||||
walk(self, &scope1)
|
walk(self, &scope1)
|
||||||
} else {
|
} else {
|
||||||
let (early, late) = generics.lifetimes.clone().partition(
|
let (early, late) = generics.lifetimes.clone().partition(
|
||||||
|l| referenced_idents.iter().any(|&i| i == l.name));
|
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
|
||||||
|
|
||||||
let scope1 = EarlyScope(subst::FnSpace, &early, scope);
|
let scope1 = EarlyScope(subst::FnSpace, &early, scope);
|
||||||
let scope2 = LateScope(n, &late, &scope1);
|
let scope2 = LateScope(n, &late, &scope1);
|
||||||
|
@ -334,29 +334,39 @@ impl<'a> LifetimeContext<'a> {
|
||||||
token::get_name(lifetime_ref.name)).as_slice());
|
token::get_name(lifetime_ref.name)).as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_lifetime_names(&self, lifetimes: &Vec<ast::Lifetime>) {
|
fn check_lifetime_names(&self, lifetimes: &Vec<ast::LifetimeDef>) {
|
||||||
for i in range(0, lifetimes.len()) {
|
for i in range(0, lifetimes.len()) {
|
||||||
let lifetime_i = lifetimes.get(i);
|
let lifetime_i = lifetimes.get(i);
|
||||||
|
|
||||||
let special_idents = [special_idents::static_lifetime];
|
let special_idents = [special_idents::static_lifetime];
|
||||||
for lifetime in lifetimes.iter() {
|
for lifetime in lifetimes.iter() {
|
||||||
if special_idents.iter().any(|&i| i.name == lifetime.name) {
|
if special_idents.iter().any(|&i| i.name == lifetime.lifetime.name) {
|
||||||
self.sess.span_err(
|
self.sess.span_err(
|
||||||
lifetime.span,
|
lifetime.lifetime.span,
|
||||||
format!("illegal lifetime parameter name: `{}`",
|
format!("illegal lifetime parameter name: `{}`",
|
||||||
token::get_name(lifetime.name)).as_slice());
|
token::get_name(lifetime.lifetime.name))
|
||||||
|
.as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for j in range(i + 1, lifetimes.len()) {
|
for j in range(i + 1, lifetimes.len()) {
|
||||||
let lifetime_j = lifetimes.get(j);
|
let lifetime_j = lifetimes.get(j);
|
||||||
|
|
||||||
if lifetime_i.name == lifetime_j.name {
|
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
|
||||||
self.sess.span_err(
|
self.sess.span_err(
|
||||||
lifetime_j.span,
|
lifetime_j.lifetime.span,
|
||||||
format!("lifetime name `{}` declared twice in \
|
format!("lifetime name `{}` declared twice in \
|
||||||
the same scope",
|
the same scope",
|
||||||
token::get_name(lifetime_j.name)).as_slice());
|
token::get_name(lifetime_j.lifetime.name))
|
||||||
|
.as_slice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for bound in lifetime_i.bounds.iter() {
|
||||||
|
if !self.sess.features.issue_5723_bootstrap.get() {
|
||||||
|
self.sess.span_err(
|
||||||
|
bound.span,
|
||||||
|
"region bounds require `issue_5723_bootstrap`");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,12 +389,12 @@ impl<'a> LifetimeContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_lifetimes(lifetimes: &Vec<ast::Lifetime>,
|
fn search_lifetimes(lifetimes: &Vec<ast::LifetimeDef>,
|
||||||
lifetime_ref: &ast::Lifetime)
|
lifetime_ref: &ast::Lifetime)
|
||||||
-> Option<(uint, ast::NodeId)> {
|
-> Option<(uint, ast::NodeId)> {
|
||||||
for (i, lifetime_decl) in lifetimes.iter().enumerate() {
|
for (i, lifetime_decl) in lifetimes.iter().enumerate() {
|
||||||
if lifetime_decl.name == lifetime_ref.name {
|
if lifetime_decl.lifetime.name == lifetime_ref.name {
|
||||||
return Some((i, lifetime_decl.id));
|
return Some((i, lifetime_decl.lifetime.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
|
@ -392,15 +402,15 @@ fn search_lifetimes(lifetimes: &Vec<ast::Lifetime>,
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::Lifetime> {
|
pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::LifetimeDef> {
|
||||||
let referenced_idents = free_lifetimes(&generics.ty_params);
|
let referenced_idents = free_lifetimes(&generics.ty_params);
|
||||||
if referenced_idents.is_empty() {
|
if referenced_idents.is_empty() {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
generics.lifetimes.iter()
|
generics.lifetimes.iter()
|
||||||
.filter(|l| referenced_idents.iter().any(|&i| i == l.name))
|
.filter(|l| referenced_idents.iter().any(|&i| i == l.lifetime.name))
|
||||||
.map(|l| *l)
|
.map(|l| (*l).clone())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -804,9 +804,10 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||||
generics.lifetimes
|
generics.lifetimes
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, def)| ty::ReEarlyBound(def.id,
|
.map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
|
||||||
subst::TypeSpace,
|
subst::TypeSpace,
|
||||||
i, def.name))
|
i,
|
||||||
|
def.lifetime.name))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let types =
|
let types =
|
||||||
|
@ -1073,7 +1074,7 @@ fn add_unsized_bound(ccx: &CrateCtxt,
|
||||||
|
|
||||||
fn ty_generics(ccx: &CrateCtxt,
|
fn ty_generics(ccx: &CrateCtxt,
|
||||||
space: subst::ParamSpace,
|
space: subst::ParamSpace,
|
||||||
lifetimes: &Vec<ast::Lifetime>,
|
lifetimes: &Vec<ast::LifetimeDef>,
|
||||||
types: &OwnedSlice<ast::TyParam>,
|
types: &OwnedSlice<ast::TyParam>,
|
||||||
base_generics: ty::Generics)
|
base_generics: ty::Generics)
|
||||||
-> ty::Generics
|
-> ty::Generics
|
||||||
|
@ -1081,10 +1082,10 @@ fn ty_generics(ccx: &CrateCtxt,
|
||||||
let mut result = base_generics;
|
let mut result = base_generics;
|
||||||
|
|
||||||
for (i, l) in lifetimes.iter().enumerate() {
|
for (i, l) in lifetimes.iter().enumerate() {
|
||||||
let def = ty::RegionParameterDef { name: l.name,
|
let def = ty::RegionParameterDef { name: l.lifetime.name,
|
||||||
space: space,
|
space: space,
|
||||||
index: i,
|
index: i,
|
||||||
def_id: local_def(l.id) };
|
def_id: local_def(l.lifetime.id) };
|
||||||
debug!("ty_generics: def for region param: {}", def);
|
debug!("ty_generics: def for region param: {}", def);
|
||||||
result.regions.push(space, def);
|
result.regions.push(space, def);
|
||||||
}
|
}
|
||||||
|
|
|
@ -976,10 +976,13 @@ impl<'a> Rebuilder<'a> {
|
||||||
-> ast::Generics {
|
-> ast::Generics {
|
||||||
let mut lifetimes = Vec::new();
|
let mut lifetimes = Vec::new();
|
||||||
for lt in add.iter() {
|
for lt in add.iter() {
|
||||||
lifetimes.push(*lt);
|
lifetimes.push(ast::LifetimeDef { lifetime: *lt,
|
||||||
|
bounds: Vec::new() });
|
||||||
}
|
}
|
||||||
for lt in generics.lifetimes.iter() {
|
for lt in generics.lifetimes.iter() {
|
||||||
if keep.contains(<.name) || !remove.contains(<.name) {
|
if keep.contains(<.lifetime.name) ||
|
||||||
|
!remove.contains(<.lifetime.name)
|
||||||
|
{
|
||||||
lifetimes.push((*lt).clone());
|
lifetimes.push((*lt).clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1439,7 +1442,7 @@ impl Resolvable for Rc<ty::TraitRef> {
|
||||||
|
|
||||||
fn lifetimes_in_scope(tcx: &ty::ctxt,
|
fn lifetimes_in_scope(tcx: &ty::ctxt,
|
||||||
scope_id: ast::NodeId)
|
scope_id: ast::NodeId)
|
||||||
-> Vec<ast::Lifetime> {
|
-> Vec<ast::LifetimeDef> {
|
||||||
let mut taken = Vec::new();
|
let mut taken = Vec::new();
|
||||||
let parent = tcx.map.get_parent(scope_id);
|
let parent = tcx.map.get_parent(scope_id);
|
||||||
let method_id_opt = match tcx.map.find(parent) {
|
let method_id_opt = match tcx.map.find(parent) {
|
||||||
|
@ -1486,10 +1489,10 @@ struct LifeGiver {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LifeGiver {
|
impl LifeGiver {
|
||||||
fn with_taken(taken: &[ast::Lifetime]) -> LifeGiver {
|
fn with_taken(taken: &[ast::LifetimeDef]) -> LifeGiver {
|
||||||
let mut taken_ = HashSet::new();
|
let mut taken_ = HashSet::new();
|
||||||
for lt in taken.iter() {
|
for lt in taken.iter() {
|
||||||
let lt_name = token::get_name(lt.name).get().to_string();
|
let lt_name = token::get_name(lt.lifetime.name).get().to_string();
|
||||||
taken_.insert(lt_name);
|
taken_.insert(lt_name);
|
||||||
}
|
}
|
||||||
LifeGiver {
|
LifeGiver {
|
||||||
|
|
|
@ -358,7 +358,8 @@ impl<'a> Visitor<()> for TermsContext<'a> {
|
||||||
ast::ItemStruct(_, ref generics) |
|
ast::ItemStruct(_, ref generics) |
|
||||||
ast::ItemTrait(ref generics, _, _, _) => {
|
ast::ItemTrait(ref generics, _, _, _) => {
|
||||||
for (i, p) in generics.lifetimes.iter().enumerate() {
|
for (i, p) in generics.lifetimes.iter().enumerate() {
|
||||||
self.add_inferred(item.id, RegionParam, TypeSpace, i, p.id);
|
let id = p.lifetime.id;
|
||||||
|
self.add_inferred(item.id, RegionParam, TypeSpace, i, id);
|
||||||
}
|
}
|
||||||
for (i, p) in generics.ty_params.iter().enumerate() {
|
for (i, p) in generics.ty_params.iter().enumerate() {
|
||||||
self.add_inferred(item.id, TypeParam, TypeSpace, i, p.id);
|
self.add_inferred(item.id, TypeParam, TypeSpace, i, p.id);
|
||||||
|
|
|
@ -410,8 +410,8 @@ mod svh_visitor {
|
||||||
SawLifetimeRef(content(l.name)).hash(self.st);
|
SawLifetimeRef(content(l.name)).hash(self.st);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lifetime_decl(&mut self, l: &Lifetime, _: E) {
|
fn visit_lifetime_decl(&mut self, l: &LifetimeDef, _: E) {
|
||||||
SawLifetimeDecl(content(l.name)).hash(self.st);
|
SawLifetimeDecl(content(l.lifetime.name)).hash(self.st);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do recursively walk the bodies of functions/methods
|
// We do recursively walk the bodies of functions/methods
|
||||||
|
|
|
@ -614,6 +614,12 @@ impl Clean<Lifetime> for ast::Lifetime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clean<Lifetime> for ast::LifetimeDef {
|
||||||
|
fn clean(&self) -> Lifetime {
|
||||||
|
Lifetime(token::get_name(self.lifetime.name).get().to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Clean<Lifetime> for ty::RegionParameterDef {
|
impl Clean<Lifetime> for ty::RegionParameterDef {
|
||||||
fn clean(&self) -> Lifetime {
|
fn clean(&self) -> Lifetime {
|
||||||
Lifetime(token::get_name(self.name).get().to_string())
|
Lifetime(token::get_name(self.name).get().to_string())
|
||||||
|
|
|
@ -160,6 +160,12 @@ pub struct Lifetime {
|
||||||
pub name: Name
|
pub name: Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
|
pub struct LifetimeDef {
|
||||||
|
pub lifetime: Lifetime,
|
||||||
|
pub bounds: Vec<Lifetime>
|
||||||
|
}
|
||||||
|
|
||||||
/// A "Path" is essentially Rust's notion of a name; for instance:
|
/// A "Path" is essentially Rust's notion of a name; for instance:
|
||||||
/// std::cmp::PartialEq . It's represented as a sequence of identifiers,
|
/// std::cmp::PartialEq . It's represented as a sequence of identifiers,
|
||||||
/// along with a bunch of supporting information.
|
/// along with a bunch of supporting information.
|
||||||
|
@ -231,7 +237,7 @@ pub struct TyParam {
|
||||||
/// of a function, enum, trait, etc.
|
/// of a function, enum, trait, etc.
|
||||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
pub struct Generics {
|
pub struct Generics {
|
||||||
pub lifetimes: Vec<Lifetime>,
|
pub lifetimes: Vec<LifetimeDef>,
|
||||||
pub ty_params: OwnedSlice<TyParam>,
|
pub ty_params: OwnedSlice<TyParam>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,7 +867,7 @@ impl fmt::Show for Onceness {
|
||||||
/// Represents the type of a closure
|
/// Represents the type of a closure
|
||||||
#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
pub struct ClosureTy {
|
pub struct ClosureTy {
|
||||||
pub lifetimes: Vec<Lifetime>,
|
pub lifetimes: Vec<LifetimeDef>,
|
||||||
pub fn_style: FnStyle,
|
pub fn_style: FnStyle,
|
||||||
pub onceness: Onceness,
|
pub onceness: Onceness,
|
||||||
pub decl: P<FnDecl>,
|
pub decl: P<FnDecl>,
|
||||||
|
@ -876,7 +882,7 @@ pub struct ClosureTy {
|
||||||
pub struct BareFnTy {
|
pub struct BareFnTy {
|
||||||
pub fn_style: FnStyle,
|
pub fn_style: FnStyle,
|
||||||
pub abi: Abi,
|
pub abi: Abi,
|
||||||
pub lifetimes: Vec<Lifetime>,
|
pub lifetimes: Vec<LifetimeDef>,
|
||||||
pub decl: P<FnDecl>
|
pub decl: P<FnDecl>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
|
||||||
self.operation.visit_id(type_parameter.id)
|
self.operation.visit_id(type_parameter.id)
|
||||||
}
|
}
|
||||||
for lifetime in generics.lifetimes.iter() {
|
for lifetime in generics.lifetimes.iter() {
|
||||||
self.operation.visit_id(lifetime.id)
|
self.operation.visit_id(lifetime.lifetime.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,11 @@ pub trait AstBuilder {
|
||||||
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
|
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
|
||||||
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
|
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
|
||||||
fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
|
fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
|
||||||
|
fn lifetime_def(&self,
|
||||||
|
span: Span,
|
||||||
|
name: ast::Name,
|
||||||
|
bounds: Vec<ast::Lifetime>)
|
||||||
|
-> ast::LifetimeDef;
|
||||||
|
|
||||||
// statements
|
// statements
|
||||||
fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt>;
|
fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt>;
|
||||||
|
@ -456,6 +461,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name }
|
ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lifetime_def(&self,
|
||||||
|
span: Span,
|
||||||
|
name: ast::Name,
|
||||||
|
bounds: Vec<ast::Lifetime>)
|
||||||
|
-> ast::LifetimeDef {
|
||||||
|
ast::LifetimeDef {
|
||||||
|
lifetime: self.lifetime(span, name),
|
||||||
|
bounds: bounds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt> {
|
fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt> {
|
||||||
box(GC) respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
|
box(GC) respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,7 +395,7 @@ impl<'a> TraitDef<'a> {
|
||||||
let mut ty_params = ty_params.into_vec();
|
let mut ty_params = ty_params.into_vec();
|
||||||
|
|
||||||
// Copy the lifetimes
|
// Copy the lifetimes
|
||||||
lifetimes.extend(generics.lifetimes.iter().map(|l| *l));
|
lifetimes.extend(generics.lifetimes.iter().map(|l| (*l).clone()));
|
||||||
|
|
||||||
// Create the type parameters.
|
// Create the type parameters.
|
||||||
ty_params.extend(generics.ty_params.iter().map(|ty_param| {
|
ty_params.extend(generics.ty_params.iter().map(|ty_param| {
|
||||||
|
@ -429,7 +429,11 @@ impl<'a> TraitDef<'a> {
|
||||||
cx.ty_ident(self.span, ty_param.ident)
|
cx.ty_ident(self.span, ty_param.ident)
|
||||||
});
|
});
|
||||||
|
|
||||||
let self_lifetimes = generics.lifetimes.clone();
|
let self_lifetimes: Vec<ast::Lifetime> =
|
||||||
|
generics.lifetimes
|
||||||
|
.iter()
|
||||||
|
.map(|ld| ld.lifetime)
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Create the type of `self`.
|
// Create the type of `self`.
|
||||||
let self_type = cx.ty_path(
|
let self_type = cx.ty_path(
|
||||||
|
|
|
@ -174,7 +174,9 @@ impl<'a> Ty<'a> {
|
||||||
let self_params = self_generics.ty_params.map(|ty_param| {
|
let self_params = self_generics.ty_params.map(|ty_param| {
|
||||||
cx.ty_ident(span, ty_param.ident)
|
cx.ty_ident(span, ty_param.ident)
|
||||||
});
|
});
|
||||||
let lifetimes = self_generics.lifetimes.clone();
|
let lifetimes = self_generics.lifetimes.iter()
|
||||||
|
.map(|d| d.lifetime)
|
||||||
|
.collect();
|
||||||
|
|
||||||
cx.path_all(span, false, vec!(self_ty), lifetimes,
|
cx.path_all(span, false, vec!(self_ty), lifetimes,
|
||||||
self_params.into_vec())
|
self_params.into_vec())
|
||||||
|
@ -200,7 +202,7 @@ fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
|
||||||
cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
|
cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
|
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam> ) -> Generics {
|
||||||
Generics {
|
Generics {
|
||||||
lifetimes: lifetimes,
|
lifetimes: lifetimes,
|
||||||
ty_params: OwnedSlice::from_vec(ty_params)
|
ty_params: OwnedSlice::from_vec(ty_params)
|
||||||
|
@ -210,7 +212,7 @@ fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) ->
|
||||||
/// Lifetimes and bounds on type parameters
|
/// Lifetimes and bounds on type parameters
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct LifetimeBounds<'a> {
|
pub struct LifetimeBounds<'a> {
|
||||||
pub lifetimes: Vec<&'a str>,
|
pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
|
||||||
pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
|
pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,8 +228,11 @@ impl<'a> LifetimeBounds<'a> {
|
||||||
self_ty: Ident,
|
self_ty: Ident,
|
||||||
self_generics: &Generics)
|
self_generics: &Generics)
|
||||||
-> Generics {
|
-> Generics {
|
||||||
let lifetimes = self.lifetimes.iter().map(|lt| {
|
let lifetimes = self.lifetimes.iter().map(|&(ref lt, ref bounds)| {
|
||||||
cx.lifetime(span, cx.ident_of(*lt).name)
|
let bounds =
|
||||||
|
bounds.iter().map(
|
||||||
|
|b| cx.lifetime(span, cx.ident_of(*b).name)).collect();
|
||||||
|
cx.lifetime_def(span, cx.ident_of(*lt).name, bounds)
|
||||||
}).collect();
|
}).collect();
|
||||||
let ty_params = self.bounds.iter().map(|t| {
|
let ty_params = self.bounds.iter().map(|t| {
|
||||||
match t {
|
match t {
|
||||||
|
|
|
@ -163,6 +163,10 @@ pub trait Folder {
|
||||||
noop_fold_lifetime(l, self)
|
noop_fold_lifetime(l, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_lifetime_def(&mut self, l: &LifetimeDef) -> LifetimeDef {
|
||||||
|
noop_fold_lifetime_def(l, self)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_attribute(&mut self, at: Attribute) -> Attribute {
|
fn fold_attribute(&mut self, at: Attribute) -> Attribute {
|
||||||
noop_fold_attribute(at, self)
|
noop_fold_attribute(at, self)
|
||||||
}
|
}
|
||||||
|
@ -187,6 +191,10 @@ pub trait Folder {
|
||||||
noop_fold_lifetimes(lts, self)
|
noop_fold_lifetimes(lts, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_lifetime_defs(&mut self, lts: &[LifetimeDef]) -> Vec<LifetimeDef> {
|
||||||
|
noop_fold_lifetime_defs(lts, self)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_ty_param(&mut self, tp: &TyParam) -> TyParam {
|
fn fold_ty_param(&mut self, tp: &TyParam) -> TyParam {
|
||||||
noop_fold_ty_param(tp, self)
|
noop_fold_ty_param(tp, self)
|
||||||
}
|
}
|
||||||
|
@ -337,7 +345,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||||
onceness: f.onceness,
|
onceness: f.onceness,
|
||||||
bounds: fld.fold_opt_bounds(&f.bounds),
|
bounds: fld.fold_opt_bounds(&f.bounds),
|
||||||
decl: fld.fold_fn_decl(&*f.decl),
|
decl: fld.fold_fn_decl(&*f.decl),
|
||||||
lifetimes: f.lifetimes.iter().map(|l| fld.fold_lifetime(l)).collect(),
|
lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
|
||||||
}, fld.fold_opt_lifetime(region))
|
}, fld.fold_opt_lifetime(region))
|
||||||
}
|
}
|
||||||
TyProc(ref f) => {
|
TyProc(ref f) => {
|
||||||
|
@ -346,12 +354,12 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
|
||||||
onceness: f.onceness,
|
onceness: f.onceness,
|
||||||
bounds: fld.fold_opt_bounds(&f.bounds),
|
bounds: fld.fold_opt_bounds(&f.bounds),
|
||||||
decl: fld.fold_fn_decl(&*f.decl),
|
decl: fld.fold_fn_decl(&*f.decl),
|
||||||
lifetimes: f.lifetimes.iter().map(|l| fld.fold_lifetime(l)).collect(),
|
lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
TyBareFn(ref f) => {
|
TyBareFn(ref f) => {
|
||||||
TyBareFn(box(GC) BareFnTy {
|
TyBareFn(box(GC) BareFnTy {
|
||||||
lifetimes: f.lifetimes.iter().map(|l| fld.fold_lifetime(l)).collect(),
|
lifetimes: fld.fold_lifetime_defs(f.lifetimes.as_slice()),
|
||||||
fn_style: f.fn_style,
|
fn_style: f.fn_style,
|
||||||
abi: f.abi,
|
abi: f.abi,
|
||||||
decl: fld.fold_fn_decl(&*f.decl)
|
decl: fld.fold_fn_decl(&*f.decl)
|
||||||
|
@ -665,10 +673,23 @@ pub fn noop_fold_lifetime<T: Folder>(l: &Lifetime, fld: &mut T) -> Lifetime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn noop_fold_lifetime_def<T: Folder>(l: &LifetimeDef, fld: &mut T)
|
||||||
|
-> LifetimeDef
|
||||||
|
{
|
||||||
|
LifetimeDef {
|
||||||
|
lifetime: fld.fold_lifetime(&l.lifetime),
|
||||||
|
bounds: fld.fold_lifetimes(l.bounds.as_slice()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn noop_fold_lifetimes<T: Folder>(lts: &[Lifetime], fld: &mut T) -> Vec<Lifetime> {
|
pub fn noop_fold_lifetimes<T: Folder>(lts: &[Lifetime], fld: &mut T) -> Vec<Lifetime> {
|
||||||
lts.iter().map(|l| fld.fold_lifetime(l)).collect()
|
lts.iter().map(|l| fld.fold_lifetime(l)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn noop_fold_lifetime_defs<T: Folder>(lts: &[LifetimeDef], fld: &mut T) -> Vec<LifetimeDef> {
|
||||||
|
lts.iter().map(|l| fld.fold_lifetime_def(l)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: &Option<Lifetime>, fld: &mut T)
|
pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: &Option<Lifetime>, fld: &mut T)
|
||||||
-> Option<Lifetime> {
|
-> Option<Lifetime> {
|
||||||
o_lt.as_ref().map(|lt| fld.fold_lifetime(lt))
|
o_lt.as_ref().map(|lt| fld.fold_lifetime(lt))
|
||||||
|
@ -676,7 +697,7 @@ pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: &Option<Lifetime>, fld: &mut T)
|
||||||
|
|
||||||
pub fn noop_fold_generics<T: Folder>(generics: &Generics, fld: &mut T) -> Generics {
|
pub fn noop_fold_generics<T: Folder>(generics: &Generics, fld: &mut T) -> Generics {
|
||||||
Generics {ty_params: fld.fold_ty_params(generics.ty_params.as_slice()),
|
Generics {ty_params: fld.fold_ty_params(generics.ty_params.as_slice()),
|
||||||
lifetimes: fld.fold_lifetimes(generics.lifetimes.as_slice())}
|
lifetimes: fld.fold_lifetime_defs(generics.lifetimes.as_slice())}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_fold_struct_def<T: Folder>(struct_def: Gc<StructDef>,
|
pub fn noop_fold_struct_def<T: Folder>(struct_def: Gc<StructDef>,
|
||||||
|
|
|
@ -1053,10 +1053,10 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let lifetimes = if self.eat(&token::LT) {
|
let lifetime_defs = if self.eat(&token::LT) {
|
||||||
let lifetimes = self.parse_lifetimes();
|
let lifetime_defs = self.parse_lifetime_defs();
|
||||||
self.expect_gt();
|
self.expect_gt();
|
||||||
lifetimes
|
lifetime_defs
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
@ -1082,7 +1082,7 @@ impl<'a> Parser<'a> {
|
||||||
onceness: Once,
|
onceness: Once,
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
decl: decl,
|
decl: decl,
|
||||||
lifetimes: lifetimes,
|
lifetimes: lifetime_defs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1096,7 +1096,7 @@ impl<'a> Parser<'a> {
|
||||||
| | | | | Return type
|
| | | | | Return type
|
||||||
| | | | Closure bounds
|
| | | | Closure bounds
|
||||||
| | | Argument types
|
| | | Argument types
|
||||||
| | Lifetimes
|
| | Lifetime defs
|
||||||
| Once-ness (a.k.a., affine)
|
| Once-ness (a.k.a., affine)
|
||||||
Function Style
|
Function Style
|
||||||
|
|
||||||
|
@ -1105,11 +1105,11 @@ impl<'a> Parser<'a> {
|
||||||
let fn_style = self.parse_unsafety();
|
let fn_style = self.parse_unsafety();
|
||||||
let onceness = if self.eat_keyword(keywords::Once) {Once} else {Many};
|
let onceness = if self.eat_keyword(keywords::Once) {Once} else {Many};
|
||||||
|
|
||||||
let lifetimes = if self.eat(&token::LT) {
|
let lifetime_defs = if self.eat(&token::LT) {
|
||||||
let lifetimes = self.parse_lifetimes();
|
let lifetime_defs = self.parse_lifetime_defs();
|
||||||
self.expect_gt();
|
self.expect_gt();
|
||||||
|
|
||||||
lifetimes
|
lifetime_defs
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
@ -1164,7 +1164,7 @@ impl<'a> Parser<'a> {
|
||||||
onceness: onceness,
|
onceness: onceness,
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
decl: decl,
|
decl: decl,
|
||||||
lifetimes: lifetimes,
|
lifetimes: lifetime_defs,
|
||||||
}, region)
|
}, region)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1179,7 +1179,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parse a function type (following the 'fn')
|
/// Parse a function type (following the 'fn')
|
||||||
pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
|
pub fn parse_ty_fn_decl(&mut self, allow_variadic: bool)
|
||||||
-> (P<FnDecl>, Vec<ast::Lifetime>) {
|
-> (P<FnDecl>, Vec<ast::LifetimeDef>) {
|
||||||
/*
|
/*
|
||||||
|
|
||||||
(fn) <'lt> (S) -> T
|
(fn) <'lt> (S) -> T
|
||||||
|
@ -1187,13 +1187,13 @@ impl<'a> Parser<'a> {
|
||||||
| | |
|
| | |
|
||||||
| | Return type
|
| | Return type
|
||||||
| Argument types
|
| Argument types
|
||||||
Lifetimes
|
Lifetime_defs
|
||||||
|
|
||||||
*/
|
*/
|
||||||
let lifetimes = if self.eat(&token::LT) {
|
let lifetime_defs = if self.eat(&token::LT) {
|
||||||
let lifetimes = self.parse_lifetimes();
|
let lifetime_defs = self.parse_lifetime_defs();
|
||||||
self.expect_gt();
|
self.expect_gt();
|
||||||
lifetimes
|
lifetime_defs
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
@ -1206,7 +1206,7 @@ impl<'a> Parser<'a> {
|
||||||
cf: ret_style,
|
cf: ret_style,
|
||||||
variadic: variadic
|
variadic: variadic
|
||||||
});
|
});
|
||||||
(decl, lifetimes)
|
(decl, lifetime_defs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the methods in a trait declaration
|
/// Parse the methods in a trait declaration
|
||||||
|
@ -1770,12 +1770,51 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_lifetime_defs(&mut self) -> Vec<ast::LifetimeDef> {
|
||||||
|
/*!
|
||||||
|
* Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]`
|
||||||
|
* where `lifetime_def = lifetime [':' lifetimes]`
|
||||||
|
*/
|
||||||
|
|
||||||
|
let mut res = Vec::new();
|
||||||
|
loop {
|
||||||
|
match self.token {
|
||||||
|
token::LIFETIME(_) => {
|
||||||
|
let lifetime = self.parse_lifetime();
|
||||||
|
let bounds =
|
||||||
|
if self.eat(&token::COLON) {
|
||||||
|
self.parse_lifetimes(token::BINOP(token::PLUS))
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
res.push(ast::LifetimeDef { lifetime: lifetime,
|
||||||
|
bounds: bounds });
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.token {
|
||||||
|
token::COMMA => { self.bump(); }
|
||||||
|
token::GT => { return res; }
|
||||||
|
token::BINOP(token::SHR) => { return res; }
|
||||||
|
_ => {
|
||||||
|
let msg = format!("expected `,` or `>` after lifetime \
|
||||||
|
name, got: {:?}",
|
||||||
|
self.token);
|
||||||
|
self.fatal(msg.as_slice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// matches lifetimes = ( lifetime ) | ( lifetime , lifetimes )
|
// matches lifetimes = ( lifetime ) | ( lifetime , lifetimes )
|
||||||
// actually, it matches the empty one too, but putting that in there
|
// actually, it matches the empty one too, but putting that in there
|
||||||
// messes up the grammar....
|
// messes up the grammar....
|
||||||
pub fn parse_lifetimes(&mut self) -> Vec<ast::Lifetime> {
|
pub fn parse_lifetimes(&mut self, sep: token::Token) -> Vec<ast::Lifetime> {
|
||||||
/*!
|
/*!
|
||||||
*
|
|
||||||
* Parses zero or more comma separated lifetimes.
|
* Parses zero or more comma separated lifetimes.
|
||||||
* Expects each lifetime to be followed by either
|
* Expects each lifetime to be followed by either
|
||||||
* a comma or `>`. Used when parsing type parameter
|
* a comma or `>`. Used when parsing type parameter
|
||||||
|
@ -1793,17 +1832,11 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.token {
|
if self.token != sep {
|
||||||
token::COMMA => { self.bump();}
|
return res;
|
||||||
token::GT => { return res; }
|
|
||||||
token::BINOP(token::SHR) => { return res; }
|
|
||||||
_ => {
|
|
||||||
let msg = format!("expected `,` or `>` after lifetime \
|
|
||||||
name, got: {:?}",
|
|
||||||
self.token);
|
|
||||||
self.fatal(msg.as_slice());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.bump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3664,7 +3697,7 @@ impl<'a> Parser<'a> {
|
||||||
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
|
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
|
||||||
pub fn parse_generics(&mut self) -> ast::Generics {
|
pub fn parse_generics(&mut self) -> ast::Generics {
|
||||||
if self.eat(&token::LT) {
|
if self.eat(&token::LT) {
|
||||||
let lifetimes = self.parse_lifetimes();
|
let lifetime_defs = self.parse_lifetime_defs();
|
||||||
let mut seen_default = false;
|
let mut seen_default = false;
|
||||||
let ty_params = self.parse_seq_to_gt(Some(token::COMMA), |p| {
|
let ty_params = self.parse_seq_to_gt(Some(token::COMMA), |p| {
|
||||||
p.forbid_lifetime();
|
p.forbid_lifetime();
|
||||||
|
@ -3678,14 +3711,14 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
ty_param
|
ty_param
|
||||||
});
|
});
|
||||||
ast::Generics { lifetimes: lifetimes, ty_params: ty_params }
|
ast::Generics { lifetimes: lifetime_defs, ty_params: ty_params }
|
||||||
} else {
|
} else {
|
||||||
ast_util::empty_generics()
|
ast_util::empty_generics()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> ) {
|
fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> ) {
|
||||||
let lifetimes = self.parse_lifetimes();
|
let lifetimes = self.parse_lifetimes(token::COMMA);
|
||||||
let result = self.parse_seq_to_gt(
|
let result = self.parse_seq_to_gt(
|
||||||
Some(token::COMMA),
|
Some(token::COMMA),
|
||||||
|p| {
|
|p| {
|
||||||
|
|
|
@ -2082,10 +2082,26 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_lifetime(&mut self,
|
pub fn print_lifetime(&mut self,
|
||||||
lifetime: &ast::Lifetime) -> IoResult<()> {
|
lifetime: &ast::Lifetime)
|
||||||
|
-> IoResult<()>
|
||||||
|
{
|
||||||
self.print_name(lifetime.name)
|
self.print_name(lifetime.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_lifetime_def(&mut self,
|
||||||
|
lifetime: &ast::LifetimeDef)
|
||||||
|
-> IoResult<()>
|
||||||
|
{
|
||||||
|
try!(self.print_lifetime(&lifetime.lifetime));
|
||||||
|
let mut sep = ":";
|
||||||
|
for v in lifetime.bounds.iter() {
|
||||||
|
try!(word(&mut self.s, sep));
|
||||||
|
try!(self.print_lifetime(v));
|
||||||
|
sep = "+";
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_generics(&mut self,
|
pub fn print_generics(&mut self,
|
||||||
generics: &ast::Generics) -> IoResult<()> {
|
generics: &ast::Generics) -> IoResult<()> {
|
||||||
let total = generics.lifetimes.len() + generics.ty_params.len();
|
let total = generics.lifetimes.len() + generics.ty_params.len();
|
||||||
|
@ -2102,7 +2118,7 @@ impl<'a> State<'a> {
|
||||||
|s, &idx| {
|
|s, &idx| {
|
||||||
if idx < generics.lifetimes.len() {
|
if idx < generics.lifetimes.len() {
|
||||||
let lifetime = generics.lifetimes.get(idx);
|
let lifetime = generics.lifetimes.get(idx);
|
||||||
s.print_lifetime(lifetime)
|
s.print_lifetime_def(lifetime)
|
||||||
} else {
|
} else {
|
||||||
let idx = idx - generics.lifetimes.len();
|
let idx = idx - generics.lifetimes.len();
|
||||||
let param = generics.ty_params.get(idx);
|
let param = generics.ty_params.get(idx);
|
||||||
|
|
|
@ -122,7 +122,7 @@ pub trait Visitor<E: Clone> {
|
||||||
fn visit_lifetime_ref(&mut self, _lifetime: &Lifetime, _e: E) {
|
fn visit_lifetime_ref(&mut self, _lifetime: &Lifetime, _e: E) {
|
||||||
/*! Visits a reference to a lifetime */
|
/*! Visits a reference to a lifetime */
|
||||||
}
|
}
|
||||||
fn visit_lifetime_decl(&mut self, _lifetime: &Lifetime, _e: E) {
|
fn visit_lifetime_decl(&mut self, _lifetime: &LifetimeDef, _e: E) {
|
||||||
/*! Visits a declaration of a lifetime */
|
/*! Visits a declaration of a lifetime */
|
||||||
}
|
}
|
||||||
fn visit_explicit_self(&mut self, es: &ExplicitSelf, e: E) {
|
fn visit_explicit_self(&mut self, es: &ExplicitSelf, e: E) {
|
||||||
|
@ -424,7 +424,7 @@ pub fn walk_ty<E: Clone, V: Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_lifetime_decls<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
fn walk_lifetime_decls<E: Clone, V: Visitor<E>>(visitor: &mut V,
|
||||||
lifetimes: &Vec<Lifetime>,
|
lifetimes: &Vec<LifetimeDef>,
|
||||||
env: E) {
|
env: E) {
|
||||||
for l in lifetimes.iter() {
|
for l in lifetimes.iter() {
|
||||||
visitor.visit_lifetime_decl(l, env.clone());
|
visitor.visit_lifetime_decl(l, env.clone());
|
||||||
|
|
18
src/test/compile-fail/regions-bound-lists-feature-gate-2.rs
Normal file
18
src/test/compile-fail/regions-bound-lists-feature-gate-2.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// ignore-pretty
|
||||||
|
|
||||||
|
trait Foo { }
|
||||||
|
|
||||||
|
fn foo<'a, 'b:'a>() { //~ ERROR region bounds require `issue_5723_bootstrap`
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() { }
|
20
src/test/run-pass/regions-bound-lists-feature-gate-2.rs
Normal file
20
src/test/run-pass/regions-bound-lists-feature-gate-2.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// ignore-pretty
|
||||||
|
|
||||||
|
#![feature(issue_5723_bootstrap)]
|
||||||
|
|
||||||
|
trait Foo { }
|
||||||
|
|
||||||
|
fn foo<'a, 'b, 'c:'a+'b, 'd>() {
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() { }
|
Loading…
Add table
Add a link
Reference in a new issue