@@ -143,80 +143,8 @@ impl LoweringContext<'_> {
143143
144144 hir:: ExprKind :: Match ( P ( scrutinee) , vec ! [ then_arm, else_arm] . into ( ) , desugar)
145145 }
146- // FIXME(#53667): handle lowering of && and parens.
147146 ExprKind :: While ( ref cond, ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
148- // Note that the block AND the condition are evaluated in the loop scope.
149- // This is done to allow `break` from inside the condition of the loop.
150-
151- // `_ => break`:
152- let else_arm = {
153- let else_pat = this. pat_wild ( e. span ) ;
154- let else_expr = this. expr_break ( e. span , ThinVec :: new ( ) ) ;
155- this. arm ( hir_vec ! [ else_pat] , else_expr)
156- } ;
157-
158- // Handle then + scrutinee:
159- let then_blk = this. lower_block ( body, false ) ;
160- let then_expr = this. expr_block ( then_blk, ThinVec :: new ( ) ) ;
161- let ( then_pats, scrutinee, desugar, source) = match cond. node {
162- ExprKind :: Let ( ref pats, ref scrutinee) => {
163- // to:
164- //
165- // [opt_ident]: loop {
166- // match <sub_expr> {
167- // <pat> => <body>,
168- // _ => break
169- // }
170- // }
171- let scrutinee = this. with_loop_condition_scope ( |t| t. lower_expr ( scrutinee) ) ;
172- let pats = pats. iter ( ) . map ( |pat| this. lower_pat ( pat) ) . collect ( ) ;
173- let desugar = hir:: MatchSource :: WhileLetDesugar ;
174- ( pats, scrutinee, desugar, hir:: LoopSource :: WhileLet )
175- }
176- _ => {
177- // We desugar: `'label: while $cond $body` into:
178- //
179- // ```
180- // 'label: loop {
181- // match DropTemps($cond) {
182- // true => $body,
183- // _ => break,
184- // }
185- // }
186- // ```
187-
188- // Lower condition:
189- let cond = this. with_loop_condition_scope ( |this| this. lower_expr ( cond) ) ;
190- let span_block = this. mark_span_with_reason (
191- DesugaringKind :: CondTemporary , cond. span , None
192- ) ;
193- // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
194- // to preserve drop semantics since `while cond { ... }` does not
195- // let temporaries live outside of `cond`.
196- let cond = this. expr_drop_temps ( span_block, P ( cond) , ThinVec :: new ( ) ) ;
197-
198- let desugar = hir:: MatchSource :: WhileDesugar ;
199- // `true => <then>`:
200- let pats = hir_vec ! [ this. pat_bool( e. span, true ) ] ;
201- ( pats, cond, desugar, hir:: LoopSource :: While )
202- }
203- } ;
204- let then_arm = this. arm ( then_pats, P ( then_expr) ) ;
205-
206- // `match <scrutinee> { ... }`
207- let match_expr = this. expr_match (
208- scrutinee. span ,
209- P ( scrutinee) ,
210- hir_vec ! [ then_arm, else_arm] ,
211- desugar,
212- ) ;
213-
214- // `[opt_ident]: loop { ... }`
215- hir:: ExprKind :: Loop (
216- P ( this. block_expr ( P ( match_expr) ) ) ,
217- this. lower_label ( opt_label) ,
218- source
219- )
147+ this. lower_expr_while_in_loop_scope ( e. span , cond, body, opt_label)
220148 } ) ,
221149 ExprKind :: Loop ( ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
222150 hir:: ExprKind :: Loop (
@@ -351,6 +279,91 @@ impl LoweringContext<'_> {
351279 }
352280 }
353281
282+ fn lower_expr_while_in_loop_scope (
283+ & mut self ,
284+ span : Span ,
285+ cond : & Expr ,
286+ body : & Block ,
287+ opt_label : Option < Label >
288+ ) -> hir:: ExprKind {
289+ // FIXME(#53667): handle lowering of && and parens.
290+
291+ // Note that the block AND the condition are evaluated in the loop scope.
292+ // This is done to allow `break` from inside the condition of the loop.
293+
294+ // `_ => break`:
295+ let else_arm = {
296+ let else_pat = self . pat_wild ( span) ;
297+ let else_expr = self . expr_break ( span, ThinVec :: new ( ) ) ;
298+ self . arm ( hir_vec ! [ else_pat] , else_expr)
299+ } ;
300+
301+ // Handle then + scrutinee:
302+ let then_blk = self . lower_block ( body, false ) ;
303+ let then_expr = self . expr_block ( then_blk, ThinVec :: new ( ) ) ;
304+ let ( then_pats, scrutinee, desugar, source) = match cond. node {
305+ ExprKind :: Let ( ref pats, ref scrutinee) => {
306+ // to:
307+ //
308+ // [opt_ident]: loop {
309+ // match <sub_expr> {
310+ // <pat> => <body>,
311+ // _ => break
312+ // }
313+ // }
314+ let scrutinee = self . with_loop_condition_scope ( |t| t. lower_expr ( scrutinee) ) ;
315+ let pats = pats. iter ( ) . map ( |pat| self . lower_pat ( pat) ) . collect ( ) ;
316+ let desugar = hir:: MatchSource :: WhileLetDesugar ;
317+ ( pats, scrutinee, desugar, hir:: LoopSource :: WhileLet )
318+ }
319+ _ => {
320+ // We desugar: `'label: while $cond $body` into:
321+ //
322+ // ```
323+ // 'label: loop {
324+ // match DropTemps($cond) {
325+ // true => $body,
326+ // _ => break,
327+ // }
328+ // }
329+ // ```
330+
331+ // Lower condition:
332+ let cond = self . with_loop_condition_scope ( |this| this. lower_expr ( cond) ) ;
333+ let span_block = self . mark_span_with_reason (
334+ DesugaringKind :: CondTemporary ,
335+ cond. span ,
336+ None ,
337+ ) ;
338+ // Wrap in a construct equivalent to `{ let _t = $cond; _t }`
339+ // to preserve drop semantics since `while cond { ... }` does not
340+ // let temporaries live outside of `cond`.
341+ let cond = self . expr_drop_temps ( span_block, P ( cond) , ThinVec :: new ( ) ) ;
342+
343+ let desugar = hir:: MatchSource :: WhileDesugar ;
344+ // `true => <then>`:
345+ let pats = hir_vec ! [ self . pat_bool( span, true ) ] ;
346+ ( pats, cond, desugar, hir:: LoopSource :: While )
347+ }
348+ } ;
349+ let then_arm = self . arm ( then_pats, P ( then_expr) ) ;
350+
351+ // `match <scrutinee> { ... }`
352+ let match_expr = self . expr_match (
353+ scrutinee. span ,
354+ P ( scrutinee) ,
355+ hir_vec ! [ then_arm, else_arm] ,
356+ desugar,
357+ ) ;
358+
359+ // `[opt_ident]: loop { ... }`
360+ hir:: ExprKind :: Loop (
361+ P ( self . block_expr ( P ( match_expr) ) ) ,
362+ self . lower_label ( opt_label) ,
363+ source
364+ )
365+ }
366+
354367 fn lower_expr_try_block ( & mut self , body : & Block ) -> hir:: ExprKind {
355368 self . with_catch_scope ( body. id , |this| {
356369 let unstable_span = this. mark_span_with_reason (
0 commit comments