@@ -4121,56 +4121,123 @@ impl<'a> LoweringContext<'a> {
41214121 let ohs = P ( self . lower_expr ( ohs) ) ;
41224122 hir:: ExprKind :: AddrOf ( m, ohs)
41234123 }
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.
41264132 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-
41334133 // `_ => else_block` where `else_block` is `{}` if there's `None`:
41344134 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 ) ,
41464138 } ;
41474139 let else_arm = self . arm ( hir_vec ! [ else_pat] , P ( else_expr) ) ;
41484140
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) ) ;
41584174
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+ }
41664240 }
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- } ) ,
41744241 ExprKind :: Loop ( ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
41754242 hir:: ExprKind :: Loop (
41764243 this. lower_block ( body, false ) ,
@@ -4490,105 +4557,6 @@ impl<'a> LoweringContext<'a> {
44904557
44914558 ExprKind :: Err => hir:: ExprKind :: Err ,
44924559
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-
45924560 // Desugar `ExprForLoop`
45934561 // from: `[opt_ident]: for <pat> in <head> <body>`
45944562 ExprKind :: ForLoop ( ref pat, ref head, ref body, opt_label) => {
0 commit comments