@@ -2332,14 +2332,105 @@ impl<'a> Parser<'a> {
23322332 }
23332333 }
23342334 } ;
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+
23352340 generics. where_clause = self . parse_where_clause ( ) ?; // `where T: Ord`
23362341
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+
23372346 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) ?;
23392350 let fn_sig_span = sig_lo. to ( sig_hi) ;
23402351 Ok ( ( ident, FnSig { header, decl, span : fn_sig_span } , generics, body) )
23412352 }
23422353
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+
23432434 /// Parse the "body" of a function.
23442435 /// This can either be `;` when there's no body,
23452436 /// or e.g. a block when the function is a provided one.
@@ -2349,6 +2440,7 @@ impl<'a> Parser<'a> {
23492440 ident : & Ident ,
23502441 sig_hi : & mut Span ,
23512442 req_body : bool ,
2443+ fn_params_end : Option < Span > ,
23522444 ) -> PResult < ' a , Option < P < Block > > > {
23532445 let has_semi = if req_body {
23542446 self . token . kind == TokenKind :: Semi
@@ -2377,33 +2469,7 @@ impl<'a> Parser<'a> {
23772469 } ) ;
23782470 ( AttrVec :: new ( ) , Some ( self . mk_block_err ( span, guar) ) )
23792471 } 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) ?;
24072473 ( AttrVec :: new ( ) , None )
24082474 } ;
24092475 attrs. extend ( inner_attrs) ;
0 commit comments