@@ -835,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
835835 on_error ( ) ;
836836 return tcx. types . err ;
837837 }
838- Res :: Def ( DefKind :: AssocConst , _ ) | Res :: Def ( DefKind :: AssocFn , _) => {
838+ Res :: Def ( DefKind :: AssocConst | DefKind :: AssocFn , _) => {
839839 report_unexpected_res ( res) ;
840840 return tcx. types . err ;
841841 }
@@ -1020,7 +1020,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10201020 ty:: Adt ( adt, substs) => ( substs, adt) ,
10211021 _ => span_bug ! ( pat. span, "struct pattern is not an ADT" ) ,
10221022 } ;
1023- let kind_name = adt. variant_descr ( ) ;
10241023
10251024 // Index the struct fields' types.
10261025 let field_map = variant
@@ -1074,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10741073
10751074 if !inexistent_fields. is_empty ( ) && !variant. recovered {
10761075 self . error_inexistent_fields (
1077- kind_name ,
1076+ adt . variant_descr ( ) ,
10781077 & inexistent_fields,
10791078 & mut unmentioned_fields,
10801079 variant,
@@ -1083,18 +1082,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10831082
10841083 // Require `..` if struct has non_exhaustive attribute.
10851084 if variant. is_field_list_non_exhaustive ( ) && !adt. did . is_local ( ) && !etc {
1086- struct_span_err ! (
1087- tcx. sess,
1088- pat. span,
1089- E0638 ,
1090- "`..` required with {} marked as non-exhaustive" ,
1091- kind_name
1092- )
1093- . emit ( ) ;
1085+ self . error_foreign_non_exhaustive_spat ( pat, adt. variant_descr ( ) , fields. is_empty ( ) ) ;
10941086 }
10951087
10961088 // Report an error if incorrect number of the fields were specified.
1097- if kind_name == "union" {
1089+ if adt . is_union ( ) {
10981090 if fields. len ( ) != 1 {
10991091 tcx. sess
11001092 . struct_span_err ( pat. span , "union patterns should have exactly one field" )
@@ -1109,6 +1101,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11091101 no_field_errors
11101102 }
11111103
1104+ fn error_foreign_non_exhaustive_spat ( & self , pat : & Pat < ' _ > , descr : & str , no_fields : bool ) {
1105+ let sess = self . tcx . sess ;
1106+ let sm = sess. source_map ( ) ;
1107+ let sp_brace = sm. end_point ( pat. span ) ;
1108+ let sp_comma = sm. end_point ( pat. span . with_hi ( sp_brace. hi ( ) ) ) ;
1109+ let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" } ;
1110+
1111+ let mut err = struct_span_err ! (
1112+ sess,
1113+ pat. span,
1114+ E0638 ,
1115+ "`..` required with {} marked as non-exhaustive" ,
1116+ descr
1117+ ) ;
1118+ err. span_suggestion_verbose (
1119+ sp_comma,
1120+ "add `..` at the end of the field list to ignore all other fields" ,
1121+ sugg. to_string ( ) ,
1122+ Applicability :: MachineApplicable ,
1123+ ) ;
1124+ err. emit ( ) ;
1125+ }
1126+
11121127 fn error_field_already_bound ( & self , span : Span , ident : ast:: Ident , other_field : Span ) {
11131128 struct_span_err ! (
11141129 self . tcx. sess,
0 commit comments