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