diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 53203663bb16..0e888b39b851 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -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)))); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index cbf558b6b483..3ef1d15cf565 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -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); } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 535294a70a06..09912b545835 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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, + pub region_bounds: Vec, pub builtin_bounds: BuiltinBounds, pub trait_bounds: Vec> } @@ -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={}", diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 549f0daef811..48fa6f823b0e 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -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), } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 0af20cf2bcce..2f5b6e1fa03b 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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() { diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 37b77e872ca6..a8f2a8f6f1db 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -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()); diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 60e502786ab3..8bcbe4b79298 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -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(); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index c7b4a78492bb..dedb860967c3 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -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 = + 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, } diff --git a/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs b/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs index 40cff3e466b7..6b3c92e0028b 100644 --- a/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs +++ b/src/test/compile-fail/region-bounds-on-objects-and-type-parameters.rs @@ -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() { } diff --git a/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs new file mode 100644 index 000000000000..cec785c6e966 --- /dev/null +++ b/src/test/compile-fail/regions-close-over-type-parameter-multiple.rs @@ -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 or the MIT license +// , 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 { + // A outlives 'a AND 'b... + box v as Box // ...hence this type is safe. +} + +fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b... + box v as Box // ...hence this type is safe. +} + +fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { + // A outlives 'a AND 'b...but not 'c. + box v as Box //~ ERROR mismatched types +} + +fn main() { +} diff --git a/src/test/run-pass/regions-close-over-type-parameter-successfully.rs b/src/test/run-pass/regions-close-over-type-parameter-successfully.rs new file mode 100644 index 000000000000..5dba80ad38a1 --- /dev/null +++ b/src/test/run-pass/regions-close-over-type-parameter-successfully.rs @@ -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 or the MIT license +// , 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 { + box v as Box +} + +fn main() { + let i: int = 22; + let obj = make_object(&i); + assert_eq!(22, obj.get()); +}