@@ -4121,56 +4121,123 @@ impl<'a> LoweringContext<'a> {
4121
4121
let ohs = P ( self . lower_expr ( ohs) ) ;
4122
4122
hir:: ExprKind :: AddrOf ( m, ohs)
4123
4123
}
4124
- // More complicated than you might expect because the else branch
4125
- // might be `if let`.
4124
+ ExprKind :: Let ( ..) => {
4125
+ // This should have been caught `ast_validation`!
4126
+ self . sess . span_err ( e. span , "`let` expressions only supported in `if`" ) ;
4127
+ // ^-- FIXME(53667): Change to `delay_span_bug` when let_chains handled in lowering.
4128
+ self . sess . abort_if_errors ( ) ;
4129
+ hir:: ExprKind :: Err
4130
+ }
4131
+ // FIXME(#53667): handle lowering of && and parens.
4126
4132
ExprKind :: If ( ref cond, ref then, ref else_opt) => {
4127
- // `true => then`:
4128
- let then_pat = self . pat_bool ( e. span , true ) ;
4129
- let then_blk = self . lower_block ( then, false ) ;
4130
- let then_expr = self . expr_block ( then_blk, ThinVec :: new ( ) ) ;
4131
- let then_arm = self . arm ( hir_vec ! [ then_pat] , P ( then_expr) ) ;
4132
-
4133
4133
// `_ => else_block` where `else_block` is `{}` if there's `None`:
4134
4134
let else_pat = self . pat_wild ( e. span ) ;
4135
- let else_expr = match else_opt {
4136
- None => self . expr_block_empty ( e. span ) ,
4137
- Some ( els) => match els. node {
4138
- ExprKind :: IfLet ( ..) => {
4139
- // Wrap the `if let` expr in a block.
4140
- let els = self . lower_expr ( els) ;
4141
- let blk = self . block_all ( els. span , hir_vec ! [ ] , Some ( P ( els) ) ) ;
4142
- self . expr_block ( P ( blk) , ThinVec :: new ( ) )
4143
- }
4144
- _ => self . lower_expr ( els) ,
4145
- }
4135
+ let ( else_expr, contains_else_clause) = match else_opt {
4136
+ None => ( self . expr_block_empty ( e. span ) , false ) ,
4137
+ Some ( els) => ( self . lower_expr ( els) , true ) ,
4146
4138
} ;
4147
4139
let else_arm = self . arm ( hir_vec ! [ else_pat] , P ( else_expr) ) ;
4148
4140
4149
- // Lower condition:
4150
- let span_block = self
4151
- . sess
4152
- . source_map ( )
4153
- . mark_span_with_reason ( IfTemporary , cond. span , None ) ;
4154
- let cond = self . lower_expr ( cond) ;
4155
- // Wrap in a construct equivalent to `{ let _t = $cond; _t }` to preserve drop
4156
- // semantics since `if cond { ... }` don't let temporaries live outside of `cond`.
4157
- let cond = self . expr_drop_temps ( span_block, P ( cond) , ThinVec :: new ( ) ) ;
4141
+ // Handle then + scrutinee:
4142
+ let then_blk = self . lower_block ( then, false ) ;
4143
+ let then_expr = self . expr_block ( then_blk, ThinVec :: new ( ) ) ;
4144
+ let ( then_pats, scrutinee, desugar) = match cond. node {
4145
+ // `<pat> => <then>`
4146
+ ExprKind :: Let ( ref pats, ref scrutinee) => {
4147
+ let scrutinee = self . lower_expr ( scrutinee) ;
4148
+ let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
4149
+ let desugar = hir:: MatchSource :: IfLetDesugar { contains_else_clause } ;
4150
+ ( pats, scrutinee, desugar)
4151
+ }
4152
+ // `true => then`:
4153
+ _ => {
4154
+ // Lower condition:
4155
+ let cond = self . lower_expr ( cond) ;
4156
+ // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
4157
+ // to preserve drop semantics since `if cond { ... }`
4158
+ // don't let temporaries live outside of `cond`.
4159
+ let span_block = self
4160
+ . sess
4161
+ . source_map ( )
4162
+ . mark_span_with_reason ( IfTemporary , cond. span , None ) ;
4163
+ // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
4164
+ // to preserve drop semantics since `if cond { ... }` does not
4165
+ // let temporaries live outside of `cond`.
4166
+ let cond = self . expr_drop_temps ( span_block, P ( cond) , ThinVec :: new ( ) ) ;
4167
+
4168
+ let desugar = hir:: MatchSource :: IfDesugar { contains_else_clause } ;
4169
+ let pats = hir_vec ! [ self . pat_bool( e. span, true ) ] ;
4170
+ ( pats, cond, desugar)
4171
+ }
4172
+ } ;
4173
+ let then_arm = self . arm ( then_pats, P ( then_expr) ) ;
4158
4174
4159
- hir:: ExprKind :: Match (
4160
- P ( cond) ,
4161
- vec ! [ then_arm, else_arm] . into ( ) ,
4162
- hir:: MatchSource :: IfDesugar {
4163
- contains_else_clause : else_opt. is_some ( )
4164
- } ,
4165
- )
4175
+ hir:: ExprKind :: Match ( P ( scrutinee) , vec ! [ then_arm, else_arm] . into ( ) , desugar)
4176
+ }
4177
+ // FIXME(#53667): handle lowering of && and parens.
4178
+ ExprKind :: While ( ref cond, ref body, opt_label) => {
4179
+ // Desugar `ExprWhileLet`
4180
+ // from: `[opt_ident]: while let <pat> = <sub_expr> <body>`
4181
+ if let ExprKind :: Let ( ref pats, ref sub_expr) = cond. node {
4182
+ // to:
4183
+ //
4184
+ // [opt_ident]: loop {
4185
+ // match <sub_expr> {
4186
+ // <pat> => <body>,
4187
+ // _ => break
4188
+ // }
4189
+ // }
4190
+
4191
+ // Note that the block AND the condition are evaluated in the loop scope.
4192
+ // This is done to allow `break` from inside the condition of the loop.
4193
+ let ( body, break_expr, sub_expr) = self . with_loop_scope ( e. id , |this| {
4194
+ (
4195
+ this. lower_block ( body, false ) ,
4196
+ this. expr_break ( e. span , ThinVec :: new ( ) ) ,
4197
+ this. with_loop_condition_scope ( |this| P ( this. lower_expr ( sub_expr) ) ) ,
4198
+ )
4199
+ } ) ;
4200
+
4201
+ // `<pat> => <body>`
4202
+ let pat_arm = {
4203
+ let body_expr = P ( self . expr_block ( body, ThinVec :: new ( ) ) ) ;
4204
+ let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
4205
+ self . arm ( pats, body_expr)
4206
+ } ;
4207
+
4208
+ // `_ => break`
4209
+ let break_arm = {
4210
+ let pat_under = self . pat_wild ( e. span ) ;
4211
+ self . arm ( hir_vec ! [ pat_under] , break_expr)
4212
+ } ;
4213
+
4214
+ // `match <sub_expr> { ... }`
4215
+ let arms = hir_vec ! [ pat_arm, break_arm] ;
4216
+ let match_expr = self . expr (
4217
+ sub_expr. span ,
4218
+ hir:: ExprKind :: Match ( sub_expr, arms, hir:: MatchSource :: WhileLetDesugar ) ,
4219
+ ThinVec :: new ( ) ,
4220
+ ) ;
4221
+
4222
+ // `[opt_ident]: loop { ... }`
4223
+ let loop_block = P ( self . block_expr ( P ( match_expr) ) ) ;
4224
+ let loop_expr = hir:: ExprKind :: Loop (
4225
+ loop_block,
4226
+ self . lower_label ( opt_label) ,
4227
+ hir:: LoopSource :: WhileLet ,
4228
+ ) ;
4229
+ // Add attributes to the outer returned expr node.
4230
+ loop_expr
4231
+ } else {
4232
+ self . with_loop_scope ( e. id , |this| {
4233
+ hir:: ExprKind :: While (
4234
+ this. with_loop_condition_scope ( |this| P ( this. lower_expr ( cond) ) ) ,
4235
+ this. lower_block ( body, false ) ,
4236
+ this. lower_label ( opt_label) ,
4237
+ )
4238
+ } )
4239
+ }
4166
4240
}
4167
- ExprKind :: While ( ref cond, ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
4168
- hir:: ExprKind :: While (
4169
- this. with_loop_condition_scope ( |this| P ( this. lower_expr ( cond) ) ) ,
4170
- this. lower_block ( body, false ) ,
4171
- this. lower_label ( opt_label) ,
4172
- )
4173
- } ) ,
4174
4241
ExprKind :: Loop ( ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
4175
4242
hir:: ExprKind :: Loop (
4176
4243
this. lower_block ( body, false ) ,
@@ -4490,105 +4557,6 @@ impl<'a> LoweringContext<'a> {
4490
4557
4491
4558
ExprKind :: Err => hir:: ExprKind :: Err ,
4492
4559
4493
- // Desugar `ExprIfLet`
4494
- // from: `if let <pat> = <sub_expr> <body> [<else_opt>]`
4495
- ExprKind :: IfLet ( ref pats, ref sub_expr, ref body, ref else_opt) => {
4496
- // to:
4497
- //
4498
- // match <sub_expr> {
4499
- // <pat> => <body>,
4500
- // _ => [<else_opt> | ()]
4501
- // }
4502
-
4503
- let mut arms = vec ! [ ] ;
4504
-
4505
- // `<pat> => <body>`
4506
- {
4507
- let body = self . lower_block ( body, false ) ;
4508
- let body_expr = P ( self . expr_block ( body, ThinVec :: new ( ) ) ) ;
4509
- let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
4510
- arms. push ( self . arm ( pats, body_expr) ) ;
4511
- }
4512
-
4513
- // _ => [<else_opt>|{}]
4514
- {
4515
- let wildcard_arm: Option < & Expr > = else_opt. as_ref ( ) . map ( |p| & * * p) ;
4516
- let wildcard_pattern = self . pat_wild ( e. span ) ;
4517
- let body = if let Some ( else_expr) = wildcard_arm {
4518
- self . lower_expr ( else_expr)
4519
- } else {
4520
- self . expr_block_empty ( e. span )
4521
- } ;
4522
- arms. push ( self . arm ( hir_vec ! [ wildcard_pattern] , P ( body) ) ) ;
4523
- }
4524
-
4525
- let contains_else_clause = else_opt. is_some ( ) ;
4526
-
4527
- let sub_expr = P ( self . lower_expr ( sub_expr) ) ;
4528
-
4529
- hir:: ExprKind :: Match (
4530
- sub_expr,
4531
- arms. into ( ) ,
4532
- hir:: MatchSource :: IfLetDesugar {
4533
- contains_else_clause,
4534
- } ,
4535
- )
4536
- }
4537
-
4538
- // Desugar `ExprWhileLet`
4539
- // from: `[opt_ident]: while let <pat> = <sub_expr> <body>`
4540
- ExprKind :: WhileLet ( ref pats, ref sub_expr, ref body, opt_label) => {
4541
- // to:
4542
- //
4543
- // [opt_ident]: loop {
4544
- // match <sub_expr> {
4545
- // <pat> => <body>,
4546
- // _ => break
4547
- // }
4548
- // }
4549
-
4550
- // Note that the block AND the condition are evaluated in the loop scope.
4551
- // This is done to allow `break` from inside the condition of the loop.
4552
- let ( body, break_expr, sub_expr) = self . with_loop_scope ( e. id , |this| {
4553
- (
4554
- this. lower_block ( body, false ) ,
4555
- this. expr_break ( e. span , ThinVec :: new ( ) ) ,
4556
- this. with_loop_condition_scope ( |this| P ( this. lower_expr ( sub_expr) ) ) ,
4557
- )
4558
- } ) ;
4559
-
4560
- // `<pat> => <body>`
4561
- let pat_arm = {
4562
- let body_expr = P ( self . expr_block ( body, ThinVec :: new ( ) ) ) ;
4563
- let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
4564
- self . arm ( pats, body_expr)
4565
- } ;
4566
-
4567
- // `_ => break`
4568
- let break_arm = {
4569
- let pat_under = self . pat_wild ( e. span ) ;
4570
- self . arm ( hir_vec ! [ pat_under] , break_expr)
4571
- } ;
4572
-
4573
- // `match <sub_expr> { ... }`
4574
- let arms = hir_vec ! [ pat_arm, break_arm] ;
4575
- let match_expr = self . expr (
4576
- sub_expr. span ,
4577
- hir:: ExprKind :: Match ( sub_expr, arms, hir:: MatchSource :: WhileLetDesugar ) ,
4578
- ThinVec :: new ( ) ,
4579
- ) ;
4580
-
4581
- // `[opt_ident]: loop { ... }`
4582
- let loop_block = P ( self . block_expr ( P ( match_expr) ) ) ;
4583
- let loop_expr = hir:: ExprKind :: Loop (
4584
- loop_block,
4585
- self . lower_label ( opt_label) ,
4586
- hir:: LoopSource :: WhileLet ,
4587
- ) ;
4588
- // Add attributes to the outer returned expr node.
4589
- loop_expr
4590
- }
4591
-
4592
4560
// Desugar `ExprForLoop`
4593
4561
// from: `[opt_ident]: for <pat> in <head> <body>`
4594
4562
ExprKind :: ForLoop ( ref pat, ref head, ref body, opt_label) => {
0 commit comments