@@ -13,7 +13,7 @@ use rustc_ast::walk_list;
13
13
use rustc_ast:: * ;
14
14
use rustc_ast_pretty:: pprust:: { self , State } ;
15
15
use 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 } ;
17
17
use rustc_parse:: validate_attr;
18
18
use rustc_session:: lint:: builtin:: {
19
19
DEPRECATED_WHERE_CLAUSE_LOCATION , MISSING_ABI , PATTERNS_IN_FNS_WITHOUT_BODY ,
@@ -390,47 +390,20 @@ impl<'a> AstValidator<'a> {
390
390
fn check_defaultness ( & self , span : Span , defaultness : Defaultness ) {
391
391
if let Defaultness :: Default ( def_span) = defaultness {
392
392
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 } ) ;
397
394
}
398
395
}
399
396
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 {
412
400
let source_map = self . session . source_map ( ) ;
413
401
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 ) {
415
404
end
416
405
} else {
417
406
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) ;
434
407
}
435
408
}
436
409
@@ -1123,37 +1096,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1123
1096
self . check_defaultness ( item. span , defaultness) ;
1124
1097
1125
1098
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
+ } ) ;
1157
1116
}
1158
1117
1159
1118
self . visit_vis ( & item. vis ) ;
@@ -1259,12 +1218,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1259
1218
}
1260
1219
ItemKind :: Const ( def, .., None ) => {
1261
1220
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
+ } ) ;
1264
1225
}
1265
1226
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
+ } ) ;
1268
1231
}
1269
1232
ItemKind :: TyAlias ( box TyAlias {
1270
1233
defaultness,
@@ -1275,8 +1238,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1275
1238
} ) => {
1276
1239
self . check_defaultness ( item. span , defaultness) ;
1277
1240
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
+ } ) ;
1280
1245
}
1281
1246
self . check_type_no_bounds ( bounds, "this context" ) ;
1282
1247
if where_clauses. 1 . 0 {
@@ -1580,10 +1545,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1580
1545
if ctxt == AssocCtxt :: Impl {
1581
1546
match & item. kind {
1582
1547
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
+ }
1584
1554
}
1585
1555
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
+ }
1587
1562
}
1588
1563
AssocItemKind :: TyAlias ( box TyAlias {
1589
1564
generics,
@@ -1593,7 +1568,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1593
1568
ty,
1594
1569
..
1595
1570
} ) => {
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
+ }
1597
1577
self . check_type_no_bounds ( bounds, "`impl`s" ) ;
1598
1578
if ty. is_some ( ) {
1599
1579
self . check_gat_where (
0 commit comments