@@ -796,66 +796,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
796796
797797 self . check_pat ( & field. pat , field_ty, def_bm, None ) ;
798798 }
799+
799800 let mut unmentioned_fields = variant. fields
800801 . iter ( )
801802 . map ( |field| field. ident . modern ( ) )
802803 . filter ( |ident| !used_fields. contains_key ( & ident) )
803804 . collect :: < Vec < _ > > ( ) ;
804- if inexistent_fields. len ( ) > 0 && !variant. recovered {
805- let ( field_names, t, plural) = if inexistent_fields. len ( ) == 1 {
806- ( format ! ( "a field named `{}`" , inexistent_fields[ 0 ] ) , "this" , "" )
807- } else {
808- ( format ! ( "fields named {}" ,
809- inexistent_fields. iter( )
810- . map( |ident| format!( "`{}`" , ident) )
811- . collect:: <Vec <String >>( )
812- . join( ", " ) ) , "these" , "s" )
813- } ;
814- let spans = inexistent_fields. iter ( ) . map ( |ident| ident. span ) . collect :: < Vec < _ > > ( ) ;
815- let mut err = struct_span_err ! ( tcx. sess,
816- spans,
817- E0026 ,
818- "{} `{}` does not have {}" ,
819- kind_name,
820- tcx. def_path_str( variant. def_id) ,
821- field_names) ;
822- if let Some ( ident) = inexistent_fields. last ( ) {
823- err. span_label ( ident. span ,
824- format ! ( "{} `{}` does not have {} field{}" ,
825- kind_name,
826- tcx. def_path_str( variant. def_id) ,
827- t,
828- plural) ) ;
829- if plural == "" {
830- let input = unmentioned_fields. iter ( ) . map ( |field| & field. name ) ;
831- let suggested_name =
832- find_best_match_for_name ( input, & ident. as_str ( ) , None ) ;
833- if let Some ( suggested_name) = suggested_name {
834- err. span_suggestion (
835- ident. span ,
836- "a field with a similar name exists" ,
837- suggested_name. to_string ( ) ,
838- Applicability :: MaybeIncorrect ,
839- ) ;
840805
841- // we don't want to throw `E0027` in case we have thrown `E0026` for them
842- unmentioned_fields. retain ( |& x| x. as_str ( ) != suggested_name. as_str ( ) ) ;
843- }
844- }
845- }
846- if tcx. sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
847- err. note (
848- "This error indicates that a struct pattern attempted to \
849- extract a non-existent field from a struct. Struct fields \
850- are identified by the name used before the colon : so struct \
851- patterns should resemble the declaration of the struct type \
852- being matched.\n \n \
853- If you are using shorthand field patterns but want to refer \
854- to the struct field by a different name, you should rename \
855- it explicitly."
856- ) ;
857- }
858- err. emit ( ) ;
806+ if inexistent_fields. len ( ) > 0 && !variant. recovered {
807+ self . error_inexistent_fields (
808+ kind_name,
809+ & inexistent_fields,
810+ & mut unmentioned_fields,
811+ variant
812+ ) ;
859813 }
860814
861815 // Require `..` if struct has non_exhaustive attribute.
@@ -874,7 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
874828 tcx. sess . span_err ( span, "`..` cannot be used in union patterns" ) ;
875829 }
876830 } else if !etc && unmentioned_fields. len ( ) > 0 {
877- self . error_unmentioned_fields ( span, unmentioned_fields, variant) ;
831+ self . error_unmentioned_fields ( span, & unmentioned_fields, variant) ;
878832 }
879833 no_field_errors
880834 }
@@ -890,10 +844,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
890844 . emit ( ) ;
891845 }
892846
847+ fn error_inexistent_fields (
848+ & self ,
849+ kind_name : & str ,
850+ inexistent_fields : & [ ast:: Ident ] ,
851+ unmentioned_fields : & mut Vec < ast:: Ident > ,
852+ variant : & ty:: VariantDef ,
853+ ) {
854+ let tcx = self . tcx ;
855+ let ( field_names, t, plural) = if inexistent_fields. len ( ) == 1 {
856+ ( format ! ( "a field named `{}`" , inexistent_fields[ 0 ] ) , "this" , "" )
857+ } else {
858+ ( format ! ( "fields named {}" ,
859+ inexistent_fields. iter( )
860+ . map( |ident| format!( "`{}`" , ident) )
861+ . collect:: <Vec <String >>( )
862+ . join( ", " ) ) , "these" , "s" )
863+ } ;
864+ let spans = inexistent_fields. iter ( ) . map ( |ident| ident. span ) . collect :: < Vec < _ > > ( ) ;
865+ let mut err = struct_span_err ! ( tcx. sess,
866+ spans,
867+ E0026 ,
868+ "{} `{}` does not have {}" ,
869+ kind_name,
870+ tcx. def_path_str( variant. def_id) ,
871+ field_names) ;
872+ if let Some ( ident) = inexistent_fields. last ( ) {
873+ err. span_label ( ident. span ,
874+ format ! ( "{} `{}` does not have {} field{}" ,
875+ kind_name,
876+ tcx. def_path_str( variant. def_id) ,
877+ t,
878+ plural) ) ;
879+ if plural == "" {
880+ let input = unmentioned_fields. iter ( ) . map ( |field| & field. name ) ;
881+ let suggested_name =
882+ find_best_match_for_name ( input, & ident. as_str ( ) , None ) ;
883+ if let Some ( suggested_name) = suggested_name {
884+ err. span_suggestion (
885+ ident. span ,
886+ "a field with a similar name exists" ,
887+ suggested_name. to_string ( ) ,
888+ Applicability :: MaybeIncorrect ,
889+ ) ;
890+
891+ // we don't want to throw `E0027` in case we have thrown `E0026` for them
892+ unmentioned_fields. retain ( |& x| x. as_str ( ) != suggested_name. as_str ( ) ) ;
893+ }
894+ }
895+ }
896+ if tcx. sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
897+ err. note (
898+ "This error indicates that a struct pattern attempted to \
899+ extract a non-existent field from a struct. Struct fields \
900+ are identified by the name used before the colon : so struct \
901+ patterns should resemble the declaration of the struct type \
902+ being matched.\n \n \
903+ If you are using shorthand field patterns but want to refer \
904+ to the struct field by a different name, you should rename \
905+ it explicitly."
906+ ) ;
907+ }
908+ err. emit ( ) ;
909+ }
910+
893911 fn error_unmentioned_fields (
894912 & self ,
895913 span : Span ,
896- unmentioned_fields : Vec < ast:: Ident > ,
914+ unmentioned_fields : & [ ast:: Ident ] ,
897915 variant : & ty:: VariantDef ,
898916 ) {
899917 let field_names = if unmentioned_fields. len ( ) == 1 {
0 commit comments