From b575c18992394f9723ddacee49665351874c7b30 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 11 May 2018 16:12:56 +0100 Subject: [PATCH] Refactoring generic counting loops --- src/librustc/ty/mod.rs | 4 +- src/librustc_typeck/astconv.rs | 66 ++++++++++++++++---------------- src/librustc_typeck/check/mod.rs | 60 +++++++++++++++-------------- src/librustc_typeck/collect.rs | 2 +- src/librustdoc/clean/mod.rs | 6 ++- 5 files changed, 71 insertions(+), 67 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fc085cbd4f8..4818006b9e7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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 => {} diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 50d76d81790..ec685dd8c4c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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" diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2ff760726d2..70d29c60a10 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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: \ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4ddbe584846..d4f9fb948fe 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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"); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 621ec641ee0..17f2c47562f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1339,11 +1339,15 @@ impl Clean for hir::TyParam { impl<'tcx> Clean 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