From 4573bb8e967e8f21f711bf9fd1dd756342829b1f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 16 Nov 2015 17:26:14 +0300 Subject: [PATCH] Add special case for `UnitVariant(..)` patterns --- src/librustc_typeck/check/_match.rs | 25 +++++++++++-------- .../compile-fail/empty-struct-unit-pat.rs | 2 +- .../match-pattern-field-mismatch-2.rs | 3 ++- .../compile-fail/pattern-error-continue.rs | 3 ++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 21958387056d9..7cc81027f024a 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -139,7 +139,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => { if let hir::PatEnum(ref path, ref subpats) = pat.node { if !(subpats.is_some() && subpats.as_ref().unwrap().is_empty()) { - bad_struct_kind_err(tcx.sess, pat.span, path); + bad_struct_kind_err(tcx.sess, pat.span, path, false); return; } } @@ -581,9 +581,9 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat, } // This function exists due to the warning "diagnostic code E0164 already used" -fn bad_struct_kind_err(sess: &Session, span: Span, path: &hir::Path) { +fn bad_struct_kind_err(sess: &Session, span: Span, path: &hir::Path, is_warning: bool) { let name = pprust::path_to_string(path); - span_err!(sess, span, E0164, + span_err_or_warn!(is_warning, sess, span, E0164, "`{}` does not name a tuple variant or a tuple struct", name); } @@ -634,8 +634,8 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, path_scheme, &ctor_predicates, opt_ty, def, pat.span, pat.id); - let report_bad_struct_kind = || { - bad_struct_kind_err(tcx.sess, pat.span, path); + let report_bad_struct_kind = |is_warning| { + bad_struct_kind_err(tcx.sess, pat.span, path, is_warning); fcx.write_error(pat.id); if let Some(subpats) = subpats { @@ -650,7 +650,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, // function uses checks specific to structs and enums. if path_res.depth != 0 { if is_tuple_struct_pat { - report_bad_struct_kind(); + report_bad_struct_kind(false); } else { let pat_ty = fcx.node_ty(pat.id); demand::suptype(fcx, pat.span, expected, pat_ty); @@ -668,8 +668,13 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, { let variant = enum_def.variant_of_def(def); if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple { - report_bad_struct_kind(); - return; + // 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() @@ -682,7 +687,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, ty::TyStruct(struct_def, expected_substs) => { let variant = struct_def.struct_variant(); if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple { - report_bad_struct_kind(); + report_bad_struct_kind(false); return; } (variant.fields @@ -694,7 +699,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, "struct") } _ => { - report_bad_struct_kind(); + report_bad_struct_kind(false); return; } }; diff --git a/src/test/compile-fail/empty-struct-unit-pat.rs b/src/test/compile-fail/empty-struct-unit-pat.rs index f9af71527a17e..6cb9a3f007f0c 100644 --- a/src/test/compile-fail/empty-struct-unit-pat.rs +++ b/src/test/compile-fail/empty-struct-unit-pat.rs @@ -34,6 +34,6 @@ fn main() { // E::Empty2() => () // ERROR `E::Empty2` does not name a tuple variant or a tuple struct // } match e2 { - E::Empty2(..) => () //~ ERROR `E::Empty2` does not name a tuple variant or a tuple struct + E::Empty2(..) => () //~ WARN `E::Empty2` does not name a tuple variant or a tuple struct } } diff --git a/src/test/compile-fail/match-pattern-field-mismatch-2.rs b/src/test/compile-fail/match-pattern-field-mismatch-2.rs index a4ba93ea17333..17debdabb61f0 100644 --- a/src/test/compile-fail/match-pattern-field-mismatch-2.rs +++ b/src/test/compile-fail/match-pattern-field-mismatch-2.rs @@ -20,7 +20,8 @@ fn main() { color::rgb(_, _, _) => { } color::cmyk(_, _, _, _) => { } color::no_color(_) => { } - //~^ ERROR `color::no_color` does not name a tuple variant or a tuple struct + //~^ ERROR this pattern has 1 field, but the corresponding variant has no fields + //~^^ WARN `color::no_color` does not name a tuple variant or a tuple struct } } } diff --git a/src/test/compile-fail/pattern-error-continue.rs b/src/test/compile-fail/pattern-error-continue.rs index 891a586423efc..1721d1f0ae11c 100644 --- a/src/test/compile-fail/pattern-error-continue.rs +++ b/src/test/compile-fail/pattern-error-continue.rs @@ -25,7 +25,8 @@ fn f(_c: char) {} fn main() { match A::B(1, 2) { A::B(_, _, _) => (), //~ ERROR this pattern has 3 fields, but - A::D(_) => (), //~ ERROR `A::D` does not name a tuple variant or a tuple struct + A::D(_) => (), //~ ERROR this pattern has 1 field, but + //~^ WARN `A::D` does not name a tuple variant or a tuple struct _ => () } match 'c' {