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)
}
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);
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
// 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;
}
{
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())
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(..) |
// 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);
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()
}
}
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);
// for `PhantomData<T>`, 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) => {
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));
// 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={:?})",
} 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 {
// 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);
// 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, .. } =
// 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 =
impl_interners!('tcx,
type_list: mk_type_list(Vec<Ty<'tcx>>, 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)
}
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);
}
}
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));
// 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, _) |
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<Ty<'tcx>> {
+ self.trait_ref.input_types()
}
pub fn self_ty(&self) -> Ty<'tcx> {
pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
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()
}
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()
}
}
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<Ty<'tcx>> {
// 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()
}
}
{
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::<Result<_, _>>()?;
- 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::<Result<_, _>>()?;
// 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};
}
}
-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<V: TypeVisitor<'tcx>>(&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 {
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;
self.0.substs
}
- pub fn input_types(&self) -> &[Ty<'tcx>] {
+ pub fn input_types(&self) -> slice::Iter<Ty<'tcx>> {
// FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
self.0.input_types()
}
}
impl<'tcx> ExistentialTraitRef<'tcx> {
- pub fn input_types(&self) -> &[Ty<'tcx>] {
+ pub fn input_types(&self) -> slice::Iter<Ty<'tcx>>{
// 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()
}
}
self.0.def_id
}
- pub fn input_types(&self) -> &[Ty<'tcx>] {
+ pub fn input_types(&self) -> slice::Iter<Ty<'tcx>> {
// FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
self.0.input_types()
}
}
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(_) |
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<Ty<'tcx>>,
- pub regions: Vec<ty::Region>,
+ types: Vec<Ty<'tcx>>,
+ regions: Vec<ty::Region>,
}
impl<'a, 'gcx, 'tcx> Substs<'tcx> {
self.regions.is_empty() && self.types.is_empty()
}
+ #[inline]
+ pub fn types(&self) -> slice::Iter<Ty<'tcx>> {
+ self.types.iter()
+ }
+
+ #[inline]
+ pub fn regions(&self) -> slice::Iter<ty::Region> {
+ 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.types[ty_param_def.index as usize]
+ 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`
}
}
+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<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ self.types.visit_with(visitor) || self.regions.visit_with(visitor)
+ }
+}
+
impl<'tcx> Encodable for &'tcx Substs<'tcx> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
cstore::tls::with_encoding_context(s, |ecx, rbml_w| {
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
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());
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) => {
push_reversed(stack, &sig.0.inputs);
}
-fn push_reversed<'tcx>(stack: &mut Vec<Ty<'tcx>>, tys: &[Ty<'tcx>]) {
+fn push_reversed<'a, 'tcx: 'a, I>(stack: &mut Vec<Ty<'tcx>>, tys: I)
+ where I: IntoIterator<Item=&'a Ty<'tcx>>,
+ 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);
}
}
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))));
use std::cell::Cell;
use std::fmt;
+use std::usize;
+
use syntax::abi::Abi;
use syntax::parse::token;
use syntax::ast::CRATE_NODE_ID;
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));
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;
}
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);
}
}
}
};
- 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)?;
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)?;
}
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)?;
}
}
}
-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)
pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, 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, "]");
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,
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;
// 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();
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));
// 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())
}
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[..]))
}
/// 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(),
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[..]))
}
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);
}
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
// 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 =
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();
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(", ");
}
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]);
}
}
(_, "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]);
}
}
(_, "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]
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);
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))
}
copy_intrinsic(bcx,
false,
false,
- substs.types[0],
+ substs.type_at(0),
llargs[1],
llargs[0],
llargs[2],
copy_intrinsic(bcx,
true,
false,
- substs.types[0],
+ substs.type_at(0),
llargs[1],
llargs[0],
llargs[2],
(_, "write_bytes") => {
memset_intrinsic(bcx,
false,
- substs.types[0],
+ substs.type_at(0),
llargs[0],
llargs[1],
llargs[2],
copy_intrinsic(bcx,
false,
true,
- substs.types[0],
+ substs.type_at(0),
llargs[0],
llargs[1],
llargs[2],
copy_intrinsic(bcx,
true,
true,
- substs.types[0],
+ substs.type_at(0),
llargs[0],
llargs[1],
llargs[2],
(_, "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());
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]));
},
(_, "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);
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],
}
"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 {
}
"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 {
_ => 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 {
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);
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> {
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.
// 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));
}
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);
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[..])
}
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,
}
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,
}
/// 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"),
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('(');
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);
},
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(_) |
}
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(", ");
}
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 {
}
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);
use machine;
use rustc::traits::Reveal;
use rustc::ty::{self, Ty, TypeFoldable};
+use rustc::ty::subst::Substs;
use type_::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 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(..) => {
// 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[..])
}
}
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<String> = tps.iter().map(|t| t.to_string()).collect();
+ let strings: Vec<String> = substs.types().map(|t| t.to_string()).collect();
let tstr = if strings.is_empty() {
base
} else {
// 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)
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);
ty::TyStruct(def, substs) if def.is_phantom_data() => {
// PhantomData<T> - 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)
}
//
// 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()]
}
})
}
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
// 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,
// 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;
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)
}
// 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())
}
/// 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);
}
}
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);
}
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);
}
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;
// 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 => {
}
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, _), ..
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);
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);
}
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
bindings: Vec<TypeBinding>, 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::<Vec<_>>();
match (trait_did, cx.tcx_opt()) {
// Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
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 {
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
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)));