@@ -4114,56 +4114,123 @@ impl<'a> LoweringContext<'a> {
41144114 let ohs = P ( self . lower_expr ( ohs) ) ;
41154115 hir:: ExprKind :: AddrOf ( m, ohs)
41164116 }
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.
41194125 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-
41264126 // `_ => else_block` where `else_block` is `{}` if there's `None`:
41274127 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 ) ,
41394131 } ;
41404132 let else_arm = self . arm ( hir_vec ! [ else_pat] , P ( else_expr) ) ;
41414133
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) ) ;
41514167
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+ }
41594233 }
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- } ) ,
41674234 ExprKind :: Loop ( ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
41684235 hir:: ExprKind :: Loop (
41694236 this. lower_block ( body, false ) ,
@@ -4482,105 +4549,6 @@ impl<'a> LoweringContext<'a> {
44824549
44834550 ExprKind :: Err => hir:: ExprKind :: Err ,
44844551
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-
45844552 // Desugar `ExprForLoop`
45854553 // from: `[opt_ident]: for <pat> in <head> <body>`
45864554 ExprKind :: ForLoop ( ref pat, ref head, ref body, opt_label) => {
0 commit comments