Refactoring generic counting loops
This commit is contained in:
parent
fe1f651e4c
commit
b575c18992
@ -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 => {}
|
||||
|
@ -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(¶meters.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"
|
||||
|
@ -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: \
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user