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).
This commit is contained in:
parent
946654a721
commit
e86c87a81e
@ -680,14 +680,14 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
|
||||
let builtin_bounds = parse_builtin_bounds(st, |x,y| conv(x,y));
|
||||
|
||||
let mut param_bounds = ty::ParamBounds {
|
||||
opt_region_bound: None,
|
||||
region_bounds: Vec::new(),
|
||||
builtin_bounds: builtin_bounds,
|
||||
trait_bounds: Vec::new()
|
||||
};
|
||||
loop {
|
||||
match next(st) {
|
||||
'R' => {
|
||||
param_bounds.opt_region_bound = Some(parse_region(st, |x, y| conv (x, y)));
|
||||
param_bounds.region_bounds.push(parse_region(st, |x, y| conv (x, y)));
|
||||
}
|
||||
'I' => {
|
||||
param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
|
||||
|
@ -366,7 +366,7 @@ pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::Exi
|
||||
pub fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
|
||||
enc_builtin_bounds(w, cx, &bs.builtin_bounds);
|
||||
|
||||
for &r in bs.opt_region_bound.iter() {
|
||||
for &r in bs.region_bounds.iter() {
|
||||
mywrite!(w, "R");
|
||||
enc_region(w, cx, r);
|
||||
}
|
||||
|
@ -1008,7 +1008,7 @@ pub enum type_err {
|
||||
/// as well as the existential type parameter in an object type.
|
||||
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
|
||||
pub struct ParamBounds {
|
||||
pub opt_region_bound: Option<ty::Region>,
|
||||
pub region_bounds: Vec<ty::Region>,
|
||||
pub builtin_bounds: BuiltinBounds,
|
||||
pub trait_bounds: Vec<Rc<TraitRef>>
|
||||
}
|
||||
@ -1016,7 +1016,8 @@ pub struct ParamBounds {
|
||||
/// Bounds suitable for an existentially quantified type parameter
|
||||
/// such as those that appear in object types or closure types. The
|
||||
/// major difference between this case and `ParamBounds` is that
|
||||
/// general purpose trait bounds are omitted.
|
||||
/// general purpose trait bounds are omitted and there must be
|
||||
/// *exactly one* region.
|
||||
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
|
||||
pub struct ExistentialBounds {
|
||||
pub region_bound: ty::Region,
|
||||
@ -4864,7 +4865,7 @@ pub fn required_region_bounds(tcx: &ctxt,
|
||||
trait_bounds,
|
||||
|trait_ref| {
|
||||
let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
|
||||
push_region_bounds(bounds.opt_region_bound.as_slice(),
|
||||
push_region_bounds(bounds.region_bounds.as_slice(),
|
||||
bounds.builtin_bounds,
|
||||
&mut all_bounds);
|
||||
debug!("from {}: bounds={} all_bounds={}",
|
||||
|
@ -287,7 +287,7 @@ impl TypeFoldable for ty::ExistentialBounds {
|
||||
impl TypeFoldable for ty::ParamBounds {
|
||||
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParamBounds {
|
||||
ty::ParamBounds {
|
||||
opt_region_bound: self.opt_region_bound.fold_with(folder),
|
||||
region_bounds: self.region_bounds.fold_with(folder),
|
||||
builtin_bounds: self.builtin_bounds.fold_with(folder),
|
||||
trait_bounds: self.trait_bounds.fold_with(folder),
|
||||
}
|
||||
|
@ -2005,7 +2005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let region_bounds =
|
||||
ty::required_region_bounds(
|
||||
self.tcx(),
|
||||
param_bound.opt_region_bound.as_slice(),
|
||||
param_bound.region_bounds.as_slice(),
|
||||
param_bound.builtin_bounds,
|
||||
param_bound.trait_bounds.as_slice());
|
||||
for &r in region_bounds.iter() {
|
||||
|
@ -1880,7 +1880,7 @@ fn param_must_outlive(rcx: &Rcx,
|
||||
let param_bound = param_env.bounds.get(param_ty.space, param_ty.idx);
|
||||
param_bounds =
|
||||
ty::required_region_bounds(rcx.tcx(),
|
||||
param_bound.opt_region_bound.as_slice(),
|
||||
param_bound.region_bounds.as_slice(),
|
||||
param_bound.builtin_bounds,
|
||||
param_bound.trait_bounds.as_slice());
|
||||
|
||||
|
@ -327,7 +327,7 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
|
||||
|
||||
// Inspect bounds on this type parameter for any
|
||||
// region bounds.
|
||||
for &r in type_param_def.bounds.opt_region_bound.iter() {
|
||||
for &r in type_param_def.bounds.region_bounds.iter() {
|
||||
self.stack.push((r, Some(ty)));
|
||||
self.accumulate_from_ty(type_param_ty);
|
||||
self.stack.pop().unwrap();
|
||||
|
@ -1044,7 +1044,7 @@ fn ty_generics_for_trait(ccx: &CrateCtxt,
|
||||
ident: special_idents::type_self,
|
||||
def_id: local_def(param_id),
|
||||
bounds: ty::ParamBounds {
|
||||
opt_region_bound: None,
|
||||
region_bounds: vec!(),
|
||||
builtin_bounds: ty::empty_builtin_bounds(),
|
||||
trait_bounds: vec!(self_trait_ref),
|
||||
},
|
||||
@ -1280,12 +1280,12 @@ fn conv_param_bounds(ccx: &CrateCtxt,
|
||||
.map(|b| instantiate_trait_ref(ccx, b, param_ty.to_ty(ccx.tcx)))
|
||||
.chain(unboxed_fn_ty_bounds)
|
||||
.collect();
|
||||
let opt_region_bound =
|
||||
astconv::compute_opt_region_bound(
|
||||
ccx.tcx, span, builtin_bounds, region_bounds.as_slice(),
|
||||
trait_bounds.as_slice());
|
||||
let region_bounds: Vec<ty::Region> =
|
||||
region_bounds.move_iter()
|
||||
.map(|r| ast_region_to_region(ccx.tcx, r))
|
||||
.collect();
|
||||
ty::ParamBounds {
|
||||
opt_region_bound: opt_region_bound,
|
||||
region_bounds: region_bounds,
|
||||
builtin_bounds: builtin_bounds,
|
||||
trait_bounds: trait_bounds,
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ fn test<
|
||||
'a,
|
||||
'b,
|
||||
A:IsStatic,
|
||||
B:Is<'a>+Is2<'b>, //~ ERROR ambiguous lifetime bound
|
||||
B:Is<'a>+Is2<'b>, // OK in a parameter, but not an object type.
|
||||
C:'b+Is<'a>+Is2<'b>,
|
||||
D:Is<'a>+Is2<'static>,
|
||||
E:'a+'b //~ ERROR only a single explicit lifetime bound is permitted
|
||||
E:'a+'b // OK in a parameter, but not an object type.
|
||||
>() { }
|
||||
|
||||
fn main() { }
|
||||
|
@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
// Various tests where we over type parameters with multiple lifetime
|
||||
// bounds.
|
||||
|
||||
trait SomeTrait { fn get(&self) -> int; }
|
||||
|
||||
fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'a> {
|
||||
// A outlives 'a AND 'b...
|
||||
box v as Box<SomeTrait+'a> // ...hence this type is safe.
|
||||
}
|
||||
|
||||
fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
|
||||
// A outlives 'a AND 'b...
|
||||
box v as Box<SomeTrait+'b> // ...hence this type is safe.
|
||||
}
|
||||
|
||||
fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
|
||||
// A outlives 'a AND 'b...but not 'c.
|
||||
box v as Box<SomeTrait+'a> //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
// 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.
|
||||
|
||||
// A test where we (successfully) close over a reference into
|
||||
// an object.
|
||||
|
||||
trait SomeTrait { fn get(&self) -> int; }
|
||||
|
||||
impl<'a> SomeTrait for &'a int {
|
||||
fn get(&self) -> int {
|
||||
**self
|
||||
}
|
||||
}
|
||||
|
||||
fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
|
||||
box v as Box<SomeTrait+'a>
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let i: int = 22;
|
||||
let obj = make_object(&i);
|
||||
assert_eq!(22, obj.get());
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user