rollup merge of #17310 : nikomatsakis/type-bounds-generalize-to-multiple-object-bounds

This commit is contained in:
Alex Crichton 2014-09-17 08:49:39 -07:00
commit 2278f9575d
11 changed files with 81 additions and 18 deletions

View file

@ -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))));

View file

@ -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);
}

View file

@ -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,
@ -4865,7 +4866,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={}",

View file

@ -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),
}

View file

@ -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() {

View file

@ -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());

View file

@ -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();

View file

@ -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,
}

View file

@ -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() { }

View file

@ -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() {
}

View file

@ -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());
}