Skip to content

Commit 199d585

Browse files
committed
lowering: extract lower_expr_let
1 parent ed1e943 commit 199d585

File tree

1 file changed

+45
-34
lines changed

1 file changed

+45
-34
lines changed

src/librustc/hir/lowering/expr.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -67,40 +67,7 @@ impl LoweringContext<'_> {
6767
let ohs = P(self.lower_expr(ohs));
6868
hir::ExprKind::AddrOf(m, ohs)
6969
}
70-
ExprKind::Let(ref pats, ref scrutinee) => {
71-
// If we got here, the `let` expression is not allowed.
72-
self.sess
73-
.struct_span_err(e.span, "`let` expressions are not supported here")
74-
.note("only supported directly in conditions of `if`- and `while`-expressions")
75-
.note("as well as when nested within `&&` and parenthesis in those conditions")
76-
.emit();
77-
78-
// For better recovery, we emit:
79-
// ```
80-
// match scrutinee { pats => true, _ => false }
81-
// ```
82-
// While this doesn't fully match the user's intent, it has key advantages:
83-
// 1. We can avoid using `abort_if_errors`.
84-
// 2. We can typeck both `pats` and `scrutinee`.
85-
// 3. `pats` is allowed to be refutable.
86-
// 4. The return type of the block is `bool` which seems like what the user wanted.
87-
let scrutinee = self.lower_expr(scrutinee);
88-
let then_arm = {
89-
let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
90-
let expr = self.expr_bool(e.span, true);
91-
self.arm(pats, P(expr))
92-
};
93-
let else_arm = {
94-
let pats = hir_vec![self.pat_wild(e.span)];
95-
let expr = self.expr_bool(e.span, false);
96-
self.arm(pats, P(expr))
97-
};
98-
hir::ExprKind::Match(
99-
P(scrutinee),
100-
vec![then_arm, else_arm].into(),
101-
hir::MatchSource::Normal,
102-
)
103-
}
70+
ExprKind::Let(ref pats, ref scrutinee) => self.lower_expr_let(e.span, pats, scrutinee),
10471
ExprKind::If(ref cond, ref then, ref else_opt) => {
10572
self.lower_expr_if(e.span, cond, then, else_opt.as_deref())
10673
}
@@ -240,6 +207,50 @@ impl LoweringContext<'_> {
240207
}
241208
}
242209

210+
/// Emit an error and lower `ast::ExprKind::Let(pats, scrutinee)` into:
211+
/// ```rust
212+
/// match scrutinee { pats => true, _ => false }
213+
/// ```
214+
fn lower_expr_let(
215+
&mut self,
216+
span: Span,
217+
pats: &[AstP<Pat>],
218+
scrutinee: &Expr
219+
) -> hir::ExprKind {
220+
// If we got here, the `let` expression is not allowed.
221+
self.sess
222+
.struct_span_err(span, "`let` expressions are not supported here")
223+
.note("only supported directly in conditions of `if`- and `while`-expressions")
224+
.note("as well as when nested within `&&` and parenthesis in those conditions")
225+
.emit();
226+
227+
// For better recovery, we emit:
228+
// ```
229+
// match scrutinee { pats => true, _ => false }
230+
// ```
231+
// While this doesn't fully match the user's intent, it has key advantages:
232+
// 1. We can avoid using `abort_if_errors`.
233+
// 2. We can typeck both `pats` and `scrutinee`.
234+
// 3. `pats` is allowed to be refutable.
235+
// 4. The return type of the block is `bool` which seems like what the user wanted.
236+
let scrutinee = self.lower_expr(scrutinee);
237+
let then_arm = {
238+
let pats = pats.iter().map(|pat| self.lower_pat(pat)).collect();
239+
let expr = self.expr_bool(span, true);
240+
self.arm(pats, P(expr))
241+
};
242+
let else_arm = {
243+
let pats = hir_vec![self.pat_wild(span)];
244+
let expr = self.expr_bool(span, false);
245+
self.arm(pats, P(expr))
246+
};
247+
hir::ExprKind::Match(
248+
P(scrutinee),
249+
vec![then_arm, else_arm].into(),
250+
hir::MatchSource::Normal,
251+
)
252+
}
253+
243254
fn lower_expr_if(
244255
&mut self,
245256
span: Span,

0 commit comments

Comments
 (0)