Skip to content

Commit 11251b9

Browse files
committed
lowering: extract lower_expr_while_in_loop_scope
1 parent c8b3b2e commit 11251b9

File tree

1 file changed

+86
-73
lines changed

1 file changed

+86
-73
lines changed

src/librustc/hir/lowering/expr.rs

Lines changed: 86 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)