Refactoring generic counting loops

This commit is contained in:
varkor 2018-05-11 16:12:56 +01:00
parent fe1f651e4c
commit b575c18992
5 changed files with 71 additions and 67 deletions

View File

@ -803,7 +803,7 @@ impl<'a, 'gcx, 'tcx> Generics {
types: 0,
};
for param in self.params.iter() {
for param in &self.params {
match param.kind {
GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
GenericParamDefKind::Type(_) => own_counts.types += 1,
@ -814,7 +814,7 @@ impl<'a, 'gcx, 'tcx> Generics {
}
pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
for param in self.params.iter() {
for param in &self.params {
match param.kind {
GenericParamDefKind::Type(_) => return true,
GenericParamDefKind::Lifetime => {}

View File

@ -208,40 +208,39 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
// region with the current anon region binding (in other words,
// whatever & would get replaced with).
let decl_generics = tcx.generics_of(def_id);
let own_counts = decl_generics.own_counts();
let num_types_provided = parameters.types.len();
let expected_num_region_params = own_counts.lifetimes;
let supplied_num_region_params = parameters.lifetimes.len();
if expected_num_region_params != supplied_num_region_params {
report_lifetime_number_error(tcx, span,
supplied_num_region_params,
expected_num_region_params);
let ty_provided = parameters.types.len();
let lt_provided = parameters.lifetimes.len();
let mut lt_accepted = 0;
let mut ty_range = (0, 0);
for param in &decl_generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {
lt_accepted += 1;
}
GenericParamDefKind::Type(ty) => {
ty_range.1 += 1;
if !ty.has_default {
ty_range.0 += 1;
}
}
};
}
if self_ty.is_some() {
ty_range.0 -= 1;
ty_range.1 -= 1;
}
if lt_accepted != lt_provided {
report_lifetime_number_error(tcx, span, lt_provided, lt_accepted);
}
// If a self-type was declared, one should be provided.
assert_eq!(decl_generics.has_self, self_ty.is_some());
// Check the number of type parameters supplied by the user.
let own_self = self_ty.is_some() as usize;
let ty_param_defs = own_counts.types - own_self;
if !infer_types || num_types_provided > ty_param_defs {
let type_params_without_defaults = {
let mut count = 0;
for param in decl_generics.params.iter() {
if let ty::GenericParamDefKind::Type(ty) = param.kind {
if !ty.has_default {
count += 1
}
}
}
count
};
check_type_argument_count(tcx,
span,
num_types_provided,
ty_param_defs,
type_params_without_defaults - own_self);
if !infer_types || ty_provided > ty_range.0 {
check_type_argument_count(tcx, span, ty_provided, ty_range);
}
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
@ -259,6 +258,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
false
};
let own_self = self_ty.is_some() as usize;
let substs = Substs::for_item(tcx, def_id, |def, _| {
let i = def.index as usize - own_self;
if let Some(lifetime) = parameters.lifetimes.get(i) {
@ -279,8 +279,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
_ => unreachable!()
};
let i = i - (own_counts.lifetimes + own_self);
if i < num_types_provided {
let i = i - (lt_accepted + own_self);
if i < ty_provided {
// A provided type parameter.
self.ast_ty_to_ty(&parameters.types[i])
} else if infer_types {
@ -1327,11 +1327,9 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
fn check_type_argument_count(tcx: TyCtxt,
span: Span,
supplied: usize,
ty_param_defs: usize,
ty_param_defs_without_default: usize)
ty_range: (usize, usize))
{
let accepted = ty_param_defs;
let required = ty_param_defs_without_default;
let (required, accepted) = ty_range;
if supplied < required {
let expected = if required < accepted {
"expected at least"

View File

@ -4923,32 +4923,34 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
// Check provided parameters.
let (ty_req_len, accepted, lt_req_len) =
segment.map_or((0, 0, 0), |(_, generics)| {
let own_counts = generics.own_counts();
let own_self = (generics.parent.is_none() && generics.has_self) as usize;
let type_params = own_counts.types - own_self;
let type_params_without_defaults = {
let mut count = 0;
for param in generics.params.iter() {
if let ty::GenericParamDefKind::Type(ty) = param.kind {
let ((ty_required, ty_accepted), lt_accepted) =
segment.map_or(((0, 0), 0), |(_, generics)| {
let mut lt_accepted = 0;
let mut ty_range = (0, 0);
for param in &generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {
lt_accepted += 1;
}
GenericParamDefKind::Type(ty) => {
ty_range.1 += 1;
if !ty.has_default {
count += 1
ty_range.0 += 1;
}
}
}
count
};
let type_params_barring_defaults =
type_params_without_defaults - own_self;
};
}
if generics.parent.is_none() && generics.has_self {
ty_range.0 -= 1;
ty_range.1 -= 1;
}
(type_params_barring_defaults, type_params, own_counts.lifetimes)
((ty_range.0, ty_range.1), lt_accepted)
});
if types.len() > accepted {
let span = types[accepted].span;
let expected_text = count_type_params(accepted);
if types.len() > ty_accepted {
let span = types[ty_accepted].span;
let expected_text = count_type_params(ty_accepted);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0087,
"too many type parameters provided: \
@ -4961,8 +4963,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_req_len && !infer_types && !supress_mismatch_error {
let expected_text = count_type_params(ty_req_len);
} else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
let expected_text = count_type_params(ty_required);
let actual_text = count_type_params(types.len());
struct_span_err!(self.tcx.sess, span, E0089,
"too few type parameters provided: \
@ -4984,8 +4986,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let primary_msg = "cannot specify lifetime arguments explicitly \
if late bound lifetime parameters are present";
let note_msg = "the late bound lifetime parameter is introduced here";
if !is_method_call && (lifetimes.len() > lt_req_len ||
lifetimes.len() < lt_req_len && !infer_lifetimes) {
if !is_method_call && (lifetimes.len() > lt_accepted ||
lifetimes.len() < lt_accepted && !infer_lifetimes) {
let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
err.span_note(span_late, note_msg);
err.emit();
@ -4999,9 +5001,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
return;
}
if lifetimes.len() > lt_req_len {
let span = lifetimes[lt_req_len].span;
let expected_text = count_lifetime_params(lt_req_len);
if lifetimes.len() > lt_accepted {
let span = lifetimes[lt_accepted].span;
let expected_text = count_lifetime_params(lt_accepted);
let actual_text = count_lifetime_params(lifetimes.len());
struct_span_err!(self.tcx.sess, span, E0088,
"too many lifetime parameters provided: \
@ -5009,8 +5011,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected_text, actual_text)
.span_label(span, format!("expected {}", expected_text))
.emit();
} else if lifetimes.len() < lt_req_len && !infer_lifetimes {
let expected_text = count_lifetime_params(lt_req_len);
} else if lifetimes.len() < lt_accepted && !infer_lifetimes {
let expected_text = count_lifetime_params(lt_accepted);
let actual_text = count_lifetime_params(lifetimes.len());
struct_span_err!(self.tcx.sess, span, E0090,
"too few lifetime parameters provided: \

View File

@ -903,7 +903,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id);
// Now create the real type parameters.
let type_start = params.len() as u32;
let type_start = own_start - has_self as u32 + params.len() as u32;
params.extend(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");

View File

@ -1339,11 +1339,15 @@ impl Clean<TyParam> for hir::TyParam {
impl<'tcx> Clean<TyParam> for ty::GenericParamDef {
fn clean(&self, cx: &DocContext) -> TyParam {
cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
let has_default = match self.kind {
ty::GenericParamDefKind::Type(ty) => ty.has_default,
_ => panic!("tried to convert a non-type GenericParamDef as a type")
};
TyParam {
name: self.name.clean(cx),
did: self.def_id,
bounds: vec![], // these are filled in from the where-clauses
default: if self.to_type().has_default {
default: if has_default {
Some(cx.tcx.type_of(self.def_id).clean(cx))
} else {
None