@@ -904,6 +904,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
904904        // Keep track of which fields have already appeared in the pattern. 
905905        let  mut  used_fields = FxHashMap ( ) ; 
906906
907+         let  mut  inexistent_fields = vec ! [ ] ; 
907908        // Typecheck each field. 
908909        for  & Spanned  {  node :  ref  field,  span }  in  fields { 
909910            let  field_ty = match  used_fields. entry ( field. name )  { 
@@ -927,34 +928,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
927928                            self . field_ty ( span,  f,  substs) 
928929                        } ) 
929930                        . unwrap_or_else ( || { 
930-                             let  mut  err = struct_span_err ! ( 
931-                                 tcx. sess, 
932-                                 span, 
933-                                 E0026 , 
934-                                 "{} `{}` does not have a field named `{}`" , 
935-                                 kind_name, 
936-                                 tcx. item_path_str( variant. did) , 
937-                                 field. name
938-                             ) ; 
939-                             err. span_label ( span, 
940-                                            format ! ( "{} `{}` does not have field `{}`" , 
941-                                                    kind_name, 
942-                                                    tcx. item_path_str( variant. did) , 
943-                                                    field. name) ) ; 
944-                             if  tcx. sess . teach ( & err. get_code ( ) . unwrap ( ) )  { 
945-                                 err. note ( 
946-                                     "This error indicates that a struct pattern attempted to \  
947- \ 
948- \ 
949- \ 
950- \n \n \ 
951- \ 
952- \ 
953- 
954-                                 ) ; 
955-                             } 
956-                             err. emit ( ) ; 
957- 
931+                             inexistent_fields. push ( ( span,  field. name ) ) ; 
958932                            tcx. types . err 
959933                        } ) 
960934                } 
@@ -963,6 +937,47 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
963937            self . check_pat_walk ( & field. pat ,  field_ty,  def_bm,  true ) ; 
964938        } 
965939
940+         if  inexistent_fields. len ( )  > 0  { 
941+             let  ( field_names,  t,  plural)  = if  inexistent_fields. len ( )  == 1  { 
942+                 ( format ! ( "a field named `{}`" ,  inexistent_fields[ 0 ] . 1 ) ,  "this" ,  "" ) 
943+             }  else  { 
944+                 ( format ! ( "fields named {}" , 
945+                          inexistent_fields. iter( ) 
946+                             . map( |( _,  name) | format!( "`{}`" ,  name) ) 
947+                             . collect:: <Vec <String >>( ) 
948+                             . join( ", " ) ) ,  "these" ,  "s" ) 
949+             } ; 
950+             let  spans = inexistent_fields. iter ( ) . map ( |( span,  _) | * span) . collect :: < Vec < _ > > ( ) ; 
951+             let  mut  err = struct_span_err ! ( tcx. sess, 
952+                                            spans, 
953+                                            E0026 , 
954+                                            "{} `{}` does not have {}" , 
955+                                            kind_name, 
956+                                            tcx. item_path_str( variant. did) , 
957+                                            field_names) ; 
958+             if  let  Some ( ( span,  _) )  = inexistent_fields. last ( )  { 
959+                 err. span_label ( * span, 
960+                                format ! ( "{} `{}` does not have {} field{}" , 
961+                                        kind_name, 
962+                                        tcx. item_path_str( variant. did) , 
963+                                        t, 
964+                                        plural) ) ; 
965+             } 
966+             if  tcx. sess . teach ( & err. get_code ( ) . unwrap ( ) )  { 
967+                 err. note ( 
968+                     "This error indicates that a struct pattern attempted to \  
969+ \ 
970+ \ 
971+ \ 
972+ \n \n \ 
973+ \ 
974+ \ 
975+ 
976+                 ) ; 
977+             } 
978+             err. emit ( ) ; 
979+         } 
980+ 
966981        // Require `..` if struct has non_exhaustive attribute. 
967982        if  adt. is_struct ( )  && adt. is_non_exhaustive ( )  && !adt. did . is_local ( )  && !etc { 
968983            span_err ! ( tcx. sess,  span,  E0638 , 
@@ -979,13 +994,25 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
979994                tcx. sess . span_err ( span,  "`..` cannot be used in union patterns" ) ; 
980995            } 
981996        }  else  if  !etc { 
982-             for  field  in  variant. fields 
997+             let  unmentioned_fields =  variant. fields 
983998                . iter ( ) 
984-                 . filter ( |field| !used_fields. contains_key ( & field. name ) )  { 
999+                 . map ( |field| field. name ) 
1000+                 . filter ( |field| !used_fields. contains_key ( & field) ) 
1001+                 . collect :: < Vec < _ > > ( ) ; 
1002+             if  unmentioned_fields. len ( )  > 0  { 
1003+                 let  field_names = if  unmentioned_fields. len ( )  == 1  { 
1004+                     format ! ( "field `{}`" ,  unmentioned_fields[ 0 ] ) 
1005+                 }  else  { 
1006+                     format ! ( "fields {}" , 
1007+                             unmentioned_fields. iter( ) 
1008+                                 . map( |name| format!( "`{}`" ,  name) ) 
1009+                                 . collect:: <Vec <String >>( ) 
1010+                                 . join( ", " ) ) 
1011+                 } ; 
9851012                let  mut  diag = struct_span_err ! ( tcx. sess,  span,  E0027 , 
986-                                                 "pattern does not mention field `{}` " , 
987-                                                 field . name ) ; 
988-                 diag. span_label ( span,  format ! ( "missing field `{}` " ,  field . name ) ) ; 
1013+                                                 "pattern does not mention {} " , 
1014+                                                 field_names ) ; 
1015+                 diag. span_label ( span,  format ! ( "missing {} " ,  field_names ) ) ; 
9891016                if  variant. ctor_kind  == CtorKind :: Fn  { 
9901017                    diag. note ( "trying to match a tuple variant with a struct variant pattern" ) ; 
9911018                } 
0 commit comments