@@ -13,7 +13,7 @@ use rustc_ast::walk_list;
1313use rustc_ast:: * ;
1414use rustc_ast_pretty:: pprust:: { self , State } ;
1515use rustc_data_structures:: fx:: FxHashMap ;
16- use rustc_errors:: { error_code, fluent, pluralize, struct_span_err, Applicability , Diagnostic } ;
16+ use rustc_errors:: { error_code, fluent, pluralize, struct_span_err, Applicability } ;
1717use rustc_parse:: validate_attr;
1818use rustc_session:: lint:: builtin:: {
1919 DEPRECATED_WHERE_CLAUSE_LOCATION , MISSING_ABI , PATTERNS_IN_FNS_WITHOUT_BODY ,
@@ -390,47 +390,20 @@ impl<'a> AstValidator<'a> {
390390 fn check_defaultness ( & self , span : Span , defaultness : Defaultness ) {
391391 if let Defaultness :: Default ( def_span) = defaultness {
392392 let span = self . session . source_map ( ) . guess_head_span ( span) ;
393- self . err_handler ( )
394- . struct_span_err ( span, "`default` is only allowed on items in trait impls" )
395- . span_label ( def_span, "`default` because of this" )
396- . emit ( ) ;
393+ self . session . emit_err ( ForbiddenDefault { span, def_span } ) ;
397394 }
398395 }
399396
400- fn error_item_without_body ( & self , sp : Span , ctx : & str , msg : & str , sugg : & str ) {
401- self . error_item_without_body_with_help ( sp, ctx, msg, sugg, |_| ( ) ) ;
402- }
403-
404- fn error_item_without_body_with_help (
405- & self ,
406- sp : Span ,
407- ctx : & str ,
408- msg : & str ,
409- sugg : & str ,
410- help : impl FnOnce ( & mut Diagnostic ) ,
411- ) {
397+ /// If `sp` ends with a semicolon, returns it as a `Span`
398+ /// Otherwise, returns `sp.shrink_to_hi()`
399+ fn ending_semi_or_hi ( & self , sp : Span ) -> Span {
412400 let source_map = self . session . source_map ( ) ;
413401 let end = source_map. end_point ( sp) ;
414- let replace_span = if source_map. span_to_snippet ( end) . map ( |s| s == ";" ) . unwrap_or ( false ) {
402+
403+ if source_map. span_to_snippet ( end) . map ( |s| s == ";" ) . unwrap_or ( false ) {
415404 end
416405 } else {
417406 sp. shrink_to_hi ( )
418- } ;
419- let mut err = self . err_handler ( ) . struct_span_err ( sp, msg) ;
420- err. span_suggestion (
421- replace_span,
422- & format ! ( "provide a definition for the {}" , ctx) ,
423- sugg,
424- Applicability :: HasPlaceholders ,
425- ) ;
426- help ( & mut err) ;
427- err. emit ( ) ;
428- }
429-
430- fn check_impl_item_provided < T > ( & self , sp : Span , body : & Option < T > , ctx : & str , sugg : & str ) {
431- if body. is_none ( ) {
432- let msg = format ! ( "associated {} in `impl` without body" , ctx) ;
433- self . error_item_without_body ( sp, ctx, & msg, sugg) ;
434407 }
435408 }
436409
@@ -1123,37 +1096,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11231096 self . check_defaultness ( item. span , defaultness) ;
11241097
11251098 if body. is_none ( ) {
1126- let msg = "free function without a body" ;
1127- let ext = sig. header . ext ;
1128-
1129- let f = |e : & mut Diagnostic | {
1130- if let Extern :: Implicit ( start_span) | Extern :: Explicit ( _, start_span) = & ext
1131- {
1132- let start_suggestion = if let Extern :: Explicit ( abi, _) = ext {
1133- format ! ( "extern \" {}\" {{" , abi. symbol_unescaped)
1134- } else {
1135- "extern {" . to_owned ( )
1136- } ;
1137-
1138- let end_suggestion = " }" . to_owned ( ) ;
1139- let end_span = item. span . shrink_to_hi ( ) ;
1140-
1141- e
1142- . multipart_suggestion (
1143- "if you meant to declare an externally defined function, use an `extern` block" ,
1144- vec ! [ ( * start_span, start_suggestion) , ( end_span, end_suggestion) ] ,
1145- Applicability :: MaybeIncorrect ,
1146- ) ;
1147- }
1148- } ;
1149-
1150- self . error_item_without_body_with_help (
1151- item. span ,
1152- "function" ,
1153- msg,
1154- " { <body> }" ,
1155- f,
1156- ) ;
1099+ self . session . emit_err ( FnWithoutBody {
1100+ span : item. span ,
1101+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1102+ extern_block_suggestion : match sig. header . ext {
1103+ Extern :: None => None ,
1104+ Extern :: Implicit ( start_span) => Some ( ExternBlockSuggestion {
1105+ start_span,
1106+ end_span : item. span . shrink_to_hi ( ) ,
1107+ abi : None ,
1108+ } ) ,
1109+ Extern :: Explicit ( abi, start_span) => Some ( ExternBlockSuggestion {
1110+ start_span,
1111+ end_span : item. span . shrink_to_hi ( ) ,
1112+ abi : Some ( abi. symbol_unescaped ) ,
1113+ } ) ,
1114+ } ,
1115+ } ) ;
11571116 }
11581117
11591118 self . visit_vis ( & item. vis ) ;
@@ -1259,12 +1218,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12591218 }
12601219 ItemKind :: Const ( def, .., None ) => {
12611220 self . check_defaultness ( item. span , def) ;
1262- let msg = "free constant item without body" ;
1263- self . error_item_without_body ( item. span , "constant" , msg, " = <expr>;" ) ;
1221+ self . session . emit_err ( ConstWithoutBody {
1222+ span : item. span ,
1223+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1224+ } ) ;
12641225 }
12651226 ItemKind :: Static ( .., None ) => {
1266- let msg = "free static item without body" ;
1267- self . error_item_without_body ( item. span , "static" , msg, " = <expr>;" ) ;
1227+ self . session . emit_err ( StaticWithoutBody {
1228+ span : item. span ,
1229+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1230+ } ) ;
12681231 }
12691232 ItemKind :: TyAlias ( box TyAlias {
12701233 defaultness,
@@ -1275,8 +1238,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12751238 } ) => {
12761239 self . check_defaultness ( item. span , defaultness) ;
12771240 if ty. is_none ( ) {
1278- let msg = "free type alias without body" ;
1279- self . error_item_without_body ( item. span , "type" , msg, " = <type>;" ) ;
1241+ self . session . emit_err ( TyAliasWithoutBody {
1242+ span : item. span ,
1243+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1244+ } ) ;
12801245 }
12811246 self . check_type_no_bounds ( bounds, "this context" ) ;
12821247 if where_clauses. 1 . 0 {
@@ -1580,10 +1545,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15801545 if ctxt == AssocCtxt :: Impl {
15811546 match & item. kind {
15821547 AssocItemKind :: Const ( _, _, body) => {
1583- self . check_impl_item_provided ( item. span , body, "constant" , " = <expr>;" ) ;
1548+ if body. is_none ( ) {
1549+ self . session . emit_err ( AssocConstWithoutBody {
1550+ span : item. span ,
1551+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1552+ } ) ;
1553+ }
15841554 }
15851555 AssocItemKind :: Fn ( box Fn { body, .. } ) => {
1586- self . check_impl_item_provided ( item. span , body, "function" , " { <body> }" ) ;
1556+ if body. is_none ( ) {
1557+ self . session . emit_err ( AssocFnWithoutBody {
1558+ span : item. span ,
1559+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1560+ } ) ;
1561+ }
15871562 }
15881563 AssocItemKind :: TyAlias ( box TyAlias {
15891564 generics,
@@ -1593,7 +1568,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15931568 ty,
15941569 ..
15951570 } ) => {
1596- self . check_impl_item_provided ( item. span , ty, "type" , " = <type>;" ) ;
1571+ if ty. is_none ( ) {
1572+ self . session . emit_err ( AssocTypeWithoutBody {
1573+ span : item. span ,
1574+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1575+ } ) ;
1576+ }
15971577 self . check_type_no_bounds ( bounds, "`impl`s" ) ;
15981578 if ty. is_some ( ) {
15991579 self . check_gat_where (
0 commit comments