let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
hir::Item_::ItemImpl(_, _, _, ref generics, ..)
| hir::Item_::ItemTrait(_, _, ref generics, ..) => {
- generics.lifetimes().cloned().collect::<Vec<_>>()
+ generics.params
+ .iter()
+ .filter_map(|param| match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => {
+ Some(param.clone())
+ }
+ _ => None,
+ })
+ .collect::<Vec<_>>()
}
_ => Vec::new(),
};
- self.lctx
- .with_parent_impl_lifetime_defs(&item_lifetimes, |this| {
- let this = &mut ItemLowerer { lctx: this };
- if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node {
- this.with_trait_impl_ref(opt_trait_ref, |this| {
- visit::walk_item(this, item)
- });
- } else {
- visit::walk_item(this, item);
- }
- });
+ self.lctx.with_parent_impl_lifetime_defs(&item_lifetimes, |this| {
+ let this = &mut ItemLowerer { lctx: this };
+ if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node {
+ this.with_trait_impl_ref(opt_trait_ref, |this| {
+ visit::walk_item(this, item)
+ });
+ } else {
+ visit::walk_item(this, item);
+ }
+ });
}
}
}
}
+pub struct GenericParamCount {
+ pub lifetimes: usize,
+ pub types: usize,
+}
+
/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
}
}
- pub fn is_lt_parameterized(&self) -> bool {
- self.params.iter().any(|param| {
- match param.kind {
- GenericParamKind::Lifetime { .. } => true,
- _ => false,
- }
- })
- }
-
- pub fn is_type_parameterized(&self) -> bool {
- self.params.iter().any(|param| {
- match param.kind {
- GenericParamKind::Type { .. } => true,
- _ => false,
- }
- })
- }
+ pub fn own_counts(&self) -> GenericParamCount {
+ // We could cache this as a property of `GenericParamCount`, but
+ // the aim is to refactor this away entirely eventually and the
+ // presence of this method will be a constant reminder.
+ let mut own_counts = GenericParamCount {
+ lifetimes: 0,
+ types: 0,
+ };
- pub fn lifetimes<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a GenericParam> {
- self.params.iter().filter(|param| {
+ for param in &self.params {
match param.kind {
- GenericParamKind::Lifetime { .. } => true,
- _ => false,
- }
- })
- }
+ GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1,
+ GenericParamKind::Type { .. } => own_counts.types += 1,
+ };
+ }
- pub fn ty_params<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a GenericParam> {
- self.params.iter().filter(|param| {
- match param.kind {
- GenericParamKind::Type { .. } => true,
- _ => false,
- }
- })
+ own_counts
}
}
} else {
0
};
- let lifetimes = generics
- .lifetimes()
- .map(|def| Region::early(&self.tcx.hir, &mut index, def))
- .collect();
- let next_early_index = index + generics.ty_params().count() as u32;
+ let mut next_early_index = index;
+ let lifetimes = generics.params.iter().filter_map(|param| {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::early(&self.tcx.hir, &mut index, param))
+ }
+ GenericParamKind::Type { .. } => {
+ next_early_index += 1;
+ None
+ }
+ }
+ }).collect();
let scope = Scope::Binder {
lifetimes,
next_early_index,
let mut elision = None;
let mut lifetimes = FxHashMap();
- for lt_def in generics.lifetimes() {
- let (lt_name, region) = Region::early(&self.tcx.hir, &mut index, <_def);
- if let hir::LifetimeName::Underscore = lt_name {
- // Pick the elided lifetime "definition" if one exists and use it to make
- // an elision scope.
- elision = Some(region);
- } else {
- lifetimes.insert(lt_name, region);
+ let mut next_early_index = index;
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m);
+ if let hir::LifetimeName::Underscore = name {
+ // Pick the elided lifetime "definition" if one exists
+ // and use it to make an elision scope.
+ elision = Some(reg);
+ } else {
+ lifetimes.insert(name, reg);
+ }
+ }
+ GenericParamKind::Type { .. } => {
+ next_early_index += 1;
+ }
}
}
- let next_early_index = index + generics.ty_params().count() as u32;
-
if let Some(elision_region) = elision {
let scope = Scope::Elision {
elide: Elide::Exact(elision_region),
let generics = &trait_item.generics;
let mut index = self.next_early_index();
debug!("visit_ty: index = {}", index);
- let lifetimes = generics
- .lifetimes()
- .map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
+ let mut next_early_index = index;
+ let lifetimes = generics.params
+ .iter()
+ .filter_map(|param| {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::early(&self.tcx.hir, &mut index, param))
+ }
+ GenericParamKind::Type { .. } => {
+ next_early_index += 1;
+ None
+ }
+ }
+ })
.collect();
- let next_early_index = index + generics.ty_params().count() as u32;
let scope = Scope::Binder {
lifetimes,
next_early_index,
Type(ref ty) => {
let generics = &impl_item.generics;
let mut index = self.next_early_index();
+ let mut next_early_index = index;
debug!("visit_ty: index = {}", index);
- let lifetimes = generics
- .lifetimes()
- .map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def))
+ let lifetimes = generics.params
+ .iter()
+ .filter_map(|param| {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ Some(Region::early(&self.tcx.hir, &mut index, param))
+ }
+ GenericParamKind::Type { .. } => {
+ next_early_index += 1;
+ None
+ }
+ }
+ })
.collect();
- let next_early_index = index + generics.ty_params().count() as u32;
let scope = Scope::Binder {
lifetimes,
next_early_index,
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
+
check_mixed_explicit_and_in_band_defs(
self.tcx,
- &generics.lifetimes().cloned().collect::<Vec<_>>(),
+ &generics.params.iter().filter_map(|param| {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => Some(param.clone()),
+ _ => None,
+ }
+ }).collect::<Vec<_>>()
);
for param in &generics.params {
match param.kind {
.map(|set| match *set {
Set1::Empty => "BaseDefault".to_string(),
Set1::One(Region::Static) => "'static".to_string(),
- Set1::One(Region::EarlyBound(i, _, _)) => generics
- .lifetimes()
- .nth(i as usize)
- .unwrap()
- .name()
- .to_string(),
+ Set1::One(Region::EarlyBound(i, _, _)) => {
+ let mut j = 0;
+ generics.params.iter().find(|param| {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => j += 1,
+ _ => {}
+ }
+ i == j
+ }).unwrap()
+ .name()
+ .to_string()
+ }
Set1::One(_) => bug!(),
Set1::Many => "Ambiguous".to_string(),
})
}
}
- let lifetimes = generics
- .lifetimes()
- .map(|param| {
- if self.map.late_bound.contains(¶m.id) {
- Region::late(&self.tcx.hir, param)
- } else {
- Region::early(&self.tcx.hir, &mut index, param)
+ let mut next_early_index = index;
+ let lifetimes = generics.params
+ .iter()
+ .filter_map(|param| {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ if self.map.late_bound.contains(¶m.id) {
+ Some(Region::late(&self.tcx.hir, param))
+ } else {
+ Some(Region::early(&self.tcx.hir, &mut index, param))
+ }
+ }
+ GenericParamKind::Type { .. } => {
+ next_early_index += 1;
+ None
+ }
}
})
.collect();
- let next_early_index = index + generics.ty_params().count() as u32;
-
let scope = Scope::Binder {
lifetimes,
next_early_index,
// - appear in the inputs
// - do not appear in the where-clauses
// - are not implicitly captured by `impl Trait`
- for lifetime in generics.lifetimes() {
- let name = match lifetime.kind {
+ for param in &generics.params {
+ let name = match param.kind {
GenericParamKind::Lifetime { name, .. } => name,
- _ => bug!(),
+ _ => continue,
};
// appears in the where clauses? early-bound.
debug!("insert_late_bound_lifetimes: lifetime {:?} with id {:?} is late-bound",
name,
- lifetime.id);
+ param.id);
- let inserted = map.late_bound.insert(lifetime.id);
- assert!(inserted, "visited lifetime {:?} twice", lifetime.id);
+ let inserted = map.late_bound.insert(param.id);
+ assert!(inserted, "visited lifetime {:?} twice", param.id);
}
return;
}
err.emit();
}
- if generics.is_type_parameterized() {
- let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
- it.span,
- "functions generic over \
- types must be mangled");
- err.span_suggestion_short(no_mangle_attr.span,
- "remove this attribute",
- "".to_owned());
- err.emit();
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { .. } => {
+ let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS,
+ it.span,
+ "functions generic over \
+ types must be mangled");
+ err.span_suggestion_short(no_mangle_attr.span,
+ "remove this attribute",
+ "".to_owned());
+ err.emit();
+ break;
+ }
+ }
}
}
}
}
hir::ItemConst(..) => self.encode_optimized_mir(def_id),
hir::ItemFn(_, _, constness, _, ref generics, _) => {
- let has_tps = generics.ty_params().next().is_some();
+ let has_types = generics.params.iter().find(|param| {
+ match param.kind {
+ hir::GenericParamKind::Type { .. } => true,
+ _ => false,
+ }
+ }).is_some();
let needs_inline =
- (has_tps || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
+ (has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) &&
!self.metadata_output_only();
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
if needs_inline || constness == hir::Constness::Const || always_encode_mir {
ref generics,
..,
ref impl_item_refs) => {
- if generics.is_type_parameterized() {
- return
+ for param in &generics.params {
+ match param.kind {
+ hir::GenericParamKind::Lifetime { .. } => {}
+ hir::GenericParamKind::Type { .. } => return,
+ }
}
let impl_def_id = tcx.hir.local_def_id(item.id);
pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
generics: &hir::Generics,
ty: Ty<'tcx>) {
- debug!("check_bounds_are_used(n_tps={}, ty={:?})",
- generics.ty_params().count(), ty);
+ let own_counts = generics.own_counts();
+ debug!("check_bounds_are_used(n_tps={}, ty={:?})", own_counts.types, ty);
- // make a vector of booleans initially false, set to true when used
- if generics.ty_params().next().is_none() { return; }
- let mut tps_used = vec![false; generics.ty_params().count()];
-
- let lifetime_count = generics.lifetimes().count();
+ if own_counts.types == 0 {
+ return;
+ }
+ // Make a vector of booleans initially false, set to true when used.
+ let mut types_used = vec![false; own_counts.types];
for leaf_ty in ty.walk() {
- if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty {
+ if let ty::TyParam(ty::ParamTy { idx, .. }) = leaf_ty.sty {
debug!("Found use of ty param num {}", idx);
- tps_used[idx as usize - lifetime_count] = true;
+ types_used[idx as usize - own_counts.lifetimes] = true;
} else if let ty::TyError = leaf_ty.sty {
- // If there already another error, do not emit an error for not using a type Parameter
+ // If there is already another error, do not emit
+ // an error for not using a type Parameter.
assert!(tcx.sess.err_count() > 0);
return;
}
}
- for (&used, param) in tps_used.iter().zip(generics.ty_params()) {
+ let types = generics.params.iter().filter(|param| {
+ match param.kind {
+ hir::GenericParamKind::Type { .. } => true,
+ _ => false,
+ }
+ });
+ for (&used, param) in types_used.iter().zip(types) {
if !used {
struct_span_err!(tcx.sess, param.span, E0091, "type parameter `{}` is unused",
param.name())
outer_index: ty::INNERMOST,
has_late_bound_regions: None,
};
- for lifetime in generics.lifetimes() {
- let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
- if tcx.is_late_bound(hir_id) {
- return Some(lifetime.span);
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let hir_id = tcx.hir.node_to_hir_id(param.id);
+ if tcx.is_late_bound(hir_id) {
+ return Some(param.span);
+ }
+ }
+ _ => {},
}
}
visitor.visit_fn_decl(decl);
// Now create the real type parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
- params.extend(ast_generics.ty_params().enumerate().map(|(i, param)| {
+ let mut i = 0;
+ params.extend(ast_generics.params.iter().filter_map(|param| {
match param.kind {
GenericParamKind::Type { ref default, synthetic, .. } => {
if param.name() == keywords::SelfType.name() {
}
}
- ty::GenericParamDef {
+ let ty_param = ty::GenericParamDef {
index: type_start + i as u32,
name: param.name().as_interned_str(),
def_id: tcx.hir.local_def_id(param.id),
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
synthetic,
},
- }
+ };
+ i += 1;
+ Some(ty_param)
}
- _ => bug!()
+ _ => None,
}
}));
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`).
- for param in ast_generics.ty_params() {
- let param_ty = ty::ParamTy::new(index, param.name().as_interned_str()).to_ty(tcx);
- index += 1;
-
- let bounds = match param.kind {
- GenericParamKind::Type { ref bounds, .. } => bounds,
- _ => bug!(),
- };
- let bounds = compute_bounds(&icx,
- param_ty,
- bounds,
- SizedByDefault::Yes,
- param.span);
- predicates.extend(bounds.predicates(tcx, param_ty));
+ for param in &ast_generics.params {
+ match param.kind {
+ GenericParamKind::Type { ref bounds, .. } => {
+ let param_ty = ty::ParamTy::new(index, param.name().as_interned_str())
+ .to_ty(tcx);
+ index += 1;
+
+ let bounds = compute_bounds(&icx,
+ param_ty,
+ bounds,
+ SizedByDefault::Yes,
+ param.span);
+ predicates.extend(bounds.predicates(tcx, param_ty));
+ }
+ _ => {}
+ }
}
// Add in the bounds that appear in the where-clause
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::def_id::DefIndexAddressSpace;
use rustc::ty::subst::Substs;
-use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind, GenericParamCount};
+use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
use rustc::middle::stability;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_typeck::hir_ty_to_ty;
let mut ty_substs = FxHashMap();
let mut lt_substs = FxHashMap();
provided_params.with_generic_args(|generic_args| {
- let mut indices = GenericParamCount {
+ let mut indices = ty::GenericParamCount {
lifetimes: 0,
types: 0
};