@@ -2329,7 +2329,8 @@ impl<'a> Parser<'a> {
2329
2329
let capture_clause = self . parse_capture_clause ( ) ?;
2330
2330
let ( fn_decl, fn_arg_span) = self . parse_fn_block_decl ( ) ?;
2331
2331
let decl_hi = self . prev_token . span ;
2332
- let mut body = match fn_decl. output {
2332
+ let mut body = match & fn_decl. output {
2333
+ // No return type.
2333
2334
FnRetTy :: Default ( _) => {
2334
2335
let restrictions =
2335
2336
self . restrictions - Restrictions :: STMT_EXPR - Restrictions :: ALLOW_LET ;
@@ -2341,11 +2342,8 @@ impl<'a> Parser<'a> {
2341
2342
Err ( err) => self . recover_closure_body ( err, before, prev, token, lo, decl_hi) ?,
2342
2343
}
2343
2344
}
2344
- _ => {
2345
- // If an explicit return type is given, require a block to appear (RFC 968).
2346
- let body_lo = self . token . span ;
2347
- self . parse_expr_block ( None , body_lo, BlockCheckMode :: Default ) ?
2348
- }
2345
+ // Explicit return type (`->`) needs block `-> T { }`.
2346
+ FnRetTy :: Ty ( ty) => self . parse_closure_block_body ( ty. span ) ?,
2349
2347
} ;
2350
2348
2351
2349
match coroutine_kind {
@@ -2397,6 +2395,49 @@ impl<'a> Parser<'a> {
2397
2395
Ok ( closure)
2398
2396
}
2399
2397
2398
+ /// If an explicit return type is given, require a block to appear (RFC 968).
2399
+ fn parse_closure_block_body ( & mut self , ret_span : Span ) -> PResult < ' a , P < Expr > > {
2400
+ if self . may_recover ( )
2401
+ && self . token . can_begin_expr ( )
2402
+ && !matches ! ( self . token. kind, TokenKind :: OpenDelim ( Delimiter :: Brace ) )
2403
+ && !self . token . is_whole_block ( )
2404
+ {
2405
+ let snapshot = self . create_snapshot_for_diagnostic ( ) ;
2406
+ let restrictions =
2407
+ self . restrictions - Restrictions :: STMT_EXPR - Restrictions :: ALLOW_LET ;
2408
+ let tok = self . token . clone ( ) ;
2409
+ match self . parse_expr_res ( restrictions, AttrWrapper :: empty ( ) ) {
2410
+ Ok ( ( expr, _) ) => {
2411
+ let descr = super :: token_descr ( & tok) ;
2412
+ let mut diag = self
2413
+ . dcx ( )
2414
+ . struct_span_err ( tok. span , format ! ( "expected `{{`, found {descr}" ) ) ;
2415
+ diag. span_label (
2416
+ ret_span,
2417
+ "explicit return type requires closure body to be enclosed in braces" ,
2418
+ ) ;
2419
+ diag. multipart_suggestion_verbose (
2420
+ "wrap the expression in curly braces" ,
2421
+ vec ! [
2422
+ ( expr. span. shrink_to_lo( ) , "{ " . to_string( ) ) ,
2423
+ ( expr. span. shrink_to_hi( ) , " }" . to_string( ) ) ,
2424
+ ] ,
2425
+ Applicability :: MachineApplicable ,
2426
+ ) ;
2427
+ diag. emit ( ) ;
2428
+ return Ok ( expr) ;
2429
+ }
2430
+ Err ( diag) => {
2431
+ diag. cancel ( ) ;
2432
+ self . restore_snapshot ( snapshot) ;
2433
+ }
2434
+ }
2435
+ }
2436
+
2437
+ let body_lo = self . token . span ;
2438
+ self . parse_expr_block ( None , body_lo, BlockCheckMode :: Default )
2439
+ }
2440
+
2400
2441
/// Parses an optional `move` or `use` prefix to a closure-like construct.
2401
2442
fn parse_capture_clause ( & mut self ) -> PResult < ' a , CaptureBy > {
2402
2443
if self . eat_keyword ( exp ! ( Move ) ) {
0 commit comments