@@ -2010,6 +2010,12 @@ impl<'a> Parser<'a> {
2010
2010
Ok ( self . mk_expr ( blk. span , ExprKind :: Block ( blk, opt_label) , attrs) )
2011
2011
}
2012
2012
2013
+ /// Parse a block which takes no attributes and has no label
2014
+ fn parse_simple_block ( & mut self ) -> PResult < ' a , P < Expr > > {
2015
+ let blk = self . parse_block ( ) ?;
2016
+ Ok ( self . mk_expr ( blk. span , ExprKind :: Block ( blk, None ) , AttrVec :: new ( ) ) )
2017
+ }
2018
+
2013
2019
/// Recover on an explicitly quantified closure expression, e.g., `for<'a> |x: &'a u8| *x + 1`.
2014
2020
fn recover_quantified_closure_expr ( & mut self , attrs : AttrVec ) -> PResult < ' a , P < Expr > > {
2015
2021
let lo = self . token . span ;
@@ -2157,14 +2163,22 @@ impl<'a> Parser<'a> {
2157
2163
let lo = self . prev_token . span ;
2158
2164
let cond = self . parse_cond_expr ( ) ?;
2159
2165
2166
+ self . parse_if_after_cond ( attrs, lo, cond)
2167
+ }
2168
+
2169
+ fn parse_if_after_cond (
2170
+ & mut self ,
2171
+ attrs : AttrVec ,
2172
+ lo : Span ,
2173
+ cond : P < Expr > ,
2174
+ ) -> PResult < ' a , P < Expr > > {
2160
2175
let missing_then_block_binop_span = || {
2161
2176
match cond. kind {
2162
2177
ExprKind :: Binary ( Spanned { span : binop_span, .. } , _, ref right)
2163
2178
if let ExprKind :: Block ( ..) = right. kind => Some ( binop_span) ,
2164
2179
_ => None
2165
2180
}
2166
2181
} ;
2167
-
2168
2182
// Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
2169
2183
// verify that the last statement is either an implicit return (no `;`) or an explicit
2170
2184
// return. This won't catch blocks with an explicit `return`, but that would be caught by
@@ -2256,15 +2270,53 @@ impl<'a> Parser<'a> {
2256
2270
2257
2271
/// Parses an `else { ... }` expression (`else` token already eaten).
2258
2272
fn parse_else_expr ( & mut self ) -> PResult < ' a , P < Expr > > {
2259
- let ctx_span = self . prev_token . span ; // `else`
2273
+ let else_span = self . prev_token . span ; // `else`
2260
2274
let attrs = self . parse_outer_attributes ( ) ?. take_for_recovery ( ) ; // For recovery.
2261
2275
let expr = if self . eat_keyword ( kw:: If ) {
2262
2276
self . parse_if_expr ( AttrVec :: new ( ) ) ?
2277
+ } else if self . check ( & TokenKind :: OpenDelim ( Delimiter :: Brace ) ) {
2278
+ self . parse_simple_block ( ) ?
2263
2279
} else {
2264
- let blk = self . parse_block ( ) ?;
2265
- self . mk_expr ( blk. span , ExprKind :: Block ( blk, None ) , AttrVec :: new ( ) )
2280
+ let snapshot = self . create_snapshot_for_diagnostic ( ) ;
2281
+ let first_tok = super :: token_descr ( & self . token ) ;
2282
+ let first_tok_span = self . token . span ;
2283
+ match self . parse_expr ( ) {
2284
+ Ok ( cond)
2285
+ // If it's not a free-standing expression, and is followed by a block,
2286
+ // then it's very likely the condition to an `else if`.
2287
+ if self . check ( & TokenKind :: OpenDelim ( Delimiter :: Brace ) )
2288
+ && classify:: expr_requires_semi_to_be_stmt ( & cond) =>
2289
+ {
2290
+ self . struct_span_err ( first_tok_span, format ! ( "expected `{{`, found {first_tok}" ) )
2291
+ . span_label ( else_span, "expected an `if` or a block after this `else`" )
2292
+ . span_suggestion (
2293
+ cond. span . shrink_to_lo ( ) ,
2294
+ "add an `if` if this is the condition to an chained `if` statement after the `else`" ,
2295
+ "if " . to_string ( ) ,
2296
+ Applicability :: MaybeIncorrect ,
2297
+ ) . multipart_suggestion (
2298
+ "... otherwise, place this expression inside of a block if it is not an `if` condition" ,
2299
+ vec ! [
2300
+ ( cond. span. shrink_to_lo( ) , "{ " . to_string( ) ) ,
2301
+ ( cond. span. shrink_to_hi( ) , " }" . to_string( ) ) ,
2302
+ ] ,
2303
+ Applicability :: MaybeIncorrect ,
2304
+ )
2305
+ . emit ( ) ;
2306
+ self . parse_if_after_cond ( AttrVec :: new ( ) , cond. span . shrink_to_lo ( ) , cond) ?
2307
+ }
2308
+ Err ( e) => {
2309
+ e. cancel ( ) ;
2310
+ self . restore_snapshot ( snapshot) ;
2311
+ self . parse_simple_block ( ) ?
2312
+ } ,
2313
+ Ok ( _) => {
2314
+ self . restore_snapshot ( snapshot) ;
2315
+ self . parse_simple_block ( ) ?
2316
+ } ,
2317
+ }
2266
2318
} ;
2267
- self . error_on_if_block_attrs ( ctx_span , true , expr. span , & attrs) ;
2319
+ self . error_on_if_block_attrs ( else_span , true , expr. span , & attrs) ;
2268
2320
Ok ( expr)
2269
2321
}
2270
2322
0 commit comments