@@ -143,80 +143,8 @@ impl LoweringContext<'_> {
143
143
144
144
hir:: ExprKind :: Match ( P ( scrutinee) , vec ! [ then_arm, else_arm] . into ( ) , desugar)
145
145
}
146
- // FIXME(#53667): handle lowering of && and parens.
147
146
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)
220
148
} ) ,
221
149
ExprKind :: Loop ( ref body, opt_label) => self . with_loop_scope ( e. id , |this| {
222
150
hir:: ExprKind :: Loop (
@@ -351,6 +279,91 @@ impl LoweringContext<'_> {
351
279
}
352
280
}
353
281
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
+
354
367
fn lower_expr_try_block ( & mut self , body : & Block ) -> hir:: ExprKind {
355
368
self . with_catch_scope ( body. id , |this| {
356
369
let unstable_span = this. mark_span_with_reason (
0 commit comments