Skip to content

Commit e86c87a

Browse files
committed
Generalize lifetime bounds on type parameters to support multiple
lifetime bounds. This doesn't really cause any difficulties, because we already had to accommodate the fact that multiple implicit bounds could accumulate. Object types still require precisely one lifetime bound. This is a pre-step towards generalized where clauses (once you have lifetime bounds in where clauses, it is harder to restrict them to exactly one).
1 parent 946654a commit e86c87a

File tree

11 files changed

+81
-18
lines changed

11 files changed

+81
-18
lines changed

src/librustc/metadata/tydecode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,14 +680,14 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
680680
let builtin_bounds = parse_builtin_bounds(st, |x,y| conv(x,y));
681681

682682
let mut param_bounds = ty::ParamBounds {
683-
opt_region_bound: None,
683+
region_bounds: Vec::new(),
684684
builtin_bounds: builtin_bounds,
685685
trait_bounds: Vec::new()
686686
};
687687
loop {
688688
match next(st) {
689689
'R' => {
690-
param_bounds.opt_region_bound = Some(parse_region(st, |x, y| conv (x, y)));
690+
param_bounds.region_bounds.push(parse_region(st, |x, y| conv (x, y)));
691691
}
692692
'I' => {
693693
param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));

src/librustc/metadata/tyencode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::Exi
366366
pub fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
367367
enc_builtin_bounds(w, cx, &bs.builtin_bounds);
368368

369-
for &r in bs.opt_region_bound.iter() {
369+
for &r in bs.region_bounds.iter() {
370370
mywrite!(w, "R");
371371
enc_region(w, cx, r);
372372
}

src/librustc/middle/ty.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,15 +1008,16 @@ pub enum type_err {
10081008
/// as well as the existential type parameter in an object type.
10091009
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
10101010
pub struct ParamBounds {
1011-
pub opt_region_bound: Option<ty::Region>,
1011+
pub region_bounds: Vec<ty::Region>,
10121012
pub builtin_bounds: BuiltinBounds,
10131013
pub trait_bounds: Vec<Rc<TraitRef>>
10141014
}
10151015

10161016
/// Bounds suitable for an existentially quantified type parameter
10171017
/// such as those that appear in object types or closure types. The
10181018
/// major difference between this case and `ParamBounds` is that
1019-
/// general purpose trait bounds are omitted.
1019+
/// general purpose trait bounds are omitted and there must be
1020+
/// *exactly one* region.
10201021
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
10211022
pub struct ExistentialBounds {
10221023
pub region_bound: ty::Region,
@@ -4864,7 +4865,7 @@ pub fn required_region_bounds(tcx: &ctxt,
48644865
trait_bounds,
48654866
|trait_ref| {
48664867
let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
4867-
push_region_bounds(bounds.opt_region_bound.as_slice(),
4868+
push_region_bounds(bounds.region_bounds.as_slice(),
48684869
bounds.builtin_bounds,
48694870
&mut all_bounds);
48704871
debug!("from {}: bounds={} all_bounds={}",

src/librustc/middle/ty_fold.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl TypeFoldable for ty::ExistentialBounds {
287287
impl TypeFoldable for ty::ParamBounds {
288288
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParamBounds {
289289
ty::ParamBounds {
290-
opt_region_bound: self.opt_region_bound.fold_with(folder),
290+
region_bounds: self.region_bounds.fold_with(folder),
291291
builtin_bounds: self.builtin_bounds.fold_with(folder),
292292
trait_bounds: self.trait_bounds.fold_with(folder),
293293
}

src/librustc/middle/typeck/check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2005,7 +2005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20052005
let region_bounds =
20062006
ty::required_region_bounds(
20072007
self.tcx(),
2008-
param_bound.opt_region_bound.as_slice(),
2008+
param_bound.region_bounds.as_slice(),
20092009
param_bound.builtin_bounds,
20102010
param_bound.trait_bounds.as_slice());
20112011
for &r in region_bounds.iter() {

src/librustc/middle/typeck/check/regionck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1880,7 +1880,7 @@ fn param_must_outlive(rcx: &Rcx,
18801880
let param_bound = param_env.bounds.get(param_ty.space, param_ty.idx);
18811881
param_bounds =
18821882
ty::required_region_bounds(rcx.tcx(),
1883-
param_bound.opt_region_bound.as_slice(),
1883+
param_bound.region_bounds.as_slice(),
18841884
param_bound.builtin_bounds,
18851885
param_bound.trait_bounds.as_slice());
18861886

src/librustc/middle/typeck/check/regionmanip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
327327

328328
// Inspect bounds on this type parameter for any
329329
// region bounds.
330-
for &r in type_param_def.bounds.opt_region_bound.iter() {
330+
for &r in type_param_def.bounds.region_bounds.iter() {
331331
self.stack.push((r, Some(ty)));
332332
self.accumulate_from_ty(type_param_ty);
333333
self.stack.pop().unwrap();

src/librustc/middle/typeck/collect.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
10441044
ident: special_idents::type_self,
10451045
def_id: local_def(param_id),
10461046
bounds: ty::ParamBounds {
1047-
opt_region_bound: None,
1047+
region_bounds: vec!(),
10481048
builtin_bounds: ty::empty_builtin_bounds(),
10491049
trait_bounds: vec!(self_trait_ref),
10501050
},
@@ -1280,12 +1280,12 @@ fn conv_param_bounds(ccx: &CrateCtxt,
12801280
.map(|b| instantiate_trait_ref(ccx, b, param_ty.to_ty(ccx.tcx)))
12811281
.chain(unboxed_fn_ty_bounds)
12821282
.collect();
1283-
let opt_region_bound =
1284-
astconv::compute_opt_region_bound(
1285-
ccx.tcx, span, builtin_bounds, region_bounds.as_slice(),
1286-
trait_bounds.as_slice());
1283+
let region_bounds: Vec<ty::Region> =
1284+
region_bounds.move_iter()
1285+
.map(|r| ast_region_to_region(ccx.tcx, r))
1286+
.collect();
12871287
ty::ParamBounds {
1288-
opt_region_bound: opt_region_bound,
1288+
region_bounds: region_bounds,
12891289
builtin_bounds: builtin_bounds,
12901290
trait_bounds: trait_bounds,
12911291
}

src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ fn test<
3535
'a,
3636
'b,
3737
A:IsStatic,
38-
B:Is<'a>+Is2<'b>, //~ ERROR ambiguous lifetime bound
38+
B:Is<'a>+Is2<'b>, // OK in a parameter, but not an object type.
3939
C:'b+Is<'a>+Is2<'b>,
4040
D:Is<'a>+Is2<'static>,
41-
E:'a+'b //~ ERROR only a single explicit lifetime bound is permitted
41+
E:'a+'b // OK in a parameter, but not an object type.
4242
>() { }
4343

4444
fn main() { }
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Various tests where we over type parameters with multiple lifetime
12+
// bounds.
13+
14+
trait SomeTrait { fn get(&self) -> int; }
15+
16+
fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'a> {
17+
// A outlives 'a AND 'b...
18+
box v as Box<SomeTrait+'a> // ...hence this type is safe.
19+
}
20+
21+
fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
22+
// A outlives 'a AND 'b...
23+
box v as Box<SomeTrait+'b> // ...hence this type is safe.
24+
}
25+
26+
fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
27+
// A outlives 'a AND 'b...but not 'c.
28+
box v as Box<SomeTrait+'a> //~ ERROR mismatched types
29+
}
30+
31+
fn main() {
32+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// A test where we (successfully) close over a reference into
12+
// an object.
13+
14+
trait SomeTrait { fn get(&self) -> int; }
15+
16+
impl<'a> SomeTrait for &'a int {
17+
fn get(&self) -> int {
18+
**self
19+
}
20+
}
21+
22+
fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
23+
box v as Box<SomeTrait+'a>
24+
}
25+
26+
fn main() {
27+
let i: int = 22;
28+
let obj = make_object(&i);
29+
assert_eq!(22, obj.get());
30+
}

0 commit comments

Comments
 (0)