@@ -2200,7 +2200,9 @@ impl<'a> Parser<'a> {
2200
2200
}
2201
2201
2202
2202
fn is_array_like_block ( & mut self ) -> bool {
2203
- self . look_ahead ( 1 , |t| matches ! ( t. kind, TokenKind :: Ident ( ..) | TokenKind :: Literal ( _) ) )
2203
+ matches ! ( self . token. kind, TokenKind :: OpenDelim ( Delimiter :: Brace ) )
2204
+ && self
2205
+ . look_ahead ( 1 , |t| matches ! ( t. kind, TokenKind :: Ident ( ..) | TokenKind :: Literal ( _) ) )
2204
2206
&& self . look_ahead ( 2 , |t| t == & token:: Comma )
2205
2207
&& self . look_ahead ( 3 , |t| t. can_begin_expr ( ) )
2206
2208
}
@@ -2212,9 +2214,9 @@ impl<'a> Parser<'a> {
2212
2214
let mut snapshot = self . create_snapshot_for_diagnostic ( ) ;
2213
2215
match snapshot. parse_expr_array_or_repeat ( exp ! ( CloseBrace ) ) {
2214
2216
Ok ( arr) => {
2215
- let guar = self . dcx ( ) . emit_err ( errors:: ArrayBracketsInsteadOfSpaces {
2217
+ let guar = self . dcx ( ) . emit_err ( errors:: ArrayBracketsInsteadOfBraces {
2216
2218
span : arr. span ,
2217
- sub : errors:: ArrayBracketsInsteadOfSpacesSugg {
2219
+ sub : errors:: ArrayBracketsInsteadOfBracesSugg {
2218
2220
left : lo,
2219
2221
right : snapshot. prev_token . span ,
2220
2222
} ,
@@ -2337,7 +2339,8 @@ impl<'a> Parser<'a> {
2337
2339
let capture_clause = self . parse_capture_clause ( ) ?;
2338
2340
let ( fn_decl, fn_arg_span) = self . parse_fn_block_decl ( ) ?;
2339
2341
let decl_hi = self . prev_token . span ;
2340
- let mut body = match fn_decl. output {
2342
+ let mut body = match & fn_decl. output {
2343
+ // No return type.
2341
2344
FnRetTy :: Default ( _) => {
2342
2345
let restrictions =
2343
2346
self . restrictions - Restrictions :: STMT_EXPR - Restrictions :: ALLOW_LET ;
@@ -2349,11 +2352,8 @@ impl<'a> Parser<'a> {
2349
2352
Err ( err) => self . recover_closure_body ( err, before, prev, token, lo, decl_hi) ?,
2350
2353
}
2351
2354
}
2352
- _ => {
2353
- // If an explicit return type is given, require a block to appear (RFC 968).
2354
- let body_lo = self . token . span ;
2355
- self . parse_expr_block ( None , body_lo, BlockCheckMode :: Default ) ?
2356
- }
2355
+ // Explicit return type (`->`) needs block `-> T { }`.
2356
+ FnRetTy :: Ty ( ty) => self . parse_closure_block_body ( ty. span ) ?,
2357
2357
} ;
2358
2358
2359
2359
match coroutine_kind {
@@ -2405,6 +2405,49 @@ impl<'a> Parser<'a> {
2405
2405
Ok ( closure)
2406
2406
}
2407
2407
2408
+ /// If an explicit return type is given, require a block to appear (RFC 968).
2409
+ fn parse_closure_block_body ( & mut self , ret_span : Span ) -> PResult < ' a , P < Expr > > {
2410
+ if self . may_recover ( )
2411
+ && self . token . can_begin_expr ( )
2412
+ && !matches ! ( self . token. kind, TokenKind :: OpenDelim ( Delimiter :: Brace ) )
2413
+ && !self . token . is_whole_block ( )
2414
+ {
2415
+ let snapshot = self . create_snapshot_for_diagnostic ( ) ;
2416
+ let restrictions =
2417
+ self . restrictions - Restrictions :: STMT_EXPR - Restrictions :: ALLOW_LET ;
2418
+ let tok = self . token . clone ( ) ;
2419
+ match self . parse_expr_res ( restrictions, AttrWrapper :: empty ( ) ) {
2420
+ Ok ( ( expr, _) ) => {
2421
+ let descr = super :: token_descr ( & tok) ;
2422
+ let mut diag = self
2423
+ . dcx ( )
2424
+ . struct_span_err ( tok. span , format ! ( "expected `{{`, found {descr}" ) ) ;
2425
+ diag. span_label (
2426
+ ret_span,
2427
+ "explicit return type requires closure body to be enclosed in braces" ,
2428
+ ) ;
2429
+ diag. multipart_suggestion_verbose (
2430
+ "wrap the expression in curly braces" ,
2431
+ vec ! [
2432
+ ( expr. span. shrink_to_lo( ) , "{ " . to_string( ) ) ,
2433
+ ( expr. span. shrink_to_hi( ) , " }" . to_string( ) ) ,
2434
+ ] ,
2435
+ Applicability :: MachineApplicable ,
2436
+ ) ;
2437
+ diag. emit ( ) ;
2438
+ return Ok ( expr) ;
2439
+ }
2440
+ Err ( diag) => {
2441
+ diag. cancel ( ) ;
2442
+ self . restore_snapshot ( snapshot) ;
2443
+ }
2444
+ }
2445
+ }
2446
+
2447
+ let body_lo = self . token . span ;
2448
+ self . parse_expr_block ( None , body_lo, BlockCheckMode :: Default )
2449
+ }
2450
+
2408
2451
/// Parses an optional `move` or `use` prefix to a closure-like construct.
2409
2452
fn parse_capture_clause ( & mut self ) -> PResult < ' a , CaptureBy > {
2410
2453
if self . eat_keyword ( exp ! ( Move ) ) {
0 commit comments