Refactor generic params loops

This commit is contained in:
varkor 2018-05-10 23:02:41 +01:00
parent 18f77e25e9
commit 9200bdee26
20 changed files with 95 additions and 165 deletions

View file

@ -374,8 +374,8 @@ impl<'a> LoweringContext<'a> {
if item_lowered {
let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node {
hir::Item_::ItemImpl(_, _, _, ref generics, .. ) |
hir::Item_::ItemTrait(_, _, ref generics, .. ) => {
hir::Item_::ItemImpl(_, _, _, ref generics, ..)
| hir::Item_::ItemTrait(_, _, ref generics, ..) => {
generics.lifetimes().cloned().collect::<Vec<_>>()
}
_ => Vec::new(),
@ -1895,13 +1895,11 @@ impl<'a> LoweringContext<'a> {
GenericParam::Lifetime(ref lifetime_def) => {
hir::GenericParam::Lifetime(self.lower_lifetime_def(lifetime_def))
}
GenericParam::Type(ref ty_param) => {
hir::GenericParam::Type(self.lower_ty_param(
ty_param,
add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x),
itctx,
))
}
GenericParam::Type(ref ty_param) => hir::GenericParam::Type(self.lower_ty_param(
ty_param,
add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x),
itctx,
)),
})
.collect()
}

View file

@ -2043,10 +2043,7 @@ impl<'a> State<'a> {
Ok(())
}
pub fn print_generic_params(&mut self,
generic_params: &[hir::GenericParam])
-> io::Result<()>
{
pub fn print_generic_params(&mut self, generic_params: &[hir::GenericParam]) -> io::Result<()> {
if !generic_params.is_empty() {
self.s.word("<")?;

View file

@ -313,16 +313,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// `['a]` for the first impl trait and `'b` for the
// second.
let mut least_region = None;
for index in abstract_type_generics.params.iter().filter_map(|param| {
if let GenericParamDefKind::Lifetime(_) = param.kind {
// Find the index of this region in the list of substitutions.
Some(param.index as usize)
} else {
None
for param in &abstract_type_generics.params {
match param.kind {
GenericParamDefKind::Lifetime(_) => {}
_ => continue
}
}) {
// Get the value supplied for this region from the substs.
let subst_arg = anon_defn.substs.region_at(index);
let subst_arg = anon_defn.substs.region_at(param.index as usize);
// Compute the least upper bound of it with the other regions.
debug!("constrain_anon_types: least_region={:?}", least_region);

View file

@ -222,9 +222,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
});
let names_map: FxHashSet<String> = generics
.regions
.params
.iter()
.map(|l| l.name.to_string())
.filter_map(|param| {
match param.kind {
ty::GenericParamDefKind::Lifetime(_) => Some(param.name.to_string()),
_ => None
}
})
.collect();
let body_ids: FxHashSet<_> = infcx

View file

@ -379,16 +379,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
}
for param in generics.params.iter().filter(|param| {
match param.kind {
GenericParamDefKind::Type(_) => true,
GenericParamDefKind::Lifetime(_) => false,
}
}) {
for param in generics.params.iter() {
let name = param.name.to_string();
let ty = trait_ref.substs.type_for_def(&param);
let ty_str = ty.to_string();
flags.push((name.clone(), Some(ty_str.clone())));
let value = match param.kind {
GenericParamDefKind::Type(_) => {
let ty = trait_ref.substs.type_for_def(&param);
ty.to_string()
},
GenericParamDefKind::Lifetime(_) => continue,
};
flags.push((name.clone(), Some(value.clone())));
}
if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {

View file

@ -254,15 +254,12 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
Position::ArgumentNamed(s) if s == name => (),
// So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
match param.kind {
GenericParamDefKind::Type(_) => param.name == s,
GenericParamDefKind::Lifetime(_) => false,
}
param.name == s
}) {
Some(_) => (),
None => {
span_err!(tcx.sess, span, E0230,
"there is no type parameter \
"there is no parameter \
{} on trait {}",
s, name);
result = Err(ErrorReported);

View file

@ -35,7 +35,6 @@ use mir::{self, Mir, interpret};
use ty::subst::{Kind, Substs, Subst};
use ty::ReprOptions;
use ty::Instance;
use ty::GenericParamDefKind;
use traits;
use traits::{Clause, Clauses, Goal, Goals};
use ty::{self, Ty, TypeAndMut};
@ -2326,20 +2325,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
let adt_def = self.adt_def(def_id);
let generics = self.generics_of(def_id);
let mut substs = vec![Kind::from(ty)];
// Add defaults for other generic params if there are some.
for (def_id, has_default) in generics.params.iter().filter_map(|param| {
match param.kind {
GenericParamDefKind::Type(ty) => Some((param.def_id, ty.has_default)),
GenericParamDefKind::Lifetime(_) => None
let substs = Substs::for_item(self, def_id, |_, _| bug!(), |def, substs| {
if def.index == 0 {
ty
} else {
match def.kind {
ty::GenericParamDefKind::Type(ty_param) => {
assert!(ty_param.has_default);
self.type_of(def.def_id).subst(self, substs)
}
_ => unreachable!()
}
}
}).skip(1) {
assert!(has_default);
let ty = self.type_of(def_id).subst(self, &substs);
substs.push(ty.into());
}
let substs = self.mk_substs(substs.into_iter());
});
self.mk_ty(TyAdt(adt_def, substs))
}

View file

@ -804,7 +804,7 @@ pub struct Generics {
pub parent_count: usize,
pub params: Vec<GenericParamDef>,
/// Reverse map to the `index` field of each `GenericParamDef`'s inner type
/// Reverse map to the `index` field of each `GenericParamDef`
pub param_def_id_to_index: FxHashMap<DefId, u32>,
pub has_self: bool,
@ -836,13 +836,11 @@ impl<'a, 'gcx, 'tcx> Generics {
}
pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
if self.params.iter().any(|param| {
for param in self.params.iter() {
match param.kind {
GenericParamDefKind::Type(_) => true,
GenericParamDefKind::Lifetime(_) => false
GenericParamDefKind::Type(_) => return true,
GenericParamDefKind::Lifetime(_) => {}
}
}) {
return true;
}
if let Some(parent_def_id) = self.parent {
let parent = tcx.generics_of(parent_def_id);
@ -858,7 +856,7 @@ impl<'a, 'gcx, 'tcx> Generics {
-> &'tcx GenericParamDef
{
if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
let ref param = self.params[index as usize];
let param = &self.params[index as usize];
match param.kind {
ty::GenericParamDefKind::Lifetime(_) => param,
_ => bug!("expected region parameter, but found another generic parameter")
@ -875,53 +873,7 @@ impl<'a, 'gcx, 'tcx> Generics {
tcx: TyCtxt<'a, 'gcx, 'tcx>)
-> &'tcx GenericParamDef {
if let Some(index) = param.idx.checked_sub(self.parent_count as u32) {
// non-Self type parameters are always offset by exactly
// `self.regions.len()`. In the absence of a Self, this is obvious,
// but even in the presence of a `Self` we just have to "compensate"
// for the regions:
//
// Without a `Self` (or in a nested generics that doesn't have
// a `Self` in itself, even through it parent does), for example
// for `fn foo<'a, T1, T2>()`, the situation is:
// Substs:
// 0 1 2
// 'a T1 T2
// generics.types:
// 0 1
// T1 T2
//
// And with a `Self`, for example for `trait Foo<'a, 'b, T1, T2>`, the
// situation is:
// Substs:
// 0 1 2 3 4
// Self 'a 'b T1 T2
// generics.types:
// 0 1 2
// Self T1 T2
//
// And it can be seen that in both cases, to move from a substs
// offset to a generics offset you just have to offset by the
// number of regions.
let type_param_offset = self.param_counts().lifetimes;
let has_self = self.has_self && self.parent.is_none();
let is_separated_self = type_param_offset != 0 && index == 0 && has_self;
if let Some(_) = (index as usize).checked_sub(type_param_offset) {
assert!(!is_separated_self, "found a Self after type_param_offset");
let ref param = self.params[index as usize];
match param.kind {
ty::GenericParamDefKind::Type(_) => param,
_ => bug!("expected type parameter, but found another generic parameter")
}
} else {
assert!(is_separated_self, "non-Self param before type_param_offset");
let ref param = self.params[type_param_offset];
match param.kind {
ty::GenericParamDefKind::Type(_) => param,
_ => bug!("expected type parameter, but found another generic parameter")
}
}
&self.params[index as usize]
} else {
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
.type_param(param, tcx)

View file

@ -366,7 +366,7 @@ struct SplitGeneratorSubsts<'tcx> {
impl<'tcx> GeneratorSubsts<'tcx> {
fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitGeneratorSubsts<'tcx> {
let generics = tcx.generics_of(def_id);
let parent_len = generics.parent_count();
let parent_len = generics.parent_count;
SplitGeneratorSubsts {
yield_ty: self.substs.type_at(parent_len),
return_ty: self.substs.type_at(parent_len + 1),

View file

@ -351,8 +351,10 @@ impl PrintContext {
let zipped = iter::once((last_ty, types.next().unwrap()))
.chain(type_params.zip(types));
for ((def_id, has_default), actual) in zipped {
if !has_default ||
tcx.type_of(def_id).subst(tcx, substs) != actual {
if !has_default {
break;
}
if tcx.type_of(def_id).subst(tcx, substs) != actual {
break;
}
num_supplied_defaults += 1;
@ -604,7 +606,7 @@ define_print! {
impl fmt::Debug for ty::GenericParamDef {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let type_name = match self.kind {
ty::GenericParamDefKind::Lifetime(_) => "Region",
ty::GenericParamDefKind::Lifetime(_) => "Lifetime",
ty::GenericParamDefKind::Type(_) => "Type",
};
write!(f, "{}({}, {:?}, {})",

View file

@ -399,7 +399,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
fn generics(&mut self) -> &mut Self {
for param in self.ev.tcx.generics_of(self.item_def_id).params.iter() {
for param in &self.ev.tcx.generics_of(self.item_def_id).params {
match param.kind {
GenericParamDefKind::Type(ty) => {
if ty.has_default {
@ -1340,7 +1340,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
fn generics(&mut self) -> &mut Self {
for param in self.tcx.generics_of(self.item_def_id).params.iter() {
for param in &self.tcx.generics_of(self.item_def_id).params {
match param.kind {
GenericParamDefKind::Type(ty) => {
if ty.has_default {

View file

@ -222,8 +222,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
assert_eq!(decl_generics.has_self, self_ty.is_some());
// Check the number of type parameters supplied by the user.
let type_params_offset = self_ty.is_some() as usize;
let ty_param_defs = param_counts.types - type_params_offset;
let own_self = self_ty.is_some() as usize;
let ty_param_defs = param_counts.types - own_self;
if !infer_types || num_types_provided > ty_param_defs {
let type_params_without_defaults = {
let mut count = 0;
@ -241,7 +241,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
span,
num_types_provided,
ty_param_defs,
type_params_without_defaults - type_params_offset);
type_params_without_defaults - own_self);
}
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
@ -258,7 +258,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
};
let substs = Substs::for_item(tcx, def_id, |def, _| {
let i = def.index as usize - type_params_offset;
let i = def.index as usize - own_self;
if let Some(lifetime) = parameters.lifetimes.get(i) {
self.ast_region_to_region(lifetime, Some(def))
} else {
@ -272,7 +272,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
return ty;
}
let i = i - (param_counts.lifetimes + type_params_offset);
let i = i - (param_counts.lifetimes + own_self);
if i < num_types_provided {
// A provided type parameter.
self.ast_ty_to_ty(&parameters.types[i])

View file

@ -316,6 +316,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// parameters from the type and those from the method.
assert_eq!(method_generics.parent_count, parent_substs.len());
let provided = &segment.parameters;
let param_counts = method_generics.param_counts();
Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
let i = def.index as usize;
if i < parent_substs.len() {
@ -333,7 +334,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
} else if let Some(ast_ty)
= provided.as_ref().and_then(|p| {
let idx =
i - parent_substs.len() - method_generics.param_counts().lifetimes;
i - parent_substs.len() - param_counts.lifetimes;
p.types.get(idx)
})
{

View file

@ -4918,13 +4918,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
// Check provided parameters.
let (ty_non_def_req_len, ty_req_len, lt_req_len) =
let (ty_req_len, accepted, lt_req_len) =
segment.map_or((0, 0, 0), |(_, generics)| {
let param_counts = generics.param_counts();
let type_params_offset
= (generics.parent.is_none() && generics.has_self) as usize;
let type_params = param_counts.types - type_params_offset;
let own_self = (generics.parent.is_none() && generics.has_self) as usize;
let type_params = param_counts.types - own_self;
let type_params_without_defaults = {
let mut count = 0;
for param in generics.params.iter() {
@ -4937,14 +4936,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
count
};
let type_params_barring_defaults =
type_params_without_defaults - type_params_offset;
type_params_without_defaults - own_self;
(type_params_barring_defaults, type_params, param_counts.lifetimes)
});
if types.len() > ty_req_len {
let span = types[ty_req_len].span;
let expected_text = count_type_params(ty_req_len);
if types.len() > accepted {
let span = types[accepted].span;
let expected_text = count_type_params(accepted);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0087,
"too many type parameters provided: \
@ -4957,8 +4956,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// type parameters, we force instantiate_value_path to
// use inference variables instead of the provided types.
*segment = None;
} else if types.len() < ty_non_def_req_len && !infer_types && !supress_mismatch_error {
let expected_text = count_type_params(ty_non_def_req_len);
} else if types.len() < ty_req_len && !infer_types && !supress_mismatch_error {
let expected_text = count_type_params(ty_req_len);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0089,
"too few type parameters provided: \

View file

@ -378,22 +378,19 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
// For example this forbids the declaration:
// struct Foo<T = Vec<[u32]>> { .. }
// Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
for d in generics.params.iter().filter_map(|param| {
for param in &generics.params {
if let GenericParamDefKind::Type(_) = param.kind {
if is_our_default(&param) {
return Some(param.def_id);
let ty = fcx.tcx.type_of(param.def_id);
// ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., <T, U = T>). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
if !ty.needs_subst() {
fcx.register_wf_obligation(ty, fcx.tcx.def_span(param.def_id),
ObligationCauseCode::MiscObligation);
}
}
}
None
}) {
let ty = fcx.tcx.type_of(d);
// ignore dependent defaults -- that is, where the default of one type
// parameter includes another (e.g., <T, U = T>). In those cases, we can't
// be sure if it will error or not as user might always specify the other.
if !ty.needs_subst() {
fcx.register_wf_obligation(ty, fcx.tcx.def_span(d),
ObligationCauseCode::MiscObligation);
}
}
// Check that trait predicates are WF when params are substituted by their defaults.
@ -662,20 +659,20 @@ fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
.collect();
for method_param in generics.params.iter() {
let (name, def_id) = match method_param.kind {
match method_param.kind {
// Shadowing is checked in resolve_lifetime.
GenericParamDefKind::Lifetime(_) => continue,
GenericParamDefKind::Type(_) => (method_param.name, method_param.def_id),
_ => {},
};
if impl_params.contains_key(&name) {
if impl_params.contains_key(&method_param.name) {
// Tighten up the span to focus on only the shadowing type
let type_span = tcx.def_span(def_id);
let type_span = tcx.def_span(method_param.def_id);
// The expectation here is that the original trait declaration is
// local so it should be okay to just unwrap everything.
let trait_def_id = impl_params[&name];
let trait_def_id = impl_params[&method_param.name];
let trait_decl_span = tcx.def_span(trait_def_id);
error_194(tcx, type_span, trait_decl_span, &name.as_str()[..]);
error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]);
}
}
}

View file

@ -903,7 +903,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Now create the real type parameters.
let type_start = own_start + lifetimes.len() as u32;
let types = ast_generics.ty_params().enumerate().map(|(i, p)| {
let mut types: Vec<_> = ast_generics.ty_params().enumerate().map(|(i, p)| {
if p.name == keywords::SelfType.name() {
span_bug!(p.span, "`Self` should not be the name of a regular parameter");
}
@ -931,9 +931,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
synthetic: p.synthetic,
}),
}
});
let mut types: Vec<_> = types.into_iter().collect();
}).collect();
// provide junk type parameter defs - the only place that
// cares about anything but the length is instantiation,

View file

@ -1753,7 +1753,7 @@ impl Clean<Generics> for hir::Generics {
let mut params = Vec::with_capacity(self.params.len());
for p in &self.params {
let p = p.clean(cx);
if let GenericParam::Type(ref tp) = p {
if let GenericParamDef::Type(ref tp) = p {
if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone());
}

View file

@ -72,9 +72,7 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) }
fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
fn visit_generic_param(&mut self, param: &'ast GenericParam) {
walk_generic_param(self, param)
}
fn visit_generic_param(&mut self, param: &'ast GenericParam) { walk_generic_param(self, param) }
fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
walk_where_predicate(self, p)

View file

@ -570,11 +570,7 @@ impl<'a> TraitDef<'a> {
bounds.push((*declared_bound).clone());
}
GenericParam::Type(cx.typaram(self.span,
ty_param.ident,
vec![],
bounds,
None))
GenericParam::Type(cx.typaram(self.span, ty_param.ident, vec![], bounds, None))
}
}
}));

View file

@ -187,9 +187,7 @@ impl<'a> Ty<'a> {
let self_params = self_generics.params
.iter()
.filter_map(|param| match *param {
GenericParam::Type(ref ty_param) => {
Some(cx.ty_ident(span, ty_param.ident))
}
GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)),
_ => None,
})
.collect();
@ -272,10 +270,7 @@ impl<'a> LifetimeBounds<'a> {
let bounds = bounds.iter()
.map(|b| cx.lifetime(span, Ident::from_str(b)))
.collect();
GenericParam::Lifetime(cx.lifetime_def(span,
Ident::from_str(lt),
vec![],
bounds))
GenericParam::Lifetime(cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds))
})
.chain(self.bounds
.iter()