@@ -796,66 +796,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
796
796
797
797
self . check_pat ( & field. pat , field_ty, def_bm, None ) ;
798
798
}
799
+
799
800
let mut unmentioned_fields = variant. fields
800
801
. iter ( )
801
802
. map ( |field| field. ident . modern ( ) )
802
803
. filter ( |ident| !used_fields. contains_key ( & ident) )
803
804
. 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
- ) ;
840
805
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
+ ) ;
859
813
}
860
814
861
815
// Require `..` if struct has non_exhaustive attribute.
@@ -874,7 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
874
828
tcx. sess . span_err ( span, "`..` cannot be used in union patterns" ) ;
875
829
}
876
830
} 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) ;
878
832
}
879
833
no_field_errors
880
834
}
@@ -890,10 +844,74 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
890
844
. emit ( ) ;
891
845
}
892
846
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
+
893
911
fn error_unmentioned_fields (
894
912
& self ,
895
913
span : Span ,
896
- unmentioned_fields : Vec < ast:: Ident > ,
914
+ unmentioned_fields : & [ ast:: Ident ] ,
897
915
variant : & ty:: VariantDef ,
898
916
) {
899
917
let field_names = if unmentioned_fields. len ( ) == 1 {
0 commit comments