rollup merge of #17310 : nikomatsakis/type-bounds-generalize-to-multiple-object-bounds
This commit is contained in:
commit
2278f9575d
11 changed files with 81 additions and 18 deletions
|
|
@ -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,
|
||||
|
|
@ -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={}",
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Add a link
Reference in a new issue