diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 2a8594c59a83..37366f38974a 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_) if self.tcx.trait_of_item(def.def_id()).is_some() => { if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) { - match substs.substs.types[0].sty { + match substs.substs.type_at(0).sty { TyEnum(tyid, _) | TyStruct(tyid, _) => { self.check_def_id(tyid.did) } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d6f263fcebeb..10112e508455 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -232,8 +232,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) { self_match_impls.push(def_id); - if trait_ref.substs.types[1..].iter() - .zip(&impl_trait_ref.substs.types[1..]) + if trait_ref.substs.types().skip(1) + .zip(impl_trait_ref.substs.types().skip(1)) .all(|(u,v)| self.fuzzy_match_tys(u, v)) { fuzzy_match_impls.push(def_id); @@ -738,8 +738,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Predicate::Trait(ref data) => { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); - let all_types = &trait_ref.substs().types; - if all_types.references_error() { + if predicate.references_error() { } else { // Typically, this ambiguity should only happen if // there are unresolved type inference variables diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 837e33b3e7fc..76477d3df936 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -142,7 +142,7 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { // Auto trait obligations on `impl Trait`. if tcx.trait_has_default_impl(predicate.def_id()) { let substs = predicate.skip_binder().trait_ref.substs; - if substs.types.len() == 1 && substs.regions.is_empty() { + if substs.types().count() == 1 && substs.regions().next().is_none() { if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty { return true; } @@ -440,7 +440,6 @@ fn trait_ref_type_vars<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 't { t.skip_binder() // ok b/c this check doesn't care about regions .input_types() - .iter() .map(|t| selcx.infcx().resolve_type_vars_if_possible(t)) .filter(|t| t.has_infer_types()) .flat_map(|t| t.walk()) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 25d2df8fdedb..219d52004676 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -145,7 +145,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match predicate { ty::Predicate::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.0.trait_ref.input_types()[1..].iter().any(|t| t.has_self_ty()) + data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty()) } ty::Predicate::Projection(..) | ty::Predicate::WellFormed(..) | diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 9ea738bd326e..f2ea14f17961 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -644,8 +644,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // This suffices to allow chains like `FnMut` implemented in // terms of `Fn` etc, but we could probably make this more // precise still. - let input_types = stack.fresh_trait_ref.0.input_types(); - let unbound_input_types = input_types.iter().any(|ty| ty.is_fresh()); + let unbound_input_types = stack.fresh_trait_ref.input_types().any(|ty| ty.is_fresh()); if unbound_input_types && self.intercrate { debug!("evaluate_stack({:?}) --> unbound argument, intercrate --> ambiguous", stack.fresh_trait_ref); @@ -1064,9 +1063,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match *candidate { Ok(Some(_)) | Err(_) => true, - Ok(None) => { - cache_fresh_trait_pred.0.trait_ref.substs.types.has_infer_types() - } + Ok(None) => cache_fresh_trait_pred.has_infer_types() } } @@ -1603,7 +1600,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } }; - let target = obligation.predicate.skip_binder().input_types()[1]; + let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1); debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target); @@ -1936,7 +1933,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // for `PhantomData`, we pass `T` ty::TyStruct(def, substs) if def.is_phantom_data() => { - substs.types.to_vec() + substs.types().cloned().collect() } ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { @@ -2180,12 +2177,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self_ty.sty { ty::TyTrait(ref data) => { // OK to skip the binder, it is reintroduced below - let input_types = data.principal.skip_binder().input_types(); + let input_types = data.principal.input_types(); let assoc_types = data.projection_bounds.iter() .map(|pb| pb.skip_binder().ty); - let all_types: Vec<_> = input_types.iter().cloned() - .chain(assoc_types) - .collect(); + let all_types: Vec<_> = input_types.cloned() + .chain(assoc_types) + .collect(); // reintroduce the two binding levels we skipped, then flatten into one let all_types = ty::Binder(ty::Binder(all_types)); @@ -2476,7 +2473,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // regions here. See the comment there for more details. let source = self.infcx.shallow_resolve( tcx.no_late_bound_regions(&obligation.self_ty()).unwrap()); - let target = obligation.predicate.skip_binder().input_types()[1]; + let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1); let target = self.infcx.shallow_resolve(target); debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", @@ -2585,7 +2582,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else { return Err(Unimplemented); }; - let mut ty_params = BitVector::new(substs_a.types.len()); + let mut ty_params = BitVector::new(substs_a.types().count()); let mut found = false; for ty in field.walk() { if let ty::TyParam(p) = ty.sty { @@ -2601,14 +2598,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // TyError and ensure they do not affect any other fields. // This could be checked after type collection for any struct // with a potentially unsized trailing field. - let types = substs_a.types.iter().enumerate().map(|(i, ty)| { + let types = substs_a.types().enumerate().map(|(i, ty)| { if ty_params.contains(i) { tcx.types.err } else { ty } }).collect(); - let substs = Substs::new(tcx, types, substs_a.regions.clone()); + let substs = Substs::new(tcx, types, substs_a.regions().cloned().collect()); for &ty in fields.split_last().unwrap().1 { if ty.subst(tcx, substs).references_error() { return Err(Unimplemented); @@ -2621,14 +2618,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check that the source structure with the target's // type parameters is a subtype of the target. - let types = substs_a.types.iter().enumerate().map(|(i, ty)| { + let types = substs_a.types().enumerate().map(|(i, ty)| { if ty_params.contains(i) { - substs_b.types[i] + substs_b.type_at(i) } else { ty } }).collect(); - let substs = Substs::new(tcx, types, substs_a.regions.clone()); + let substs = Substs::new(tcx, types, substs_a.regions().cloned().collect()); let new_struct = tcx.mk_struct(def, substs); let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = @@ -2753,7 +2750,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // substitution if we find that any of the input types, when // simplified, do not match. - obligation.predicate.0.input_types().iter() + obligation.predicate.skip_binder().input_types() .zip(impl_trait_ref.input_types()) .any(|(&obligation_ty, &impl_ty)| { let simplified_obligation_ty = diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 3501dd484608..2cae19d95ccb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1152,7 +1152,7 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { impl_interners!('tcx, type_list: mk_type_list(Vec>, keep_local) -> [Ty<'tcx>], substs: mk_substs(Substs<'tcx>, |substs: &Substs| { - keep_local(&substs.types) || keep_local(&substs.regions) + substs.types().any(keep_local) || substs.regions().any(keep_local) }) -> Substs<'tcx>, bare_fn: mk_bare_fn(BareFnTy<'tcx>, |fty: &BareFnTy| { keep_local(&fty.sig) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index c6c37296e9e1..c7300946eade 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -208,8 +208,11 @@ impl FlagComputation { } fn add_substs(&mut self, substs: &Substs) { - self.add_tys(&substs.types); - for &r in &substs.regions { + for &ty in substs.types() { + self.add_ty(ty); + } + + for &r in substs.regions() { self.add_region(r); } } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 1dcc623d3655..62bd30e25559 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -264,7 +264,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match self_ty.sty { ty::TyStruct(adt_def, substs) | ty::TyEnum(adt_def, substs) => { - if substs.types.is_empty() { // ignore regions + if substs.types().next().is_none() { // ignore regions self.push_item_path(buffer, adt_def.did); } else { buffer.push(&format!("<{}>", self_ty)); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 6c82157c8ca7..571ad3ca8b9a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -951,7 +951,6 @@ impl<'tcx> TraitPredicate<'tcx> { // leads to more recompilation. let def_ids: Vec<_> = self.input_types() - .iter() .flat_map(|t| t.walk()) .filter_map(|t| match t.sty { ty::TyStruct(adt_def, _) | @@ -964,8 +963,8 @@ impl<'tcx> TraitPredicate<'tcx> { DepNode::TraitSelect(self.def_id(), def_ids) } - pub fn input_types(&self) -> &[Ty<'tcx>] { - &self.trait_ref.substs.types + pub fn input_types(&self) -> slice::Iter> { + self.trait_ref.input_types() } pub fn self_ty(&self) -> Ty<'tcx> { @@ -1107,7 +1106,7 @@ impl<'tcx> Predicate<'tcx> { pub fn walk_tys(&self) -> IntoIter> { let vec: Vec<_> = match *self { ty::Predicate::Trait(ref data) => { - data.0.trait_ref.input_types().to_vec() + data.skip_binder().input_types().cloned().collect() } ty::Predicate::Rfc1592(ref data) => { return data.walk_tys() @@ -1123,8 +1122,7 @@ impl<'tcx> Predicate<'tcx> { } ty::Predicate::Projection(ref data) => { let trait_inputs = data.0.projection_ty.trait_ref.input_types(); - trait_inputs.iter() - .cloned() + trait_inputs.cloned() .chain(Some(data.0.ty)) .collect() } @@ -1206,15 +1204,15 @@ impl<'tcx> TraitRef<'tcx> { } pub fn self_ty(&self) -> Ty<'tcx> { - self.substs.types[0] + self.substs.type_at(0) } - pub fn input_types(&self) -> &[Ty<'tcx>] { + pub fn input_types(&self) -> slice::Iter> { // Select only the "input types" from a trait-reference. For // now this is all the types that appear in the // trait-reference, but it should eventually exclude // associated types. - &self.substs.types + self.substs.types() } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 8975a799be14..481e8c97974a 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -147,14 +147,12 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, { let tcx = relation.tcx(); - let types = a_subst.types.iter().enumerate().map(|(i, a_ty)| { - let b_ty = &b_subst.types[i]; + let types = a_subst.types().zip(b_subst.types()).enumerate().map(|(i, (a_ty, b_ty))| { let variance = variances.map_or(ty::Invariant, |v| v.types[i]); relation.relate_with_variance(variance, a_ty, b_ty) }).collect::>()?; - let regions = a_subst.regions.iter().enumerate().map(|(i, a_r)| { - let b_r = &b_subst.regions[i]; + let regions = a_subst.regions().zip(b_subst.regions()).enumerate().map(|(i, (a_r, b_r))| { let variance = variances.map_or(ty::Invariant, |v| v.regions[i]); relation.relate_with_variance(variance, a_r, b_r) }).collect::>()?; diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index f7c4b9938c27..9ccf817a5362 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -9,7 +9,6 @@ // except according to those terms. use infer::type_variable; -use ty::subst::Substs; use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -692,22 +691,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Region { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let types = self.types.fold_with(folder); - let regions = self.regions.fold_with(folder); - Substs::new(folder.tcx(), types, regions) - } - - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_substs(self) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.types.visit_with(visitor) || self.regions.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ClosureSubsts { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 8aa81cc4743c..3f8d55b4634e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -19,8 +19,9 @@ use util::common::ErrorReported; use collections::enum_set::{self, EnumSet, CLike}; use std::fmt; -use std::ops; use std::mem; +use std::ops; +use std::slice; use syntax::abi; use syntax::ast::{self, Name}; use syntax::parse::token::keywords; @@ -335,7 +336,7 @@ impl<'tcx> PolyTraitRef<'tcx> { self.0.substs } - pub fn input_types(&self) -> &[Ty<'tcx>] { + pub fn input_types(&self) -> slice::Iter> { // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> self.0.input_types() } @@ -360,12 +361,12 @@ pub struct ExistentialTraitRef<'tcx> { } impl<'tcx> ExistentialTraitRef<'tcx> { - pub fn input_types(&self) -> &[Ty<'tcx>] { + pub fn input_types(&self) -> slice::Iter>{ // Select only the "input types" from a trait-reference. For // now this is all the types that appear in the // trait-reference, but it should eventually exclude // associated types. - &self.substs.types + self.substs.types() } } @@ -376,7 +377,7 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { self.0.def_id } - pub fn input_types(&self) -> &[Ty<'tcx>] { + pub fn input_types(&self) -> slice::Iter> { // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> self.0.input_types() } @@ -1213,19 +1214,19 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } TyTrait(ref obj) => { let mut v = vec![obj.region_bound]; - v.extend_from_slice(&obj.principal.skip_binder().substs.regions); + v.extend(obj.principal.skip_binder().substs.regions()); v } TyEnum(_, substs) | TyStruct(_, substs) | TyAnon(_, substs) => { - substs.regions.to_vec() + substs.regions().cloned().collect() } TyClosure(_, ref substs) => { - substs.func_substs.regions.to_vec() + substs.func_substs.regions().cloned().collect() } TyProjection(ref data) => { - data.trait_ref.substs.regions.to_vec() + data.trait_ref.substs.regions().cloned().collect() } TyFnDef(..) | TyFnPtr(_) | diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index e1a19a7b7992..96f4bda361b6 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -13,18 +13,20 @@ use middle::cstore; use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; -use ty::fold::{TypeFoldable, TypeFolder}; +use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use serialize::{Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; +use std::slice; + /////////////////////////////////////////////////////////////////////////// /// A substitution mapping type/region parameters to new values. -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct Substs<'tcx> { - pub types: Vec>, - pub regions: Vec, + types: Vec>, + regions: Vec, } impl<'a, 'gcx, 'tcx> Substs<'tcx> { @@ -104,12 +106,34 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { self.regions.is_empty() && self.types.is_empty() } - pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> { - self.types[ty_param_def.index as usize] + #[inline] + pub fn types(&self) -> slice::Iter> { + self.types.iter() } + #[inline] + pub fn regions(&self) -> slice::Iter { + self.regions.iter() + } + + #[inline] + pub fn type_at(&self, i: usize) -> Ty<'tcx> { + self.types[i] + } + + #[inline] + pub fn region_at(&self, i: usize) -> ty::Region { + self.regions[i] + } + + #[inline] + pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> { + self.type_at(ty_param_def.index as usize) + } + + #[inline] pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region { - self.regions[def.index as usize] + self.region_at(def.index as usize) } /// Transform from substitutions for a child of `source_ancestor` @@ -130,6 +154,22 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + let types = self.types.fold_with(folder); + let regions = self.regions.fold_with(folder); + Substs::new(folder.tcx(), types, regions) + } + + fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + folder.fold_substs(self) + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.types.visit_with(visitor) || self.regions.visit_with(visitor) + } +} + impl<'tcx> Encodable for &'tcx Substs<'tcx> { fn encode(&self, s: &mut S) -> Result<(), S::Error> { cstore::tls::with_encoding_context(s, |ecx, rbml_w| { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 51710c13a7de..641dfa67c5b9 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -693,10 +693,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { return false; } - let types_a = &substs_a.types; - let types_b = &substs_b.types; - - types_a.iter().zip(types_b).all(|(&a, &b)| same_type(a, b)) + substs_a.types().zip(substs_b.types()).all(|(&a, &b)| same_type(a, b)) } _ => { a == b diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 8a9ee45351df..5a94ba3cf6cd 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -79,7 +79,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { stack.push(mt.ty); } ty::TyProjection(ref data) => { - push_reversed(stack, &data.trait_ref.substs.types); + push_reversed(stack, data.trait_ref.substs.types()); } ty::TyTrait(ref obj) => { push_reversed(stack, obj.principal.input_types()); @@ -90,17 +90,17 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { ty::TyEnum(_, ref substs) | ty::TyStruct(_, ref substs) | ty::TyAnon(_, ref substs) => { - push_reversed(stack, &substs.types); + push_reversed(stack, substs.types()); } ty::TyClosure(_, ref substs) => { - push_reversed(stack, &substs.func_substs.types); - push_reversed(stack, &substs.upvar_tys); + push_reversed(stack, substs.func_substs.types()); + push_reversed(stack, substs.upvar_tys); } - ty::TyTuple(ref ts) => { + ty::TyTuple(ts) => { push_reversed(stack, ts); } ty::TyFnDef(_, substs, ref ft) => { - push_reversed(stack, &substs.types); + push_reversed(stack, substs.types()); push_sig_subtypes(stack, &ft.sig); } ty::TyFnPtr(ref ft) => { @@ -114,14 +114,17 @@ fn push_sig_subtypes<'tcx>(stack: &mut Vec>, sig: &ty::PolyFnSig<'tcx>) push_reversed(stack, &sig.0.inputs); } -fn push_reversed<'tcx>(stack: &mut Vec>, tys: &[Ty<'tcx>]) { +fn push_reversed<'a, 'tcx: 'a, I>(stack: &mut Vec>, tys: I) + where I: IntoIterator>, + I::IntoIter: DoubleEndedIterator +{ // We push slices on the stack in reverse order so as to // maintain a pre-order traversal. As of the time of this // writing, the fact that the traversal is pre-order is not // known to be significant to any code, but it seems like the // natural order one would expect (basically, the order of the // types as they are written). - for &ty in tys.iter().rev() { + for &ty in tys.into_iter().rev() { stack.push(ty); } } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 54b19362b1d8..e1a39e6957a4 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -260,8 +260,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); self.out.extend( - trait_ref.substs.types - .iter() + trait_ref.substs.types() .filter(|ty| !ty.has_escaping_regions()) .map(|ty| traits::Obligation::new(cause.clone(), ty::Predicate::WellFormed(ty)))); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 02ad8fb7033e..c75fbf9579f5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -22,6 +22,8 @@ use ty::fold::{TypeFolder, TypeVisitor}; use std::cell::Cell; use std::fmt; +use std::usize; + use syntax::abi::Abi; use syntax::parse::token; use syntax::ast::CRATE_NODE_ID; @@ -80,15 +82,17 @@ pub fn parameterized(f: &mut fmt::Formatter, verbose = tcx.sess.verbose(); has_self = generics.has_self; + let mut child_types = 0; if let Some(def_id) = generics.parent { // Methods. assert_eq!(ns, Ns::Value); + child_types = generics.types.len(); generics = tcx.lookup_generics(def_id); num_regions = generics.regions.len(); num_types = generics.types.len(); if has_self { - write!(f, "<{} as ", substs.types[0])?; + write!(f, "<{} as ", substs.type_at(0))?; } item_name = Some(tcx.item_name(did)); @@ -107,8 +111,8 @@ pub fn parameterized(f: &mut fmt::Formatter, if !verbose { if generics.types.last().map_or(false, |def| def.default.is_some()) { if let Some(substs) = tcx.lift(&substs) { - let tps = &substs.types[..num_types]; - for (def, actual) in generics.types.iter().zip(tps).rev() { + let tps = substs.types().rev().skip(child_types); + for (def, actual) in generics.types.iter().rev().zip(tps) { if def.default.subst(tcx, substs) != Some(actual) { break; } @@ -124,7 +128,7 @@ pub fn parameterized(f: &mut fmt::Formatter, if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.types[1].sty { + if let TyTuple(ref args) = substs.type_at(1).sty { return fn_sig(f, args, false, projection_ty); } } @@ -139,13 +143,15 @@ pub fn parameterized(f: &mut fmt::Formatter, } }; - let print_regions = |f: &mut fmt::Formatter, start: &str, regions: &[ty::Region]| { + let print_regions = |f: &mut fmt::Formatter, start: &str, regions| { // Don't print any regions if they're all erased. - if regions.iter().all(|r| *r == ty::ReErased) { + if Iterator::all(&mut Clone::clone(®ions), + |r: &ty::Region| *r == ty::ReErased) { return Ok(()); } for region in regions { + let region: &ty::Region = region; start_or_continue(f, start, ", ")?; if verbose { write!(f, "{:?}", region)?; @@ -167,11 +173,12 @@ pub fn parameterized(f: &mut fmt::Formatter, Ok(()) }; - print_regions(f, "<", &substs.regions[..num_regions])?; + print_regions(f, "<", substs.regions().take(num_regions).skip(0))?; - let tps = &substs.types[..num_types]; + let tps = substs.types().take(num_types - num_supplied_defaults) + .skip(has_self as usize); - for &ty in &tps[has_self as usize..tps.len() - num_supplied_defaults] { + for &ty in tps { start_or_continue(f, "<", ", ")?; write!(f, "{}", ty)?; } @@ -197,10 +204,10 @@ pub fn parameterized(f: &mut fmt::Formatter, write!(f, "::{}", item_name)?; } - print_regions(f, "::<", &substs.regions[num_regions..])?; + print_regions(f, "::<", substs.regions().take(usize::MAX).skip(num_regions))?; // FIXME: consider being smart with defaults here too - for ty in &substs.types[num_types..] { + for ty in substs.types().skip(num_types) { start_or_continue(f, "::<", ", ")?; write!(f, "{}", ty)?; } @@ -368,13 +375,6 @@ impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> { } } -impl<'tcx> fmt::Debug for Substs<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "Substs[types={:?}, regions={:?}]", - self.types, self.regions) - } -} - impl<'tcx> fmt::Debug for ty::ItemSubsts<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "ItemSubsts({:?})", self.substs) diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 90fd8a0eb2f6..10f503f4e369 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -251,11 +251,11 @@ fn enc_opt(w: &mut Cursor>, t: Option, enc_f: F) where pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, substs: &Substs<'tcx>) { write!(w, "["); - for &r in &substs.regions { + for &r in substs.regions() { enc_region(w, cx, r); } write!(w, "|"); - for &ty in &substs.types { + for &ty in substs.types() { enc_ty(w, cx, ty); } write!(w, "]"); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index bcdc0d2ea3f9..32c78ca4a5ad 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -543,7 +543,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if let Literal::Item { def_id, substs } = constant.literal { // Don't peek inside generic (associated) constants. - if !substs.types.is_empty() { + if substs.types().next().is_some() { self.add_type(constant.ty); } else { let qualif = qualify_const_item_cached(self.tcx, diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 25a1479c2894..9b02cbe6721f 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -104,8 +104,9 @@ use util::sha2::{Digest, Sha256}; use rustc::middle::{cstore, weak_lang_items}; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; -use rustc::ty::{self, TyCtxt, TypeFoldable}; +use rustc::ty::{Ty, TyCtxt, TypeFoldable}; use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; +use rustc::ty::subst::Substs; use rustc::hir::map::definitions::{DefPath, DefPathData}; use syntax::attr; @@ -126,14 +127,14 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // parameters substituted; this is // included in the hash as a kind of // safeguard. - item_type: ty::Ty<'tcx>, + item_type: Ty<'tcx>, // values for generic type parameters, // if any. - parameters: &[ty::Ty<'tcx>]) + substs: Option<&Substs<'tcx>>) -> String { debug!("get_symbol_hash(def_path={:?}, parameters={:?})", - def_path, parameters); + def_path, substs); let tcx = scx.tcx(); @@ -154,11 +155,13 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, hash_state.input(&encoded_item_type[..]); // also include any type parameters (for generic items) - for t in parameters { - assert!(!t.has_erasable_regions()); - assert!(!t.needs_subst()); - let encoded_type = tcx.sess.cstore.encode_type(tcx, t, def_id_to_string); - hash_state.input(&encoded_type[..]); + if let Some(substs) = substs { + for t in substs.types() { + assert!(!t.has_erasable_regions()); + assert!(!t.needs_subst()); + let encoded_type = tcx.sess.cstore.encode_type(tcx, t, def_id_to_string); + hash_state.input(&encoded_type[..]); + } } return format!("h{}", truncated_hash_result(&mut *hash_state)); @@ -252,7 +255,7 @@ impl<'a, 'tcx> Instance<'tcx> { // and should not matter anyhow. let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); - let hash = get_symbol_hash(scx, &def_path, instance_ty, &substs.types); + let hash = get_symbol_hash(scx, &def_path, instance_ty, Some(substs)); let mut buffer = SymbolPathBuffer { names: Vec::with_capacity(def_path.data.len()) @@ -282,14 +285,14 @@ impl ItemPathBuffer for SymbolPathBuffer { } pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, - t: ty::Ty<'tcx>, + t: Ty<'tcx>, prefix: &str) -> String { let empty_def_path = DefPath { data: vec![], krate: cstore::LOCAL_CRATE, }; - let hash = get_symbol_hash(scx, &empty_def_path, t, &[]); + let hash = get_symbol_hash(scx, &empty_def_path, t, None); let path = [token::intern_and_get_ident(prefix)]; mangle(path.iter().cloned(), Some(&hash[..])) } @@ -297,7 +300,7 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, /// Only symbols that are invisible outside their compilation unit should use a /// name generated by this function. pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - t: ty::Ty<'tcx>, + t: Ty<'tcx>, suffix: &str) -> String { let path = [token::intern(&t.to_string()).as_str(), @@ -306,7 +309,7 @@ pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx> data: vec![], krate: cstore::LOCAL_CRATE, }; - let hash = get_symbol_hash(ccx.shared(), &def_path, t, &[]); + let hash = get_symbol_hash(ccx.shared(), &def_path, t, None); mangle(path.iter().cloned(), Some(&hash[..])) } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 9aa486dc6281..a30f8f291a67 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -400,9 +400,9 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("get_fn(def_id={:?}, substs={:?})", def_id, substs); - assert!(!substs.types.needs_infer()); - assert!(!substs.types.has_escaping_regions()); - assert!(!substs.types.has_param_types()); + assert!(!substs.needs_infer()); + assert!(!substs.has_escaping_regions()); + assert!(!substs.has_param_types()); let substs = tcx.normalize_associated_type(&substs); let instance = Instance::new(def_id, substs); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index c5053e4feee6..5055ed86a038 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -265,7 +265,7 @@ pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res { } pub fn validate_substs(substs: &Substs) { - assert!(!substs.types.needs_infer()); + assert!(!substs.needs_infer()); } // Function context. Every LLVM function we create will have one of diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index fccb326b2322..49aa19557309 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -342,11 +342,10 @@ impl<'tcx> TypeMap<'tcx> { // Add the def-index as the second part output.push_str(&format!("{:x}", def_id.index.as_usize())); - let tps = &substs.types; - if !tps.is_empty() { + if substs.types().next().is_some() { output.push('<'); - for &type_parameter in tps { + for &type_parameter in substs.types() { let param_type_id = type_map.get_unique_type_id_of_type(cx, type_parameter); let param_type_id = diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 58425cf60d55..72a91f50be35 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -344,36 +344,34 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, generics: &ty::Generics<'tcx>, - param_substs: &Substs<'tcx>, + substs: &Substs<'tcx>, file_metadata: DIFile, name_to_append_suffix_to: &mut String) -> DIArray { - let actual_types = ¶m_substs.types; - - if actual_types.is_empty() { + if substs.types().next().is_none() { return create_DIArray(DIB(cx), &[]); } name_to_append_suffix_to.push('<'); - for (i, &actual_type) in actual_types.iter().enumerate() { + for (i, &actual_type) in substs.types().enumerate() { + if i != 0 { + name_to_append_suffix_to.push_str(","); + } + let actual_type = cx.tcx().normalize_associated_type(&actual_type); // Add actual type name to <...> clause of function name let actual_type_name = compute_debuginfo_type_name(cx, actual_type, true); name_to_append_suffix_to.push_str(&actual_type_name[..]); - - if i != actual_types.len() - 1 { - name_to_append_suffix_to.push_str(","); - } } name_to_append_suffix_to.push('>'); // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { let names = get_type_parameter_names(cx, generics); - actual_types.iter().zip(names).map(|(ty, name)| { + substs.types().zip(names).map(|(ty, name)| { let actual_type = cx.tcx().normalize_associated_type(ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let name = CString::new(name.as_str().as_bytes()).unwrap(); diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 2a996ca75a37..9337f7e58ffc 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -175,13 +175,13 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, substs: &Substs<'tcx>, output: &mut String) { - if substs.types.is_empty() { + if substs.types().next().is_none() { return; } output.push('<'); - for &type_parameter in &substs.types { + for &type_parameter in substs.types() { push_debuginfo_type_name(cx, type_parameter, true, output); output.push_str(", "); } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 7faff98aea44..8bef7584db9e 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -146,12 +146,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Call(bcx, llfn, &[], call_debug_location) } (_, "size_of") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); let lltp_ty = type_of::type_of(ccx, tp_ty); C_uint(ccx, machine::llsize_of_alloc(ccx, lltp_ty)) } (_, "size_of_val") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); if !type_is_sized(tcx, tp_ty) { let (llsize, _) = glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); @@ -162,11 +162,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } (_, "min_align_of") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); C_uint(ccx, type_of::align_of(ccx, tp_ty)) } (_, "min_align_of_val") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); if !type_is_sized(tcx, tp_ty) { let (_, llalign) = glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); @@ -176,12 +176,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } (_, "pref_align_of") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); let lltp_ty = type_of::type_of(ccx, tp_ty); C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty)) } (_, "drop_in_place") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); let is_sized = type_is_sized(tcx, tp_ty); let ptr = if is_sized { llargs[0] @@ -199,15 +199,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) } (_, "type_name") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); let ty_name = token::intern_and_get_ident(&tp_ty.to_string()); C_str_slice(ccx, ty_name) } (_, "type_id") => { - C_u64(ccx, ccx.tcx().type_id_hash(substs.types[0])) + C_u64(ccx, ccx.tcx().type_id_hash(substs.type_at(0))) } (_, "init") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); if !type_is_zero_size(ccx, tp_ty) { // Just zero out the stack slot. (See comment on base::memzero for explanation) init_zero_mem(bcx, llresult, tp_ty); @@ -219,7 +219,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) } (_, "needs_drop") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); C_bool(ccx, bcx.fcx.type_needs_drop(tp_ty)) } @@ -238,7 +238,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, false, false, - substs.types[0], + substs.type_at(0), llargs[1], llargs[0], llargs[2], @@ -248,7 +248,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, true, false, - substs.types[0], + substs.type_at(0), llargs[1], llargs[0], llargs[2], @@ -257,7 +257,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "write_bytes") => { memset_intrinsic(bcx, false, - substs.types[0], + substs.type_at(0), llargs[0], llargs[1], llargs[2], @@ -268,7 +268,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, false, true, - substs.types[0], + substs.type_at(0), llargs[0], llargs[1], llargs[2], @@ -278,7 +278,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, true, true, - substs.types[0], + substs.type_at(0), llargs[0], llargs[1], llargs[2], @@ -287,14 +287,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "volatile_set_memory") => { memset_intrinsic(bcx, true, - substs.types[0], + substs.type_at(0), llargs[0], llargs[1], llargs[2], call_debug_location) } (_, "volatile_load") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); let mut ptr = llargs[0]; if let Some(ty) = fn_ty.ret.cast { ptr = PointerCast(bcx, ptr, ty.ptr_to()); @@ -306,7 +306,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, to_immediate(bcx, load, tp_ty) }, (_, "volatile_store") => { - let tp_ty = substs.types[0]; + let tp_ty = substs.type_at(0); if type_is_fat_ptr(bcx.tcx(), tp_ty) { VolatileStore(bcx, llargs[1], get_dataptr(bcx, llargs[0])); VolatileStore(bcx, llargs[2], get_meta(bcx, llargs[0])); @@ -406,7 +406,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }, (_, "discriminant_value") => { - let val_ty = substs.types[0]; + let val_ty = substs.type_at(0); match val_ty.sty { ty::TyEnum(..) => { let repr = adt::represent_type(ccx, val_ty); @@ -458,7 +458,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, match split[1] { "cxchg" | "cxchgweak" => { - let sty = &substs.types[0].sty; + let sty = &substs.type_at(0).sty; if int_type_width_signed(sty, ccx).is_some() { let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False }; let val = AtomicCmpXchg(bcx, llargs[0], llargs[1], llargs[2], @@ -477,7 +477,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "load" => { - let sty = &substs.types[0].sty; + let sty = &substs.type_at(0).sty; if int_type_width_signed(sty, ccx).is_some() { AtomicLoad(bcx, llargs[0], order) } else { @@ -490,7 +490,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "store" => { - let sty = &substs.types[0].sty; + let sty = &substs.type_at(0).sty; if int_type_width_signed(sty, ccx).is_some() { AtomicStore(bcx, llargs[1], llargs[0], order); } else { @@ -529,7 +529,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => ccx.sess().fatal("unknown atomic operation") }; - let sty = &substs.types[0].sty; + let sty = &substs.type_at(0).sty; if int_type_width_signed(sty, ccx).is_some() { AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order) } else { diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 97c77ee3d8c7..103afd827de9 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -307,7 +307,7 @@ pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Name) -> ImplMethod<'tcx> { - assert!(!substs.types.needs_infer()); + assert!(!substs.needs_infer()); let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); let trait_def = tcx.lookup_trait_def(trait_def_id); diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 020ac8d643b8..0ffb83067f91 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -32,7 +32,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { impl<'tcx> Instance<'tcx> { pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> Instance<'tcx> { - assert!(substs.regions.iter().all(|&r| r == ty::ReErased)); + assert!(substs.regions().all(|&r| r == ty::ReErased)); Instance { def: def_id, substs: substs } } pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> { diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 87d0ea0fe81f..7341e8db41de 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -342,7 +342,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, TransItem::DropGlue(..) => unreachable!(), // Is there any benefit to using ExternalLinkage?: TransItem::Fn(ref instance) => { - if instance.substs.types.is_empty() { + if instance.substs.types().next().is_none() { // This is a non-generic functions, we always // make it visible externally on the chance that // it might be used in another codegen unit. @@ -487,7 +487,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // DefId, we use the location of the impl after all. if tcx.trait_of_item(instance.def).is_some() { - let self_ty = instance.substs.types[0]; + let self_ty = instance.substs.type_at(0); // This is an implementation of a trait method. return characteristic_def_id_of_type(self_ty).or(Some(instance.def)); } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 90dcc3a61fd7..93302ab3b3be 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -171,8 +171,8 @@ impl<'a, 'tcx> TransItem<'tcx> { instance: Instance<'tcx>, linkage: llvm::Linkage, symbol_name: &str) { - assert!(!instance.substs.types.needs_infer() && - !instance.substs.types.has_param_types()); + assert!(!instance.substs.needs_infer() && + !instance.substs.has_param_types()); let item_ty = ccx.tcx().lookup_item_type(instance.def).ty; let item_ty = ccx.tcx().erase_regions(&item_ty); @@ -244,7 +244,7 @@ impl<'a, 'tcx> TransItem<'tcx> { pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { match *self { TransItem::Fn(ref instance) => { - !instance.substs.types.is_empty() || { + instance.substs.types().next().is_some() || { let attributes = tcx.get_attrs(instance.def); attr::requests_inline(&attributes[..]) } @@ -264,8 +264,9 @@ impl<'a, 'tcx> TransItem<'tcx> { pub fn is_instantiated_only_on_demand(&self) -> bool { match *self { - TransItem::Fn(ref instance) => !instance.def.is_local() || - !instance.substs.types.is_empty(), + TransItem::Fn(ref instance) => { + !instance.def.is_local() || instance.substs.types().next().is_some() + } TransItem::DropGlue(..) => true, TransItem::Static(..) => false, } @@ -273,7 +274,9 @@ impl<'a, 'tcx> TransItem<'tcx> { pub fn is_generic_fn(&self) -> bool { match *self { - TransItem::Fn(ref instance) => !instance.substs.types.is_empty(), + TransItem::Fn(ref instance) => { + instance.substs.types().next().is_some() + } TransItem::DropGlue(..) | TransItem::Static(..) => false, } @@ -374,7 +377,7 @@ impl<'a, 'tcx> TransItem<'tcx> { /// Same as `unique_type_name()` but with the result pushed onto the given /// `output` parameter. pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - t: ty::Ty<'tcx>, + t: Ty<'tcx>, output: &mut String) { match t.sty { ty::TyBool => output.push_str("bool"), @@ -396,7 +399,7 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::TyStruct(adt_def, substs) | ty::TyEnum(adt_def, substs) => { push_item_name(tcx, adt_def.did, output); - push_type_params(tcx, &substs.types, &[], output); + push_type_params(tcx, substs, &[], output); }, ty::TyTuple(component_types) => { output.push('('); @@ -446,7 +449,7 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::TyTrait(ref trait_data) => { push_item_name(tcx, trait_data.principal.def_id(), output); push_type_params(tcx, - &trait_data.principal.skip_binder().substs.types, + trait_data.principal.skip_binder().substs, &trait_data.projection_bounds, output); }, @@ -494,7 +497,7 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output.push_str("{"); output.push_str(&format!("{}:{}", def_id.krate, def_id.index.as_usize())); output.push_str("}"); - push_type_params(tcx, &closure_substs.func_substs.types, &[], output); + push_type_params(tcx, closure_substs.func_substs, &[], output); } ty::TyError | ty::TyInfer(_) | @@ -529,16 +532,16 @@ fn push_item_name(tcx: TyCtxt, } fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - types: &[Ty<'tcx>], + substs: &Substs<'tcx>, projections: &[ty::PolyExistentialProjection<'tcx>], output: &mut String) { - if types.is_empty() && projections.is_empty() { + if substs.types().next().is_none() && projections.is_empty() { return; } output.push('<'); - for &type_parameter in types { + for &type_parameter in substs.types() { push_unique_type_name(tcx, type_parameter, output); output.push_str(", "); } @@ -562,7 +565,7 @@ fn push_instance_as_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>, output: &mut String) { push_item_name(tcx, instance.def, output); - push_type_params(tcx, &instance.substs.types, &[], output); + push_type_params(tcx, instance.substs, &[], output); } pub fn def_id_to_string(tcx: TyCtxt, def_id: DefId) -> String { @@ -572,7 +575,7 @@ pub fn def_id_to_string(tcx: TyCtxt, def_id: DefId) -> String { } pub fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - ty: ty::Ty<'tcx>) + ty: Ty<'tcx>) -> String { let mut output = String::new(); push_unique_type_name(tcx, ty, &mut output); diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 6862002ed83b..b47d2cd0f204 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -17,6 +17,7 @@ use common::*; use machine; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TypeFoldable}; +use rustc::ty::subst::Substs; use type_::Type; @@ -256,7 +257,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // 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 name = llvm_type_name(cx, def.did, &substs.types); + let name = llvm_type_name(cx, def.did, substs); adt::incomplete_type_of(cx, &repr, &name[..]) } ty::TyClosure(..) => { @@ -330,7 +331,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // in *after* placing it into the type cache. This prevents // infinite recursion with recursive struct types. let repr = adt::represent_type(cx, t); - let name = llvm_type_name(cx, def.did, &substs.types); + let name = llvm_type_name(cx, def.did, substs); adt::incomplete_type_of(cx, &repr, &name[..]) } } @@ -367,10 +368,10 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, did: DefId, - tps: &[Ty<'tcx>]) + substs: &Substs<'tcx>) -> String { let base = cx.tcx().item_path_str(did); - let strings: Vec = tps.iter().map(|t| t.to_string()).collect(); + let strings: Vec = substs.types().map(|t| t.to_string()).collect(); let tstr = if strings.is_empty() { base } else { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index f6984f42cab3..72f81c7d48da 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -937,8 +937,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // FIXME(#12938): This is a hack until we have full support for DST. if Some(did) == self.tcx().lang_items.owned_box() { - assert_eq!(substs.types.len(), 1); - return self.tcx().mk_box(substs.types[0]); + assert_eq!(substs.types().count(), 1); + return self.tcx().mk_box(substs.type_at(0)); } decl_ty.subst(self.tcx(), substs) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 377ca5eaebe3..46e8c27f6d33 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -203,7 +203,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return None; } - let arg_param_ty = trait_ref.substs().types[1]; + let arg_param_ty = trait_ref.substs().type_at(1); let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 82545d564a20..4e48838f85cf 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -438,7 +438,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( ty::TyStruct(def, substs) if def.is_phantom_data() => { // PhantomData - behaves identically to T - let ity = substs.types[0]; + let ity = substs.type_at(0); iterate_over_potentially_unsafe_regions_in_type( cx, context, ity, depth+1) } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 9e0b38fd9fe5..8b757309f488 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -328,18 +328,20 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // // FIXME -- permit users to manually specify lifetimes Substs::for_item(self.tcx, method.def_id, |def, _| { - if let Some(&r) = substs.regions.get(def.index as usize) { - r + let i = def.index as usize; + if i < substs.regions().count() { + substs.region_at(i) } else { self.region_var_for_def(self.span, def) } }, |def, cur_substs| { - if let Some(&ty) = substs.types.get(def.index as usize) { - ty + let i = def.index as usize; + if i < substs.types().count() { + substs.type_at(i) } else if supplied_method_types.is_empty() { self.type_var_for_def(self.span, def, cur_substs) } else { - supplied_method_types[def.index as usize - substs.types.len()] + supplied_method_types[i - substs.types().count()] } }) } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c306463ec1de..d8ff9b4057f3 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -519,9 +519,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { trait_ref.substs, m); assert_eq!(m.generics.parent_types as usize, - trait_ref.substs.types.len()); + trait_ref.substs.types().count()); assert_eq!(m.generics.parent_regions as usize, - trait_ref.substs.regions.len()); + trait_ref.substs.regions().count()); } // Because this trait derives from a where-clause, it @@ -529,7 +529,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // artifacts. This means it is safe to put into the // `WhereClauseCandidate` and (eventually) into the // `WhereClausePick`. - assert!(!trait_ref.substs.types.needs_infer()); + assert!(!trait_ref.substs.needs_infer()); this.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, @@ -1220,8 +1220,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // are given do not include type/lifetime parameters for the // method yet. So create fresh variables here for those too, // if there are any. - assert_eq!(substs.types.len(), method.generics.parent_types as usize); - assert_eq!(substs.regions.len(), method.generics.parent_regions as usize); + assert_eq!(substs.types().count(), method.generics.parent_types as usize); + assert_eq!(substs.regions().count(), method.generics.parent_regions as usize); if self.mode == Mode::Path { return impl_ty; @@ -1236,16 +1236,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { xform_self_ty.subst(self.tcx, substs) } else { let substs = Substs::for_item(self.tcx, method.def_id, |def, _| { - if let Some(&r) = substs.regions.get(def.index as usize) { - r + let i = def.index as usize; + if i < substs.regions().count() { + substs.region_at(i) } else { // In general, during probe we erase regions. See // `impl_self_ty()` for an explanation. ty::ReErased } }, |def, cur_substs| { - if let Some(&ty) = substs.types.get(def.index as usize) { - ty + let i = def.index as usize; + if i < substs.types().count() { + substs.type_at(i) } else { self.type_var_for_def(self.span, def, cur_substs) } @@ -1324,7 +1326,7 @@ impl<'tcx> Candidate<'tcx> { // inference variables or other artifacts. This // means they are safe to put into the // `WhereClausePick`. - assert!(!trait_ref.substs().types.needs_infer()); + assert!(!trait_ref.substs().needs_infer()); WhereClausePick(trait_ref.clone()) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 16300d869abf..f2ed3e37c1a2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1899,7 +1899,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr) { - for &ty in &substs.types { + for &ty in substs.types() { self.register_wf_obligation(ty, expr.span, traits::MiscObligation); } } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 859d5ff0543d..a596b3cdcbb8 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1445,11 +1445,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let origin = infer::ParameterInScope(origin, expr_span); - for ®ion in &substs.regions { + for ®ion in substs.regions() { self.sub_regions(origin.clone(), expr_region, region); } - for &ty in &substs.types { + for &ty in substs.types() { let ty = self.resolve_type(ty); self.type_must_outlive(origin.clone(), ty, expr_region); } @@ -1575,11 +1575,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { if env_bounds.is_empty() && needs_infer { debug!("projection_must_outlive: no declared bounds"); - for &component_ty in &projection_ty.trait_ref.substs.types { + for &component_ty in projection_ty.trait_ref.substs.types() { self.type_must_outlive(origin.clone(), component_ty, region); } - for &r in &projection_ty.trait_ref.substs.regions { + for &r in projection_ty.trait_ref.substs.regions() { self.sub_regions(origin.clone(), region, r); } @@ -1597,10 +1597,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) { let unique_bound = env_bounds[0]; debug!("projection_must_outlive: unique declared bound = {:?}", unique_bound); - if projection_ty.trait_ref.substs.regions - .iter() - .any(|r| env_bounds.contains(r)) - { + if projection_ty.trait_ref.substs.regions().any(|r| env_bounds.contains(r)) { debug!("projection_must_outlive: unique declared bound appears in trait ref"); self.sub_regions(origin.clone(), region, unique_bound); return; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index bcad7dd3bd0f..ecec4913fb7d 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -597,7 +597,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Trait impl: take implied bounds from all types that // appear in the trait reference. let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref); - trait_ref.substs.types.to_vec() + trait_ref.substs.types().cloned().collect() } None => { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index cfc1292c34b7..3e5623404ed3 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -103,7 +103,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } let free_substs = fcx.parameter_environment.free_substs; - for (i, r) in free_substs.regions.iter().enumerate() { + for (i, r) in free_substs.regions().enumerate() { match *r { ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(def_id, name, _), .. diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index d00cbf0221e0..4362e040d266 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let source = tcx.lookup_item_type(impl_did).ty; let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap(); - let target = trait_ref.substs.types[1]; + let target = trait_ref.substs.type_at(1); debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 8a8232535c77..2a989105c9cb 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -172,7 +172,7 @@ fn write_substs_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, node_id, item_substs); - assert!(!item_substs.substs.types.needs_infer()); + assert!(!item_substs.substs.needs_infer()); ccx.tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e2e655ce38bc..51a697dad2fd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -642,8 +642,8 @@ impl Clean for hir::TyParamBound { fn external_path_params(cx: &DocContext, trait_did: Option, has_self: bool, bindings: Vec, substs: &Substs) -> PathParameters { - let lifetimes = substs.regions.iter().filter_map(|v| v.clean(cx)).collect(); - let types = substs.types[has_self as usize..].to_vec(); + let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect(); + let types = substs.types().skip(has_self as usize).cloned().collect::>(); match (trait_did, cx.tcx_opt()) { // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C @@ -737,12 +737,11 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { let path = external_path(cx, &tcx.item_name(self.def_id).as_str(), Some(self.def_id), true, vec![], self.substs); - debug!("ty::TraitRef\n substs.types: {:?}\n", - &self.input_types()[1..]); + debug!("ty::TraitRef\n subst: {:?}\n", self.substs); // collect any late bound regions let mut late_bounds = vec![]; - for &ty_s in &self.input_types()[1..] { + for &ty_s in self.input_types().skip(1) { if let ty::TyTuple(ts) = ty_s.sty { for &ty_s in ts { if let ty::TyRef(ref reg, _) = ty_s.sty { @@ -775,9 +774,9 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { impl<'tcx> Clean>> for Substs<'tcx> { fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); - v.extend(self.regions.iter().filter_map(|r| r.clean(cx)) + v.extend(self.regions().filter_map(|r| r.clean(cx)) .map(RegionBound)); - v.extend(self.types.iter().map(|t| TraitBound(PolyTrait { + v.extend(self.types().map(|t| TraitBound(PolyTrait { trait_: t.clean(cx), lifetimes: vec![] }, hir::TraitBoundModifier::None)));