@@ -2332,14 +2332,105 @@ impl<'a> Parser<'a> {
2332
2332
}
2333
2333
}
2334
2334
} ;
2335
+
2336
+ // Store the end of function parameters to give better diagnostics
2337
+ // inside `parse_fn_body()`.
2338
+ let fn_params_end = self . prev_token . span . shrink_to_hi ( ) ;
2339
+
2335
2340
generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Ord`
2336
2341
2342
+ // `fn_params_end` is needed only when it's followed by a where clause.
2343
+ let fn_params_end =
2344
+ if generics. where_clause . has_where_token { Some ( fn_params_end) } else { None } ;
2345
+
2337
2346
let mut sig_hi = self . prev_token . span ;
2338
- let body = self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode. req_body ) ?; // `;` or `{ ... }`.
2347
+ // Either `;` or `{ ... }`.
2348
+ let body =
2349
+ self . parse_fn_body ( attrs, & ident, & mut sig_hi, fn_parse_mode. req_body , fn_params_end) ?;
2339
2350
let fn_sig_span = sig_lo. to ( sig_hi) ;
2340
2351
Ok ( ( ident, FnSig { header, decl, span : fn_sig_span } , generics, body) )
2341
2352
}
2342
2353
2354
+ /// Provide diagnostics when function body is not found
2355
+ fn error_fn_body_not_found (
2356
+ & mut self ,
2357
+ ident_span : Span ,
2358
+ req_body : bool ,
2359
+ fn_params_end : Option < Span > ,
2360
+ ) -> PResult < ' a , ( ) > {
2361
+ let expected = if req_body {
2362
+ & [ token:: OpenDelim ( Delimiter :: Brace ) ] [ ..]
2363
+ } else {
2364
+ & [ token:: Semi , token:: OpenDelim ( Delimiter :: Brace ) ]
2365
+ } ;
2366
+ if let Err ( mut err) = self . expected_one_of_not_found ( & [ ] , expected) {
2367
+ if self . token . kind == token:: CloseDelim ( Delimiter :: Brace ) {
2368
+ // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
2369
+ // the AST for typechecking.
2370
+ err. span_label ( ident_span, "while parsing this `fn`" ) ;
2371
+ err. emit ( ) ;
2372
+ Ok ( ( ) )
2373
+ } else if self . token . kind == token:: RArrow
2374
+ && let Some ( fn_params_end) = fn_params_end
2375
+ {
2376
+ // Instead of a function body, the parser has encountered a right arrow
2377
+ // preceded by a where clause.
2378
+
2379
+ // Find whether token behind the right arrow is a function trait and
2380
+ // store its span.
2381
+ let fn_trait_span =
2382
+ [ sym:: FnOnce , sym:: FnMut , sym:: Fn ] . into_iter ( ) . find_map ( |symbol| {
2383
+ if self . prev_token . is_ident_named ( symbol) {
2384
+ Some ( self . prev_token . span )
2385
+ } else {
2386
+ None
2387
+ }
2388
+ } ) ;
2389
+
2390
+ // Parse the return type (along with the right arrow) and store its span.
2391
+ // If there's a parse error, cancel it and return the existing error
2392
+ // as we are primarily concerned with the
2393
+ // expected-function-body-but-found-something-else error here.
2394
+ let arrow_span = self . token . span ;
2395
+ let ty_span = match self . parse_ret_ty (
2396
+ AllowPlus :: Yes ,
2397
+ RecoverQPath :: Yes ,
2398
+ RecoverReturnSign :: Yes ,
2399
+ ) {
2400
+ Ok ( ty_span) => ty_span. span ( ) . shrink_to_hi ( ) ,
2401
+ Err ( parse_error) => {
2402
+ parse_error. cancel ( ) ;
2403
+ return Err ( err) ;
2404
+ }
2405
+ } ;
2406
+ let ret_ty_span = arrow_span. to ( ty_span) ;
2407
+
2408
+ if let Some ( fn_trait_span) = fn_trait_span {
2409
+ // Typo'd Fn* trait bounds such as
2410
+ // fn foo<F>() where F: FnOnce -> () {}
2411
+ err. subdiagnostic ( errors:: FnTraitMissingParen { span : fn_trait_span } ) ;
2412
+ } else if let Ok ( snippet) = self . psess . source_map ( ) . span_to_snippet ( ret_ty_span) {
2413
+ // If token behind right arrow is not a Fn* trait, the programmer
2414
+ // probably misplaced the return type after the where clause like
2415
+ // `fn foo<T>() where T: Default -> u8 {}`
2416
+ err. primary_message (
2417
+ "return type should be specified after the function parameters" ,
2418
+ ) ;
2419
+ err. subdiagnostic ( errors:: MisplacedReturnType {
2420
+ fn_params_end,
2421
+ snippet,
2422
+ ret_ty_span,
2423
+ } ) ;
2424
+ }
2425
+ Err ( err)
2426
+ } else {
2427
+ Err ( err)
2428
+ }
2429
+ } else {
2430
+ Ok ( ( ) )
2431
+ }
2432
+ }
2433
+
2343
2434
/// Parse the "body" of a function.
2344
2435
/// This can either be `;` when there's no body,
2345
2436
/// or e.g. a block when the function is a provided one.
@@ -2349,6 +2440,7 @@ impl<'a> Parser<'a> {
2349
2440
ident : & Ident ,
2350
2441
sig_hi : & mut Span ,
2351
2442
req_body : bool ,
2443
+ fn_params_end : Option < Span > ,
2352
2444
) -> PResult < ' a , Option < P < Block > > > {
2353
2445
let has_semi = if req_body {
2354
2446
self . token . kind == TokenKind :: Semi
@@ -2377,33 +2469,7 @@ impl<'a> Parser<'a> {
2377
2469
} ) ;
2378
2470
( AttrVec :: new ( ) , Some ( self . mk_block_err ( span, guar) ) )
2379
2471
} else {
2380
- let expected = if req_body {
2381
- & [ token:: OpenDelim ( Delimiter :: Brace ) ] [ ..]
2382
- } else {
2383
- & [ token:: Semi , token:: OpenDelim ( Delimiter :: Brace ) ]
2384
- } ;
2385
- if let Err ( mut err) = self . expected_one_of_not_found ( & [ ] , expected) {
2386
- if self . token . kind == token:: CloseDelim ( Delimiter :: Brace ) {
2387
- // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
2388
- // the AST for typechecking.
2389
- err. span_label ( ident. span , "while parsing this `fn`" ) ;
2390
- err. emit ( ) ;
2391
- } else {
2392
- // check for typo'd Fn* trait bounds such as
2393
- // fn foo<F>() where F: FnOnce -> () {}
2394
- if self . token . kind == token:: RArrow {
2395
- let machine_applicable = [ sym:: FnOnce , sym:: FnMut , sym:: Fn ]
2396
- . into_iter ( )
2397
- . any ( |s| self . prev_token . is_ident_named ( s) ) ;
2398
-
2399
- err. subdiagnostic ( errors:: FnTraitMissingParen {
2400
- span : self . prev_token . span ,
2401
- machine_applicable,
2402
- } ) ;
2403
- }
2404
- return Err ( err) ;
2405
- }
2406
- }
2472
+ self . error_fn_body_not_found ( ident. span , req_body, fn_params_end) ?;
2407
2473
( AttrVec :: new ( ) , None )
2408
2474
} ;
2409
2475
attrs. extend ( inner_attrs) ;
0 commit comments