Skip to content

Commit 8a02304

Browse files
committed
auto merge of #16318 : nikomatsakis/rust/issue-5723-bootstrap-2, r=pnkfelix
Introduce syntax for lifetime 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.
2 parents 1a53c00 + fcab980 commit 8a02304

File tree

19 files changed

+240
-80
lines changed

19 files changed

+240
-80
lines changed

src/librustc/lint/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ impl<'a> Visitor<()> for Context<'a> {
576576
run_lints!(self, check_lifetime_ref, lt);
577577
}
578578

579-
fn visit_lifetime_decl(&mut self, lt: &ast::Lifetime, _: ()) {
579+
fn visit_lifetime_decl(&mut self, lt: &ast::LifetimeDef, _: ()) {
580580
run_lints!(self, check_lifetime_decl, lt);
581581
}
582582

src/librustc/lint/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ pub trait LintPass {
150150
fn check_variant(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) { }
151151
fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option<ast::Lifetime>) { }
152152
fn check_lifetime_ref(&mut self, _: &Context, _: &ast::Lifetime) { }
153-
fn check_lifetime_decl(&mut self, _: &Context, _: &ast::Lifetime) { }
153+
fn check_lifetime_decl(&mut self, _: &Context, _: &ast::LifetimeDef) { }
154154
fn check_explicit_self(&mut self, _: &Context, _: &ast::ExplicitSelf) { }
155155
fn check_mac(&mut self, _: &Context, _: &ast::Mac) { }
156156
fn check_path(&mut self, _: &Context, _: &ast::Path, _: ast::NodeId) { }

src/librustc/middle/resolve_lifetime.rs

+27-17
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ struct LifetimeContext<'a> {
5959
enum ScopeChain<'a> {
6060
/// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound
6161
/// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc.
62-
EarlyScope(subst::ParamSpace, &'a Vec<ast::Lifetime>, Scope<'a>),
62+
EarlyScope(subst::ParamSpace, &'a Vec<ast::LifetimeDef>, Scope<'a>),
6363
/// LateScope(binder_id, ['a, 'b, ...], s) extends s with late-bound
6464
/// lifetimes introduced by the declaration binder_id.
65-
LateScope(ast::NodeId, &'a Vec<ast::Lifetime>, Scope<'a>),
65+
LateScope(ast::NodeId, &'a Vec<ast::LifetimeDef>, Scope<'a>),
6666
/// lifetimes introduced by items within a code block are scoped
6767
/// to that block.
6868
BlockScope(ast::NodeId, Scope<'a>),
@@ -136,7 +136,7 @@ impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
136136
fn push_fn_scope(this: &mut LifetimeContext,
137137
ty: &ast::Ty,
138138
scope: Scope,
139-
lifetimes: &Vec<ast::Lifetime>) {
139+
lifetimes: &Vec<ast::LifetimeDef>) {
140140
let scope1 = LateScope(ty.id, lifetimes, scope);
141141
this.check_lifetime_names(lifetimes);
142142
debug!("pushing fn scope id={} due to type", ty.id);
@@ -216,7 +216,7 @@ impl<'a> LifetimeContext<'a> {
216216
walk(self, &scope1)
217217
} else {
218218
let (early, late) = generics.lifetimes.clone().partition(
219-
|l| referenced_idents.iter().any(|&i| i == l.name));
219+
|l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
220220

221221
let scope1 = EarlyScope(subst::FnSpace, &early, scope);
222222
let scope2 = LateScope(n, &late, &scope1);
@@ -334,29 +334,39 @@ impl<'a> LifetimeContext<'a> {
334334
token::get_name(lifetime_ref.name)).as_slice());
335335
}
336336

337-
fn check_lifetime_names(&self, lifetimes: &Vec<ast::Lifetime>) {
337+
fn check_lifetime_names(&self, lifetimes: &Vec<ast::LifetimeDef>) {
338338
for i in range(0, lifetimes.len()) {
339339
let lifetime_i = lifetimes.get(i);
340340

341341
let special_idents = [special_idents::static_lifetime];
342342
for lifetime in lifetimes.iter() {
343-
if special_idents.iter().any(|&i| i.name == lifetime.name) {
343+
if special_idents.iter().any(|&i| i.name == lifetime.lifetime.name) {
344344
self.sess.span_err(
345-
lifetime.span,
345+
lifetime.lifetime.span,
346346
format!("illegal lifetime parameter name: `{}`",
347-
token::get_name(lifetime.name)).as_slice());
347+
token::get_name(lifetime.lifetime.name))
348+
.as_slice());
348349
}
349350
}
350351

351352
for j in range(i + 1, lifetimes.len()) {
352353
let lifetime_j = lifetimes.get(j);
353354

354-
if lifetime_i.name == lifetime_j.name {
355+
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
355356
self.sess.span_err(
356-
lifetime_j.span,
357+
lifetime_j.lifetime.span,
357358
format!("lifetime name `{}` declared twice in \
358359
the same scope",
359-
token::get_name(lifetime_j.name)).as_slice());
360+
token::get_name(lifetime_j.lifetime.name))
361+
.as_slice());
362+
}
363+
}
364+
365+
for bound in lifetime_i.bounds.iter() {
366+
if !self.sess.features.issue_5723_bootstrap.get() {
367+
self.sess.span_err(
368+
bound.span,
369+
"region bounds require `issue_5723_bootstrap`");
360370
}
361371
}
362372
}
@@ -379,28 +389,28 @@ impl<'a> LifetimeContext<'a> {
379389
}
380390
}
381391

382-
fn search_lifetimes(lifetimes: &Vec<ast::Lifetime>,
392+
fn search_lifetimes(lifetimes: &Vec<ast::LifetimeDef>,
383393
lifetime_ref: &ast::Lifetime)
384394
-> Option<(uint, ast::NodeId)> {
385395
for (i, lifetime_decl) in lifetimes.iter().enumerate() {
386-
if lifetime_decl.name == lifetime_ref.name {
387-
return Some((i, lifetime_decl.id));
396+
if lifetime_decl.lifetime.name == lifetime_ref.name {
397+
return Some((i, lifetime_decl.lifetime.id));
388398
}
389399
}
390400
return None;
391401
}
392402

393403
///////////////////////////////////////////////////////////////////////////
394404

395-
pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::Lifetime> {
405+
pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::LifetimeDef> {
396406
let referenced_idents = free_lifetimes(&generics.ty_params);
397407
if referenced_idents.is_empty() {
398408
return Vec::new();
399409
}
400410

401411
generics.lifetimes.iter()
402-
.filter(|l| referenced_idents.iter().any(|&i| i == l.name))
403-
.map(|l| *l)
412+
.filter(|l| referenced_idents.iter().any(|&i| i == l.lifetime.name))
413+
.map(|l| (*l).clone())
404414
.collect()
405415
}
406416

src/librustc/middle/typeck/collect.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -804,9 +804,10 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
804804
generics.lifetimes
805805
.iter()
806806
.enumerate()
807-
.map(|(i, def)| ty::ReEarlyBound(def.id,
807+
.map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
808808
subst::TypeSpace,
809-
i, def.name))
809+
i,
810+
def.lifetime.name))
810811
.collect();
811812

812813
let types =
@@ -1073,18 +1074,18 @@ fn add_unsized_bound(ccx: &CrateCtxt,
10731074

10741075
fn ty_generics(ccx: &CrateCtxt,
10751076
space: subst::ParamSpace,
1076-
lifetimes: &Vec<ast::Lifetime>,
1077+
lifetimes: &Vec<ast::LifetimeDef>,
10771078
types: &OwnedSlice<ast::TyParam>,
10781079
base_generics: ty::Generics)
10791080
-> ty::Generics
10801081
{
10811082
let mut result = base_generics;
10821083

10831084
for (i, l) in lifetimes.iter().enumerate() {
1084-
let def = ty::RegionParameterDef { name: l.name,
1085+
let def = ty::RegionParameterDef { name: l.lifetime.name,
10851086
space: space,
10861087
index: i,
1087-
def_id: local_def(l.id) };
1088+
def_id: local_def(l.lifetime.id) };
10881089
debug!("ty_generics: def for region param: {}", def);
10891090
result.regions.push(space, def);
10901091
}

src/librustc/middle/typeck/infer/error_reporting.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -976,10 +976,13 @@ impl<'a> Rebuilder<'a> {
976976
-> ast::Generics {
977977
let mut lifetimes = Vec::new();
978978
for lt in add.iter() {
979-
lifetimes.push(*lt);
979+
lifetimes.push(ast::LifetimeDef { lifetime: *lt,
980+
bounds: Vec::new() });
980981
}
981982
for lt in generics.lifetimes.iter() {
982-
if keep.contains(&lt.name) || !remove.contains(&lt.name) {
983+
if keep.contains(&lt.lifetime.name) ||
984+
!remove.contains(&lt.lifetime.name)
985+
{
983986
lifetimes.push((*lt).clone());
984987
}
985988
}
@@ -1439,7 +1442,7 @@ impl Resolvable for Rc<ty::TraitRef> {
14391442

14401443
fn lifetimes_in_scope(tcx: &ty::ctxt,
14411444
scope_id: ast::NodeId)
1442-
-> Vec<ast::Lifetime> {
1445+
-> Vec<ast::LifetimeDef> {
14431446
let mut taken = Vec::new();
14441447
let parent = tcx.map.get_parent(scope_id);
14451448
let method_id_opt = match tcx.map.find(parent) {
@@ -1486,10 +1489,10 @@ struct LifeGiver {
14861489
}
14871490

14881491
impl LifeGiver {
1489-
fn with_taken(taken: &[ast::Lifetime]) -> LifeGiver {
1492+
fn with_taken(taken: &[ast::LifetimeDef]) -> LifeGiver {
14901493
let mut taken_ = HashSet::new();
14911494
for lt in taken.iter() {
1492-
let lt_name = token::get_name(lt.name).get().to_string();
1495+
let lt_name = token::get_name(lt.lifetime.name).get().to_string();
14931496
taken_.insert(lt_name);
14941497
}
14951498
LifeGiver {

src/librustc/middle/typeck/variance.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,8 @@ impl<'a> Visitor<()> for TermsContext<'a> {
358358
ast::ItemStruct(_, ref generics) |
359359
ast::ItemTrait(ref generics, _, _, _) => {
360360
for (i, p) in generics.lifetimes.iter().enumerate() {
361-
self.add_inferred(item.id, RegionParam, TypeSpace, i, p.id);
361+
let id = p.lifetime.id;
362+
self.add_inferred(item.id, RegionParam, TypeSpace, i, id);
362363
}
363364
for (i, p) in generics.ty_params.iter().enumerate() {
364365
self.add_inferred(item.id, TypeParam, TypeSpace, i, p.id);

src/librustc_back/svh.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,8 @@ mod svh_visitor {
410410
SawLifetimeRef(content(l.name)).hash(self.st);
411411
}
412412

413-
fn visit_lifetime_decl(&mut self, l: &Lifetime, _: E) {
414-
SawLifetimeDecl(content(l.name)).hash(self.st);
413+
fn visit_lifetime_decl(&mut self, l: &LifetimeDef, _: E) {
414+
SawLifetimeDecl(content(l.lifetime.name)).hash(self.st);
415415
}
416416

417417
// We do recursively walk the bodies of functions/methods

src/librustdoc/clean/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,12 @@ impl Clean<Lifetime> for ast::Lifetime {
614614
}
615615
}
616616

617+
impl Clean<Lifetime> for ast::LifetimeDef {
618+
fn clean(&self) -> Lifetime {
619+
Lifetime(token::get_name(self.lifetime.name).get().to_string())
620+
}
621+
}
622+
617623
impl Clean<Lifetime> for ty::RegionParameterDef {
618624
fn clean(&self) -> Lifetime {
619625
Lifetime(token::get_name(self.name).get().to_string())

src/libsyntax/ast.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ pub struct Lifetime {
160160
pub name: Name
161161
}
162162

163+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
164+
pub struct LifetimeDef {
165+
pub lifetime: Lifetime,
166+
pub bounds: Vec<Lifetime>
167+
}
168+
163169
/// A "Path" is essentially Rust's notion of a name; for instance:
164170
/// std::cmp::PartialEq . It's represented as a sequence of identifiers,
165171
/// along with a bunch of supporting information.
@@ -231,7 +237,7 @@ pub struct TyParam {
231237
/// of a function, enum, trait, etc.
232238
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
233239
pub struct Generics {
234-
pub lifetimes: Vec<Lifetime>,
240+
pub lifetimes: Vec<LifetimeDef>,
235241
pub ty_params: OwnedSlice<TyParam>,
236242
}
237243

@@ -861,7 +867,7 @@ impl fmt::Show for Onceness {
861867
/// Represents the type of a closure
862868
#[deriving(PartialEq, Eq, Encodable, Decodable, Hash, Show)]
863869
pub struct ClosureTy {
864-
pub lifetimes: Vec<Lifetime>,
870+
pub lifetimes: Vec<LifetimeDef>,
865871
pub fn_style: FnStyle,
866872
pub onceness: Onceness,
867873
pub decl: P<FnDecl>,
@@ -876,7 +882,7 @@ pub struct ClosureTy {
876882
pub struct BareFnTy {
877883
pub fn_style: FnStyle,
878884
pub abi: Abi,
879-
pub lifetimes: Vec<Lifetime>,
885+
pub lifetimes: Vec<LifetimeDef>,
880886
pub decl: P<FnDecl>
881887
}
882888

src/libsyntax/ast_util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ impl<'a, O: IdVisitingOperation> IdVisitor<'a, O> {
369369
self.operation.visit_id(type_parameter.id)
370370
}
371371
for lifetime in generics.lifetimes.iter() {
372-
self.operation.visit_id(lifetime.id)
372+
self.operation.visit_id(lifetime.lifetime.id)
373373
}
374374
}
375375
}

src/libsyntax/ext/build.rs

+16
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ pub trait AstBuilder {
7373
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
7474
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
7575
fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
76+
fn lifetime_def(&self,
77+
span: Span,
78+
name: ast::Name,
79+
bounds: Vec<ast::Lifetime>)
80+
-> ast::LifetimeDef;
7681

7782
// statements
7883
fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt>;
@@ -456,6 +461,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
456461
ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name }
457462
}
458463

464+
fn lifetime_def(&self,
465+
span: Span,
466+
name: ast::Name,
467+
bounds: Vec<ast::Lifetime>)
468+
-> ast::LifetimeDef {
469+
ast::LifetimeDef {
470+
lifetime: self.lifetime(span, name),
471+
bounds: bounds
472+
}
473+
}
474+
459475
fn stmt_expr(&self, expr: Gc<ast::Expr>) -> Gc<ast::Stmt> {
460476
box(GC) respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
461477
}

src/libsyntax/ext/deriving/generic/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ impl<'a> TraitDef<'a> {
395395
let mut ty_params = ty_params.into_vec();
396396

397397
// Copy the lifetimes
398-
lifetimes.extend(generics.lifetimes.iter().map(|l| *l));
398+
lifetimes.extend(generics.lifetimes.iter().map(|l| (*l).clone()));
399399

400400
// Create the type parameters.
401401
ty_params.extend(generics.ty_params.iter().map(|ty_param| {
@@ -429,7 +429,11 @@ impl<'a> TraitDef<'a> {
429429
cx.ty_ident(self.span, ty_param.ident)
430430
});
431431

432-
let self_lifetimes = generics.lifetimes.clone();
432+
let self_lifetimes: Vec<ast::Lifetime> =
433+
generics.lifetimes
434+
.iter()
435+
.map(|ld| ld.lifetime)
436+
.collect();
433437

434438
// Create the type of `self`.
435439
let self_type = cx.ty_path(

src/libsyntax/ext/deriving/generic/ty.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,9 @@ impl<'a> Ty<'a> {
174174
let self_params = self_generics.ty_params.map(|ty_param| {
175175
cx.ty_ident(span, ty_param.ident)
176176
});
177-
let lifetimes = self_generics.lifetimes.clone();
177+
let lifetimes = self_generics.lifetimes.iter()
178+
.map(|d| d.lifetime)
179+
.collect();
178180

179181
cx.path_all(span, false, vec!(self_ty), lifetimes,
180182
self_params.into_vec())
@@ -200,7 +202,7 @@ fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
200202
cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
201203
}
202204

203-
fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) -> Generics {
205+
fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam> ) -> Generics {
204206
Generics {
205207
lifetimes: lifetimes,
206208
ty_params: OwnedSlice::from_vec(ty_params)
@@ -210,7 +212,7 @@ fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) ->
210212
/// Lifetimes and bounds on type parameters
211213
#[deriving(Clone)]
212214
pub struct LifetimeBounds<'a> {
213-
pub lifetimes: Vec<&'a str>,
215+
pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
214216
pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
215217
}
216218

@@ -226,8 +228,11 @@ impl<'a> LifetimeBounds<'a> {
226228
self_ty: Ident,
227229
self_generics: &Generics)
228230
-> Generics {
229-
let lifetimes = self.lifetimes.iter().map(|lt| {
230-
cx.lifetime(span, cx.ident_of(*lt).name)
231+
let lifetimes = self.lifetimes.iter().map(|&(ref lt, ref bounds)| {
232+
let bounds =
233+
bounds.iter().map(
234+
|b| cx.lifetime(span, cx.ident_of(*b).name)).collect();
235+
cx.lifetime_def(span, cx.ident_of(*lt).name, bounds)
231236
}).collect();
232237
let ty_params = self.bounds.iter().map(|t| {
233238
match t {

0 commit comments

Comments
 (0)