auto merge of #15418 : pnkfelix/rust/fsk-revise-VecPerParamSpace, r=pcwalton

In my informal measurements, this brings the peak memory usage when
building librustc from 1662M down to 1502M.  Since 1662 - 1502 = 160,
this may not recover the entirety of the observed memory regression
(250M) from PR #14604.  (However, according to my local measurements,
the regression when building librustc was more like 209M, so perhaps
this will still recover the lions share of the lost memory.)
This commit is contained in:
bors 2014-07-05 08:31:48 +00:00
commit e0d3cf6b2a
16 changed files with 239 additions and 137 deletions

View file

@ -100,7 +100,7 @@ fn enc_vec_per_param_space<T>(w: &mut MemWriter,
op: |&mut MemWriter, &ctxt, &T|) {
for &space in subst::ParamSpace::all().iter() {
mywrite!(w, "[");
for t in v.get_vec(space).iter() {
for t in v.get_slice(space).iter() {
op(w, cx, t);
}
mywrite!(w, "]");

View file

@ -810,7 +810,7 @@ fn encode_vec_per_param_space<T>(ebml_w: &mut Encoder,
v: &subst::VecPerParamSpace<T>,
f: |&mut Encoder, &T|) {
for &space in subst::ParamSpace::all().iter() {
ebml_w.emit_from_vec(v.get_vec(space).as_slice(),
ebml_w.emit_from_vec(v.get_slice(space),
|ebml_w, n| Ok(f(ebml_w, n))).unwrap();
}
}

View file

@ -15,7 +15,6 @@ use middle::ty_fold;
use middle::ty_fold::{TypeFoldable, TypeFolder};
use util::ppaux::Repr;
use std::iter::Chain;
use std::mem;
use std::raw;
use std::slice::{Items, MutItems};
@ -191,8 +190,8 @@ impl Substs {
}
pub fn with_method_from(self, substs: &Substs) -> Substs {
self.with_method((*substs.types.get_vec(FnSpace)).clone(),
(*substs.regions().get_vec(FnSpace)).clone())
self.with_method(Vec::from_slice(substs.types.get_slice(FnSpace)),
Vec::from_slice(substs.regions().get_slice(FnSpace)))
}
pub fn with_method(self,
@ -261,13 +260,44 @@ impl ParamSpace {
*/
#[deriving(PartialEq, Eq, Clone, Hash, Encodable, Decodable)]
pub struct VecPerParamSpace<T> {
vecs: (Vec<T>, Vec<T>, Vec<T>)
// This was originally represented as a tuple with one Vec<T> for
// each variant of ParamSpace, and that remains the abstraction
// that it provides to its clients.
//
// Here is how the representation corresponds to the abstraction
// i.e. the "abstraction function" AF:
//
// AF(self) = (self.content.slice_to(self.type_limit),
// self.content.slice(self.type_limit, self.self_limit),
// self.content.slice_from(self.self_limit))
type_limit: uint,
self_limit: uint,
content: Vec<T>,
}
impl<T:Clone> VecPerParamSpace<T> {
pub fn push_all(&mut self, space: ParamSpace, values: &[T]) {
// FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
for t in values.iter() {
self.push(space, t.clone());
}
}
}
impl<T> VecPerParamSpace<T> {
fn limits(&self, space: ParamSpace) -> (uint, uint) {
match space {
TypeSpace => (0, self.type_limit),
SelfSpace => (self.type_limit, self.self_limit),
FnSpace => (self.self_limit, self.content.len()),
}
}
pub fn empty() -> VecPerParamSpace<T> {
VecPerParamSpace {
vecs: (Vec::new(), Vec::new(), Vec::new())
type_limit: 0,
self_limit: 0,
content: Vec::new()
}
}
@ -276,8 +306,15 @@ impl<T> VecPerParamSpace<T> {
}
pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
let type_limit = t.len();
let self_limit = t.len() + s.len();
let mut content = t;
content.push_all_move(s);
content.push_all_move(f);
VecPerParamSpace {
vecs: (t, s, f)
type_limit: type_limit,
self_limit: self_limit,
content: content,
}
}
@ -289,55 +326,98 @@ impl<T> VecPerParamSpace<T> {
result
}
/// Appends `value` to the vector associated with `space`.
///
/// Unlike the `push` method in `Vec`, this should not be assumed
/// to be a cheap operation (even when amortized over many calls).
pub fn push(&mut self, space: ParamSpace, value: T) {
self.get_mut_vec(space).push(value);
let (_, limit) = self.limits(space);
match space {
TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
SelfSpace => { self.self_limit += 1; }
FnSpace => {}
}
self.content.insert(limit, value);
}
pub fn pop(&mut self, space: ParamSpace) -> Option<T> {
let (start, limit) = self.limits(space);
if start == limit {
None
} else {
match space {
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
SelfSpace => { self.self_limit -= 1; }
FnSpace => {}
}
self.content.remove(limit - 1)
}
}
pub fn truncate(&mut self, space: ParamSpace, len: uint) {
// FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
while self.len(space) > len {
self.pop(space);
}
}
pub fn replace(&mut self, space: ParamSpace, elems: Vec<T>) {
// FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
self.truncate(space, 0);
for t in elems.move_iter() {
self.push(space, t);
}
}
pub fn get_self<'a>(&'a self) -> Option<&'a T> {
let v = self.get_vec(SelfSpace);
let v = self.get_slice(SelfSpace);
assert!(v.len() <= 1);
if v.len() == 0 { None } else { Some(v.get(0)) }
if v.len() == 0 { None } else { Some(&v[0]) }
}
pub fn len(&self, space: ParamSpace) -> uint {
self.get_vec(space).len()
self.get_slice(space).len()
}
pub fn get_vec<'a>(&'a self, space: ParamSpace) -> &'a Vec<T> {
self.vecs.get(space as uint).unwrap()
pub fn is_empty_in(&self, space: ParamSpace) -> bool {
self.len(space) == 0
}
pub fn get_mut_vec<'a>(&'a mut self, space: ParamSpace) -> &'a mut Vec<T> {
self.vecs.get_mut(space as uint).unwrap()
pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] {
let (start, limit) = self.limits(space);
self.content.slice(start, limit)
}
fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] {
let (start, limit) = self.limits(space);
self.content.mut_slice(start, limit)
}
pub fn opt_get<'a>(&'a self,
space: ParamSpace,
index: uint)
-> Option<&'a T> {
let v = self.get_vec(space);
if index < v.len() { Some(v.get(index)) } else { None }
let v = self.get_slice(space);
if index < v.len() { Some(&v[index]) } else { None }
}
pub fn get<'a>(&'a self, space: ParamSpace, index: uint) -> &'a T {
self.get_vec(space).get(index)
&self.get_slice(space)[index]
}
pub fn get_mut<'a>(&'a mut self,
space: ParamSpace,
index: uint) -> &'a mut T {
self.get_mut_vec(space).get_mut(index)
&mut self.get_mut_slice(space)[index]
}
pub fn iter<'a>(&'a self) -> Chain<Items<'a,T>,
Chain<Items<'a,T>,
Items<'a,T>>> {
let (ref r, ref s, ref f) = self.vecs;
r.iter().chain(s.iter().chain(f.iter()))
pub fn iter<'a>(&'a self) -> Items<'a,T> {
self.content.iter()
}
pub fn all_vecs(&self, pred: |&Vec<T>| -> bool) -> bool {
self.vecs.iter().all(pred)
pub fn all_vecs(&self, pred: |&[T]| -> bool) -> bool {
let spaces = [TypeSpace, SelfSpace, FnSpace];
spaces.iter().all(|&space| { pred(self.get_slice(space)) })
}
pub fn all(&self, pred: |&T| -> bool) -> bool {
@ -353,9 +433,13 @@ impl<T> VecPerParamSpace<T> {
}
pub fn map<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
VecPerParamSpace::new(self.vecs.ref0().iter().map(|p| pred(p)).collect(),
self.vecs.ref1().iter().map(|p| pred(p)).collect(),
self.vecs.ref2().iter().map(|p| pred(p)).collect())
// FIXME (#15418): this could avoid allocating the intermediate
// Vec's, but note that the values of type_limit and self_limit
// also need to be kept in sync during construction.
VecPerParamSpace::new(
self.get_slice(TypeSpace).iter().map(|p| pred(p)).collect(),
self.get_slice(SelfSpace).iter().map(|p| pred(p)).collect(),
self.get_slice(FnSpace).iter().map(|p| pred(p)).collect())
}
pub fn map_rev<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
@ -368,29 +452,46 @@ impl<T> VecPerParamSpace<T> {
* can be run to a fixed point
*/
let mut fns: Vec<U> = self.vecs.ref2().iter().rev().map(|p| pred(p)).collect();
let mut fns: Vec<U> = self.get_slice(FnSpace).iter().rev().map(|p| pred(p)).collect();
// NB: Calling foo.rev().map().rev() causes the calls to map
// to occur in the wrong order. This was somewhat surprising
// to me, though it makes total sense.
fns.reverse();
let mut selfs: Vec<U> = self.vecs.ref1().iter().rev().map(|p| pred(p)).collect();
let mut selfs: Vec<U> = self.get_slice(SelfSpace).iter().rev().map(|p| pred(p)).collect();
selfs.reverse();
let mut tys: Vec<U> = self.vecs.ref0().iter().rev().map(|p| pred(p)).collect();
let mut tys: Vec<U> = self.get_slice(TypeSpace).iter().rev().map(|p| pred(p)).collect();
tys.reverse();
VecPerParamSpace::new(tys, selfs, fns)
}
pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
self.vecs
// FIXME (#15418): this does two traversals when in principle
// one would suffice. i.e. change to use `move_iter`.
let VecPerParamSpace { type_limit, self_limit, content } = self;
let mut i = 0;
let (prefix, fn_vec) = content.partition(|_| {
let on_left = i < self_limit;
i += 1;
on_left
});
let mut i = 0;
let (type_vec, self_vec) = prefix.partition(|_| {
let on_left = i < type_limit;
i += 1;
on_left
});
(type_vec, self_vec, fn_vec)
}
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
-> VecPerParamSpace<T>
{
assert!(self.get_vec(space).is_empty());
*self.get_mut_vec(space) = vec;
assert!(self.is_empty_in(space));
self.replace(space, vec);
self
}
}

View file

@ -216,10 +216,8 @@ fn resolve_default_method_vtables(bcx: &Block,
bcx.tcx(), &param_substs, &impl_res);
// Now we pull any vtables for parameters on the actual method.
param_vtables
.get_mut_vec(subst::FnSpace)
.push_all(
impl_vtables.get_vec(subst::FnSpace).as_slice());
param_vtables.push_all(subst::FnSpace,
impl_vtables.get_slice(subst::FnSpace));
param_vtables
}

View file

@ -554,7 +554,7 @@ impl TypeMap {
// Maybe check that there is no self type here.
let tps = substs.types.get_vec(subst::TypeSpace);
let tps = substs.types.get_slice(subst::TypeSpace);
if tps.len() > 0 {
output.push_char('<');
@ -1377,9 +1377,9 @@ pub fn create_function_debug_context(cx: &CrateContext,
}
// Handle other generic parameters
let actual_types = param_substs.substs.types.get_vec(subst::FnSpace);
let actual_types = param_substs.substs.types.get_slice(subst::FnSpace);
for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
let actual_type = *actual_types.get(index);
let actual_type = actual_types[index];
// Add actual type name to <...> clause of function name
let actual_type_name = compute_debuginfo_type_name(cx,
actual_type,

View file

@ -209,7 +209,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
// avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_vec(subst::TypeSpace);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, an_enum, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
@ -266,7 +266,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
// in *after* placing it into the type cache. This prevents
// infinite recursion with recursive struct types.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_vec(subst::TypeSpace);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, a_struct, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
@ -305,7 +305,7 @@ pub enum named_ty { a_struct, an_enum }
pub fn llvm_type_name(cx: &CrateContext,
what: named_ty,
did: ast::DefId,
tps: &Vec<ty::t>)
tps: &[ty::t])
-> String
{
let name = match what {

View file

@ -981,7 +981,7 @@ impl Generics {
}
pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
!self.types.get_vec(space).is_empty()
!self.types.is_empty_in(space)
}
}
@ -4644,14 +4644,14 @@ pub fn construct_parameter_environment(
let mut types = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_types_from_defs(tcx, &mut types, space,
generics.types.get_vec(space));
generics.types.get_slice(space));
}
// map bound 'a => free 'a
let mut regions = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_region_params(&mut regions, space, free_id,
generics.regions.get_vec(space));
generics.regions.get_slice(space));
}
let free_substs = Substs {
@ -4666,7 +4666,7 @@ pub fn construct_parameter_environment(
let mut bounds = VecPerParamSpace::empty();
for &space in subst::ParamSpace::all().iter() {
push_bounds_from_defs(tcx, &mut bounds, space, &free_substs,
generics.types.get_vec(space));
generics.types.get_slice(space));
}
debug!("construct_parameter_environment: free_id={} \
@ -4684,7 +4684,7 @@ pub fn construct_parameter_environment(
fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
space: subst::ParamSpace,
free_id: ast::NodeId,
region_params: &Vec<RegionParameterDef>)
region_params: &[RegionParameterDef])
{
for r in region_params.iter() {
regions.push(space, ty::free_region_from_def(free_id, r));
@ -4694,7 +4694,7 @@ pub fn construct_parameter_environment(
fn push_types_from_defs(tcx: &ty::ctxt,
types: &mut subst::VecPerParamSpace<ty::t>,
space: subst::ParamSpace,
defs: &Vec<TypeParameterDef>) {
defs: &[TypeParameterDef]) {
for (i, def) in defs.iter().enumerate() {
let ty = ty::mk_param(tcx, space, i, def.def_id);
types.push(space, ty);
@ -4705,7 +4705,7 @@ pub fn construct_parameter_environment(
bounds: &mut subst::VecPerParamSpace<ParamBounds>,
space: subst::ParamSpace,
free_substs: &subst::Substs,
defs: &Vec<TypeParameterDef>) {
defs: &[TypeParameterDef]) {
for def in defs.iter() {
let b = (*def.bounds).subst(tcx, free_substs);
bounds.push(space, b);

View file

@ -203,7 +203,7 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
};
// Convert the type parameters supplied by the user.
let ty_param_defs = decl_generics.types.get_vec(TypeSpace);
let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
let supplied_ty_param_count = path.segments.iter().flat_map(|s| s.types.iter()).count();
let formal_ty_param_count = ty_param_defs.len();
let required_ty_param_count = ty_param_defs.iter()

View file

@ -264,7 +264,7 @@ fn construct_transformed_self_ty_for_object(
// The subst we get in has Err as the "Self" type. For an object
// type, we don't put any type into the Self paramspace, so let's
// make a copy of rcvr_substs that has the Self paramspace empty.
obj_substs.types.get_mut_vec(subst::SelfSpace).pop().unwrap();
obj_substs.types.pop(subst::SelfSpace).unwrap();
match method_ty.explicit_self {
ast::SelfStatic => {
@ -1133,7 +1133,7 @@ impl<'a> LookupContext<'a> {
let m_regions =
self.fcx.infcx().region_vars_for_defs(
self.span,
candidate.method_ty.generics.regions.get_vec(subst::FnSpace));
candidate.method_ty.generics.regions.get_slice(subst::FnSpace));
let all_substs = candidate.rcvr_substs.clone().with_method(m_types, m_regions);

View file

@ -917,8 +917,8 @@ fn compare_impl_method(tcx: &ty::ctxt,
return;
}
let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
.zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
.zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
// This code is best explained by example. Consider a trait:
//
@ -989,8 +989,8 @@ fn compare_impl_method(tcx: &ty::ctxt,
let trait_to_skol_substs =
trait_to_impl_substs
.subst(tcx, &impl_to_skol_substs)
.with_method(skol_tps.get_vec(subst::FnSpace).clone(),
skol_regions.get_vec(subst::FnSpace).clone());
.with_method(Vec::from_slice(skol_tps.get_slice(subst::FnSpace)),
Vec::from_slice(skol_regions.get_slice(subst::FnSpace)));
let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
@ -2002,7 +2002,7 @@ pub fn impl_self_ty(vcx: &VtableContext,
let ity = ty::lookup_item_type(tcx, did);
let (n_tps, rps, raw_ty) =
(ity.generics.types.len(subst::TypeSpace),
ity.generics.regions.get_vec(subst::TypeSpace),
ity.generics.regions.get_slice(subst::TypeSpace),
ity.ty);
let rps = vcx.infcx.region_vars_for_defs(span, rps);
@ -4126,12 +4126,10 @@ pub fn instantiate_path(fcx: &FnCtxt,
// a problem.
for &space in ParamSpace::all().iter() {
adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
assert_eq!(substs.types.get_vec(space).len(),
type_defs.get_vec(space).len());
assert_eq!(substs.types.len(space), type_defs.len(space));
adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
assert_eq!(substs.regions().get_vec(space).len(),
region_defs.get_vec(space).len());
assert_eq!(substs.regions().len(space), region_defs.len(space));
}
fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
@ -4183,8 +4181,8 @@ pub fn instantiate_path(fcx: &FnCtxt,
*/
{
let type_count = type_defs.get_vec(space).len();
assert_eq!(substs.types.get_vec(space).len(), 0);
let type_count = type_defs.len(space);
assert_eq!(substs.types.len(space), 0);
for (i, &typ) in segment.types.iter().enumerate() {
let t = fcx.to_ty(&*typ);
if i < type_count {
@ -4198,14 +4196,14 @@ pub fn instantiate_path(fcx: &FnCtxt,
but found {} parameter(s)",
type_count,
segment.types.len()).as_slice());
substs.types.get_mut_vec(space).truncate(0);
substs.types.truncate(space, 0);
}
}
}
{
let region_count = region_defs.get_vec(space).len();
assert_eq!(substs.regions().get_vec(space).len(), 0);
let region_count = region_defs.len(space);
assert_eq!(substs.regions().len(space), 0);
for (i, lifetime) in segment.lifetimes.iter().enumerate() {
let r = ast_region_to_region(fcx.tcx(), lifetime);
if i < region_count {
@ -4218,7 +4216,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
expected {} parameter(s) but found {} parameter(s)",
region_count,
segment.lifetimes.len()).as_slice());
substs.mut_regions().get_mut_vec(space).truncate(0);
substs.mut_regions().truncate(space, 0);
}
}
}
@ -4231,8 +4229,8 @@ pub fn instantiate_path(fcx: &FnCtxt,
defs: &VecPerParamSpace<ty::TypeParameterDef>,
substs: &mut Substs)
{
let provided_len = substs.types.get_vec(space).len();
let desired = defs.get_vec(space).as_slice();
let provided_len = substs.types.len(space);
let desired = defs.get_slice(space);
let required_len = desired.iter()
.take_while(|d| d.default.is_none())
.count();
@ -4252,8 +4250,8 @@ pub fn instantiate_path(fcx: &FnCtxt,
// Nothing specified at all: supply inference variables for
// everything.
if provided_len == 0 {
let provided = substs.types.get_mut_vec(space);
*provided = fcx.infcx().next_ty_vars(desired.len());
substs.types.replace(space,
fcx.infcx().next_ty_vars(desired.len()));
return;
}
@ -4270,8 +4268,8 @@ pub fn instantiate_path(fcx: &FnCtxt,
qualifier,
required_len,
provided_len).as_slice());
let provided = substs.types.get_mut_vec(space);
*provided = Vec::from_elem(desired.len(), ty::mk_err());
substs.types.replace(space,
Vec::from_elem(desired.len(), ty::mk_err()));
return;
}
@ -4287,7 +4285,7 @@ pub fn instantiate_path(fcx: &FnCtxt,
let default = default.subst_spanned(fcx.tcx(), substs, Some(span));
substs.types.push(space, default);
}
assert_eq!(substs.types.get_vec(space).len(), desired.len());
assert_eq!(substs.types.len(space), desired.len());
debug!("Final substs: {}", substs.repr(fcx.tcx()));
}
@ -4299,20 +4297,22 @@ pub fn instantiate_path(fcx: &FnCtxt,
defs: &VecPerParamSpace<ty::RegionParameterDef>,
substs: &mut Substs)
{
let provided = substs.mut_regions().get_mut_vec(space);
let desired = defs.get_vec(space);
let provided_len = substs.mut_regions().len(space);
let desired = defs.get_slice(space);
// Enforced by `push_explicit_parameters_from_segment_to_substs()`.
assert!(provided.len() <= desired.len());
assert!(provided_len <= desired.len());
// If nothing was provided, just use inference variables.
if provided.len() == 0 {
*provided = fcx.infcx().region_vars_for_defs(span, desired);
if provided_len == 0 {
substs.mut_regions().replace(
space,
fcx.infcx().region_vars_for_defs(span, desired));
return;
}
// If just the right number were provided, everybody is happy.
if provided.len() == desired.len() {
if provided_len == desired.len() {
return;
}
@ -4325,9 +4325,11 @@ pub fn instantiate_path(fcx: &FnCtxt,
expected {} parameter(s) \
but found {} parameter(s)",
desired.len(),
provided.len()).as_slice());
provided_len).as_slice());
*provided = fcx.infcx().region_vars_for_defs(span, desired);
substs.mut_regions().replace(
space,
fcx.infcx().region_vars_for_defs(span, desired));
}
}

View file

@ -735,12 +735,12 @@ pub fn make_substs_for_receiver_types(tcx: &ty::ctxt,
*/
let meth_tps: Vec<ty::t> =
method.generics.types.get_vec(subst::FnSpace)
method.generics.types.get_slice(subst::FnSpace)
.iter()
.map(|def| ty::mk_param_from_def(tcx, def))
.collect();
let meth_regions: Vec<ty::Region> =
method.generics.regions.get_vec(subst::FnSpace)
method.generics.regions.get_slice(subst::FnSpace)
.iter()
.map(|def| ty::ReEarlyBound(def.def_id.node, def.space,
def.index, def.name))
@ -767,10 +767,12 @@ fn subst_receiver_types_in_method_ty(tcx: &ty::ctxt,
// replace the type parameters declared on the trait with those
// from the impl
for &space in [subst::TypeSpace, subst::SelfSpace].iter() {
*method_generics.types.get_mut_vec(space) =
impl_poly_type.generics.types.get_vec(space).clone();
*method_generics.regions.get_mut_vec(space) =
impl_poly_type.generics.regions.get_vec(space).clone();
method_generics.types.replace(
space,
Vec::from_slice(impl_poly_type.generics.types.get_slice(space)));
method_generics.regions.replace(
space,
Vec::from_slice(impl_poly_type.generics.regions.get_slice(space)));
}
debug!("subst_receiver_types_in_method_ty: method_generics={}",

View file

@ -115,32 +115,30 @@ pub trait Combine {
let mut substs = subst::Substs::empty();
for &space in subst::ParamSpace::all().iter() {
let a_tps = a_subst.types.get_vec(space);
let b_tps = b_subst.types.get_vec(space);
let tps = if_ok!(self.tps(space,
a_tps.as_slice(),
b_tps.as_slice()));
let a_tps = a_subst.types.get_slice(space);
let b_tps = b_subst.types.get_slice(space);
let tps = if_ok!(self.tps(space, a_tps, b_tps));
let a_regions = a_subst.regions().get_vec(space);
let b_regions = b_subst.regions().get_vec(space);
let r_variances = variances.regions.get_vec(space);
let a_regions = a_subst.regions().get_slice(space);
let b_regions = b_subst.regions().get_slice(space);
let r_variances = variances.regions.get_slice(space);
let regions = if_ok!(relate_region_params(self,
item_def_id,
r_variances,
a_regions,
b_regions));
*substs.types.get_mut_vec(space) = tps;
*substs.mut_regions().get_mut_vec(space) = regions;
substs.types.replace(space, tps);
substs.mut_regions().replace(space, regions);
}
return Ok(substs);
fn relate_region_params<C:Combine>(this: &C,
item_def_id: ast::DefId,
variances: &Vec<ty::Variance>,
a_rs: &Vec<ty::Region>,
b_rs: &Vec<ty::Region>)
variances: &[ty::Variance],
a_rs: &[ty::Region],
b_rs: &[ty::Region])
-> cres<Vec<ty::Region>>
{
let tcx = this.infcx().tcx;
@ -160,9 +158,9 @@ pub trait Combine {
assert_eq!(num_region_params, b_rs.len());
let mut rs = vec!();
for i in range(0, num_region_params) {
let a_r = *a_rs.get(i);
let b_r = *b_rs.get(i);
let variance = *variances.get(i);
let a_r = a_rs[i];
let b_r = b_rs[i];
let variance = variances[i];
let r = match variance {
ty::Invariant => {
eq_regions(this, a_r, b_r)

View file

@ -624,7 +624,7 @@ impl<'a> InferCtxt<'a> {
pub fn region_vars_for_defs(&self,
span: Span,
defs: &Vec<ty::RegionParameterDef>)
defs: &[ty::RegionParameterDef])
-> Vec<ty::Region> {
defs.iter()
.map(|d| self.next_region_var(EarlyBoundRegion(span, d.name)))
@ -647,7 +647,7 @@ impl<'a> InferCtxt<'a> {
assert!(generics.regions.len(subst::FnSpace) == 0);
let type_parameter_count = generics.types.len(subst::TypeSpace);
let region_param_defs = generics.regions.get_vec(subst::TypeSpace);
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
let regions = self.region_vars_for_defs(span, region_param_defs);
let type_parameters = self.next_ty_vars(type_parameter_count);
subst::Substs::new_type(type_parameters, regions)

View file

@ -749,15 +749,15 @@ impl<'a> ConstraintContext<'a> {
// All type parameters on enums and structs should be
// in the TypeSpace.
assert!(generics.types.get_vec(subst::SelfSpace).is_empty());
assert!(generics.types.get_vec(subst::FnSpace).is_empty());
assert!(generics.regions.get_vec(subst::SelfSpace).is_empty());
assert!(generics.regions.get_vec(subst::FnSpace).is_empty());
assert!(generics.types.is_empty_in(subst::SelfSpace));
assert!(generics.types.is_empty_in(subst::FnSpace));
assert!(generics.regions.is_empty_in(subst::SelfSpace));
assert!(generics.regions.is_empty_in(subst::FnSpace));
self.add_constraints_from_substs(
def_id,
generics.types.get_vec(subst::TypeSpace),
generics.regions.get_vec(subst::TypeSpace),
generics.types.get_slice(subst::TypeSpace),
generics.regions.get_slice(subst::TypeSpace),
substs,
variance);
}
@ -768,22 +768,22 @@ impl<'a> ConstraintContext<'a> {
// Traits DO have a Self type parameter, but it is
// erased from object types.
assert!(!generics.types.get_vec(subst::SelfSpace).is_empty() &&
substs.types.get_vec(subst::SelfSpace).is_empty());
assert!(!generics.types.is_empty_in(subst::SelfSpace) &&
substs.types.is_empty_in(subst::SelfSpace));
// Traits never declare region parameters in the self
// space.
assert!(generics.regions.get_vec(subst::SelfSpace).is_empty());
assert!(generics.regions.is_empty_in(subst::SelfSpace));
// Traits never declare type/region parameters in the
// fn space.
assert!(generics.types.get_vec(subst::FnSpace).is_empty());
assert!(generics.regions.get_vec(subst::FnSpace).is_empty());
assert!(generics.types.is_empty_in(subst::FnSpace));
assert!(generics.regions.is_empty_in(subst::FnSpace));
self.add_constraints_from_substs(
def_id,
generics.types.get_vec(subst::TypeSpace),
generics.regions.get_vec(subst::TypeSpace),
generics.types.get_slice(subst::TypeSpace),
generics.regions.get_slice(subst::TypeSpace),
substs,
variance);
}
@ -832,8 +832,8 @@ impl<'a> ConstraintContext<'a> {
/// object, etc) appearing in a context with ambient variance `variance`
fn add_constraints_from_substs(&mut self,
def_id: ast::DefId,
type_param_defs: &Vec<ty::TypeParameterDef>,
region_param_defs: &Vec<ty::RegionParameterDef>,
type_param_defs: &[ty::TypeParameterDef],
region_param_defs: &[ty::RegionParameterDef],
substs: &subst::Substs,
variance: VarianceTermPtr<'a>) {
debug!("add_constraints_from_substs(def_id={:?})", def_id);

View file

@ -449,8 +449,8 @@ pub fn parameterized(cx: &ctxt,
}
}
let tps = substs.types.get_vec(subst::TypeSpace);
let ty_params = generics.types.get_vec(subst::TypeSpace);
let tps = substs.types.get_slice(subst::TypeSpace);
let ty_params = generics.types.get_slice(subst::TypeSpace);
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
let num_defaults = if has_defaults && !cx.sess.verbose() {
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
@ -468,7 +468,7 @@ pub fn parameterized(cx: &ctxt,
}
if cx.sess.verbose() {
for t in substs.types.get_vec(subst::SelfSpace).iter() {
for t in substs.types.get_slice(subst::SelfSpace).iter() {
strs.push(format!("for {}", t.repr(cx)));
}
}
@ -598,9 +598,9 @@ impl Repr for subst::Substs {
impl<T:Repr> Repr for subst::VecPerParamSpace<T> {
fn repr(&self, tcx: &ctxt) -> String {
format!("[{};{};{}]",
self.get_vec(subst::TypeSpace).repr(tcx),
self.get_vec(subst::SelfSpace).repr(tcx),
self.get_vec(subst::FnSpace).repr(tcx))
self.get_slice(subst::TypeSpace).repr(tcx),
self.get_slice(subst::SelfSpace).repr(tcx),
self.get_slice(subst::FnSpace).repr(tcx))
}
}

View file

@ -505,11 +505,12 @@ impl Clean<TyParamBound> for ast::TyParamBound {
}
fn external_path(name: &str, substs: &subst::Substs) -> Path {
let lifetimes = substs.regions().get_vec(subst::TypeSpace)
let lifetimes = substs.regions().get_slice(subst::TypeSpace)
.iter()
.filter_map(|v| v.clean())
.collect();
let types = substs.types.get_vec(subst::TypeSpace).clean();
let types = Vec::from_slice(substs.types.get_slice(subst::TypeSpace));
let types = types.clean();
Path {
global: false,
segments: vec![PathSegment {
@ -674,8 +675,8 @@ impl Clean<Generics> for ty::Generics {
// is implicit.
let space = {
if !self.types.get_vec(subst::FnSpace).is_empty() ||
!self.regions.get_vec(subst::FnSpace).is_empty()
if !self.types.is_empty_in(subst::FnSpace) ||
!self.regions.is_empty_in(subst::FnSpace)
{
subst::FnSpace
} else {
@ -684,8 +685,8 @@ impl Clean<Generics> for ty::Generics {
};
Generics {
type_params: self.types.get_vec(space).clean(),
lifetimes: self.regions.get_vec(space).clean(),
type_params: Vec::from_slice(self.types.get_slice(space)).clean(),
lifetimes: Vec::from_slice(self.regions.get_slice(space)).clean(),
}
}
}