Remove specific parameter iterators from hir::Generics

This commit is contained in:
varkor 2018-05-26 13:11:39 +01:00
parent 82dba3d419
commit c818a1df9b
9 changed files with 213 additions and 135 deletions

View file

@ -379,22 +379,29 @@ impl<'a> LoweringContext<'a> {
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);
}
});
}
}

View file

@ -519,6 +519,11 @@ impl GenericParam {
}
}
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)]
@ -540,40 +545,23 @@ impl Generics {
}
}
pub fn is_lt_parameterized(&self) -> bool {
self.params.iter().any(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => 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 is_type_parameterized(&self) -> bool {
self.params.iter().any(|param| {
for param in &self.params {
match param.kind {
GenericParamKind::Type { .. } => true,
_ => false,
}
})
}
GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1,
GenericParamKind::Type { .. } => own_counts.types += 1,
};
}
pub fn lifetimes<'a>(&'a self) -> impl DoubleEndedIterator<Item = &'a GenericParam> {
self.params.iter().filter(|param| {
match param.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
}
})
}
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
}
}

View file

@ -532,11 +532,18 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
} 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,
@ -691,19 +698,25 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
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, &lt_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, &param);
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),
@ -760,12 +773,22 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
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,
@ -806,13 +829,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
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,
@ -863,9 +896,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
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 {
@ -1216,12 +1255,18 @@ fn compute_object_lifetime_defaults(
.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(),
})
@ -1485,19 +1530,26 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
}
let lifetimes = generics
.lifetimes()
.map(|param| {
if self.map.late_bound.contains(&param.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(&param.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,
@ -2513,10 +2565,10 @@ fn insert_late_bound_lifetimes(
// - 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.
@ -2533,10 +2585,10 @@ fn insert_late_bound_lifetimes(
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;

View file

@ -1196,15 +1196,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
}
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;
}
}
}
}
}

View file

@ -1236,9 +1236,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
}
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 {

View file

@ -1105,8 +1105,11 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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);

View file

@ -5166,27 +5166,34 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
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())

View file

@ -756,10 +756,15 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
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);
@ -915,7 +920,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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() {
@ -934,7 +940,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
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),
@ -945,9 +951,11 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
synthetic,
},
}
};
i += 1;
Some(ty_param)
}
_ => bug!()
_ => None,
}
}));
@ -1462,20 +1470,22 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// 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;
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 = 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));
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

View file

@ -41,7 +41,7 @@ use rustc::hir::def::{self, Def, CtorKind};
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;
@ -2863,7 +2863,7 @@ impl Clean<Type> for hir::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
};