1
Fork 0

clean up check_pat_enum

This commit is contained in:
Ariel Ben-Yehuda 2016-03-04 02:26:42 +02:00
parent b9e61c9f40
commit af55b4189f

View file

@ -599,12 +599,12 @@ fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: b
} }
} }
pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
pat: &hir::Pat, pat: &hir::Pat,
path: &hir::Path, path: &hir::Path,
subpats: Option<&'tcx [P<hir::Pat>]>, subpats: Option<&'tcx [P<hir::Pat>]>,
expected: Ty<'tcx>, expected: Ty<'tcx>,
is_tuple_struct_pat: bool) is_tuple_struct_pat: bool)
{ {
// Typecheck the path. // Typecheck the path.
let fcx = pcx.fcx; let fcx = pcx.fcx;
@ -687,46 +687,14 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
demand::eqtype(fcx, pat.span, expected, pat_ty); demand::eqtype(fcx, pat.span, expected, pat_ty);
let real_path_ty = fcx.node_ty(pat.id); let real_path_ty = fcx.node_ty(pat.id);
let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty { let (kind_name, variant, expected_substs) = match real_path_ty.sty {
ty::TyEnum(enum_def, expected_substs) => { ty::TyEnum(enum_def, expected_substs) => {
let variant = enum_def.variant_of_def(def); let variant = enum_def.variant_of_def(def);
if variant.kind() == ty::VariantKind::Struct { ("variant", variant, expected_substs)
report_bad_struct_kind(false);
return;
}
if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
// Matching unit variants with tuple variant patterns (`UnitVariant(..)`)
// is allowed for backward compatibility.
let is_special_case = variant.kind() == ty::VariantKind::Unit;
report_bad_struct_kind(is_special_case);
if !is_special_case {
return
}
}
(variant.fields
.iter()
.map(|f| fcx.instantiate_type_scheme(pat.span,
expected_substs,
&f.unsubst_ty()))
.collect(),
"variant")
} }
ty::TyStruct(struct_def, expected_substs) => { ty::TyStruct(struct_def, expected_substs) => {
let variant = struct_def.struct_variant(); let variant = struct_def.struct_variant();
if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple { ("struct", variant, expected_substs)
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
// is allowed for backward compatibility.
let is_special_case = variant.kind() == ty::VariantKind::Unit;
report_bad_struct_kind(is_special_case);
return;
}
(variant.fields
.iter()
.map(|f| fcx.instantiate_type_scheme(pat.span,
expected_substs,
&f.unsubst_ty()))
.collect(),
"struct")
} }
_ => { _ => {
report_bad_struct_kind(false); report_bad_struct_kind(false);
@ -734,12 +702,26 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
} }
}; };
match (is_tuple_struct_pat, variant.kind()) {
(true, ty::VariantKind::Unit) => {
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
// is allowed for backward compatibility.
report_bad_struct_kind(true);
}
(_, ty::VariantKind::Struct) => {
report_bad_struct_kind(false);
return
}
_ => {}
}
if let Some(subpats) = subpats { if let Some(subpats) = subpats {
if subpats.len() == arg_tys.len() { if subpats.len() == variant.fields.len() {
for (subpat, arg_ty) in subpats.iter().zip(arg_tys) { for (subpat, field) in subpats.iter().zip(&variant.fields) {
check_pat(pcx, &subpat, arg_ty); let field_ty = fcx.field_ty(subpat.span, field, expected_substs);
check_pat(pcx, &subpat, field_ty);
} }
} else if arg_tys.is_empty() { } else if variant.fields.is_empty() {
span_err!(tcx.sess, pat.span, E0024, span_err!(tcx.sess, pat.span, E0024,
"this pattern has {} field{}, but the corresponding {} has no fields", "this pattern has {} field{}, but the corresponding {} has no fields",
subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name); subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
@ -752,7 +734,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
"this pattern has {} field{}, but the corresponding {} has {} field{}", "this pattern has {} field{}, but the corresponding {} has {} field{}",
subpats.len(), if subpats.len() == 1 {""} else {"s"}, subpats.len(), if subpats.len() == 1 {""} else {"s"},
kind_name, kind_name,
arg_tys.len(), if arg_tys.len() == 1 {""} else {"s"}); variant.fields.len(), if variant.fields.len() == 1 {""} else {"s"});
for pat in subpats { for pat in subpats {
check_pat(pcx, &pat, tcx.types.err); check_pat(pcx, &pat, tcx.types.err);