@@ -21,7 +21,7 @@ use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, Er
2121use rustc_errors:: {
2222 Applicability , DiagnosticBuilder , DiagnosticMessage , Handler , MultiSpan , PResult ,
2323} ;
24- use rustc_macros:: SessionDiagnostic ;
24+ use rustc_macros:: { SessionDiagnostic , SessionSubdiagnostic } ;
2525use rustc_span:: source_map:: Spanned ;
2626use rustc_span:: symbol:: { kw, Ident } ;
2727use rustc_span:: { Span , SpanSnippetError , DUMMY_SP } ;
@@ -252,6 +252,40 @@ struct AmbiguousPlus {
252252 pub span : Span ,
253253}
254254
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+
255289// SnapshotParser is used to create a snapshot of the parser
256290// without causing duplicate errors being emitted when the `Parser`
257291// is dropped.
@@ -1255,17 +1289,11 @@ impl<'a> Parser<'a> {
12551289 let bounds = self . parse_generic_bounds ( None ) ?;
12561290 let sum_span = ty. span . to ( self . prev_token . span ) ;
12571291
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 ;
12651293
1266- match ty. kind {
1294+ let sub = match ty. kind {
12671295 TyKind :: Rptr ( ref lifetime, ref mut_ty) => {
1268- let sum_with_parens = pprust:: to_string ( |s| {
1296+ sum_with_parens = pprust:: to_string ( |s| {
12691297 s. s . word ( "&" ) ;
12701298 s. print_opt_lifetime ( lifetime) ;
12711299 s. print_mutability ( mut_ty. mutbl , false ) ;
@@ -1274,21 +1302,15 @@ impl<'a> Parser<'a> {
12741302 s. print_type_bounds ( " +" , & bounds) ;
12751303 s. pclose ( )
12761304 } ) ;
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 }
12891307 }
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+
12921314 Ok ( ( ) )
12931315 }
12941316
0 commit comments