Clean up generic param handling

This commit is contained in:
varkor 2018-05-14 12:49:32 +01:00
parent 25bf73d31c
commit 030f10f752
6 changed files with 35 additions and 22 deletions

View File

@ -382,13 +382,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
for param in generics.params.iter() { for param in generics.params.iter() {
let value = match param.kind { let value = match param.kind {
GenericParamDefKind::Type(_) => { GenericParamDefKind::Type(_) => {
let ty = trait_ref.substs.type_for_def(&param); trait_ref.substs[param.index as usize].to_string()
ty.to_string()
}, },
GenericParamDefKind::Lifetime => continue, GenericParamDefKind::Lifetime => continue,
}; };
let name = param.name.to_string(); let name = param.name.to_string();
flags.push((name.clone(), Some(value.clone()))); flags.push((name, Some(value)));
} }
if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) { if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {

View File

@ -290,7 +290,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
let generic_map = generics.params.iter().filter_map(|param| { let generic_map = generics.params.iter().filter_map(|param| {
let value = match param.kind { let value = match param.kind {
GenericParamDefKind::Type(_) => { GenericParamDefKind::Type(_) => {
trait_ref.substs.type_for_def(&param).to_string() trait_ref.substs[param.index as usize].to_string()
}, },
GenericParamDefKind::Lifetime => return None GenericParamDefKind::Lifetime => return None
}; };

View File

@ -837,7 +837,7 @@ impl<'a, 'gcx, 'tcx> Generics {
let param = &self.params[index as usize]; let param = &self.params[index as usize];
match param.kind { match param.kind {
ty::GenericParamDefKind::Lifetime => param, ty::GenericParamDefKind::Lifetime => param,
_ => bug!("expected region parameter, but found another generic parameter") _ => bug!("expected lifetime parameter, but found another generic parameter")
} }
} else { } else {
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?")) tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
@ -851,7 +851,11 @@ impl<'a, 'gcx, 'tcx> Generics {
tcx: TyCtxt<'a, 'gcx, 'tcx>) tcx: TyCtxt<'a, 'gcx, 'tcx>)
-> &'tcx GenericParamDef { -> &'tcx GenericParamDef {
if let Some(index) = param.idx.checked_sub(self.parent_count as u32) { if let Some(index) = param.idx.checked_sub(self.parent_count as u32) {
&self.params[index as usize] let param = &self.params[index as usize];
match param.kind {
ty::GenericParamDefKind::Type(_) => param,
_ => bug!("expected type parameter, but found another generic parameter")
}
} else { } else {
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?")) tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
.type_param(param, tcx) .type_param(param, tcx)

View File

@ -87,6 +87,11 @@ struct ConvertedBinding<'tcx> {
span: Span, span: Span,
} }
struct ParamRange {
required: usize,
accepted: usize
}
/// Dummy type used for the `Self` of a `TraitRef` created for converting /// Dummy type used for the `Self` of a `TraitRef` created for converting
/// a trait object, and which gets removed in `ExistentialTraitRef`. /// a trait object, and which gets removed in `ExistentialTraitRef`.
/// This type must not appear anywhere in other converted types. /// This type must not appear anywhere in other converted types.
@ -212,23 +217,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let lt_provided = parameters.lifetimes.len(); let lt_provided = parameters.lifetimes.len();
let mut lt_accepted = 0; let mut lt_accepted = 0;
let mut ty_range = (0, 0); let mut ty_params = ParamRange { required: 0, accepted: 0 };
for param in &decl_generics.params { for param in &decl_generics.params {
match param.kind { match param.kind {
GenericParamDefKind::Lifetime => { GenericParamDefKind::Lifetime => {
lt_accepted += 1; lt_accepted += 1;
} }
GenericParamDefKind::Type(ty) => { GenericParamDefKind::Type(ty) => {
ty_range.1 += 1; ty_params.accepted += 1;
if !ty.has_default { if !ty.has_default {
ty_range.0 += 1; ty_params.required += 1;
} }
} }
}; };
} }
if self_ty.is_some() { if self_ty.is_some() {
ty_range.0 -= 1; ty_params.required -= 1;
ty_range.1 -= 1; ty_params.accepted -= 1;
} }
if lt_accepted != lt_provided { if lt_accepted != lt_provided {
@ -239,8 +244,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
assert_eq!(decl_generics.has_self, self_ty.is_some()); assert_eq!(decl_generics.has_self, self_ty.is_some());
// Check the number of type parameters supplied by the user. // Check the number of type parameters supplied by the user.
if !infer_types || ty_provided > ty_range.0 { if !infer_types || ty_provided > ty_params.required {
check_type_argument_count(tcx, span, ty_provided, ty_range); check_type_argument_count(tcx, span, ty_provided, ty_params);
} }
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
@ -1327,9 +1332,9 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
fn check_type_argument_count(tcx: TyCtxt, fn check_type_argument_count(tcx: TyCtxt,
span: Span, span: Span,
supplied: usize, supplied: usize,
ty_range: (usize, usize)) ty_params: ParamRange)
{ {
let (required, accepted) = ty_range; let (required, accepted) = (ty_params.required, ty_params.accepted);
if supplied < required { if supplied < required {
let expected = if required < accepted { let expected = if required < accepted {
"expected at least" "expected at least"

View File

@ -4925,27 +4925,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Check provided parameters. // Check provided parameters.
let ((ty_required, ty_accepted), lt_accepted) = let ((ty_required, ty_accepted), lt_accepted) =
segment.map_or(((0, 0), 0), |(_, generics)| { segment.map_or(((0, 0), 0), |(_, generics)| {
struct ParamRange {
required: usize,
accepted: usize
};
let mut lt_accepted = 0; let mut lt_accepted = 0;
let mut ty_range = (0, 0); let mut ty_params = ParamRange { required: 0, accepted: 0 };
for param in &generics.params { for param in &generics.params {
match param.kind { match param.kind {
GenericParamDefKind::Lifetime => { GenericParamDefKind::Lifetime => {
lt_accepted += 1; lt_accepted += 1;
} }
GenericParamDefKind::Type(ty) => { GenericParamDefKind::Type(ty) => {
ty_range.1 += 1; ty_params.accepted += 1;
if !ty.has_default { if !ty.has_default {
ty_range.0 += 1; ty_params.required += 1;
} }
} }
}; };
} }
if generics.parent.is_none() && generics.has_self { if generics.parent.is_none() && generics.has_self {
ty_range.0 -= 1; ty_params.required -= 1;
ty_range.1 -= 1; ty_params.accepted -= 1;
} }
((ty_range.0, ty_range.1), lt_accepted) ((ty_params.required, ty_params.accepted), lt_accepted)
}); });
if types.len() > ty_accepted { if types.len() > ty_accepted {

View File

@ -72,7 +72,7 @@ struct ImplWfCheck<'a, 'tcx: 'a> {
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item) { fn visit_item(&mut self, item: &'tcx hir::Item) {
match item.node { match item.node {
hir::ItemImpl(.., _, _, _, ref impl_item_refs) => { hir::ItemImpl(.., ref impl_item_refs) => {
let impl_def_id = self.tcx.hir.local_def_id(item.id); let impl_def_id = self.tcx.hir.local_def_id(item.id);
enforce_impl_params_are_constrained(self.tcx, enforce_impl_params_are_constrained(self.tcx,
impl_def_id, impl_def_id,