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