@@ -21,7 +21,7 @@ use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, Er
21
21
use rustc_errors:: {
22
22
Applicability , DiagnosticBuilder , DiagnosticMessage , Handler , MultiSpan , PResult ,
23
23
} ;
24
- use rustc_macros:: SessionDiagnostic ;
24
+ use rustc_macros:: { SessionDiagnostic , SessionSubdiagnostic } ;
25
25
use rustc_span:: source_map:: Spanned ;
26
26
use rustc_span:: symbol:: { kw, Ident } ;
27
27
use rustc_span:: { Span , SpanSnippetError , DUMMY_SP } ;
@@ -252,6 +252,40 @@ struct AmbiguousPlus {
252
252
pub span : Span ,
253
253
}
254
254
255
+ #[ derive( SessionDiagnostic ) ]
256
+ #[ error( code = "E0178" , slug = "parser-maybe-recover-from-bad-type-plus" ) ]
257
+ struct BadTypePlus < ' a > {
258
+ pub ty : String ,
259
+ #[ primary_span]
260
+ pub span : Span ,
261
+ #[ subdiagnostic]
262
+ pub sub : BadTypePlusSub < ' a > ,
263
+ }
264
+
265
+ #[ derive( SessionSubdiagnostic , Clone , Copy ) ]
266
+ pub enum BadTypePlusSub < ' a > {
267
+ #[ suggestion(
268
+ slug = "parser-add-paren" ,
269
+ code = "{sum_with_parens}" ,
270
+ applicability = "machine-applicable"
271
+ ) ]
272
+ AddParen {
273
+ sum_with_parens : & ' a str ,
274
+ #[ primary_span]
275
+ span : Span ,
276
+ } ,
277
+ #[ label( slug = "parser-forgot-paren" ) ]
278
+ ForgotParen {
279
+ #[ primary_span]
280
+ span : Span ,
281
+ } ,
282
+ #[ label( slug = "parser-expect-path" ) ]
283
+ ExpectPath {
284
+ #[ primary_span]
285
+ span : Span ,
286
+ } ,
287
+ }
288
+
255
289
// SnapshotParser is used to create a snapshot of the parser
256
290
// without causing duplicate errors being emitted when the `Parser`
257
291
// is dropped.
@@ -1255,17 +1289,11 @@ impl<'a> Parser<'a> {
1255
1289
let bounds = self . parse_generic_bounds ( None ) ?;
1256
1290
let sum_span = ty. span . to ( self . prev_token . span ) ;
1257
1291
1258
- let mut err = struct_span_err ! (
1259
- self . sess. span_diagnostic,
1260
- sum_span,
1261
- E0178 ,
1262
- "expected a path on the left-hand side of `+`, not `{}`" ,
1263
- pprust:: ty_to_string( ty)
1264
- ) ;
1292
+ let sum_with_parens: String ;
1265
1293
1266
- match ty. kind {
1294
+ let sub = match ty. kind {
1267
1295
TyKind :: Rptr ( ref lifetime, ref mut_ty) => {
1268
- let sum_with_parens = pprust:: to_string ( |s| {
1296
+ sum_with_parens = pprust:: to_string ( |s| {
1269
1297
s. s . word ( "&" ) ;
1270
1298
s. print_opt_lifetime ( lifetime) ;
1271
1299
s. print_mutability ( mut_ty. mutbl , false ) ;
@@ -1274,21 +1302,15 @@ impl<'a> Parser<'a> {
1274
1302
s. print_type_bounds ( " +" , & bounds) ;
1275
1303
s. pclose ( )
1276
1304
} ) ;
1277
- err. span_suggestion (
1278
- sum_span,
1279
- "try adding parentheses" ,
1280
- sum_with_parens,
1281
- Applicability :: MachineApplicable ,
1282
- ) ;
1283
- }
1284
- TyKind :: Ptr ( ..) | TyKind :: BareFn ( ..) => {
1285
- err. span_label ( sum_span, "perhaps you forgot parentheses?" ) ;
1286
- }
1287
- _ => {
1288
- err. span_label ( sum_span, "expected a path" ) ;
1305
+
1306
+ BadTypePlusSub :: AddParen { sum_with_parens : & sum_with_parens, span : sum_span }
1289
1307
}
1290
- }
1291
- err. emit ( ) ;
1308
+ TyKind :: Ptr ( ..) | TyKind :: BareFn ( ..) => BadTypePlusSub :: ForgotParen { span : sum_span } ,
1309
+ _ => BadTypePlusSub :: ExpectPath { span : sum_span } ,
1310
+ } ;
1311
+
1312
+ self . sess . emit_err ( BadTypePlus { ty : pprust:: ty_to_string ( ty) , span : sum_span, sub } ) ;
1313
+
1292
1314
Ok ( ( ) )
1293
1315
}
1294
1316
0 commit comments