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:
commit
e0d3cf6b2a
16 changed files with 239 additions and 137 deletions
|
|
@ -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, "]");
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,10 +216,8 @@ fn resolve_default_method_vtables(bcx: &Block,
|
|||
bcx.tcx(), ¶m_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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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={}",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue