@@ -19,6 +19,7 @@ use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
19
19
use check:: { check_expr_coercable_to_type, demand, FnCtxt , Expectation } ;
20
20
use check:: { check_expr_with_lvalue_pref} ;
21
21
use check:: { instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type} ;
22
+ use lint;
22
23
use require_same_types;
23
24
use util:: nodemap:: FnvHashMap ;
24
25
use session:: Session ;
@@ -138,7 +139,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
138
139
if pat_is_resolved_const ( & tcx. def_map . borrow ( ) , pat) => {
139
140
if let hir:: PatEnum ( ref path, ref subpats) = pat. node {
140
141
if !( subpats. is_some ( ) && subpats. as_ref ( ) . unwrap ( ) . is_empty ( ) ) {
141
- bad_struct_kind_err ( tcx. sess , pat. span , path, false ) ;
142
+ bad_struct_kind_err ( tcx. sess , pat, path, false ) ;
142
143
return ;
143
144
}
144
145
}
@@ -580,10 +581,21 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
580
581
}
581
582
582
583
// This function exists due to the warning "diagnostic code E0164 already used"
583
- fn bad_struct_kind_err ( sess : & Session , span : Span , path : & hir:: Path , is_warning : bool ) {
584
+ fn bad_struct_kind_err ( sess : & Session , pat : & hir :: Pat , path : & hir:: Path , lint : bool ) {
584
585
let name = pprust:: path_to_string ( path) ;
585
- span_err_or_warn ! ( is_warning, sess, span, E0164 ,
586
- "`{}` does not name a tuple variant or a tuple struct" , name) ;
586
+ let msg = format ! ( "`{}` does not name a tuple variant or a tuple struct" , name) ;
587
+ if lint {
588
+ let expanded_msg =
589
+ format ! ( "{}; RFC 218 disallowed matching of unit variants or unit structs via {}(..)" ,
590
+ msg,
591
+ name) ;
592
+ sess. add_lint ( lint:: builtin:: MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT ,
593
+ pat. id ,
594
+ pat. span ,
595
+ expanded_msg) ;
596
+ } else {
597
+ span_err ! ( sess, pat. span, E0164 , "{}" , msg) ;
598
+ }
587
599
}
588
600
589
601
pub fn check_pat_enum < ' a , ' tcx > ( pcx : & pat_ctxt < ' a , ' tcx > ,
@@ -634,11 +646,8 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
634
646
opt_ty, def, pat. span , pat. id ) ;
635
647
636
648
let report_bad_struct_kind = |is_warning| {
637
- bad_struct_kind_err ( tcx. sess , pat. span , path, is_warning) ;
638
- if is_warning {
639
- return
640
- }
641
-
649
+ bad_struct_kind_err ( tcx. sess , pat, path, is_warning) ;
650
+ if is_warning { return ; }
642
651
fcx. write_error ( pat. id ) ;
643
652
if let Some ( subpats) = subpats {
644
653
for pat in subpats {
@@ -676,10 +685,6 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
676
685
report_bad_struct_kind ( is_special_case) ;
677
686
if !is_special_case {
678
687
return
679
- } else {
680
- span_note ! ( tcx. sess, pat. span,
681
- "this warning will become a HARD ERROR in a future release. \
682
- See RFC 218 for details.") ;
683
688
}
684
689
}
685
690
( variant. fields
@@ -693,7 +698,10 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
693
698
ty:: TyStruct ( struct_def, expected_substs) => {
694
699
let variant = struct_def. struct_variant ( ) ;
695
700
if is_tuple_struct_pat && variant. kind ( ) != ty:: VariantKind :: Tuple {
696
- report_bad_struct_kind ( false ) ;
701
+ // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
702
+ // is allowed for backward compatibility.
703
+ let is_special_case = variant. kind ( ) == ty:: VariantKind :: Unit ;
704
+ report_bad_struct_kind ( is_special_case) ;
697
705
return ;
698
706
}
699
707
( variant. fields
0 commit comments