1111use hir:: def:: Def ;
1212use rustc:: infer:: { self , InferOk , TypeOrigin } ;
1313use hir:: pat_util:: EnumerateAndAdjustIterator ;
14- use rustc:: ty:: subst:: Substs ;
1514use rustc:: ty:: { self , Ty , TypeFoldable , LvaluePreference , VariantKind } ;
1615use check:: { FnCtxt , Expectation } ;
1716use lint;
@@ -509,11 +508,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
509508 self . demand_eqtype ( pat. span , expected, pat_ty) ;
510509
511510 // Type check subpatterns.
512- let substs = match pat_ty. sty {
513- ty:: TyStruct ( _, substs) | ty:: TyUnion ( _, substs) | ty:: TyEnum ( _, substs) => substs,
514- _ => span_bug ! ( pat. span, "struct variant is not an ADT" )
515- } ;
516- self . check_struct_pat_fields ( pat. span , fields, variant, substs, etc) ;
511+ self . check_struct_pat_fields ( pat_ty, pat. span , variant, fields, etc) ;
517512 }
518513
519514 fn check_pat_path ( & self ,
@@ -658,19 +653,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
658653 }
659654 }
660655
661- /// `path` is the AST path item naming the type of this struct.
662- /// `fields` is the field patterns of the struct pattern.
663- /// `struct_fields` describes the type of each field of the struct.
664- /// `struct_id` is the ID of the struct.
665- /// `etc` is true if the pattern said '...' and false otherwise.
666- pub fn check_struct_pat_fields ( & self ,
667- span : Span ,
668- fields : & ' gcx [ Spanned < hir:: FieldPat > ] ,
669- variant : ty:: VariantDef < ' tcx > ,
670- substs : & Substs < ' tcx > ,
671- etc : bool ) {
656+ fn check_struct_pat_fields ( & self ,
657+ adt_ty : Ty < ' tcx > ,
658+ span : Span ,
659+ variant : ty:: VariantDef < ' tcx > ,
660+ fields : & ' gcx [ Spanned < hir:: FieldPat > ] ,
661+ etc : bool ) {
672662 let tcx = self . tcx ;
673663
664+ let ( substs, kind_name) = match adt_ty. sty {
665+ ty:: TyEnum ( _, substs) => ( substs, "variant" ) ,
666+ ty:: TyStruct ( _, substs) => ( substs, "struct" ) ,
667+ ty:: TyUnion ( _, substs) => ( substs, "union" ) ,
668+ _ => span_bug ! ( span, "struct pattern is not an ADT" )
669+ } ;
670+
674671 // Index the struct fields' types.
675672 let field_map = variant. fields
676673 . iter ( )
@@ -700,11 +697,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
700697 . map ( |f| self . field_ty ( span, f, substs) )
701698 . unwrap_or_else ( || {
702699 struct_span_err ! ( tcx. sess, span, E0026 ,
703- "struct `{}` does not have a field named `{}`" ,
700+ "{} `{}` does not have a field named `{}`" ,
701+ kind_name,
704702 tcx. item_path_str( variant. did) ,
705703 field. name)
706704 . span_label ( span,
707- & format ! ( "struct `{}` does not have field `{}`" ,
705+ & format ! ( "{} `{}` does not have field `{}`" ,
706+ kind_name,
708707 tcx. item_path_str( variant. did) ,
709708 field. name) )
710709 . emit ( ) ;
@@ -717,8 +716,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
717716 self . check_pat ( & field. pat , field_ty) ;
718717 }
719718
720- // Report an error if not all the fields were specified.
721- if !etc {
719+ // Report an error if incorrect number of the fields were specified.
720+ if kind_name == "union" {
721+ if fields. len ( ) > 1 {
722+ tcx. sess . span_err ( span, "union patterns can have at most one field" ) ;
723+ }
724+ if fields. is_empty ( ) && !etc {
725+ tcx. sess . span_err ( span, "union patterns without `..` \
726+ should have at least one field") ;
727+ }
728+ } else if !etc {
722729 for field in variant. fields
723730 . iter ( )
724731 . filter ( |field| !used_fields. contains_key ( & field. name ) ) {
0 commit comments