Lowering: Fuse ExprKind::While logic + Cleanup.
This commit is contained in:
parent
547735457f
commit
26144fe869
|
@ -4394,20 +4394,17 @@ impl<'a> LoweringContext<'a> {
|
||||||
let then_blk = self.lower_block(then, false);
|
let then_blk = self.lower_block(then, false);
|
||||||
let then_expr = self.expr_block(then_blk, ThinVec::new());
|
let then_expr = self.expr_block(then_blk, ThinVec::new());
|
||||||
let (then_pats, scrutinee, desugar) = match cond.node {
|
let (then_pats, scrutinee, desugar) = match cond.node {
|
||||||
// `<pat> => <then>`
|
// `<pat> => <then>`:
|
||||||
ExprKind::Let(ref pats, ref scrutinee) => {
|
ExprKind::Let(ref pats, ref scrutinee) => {
|
||||||
let scrutinee = self.lower_expr(scrutinee);
|
let scrutinee = self.lower_expr(scrutinee);
|
||||||
let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
|
let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
|
||||||
let desugar = hir::MatchSource::IfLetDesugar { contains_else_clause };
|
let desugar = hir::MatchSource::IfLetDesugar { contains_else_clause };
|
||||||
(pats, scrutinee, desugar)
|
(pats, scrutinee, desugar)
|
||||||
}
|
}
|
||||||
// `true => then`:
|
// `true => <then>`:
|
||||||
_ => {
|
_ => {
|
||||||
// Lower condition:
|
// Lower condition:
|
||||||
let cond = self.lower_expr(cond);
|
let cond = self.lower_expr(cond);
|
||||||
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
|
|
||||||
// to preserve drop semantics since `if cond { ... }`
|
|
||||||
// don't let temporaries live outside of `cond`.
|
|
||||||
let span_block = self.mark_span_with_reason(CondTemporary, cond.span, None);
|
let span_block = self.mark_span_with_reason(CondTemporary, cond.span, None);
|
||||||
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
|
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
|
||||||
// to preserve drop semantics since `if cond { ... }` does not
|
// to preserve drop semantics since `if cond { ... }` does not
|
||||||
|
@ -4424,10 +4421,22 @@ impl<'a> LoweringContext<'a> {
|
||||||
hir::ExprKind::Match(P(scrutinee), vec![then_arm, else_arm].into(), desugar)
|
hir::ExprKind::Match(P(scrutinee), vec![then_arm, else_arm].into(), desugar)
|
||||||
}
|
}
|
||||||
// FIXME(#53667): handle lowering of && and parens.
|
// FIXME(#53667): handle lowering of && and parens.
|
||||||
ExprKind::While(ref cond, ref body, opt_label) => {
|
ExprKind::While(ref cond, ref body, opt_label) => self.with_loop_scope(e.id, |this| {
|
||||||
// Desugar `ExprWhileLet`
|
// Note that the block AND the condition are evaluated in the loop scope.
|
||||||
// from: `[opt_ident]: while let <pat> = <sub_expr> <body>`
|
// This is done to allow `break` from inside the condition of the loop.
|
||||||
if let ExprKind::Let(ref pats, ref sub_expr) = cond.node {
|
|
||||||
|
// `_ => break`:
|
||||||
|
let else_arm = {
|
||||||
|
let else_pat = this.pat_wild(e.span);
|
||||||
|
let else_expr = this.expr_break(e.span, ThinVec::new());
|
||||||
|
this.arm(hir_vec![else_pat], else_expr)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle then + scrutinee:
|
||||||
|
let then_blk = this.lower_block(body, false);
|
||||||
|
let then_expr = this.expr_block(then_blk, ThinVec::new());
|
||||||
|
let (then_pats, scrutinee, desugar, source) = match cond.node {
|
||||||
|
ExprKind::Let(ref pats, ref scrutinee) => {
|
||||||
// to:
|
// to:
|
||||||
//
|
//
|
||||||
// [opt_ident]: loop {
|
// [opt_ident]: loop {
|
||||||
|
@ -4436,49 +4445,12 @@ impl<'a> LoweringContext<'a> {
|
||||||
// _ => break
|
// _ => break
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
let scrutinee = this.with_loop_condition_scope(|t| t.lower_expr(scrutinee));
|
||||||
// Note that the block AND the condition are evaluated in the loop scope.
|
let pats = pats.iter().map(|pat| this.lower_pat(pat)).collect();
|
||||||
// This is done to allow `break` from inside the condition of the loop.
|
let desugar = hir::MatchSource::WhileLetDesugar;
|
||||||
let (body, break_expr, sub_expr) = self.with_loop_scope(e.id, |this| {
|
(pats, scrutinee, desugar, hir::LoopSource::WhileLet)
|
||||||
(
|
}
|
||||||
this.lower_block(body, false),
|
_ => {
|
||||||
this.expr_break(e.span, ThinVec::new()),
|
|
||||||
this.with_loop_condition_scope(|this| P(this.lower_expr(sub_expr))),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
// `<pat> => <body>`
|
|
||||||
let pat_arm = {
|
|
||||||
let body_expr = P(self.expr_block(body, ThinVec::new()));
|
|
||||||
let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
|
|
||||||
self.arm(pats, body_expr)
|
|
||||||
};
|
|
||||||
|
|
||||||
// `_ => break`
|
|
||||||
let break_arm = {
|
|
||||||
let pat_under = self.pat_wild(e.span);
|
|
||||||
self.arm(hir_vec![pat_under], break_expr)
|
|
||||||
};
|
|
||||||
|
|
||||||
// `match <sub_expr> { ... }`
|
|
||||||
let match_expr = self.expr_match(
|
|
||||||
sub_expr.span,
|
|
||||||
sub_expr,
|
|
||||||
hir_vec![pat_arm, break_arm],
|
|
||||||
hir::MatchSource::WhileLetDesugar,
|
|
||||||
);
|
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
|
||||||
let loop_block = P(self.block_expr(P(match_expr)));
|
|
||||||
let loop_expr = hir::ExprKind::Loop(
|
|
||||||
loop_block,
|
|
||||||
self.lower_label(opt_label),
|
|
||||||
hir::LoopSource::WhileLet,
|
|
||||||
);
|
|
||||||
// Add attributes to the outer returned expr node.
|
|
||||||
loop_expr
|
|
||||||
} else {
|
|
||||||
self.with_loop_scope(e.id, |this| {
|
|
||||||
// We desugar: `'label: while $cond $body` into:
|
// We desugar: `'label: while $cond $body` into:
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
|
@ -4490,40 +4462,37 @@ impl<'a> LoweringContext<'a> {
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
|
|
||||||
// `true => then`:
|
|
||||||
let then_pat = this.pat_bool(e.span, true);
|
|
||||||
let then_blk = this.lower_block(body, false);
|
|
||||||
let then_expr = this.expr_block(then_blk, ThinVec::new());
|
|
||||||
let then_arm = this.arm(hir_vec![then_pat], P(then_expr));
|
|
||||||
|
|
||||||
// `_ => break`:
|
|
||||||
let else_pat = this.pat_wild(e.span);
|
|
||||||
let else_expr = this.expr_break(e.span, ThinVec::new());
|
|
||||||
let else_arm = this.arm(hir_vec![else_pat], else_expr);
|
|
||||||
|
|
||||||
// Lower condition:
|
// Lower condition:
|
||||||
let span_block = this.mark_span_with_reason(CondTemporary, cond.span, None);
|
|
||||||
let cond = this.with_loop_condition_scope(|this| this.lower_expr(cond));
|
let cond = this.with_loop_condition_scope(|this| this.lower_expr(cond));
|
||||||
|
let span_block = this.mark_span_with_reason(CondTemporary, cond.span, None);
|
||||||
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
|
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
|
||||||
// to preserve drop semantics since `if cond { ... }` does not
|
// to preserve drop semantics since `while cond { ... }` does not
|
||||||
// let temporaries live outside of `cond`.
|
// let temporaries live outside of `cond`.
|
||||||
let cond = this.expr_drop_temps(span_block, P(cond), ThinVec::new());
|
let cond = this.expr_drop_temps(span_block, P(cond), ThinVec::new());
|
||||||
|
|
||||||
|
let desugar = hir::MatchSource::WhileDesugar;
|
||||||
|
// `true => <then>`:
|
||||||
|
let pats = hir_vec![this.pat_bool(e.span, true)];
|
||||||
|
(pats, cond, desugar, hir::LoopSource::While)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let then_arm = this.arm(then_pats, P(then_expr));
|
||||||
|
|
||||||
|
// `match <scrutinee> { ... }`
|
||||||
let match_expr = this.expr_match(
|
let match_expr = this.expr_match(
|
||||||
cond.span,
|
scrutinee.span,
|
||||||
P(cond),
|
P(scrutinee),
|
||||||
vec![then_arm, else_arm].into(),
|
hir_vec![then_arm, else_arm],
|
||||||
hir::MatchSource::WhileDesugar,
|
desugar,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// `[opt_ident]: loop { ... }`
|
||||||
hir::ExprKind::Loop(
|
hir::ExprKind::Loop(
|
||||||
P(this.block_expr(P(match_expr))),
|
P(this.block_expr(P(match_expr))),
|
||||||
this.lower_label(opt_label),
|
this.lower_label(opt_label),
|
||||||
hir::LoopSource::While,
|
source
|
||||||
)
|
)
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
}
|
|
||||||
ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
|
ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
|
||||||
hir::ExprKind::Loop(
|
hir::ExprKind::Loop(
|
||||||
this.lower_block(body, false),
|
this.lower_block(body, false),
|
||||||
|
|
Loading…
Reference in New Issue