Skip to content

Commit c7e0724

Browse files
committed
auto merge of #17733 : jgallagher/rust/while-let, r=alexcrichton
This is *heavily* based on `if let` (#17634) by @jakub- and @kballard This should close #17687
2 parents daa71e4 + 16ccdba commit c7e0724

File tree

25 files changed

+266
-15
lines changed

25 files changed

+266
-15
lines changed

src/doc/reference.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,8 @@ The currently implemented features of the reference compiler are:
24882488

24892489
* `if_let` - Allows use of the `if let` syntax.
24902490

2491+
* `while_let` - Allows use of the `while let` syntax.
2492+
24912493
* `intrinsics` - Allows use of the "rust-intrinsics" ABI. Compiler intrinsics
24922494
are inherently unstable and no promise about them is made.
24932495

@@ -3494,6 +3496,18 @@ of a condition expression it expects a refutable let statement. If the value of
34943496
expression on the right hand side of the let statement matches the pattern, the corresponding
34953497
block will execute, otherwise flow proceeds to the first `else` block that follows.
34963498

3499+
### While let loops
3500+
3501+
```{.ebnf .gram}
3502+
while_let_expr : "while" "let" pat '=' expr '{' block '}' ;
3503+
```
3504+
3505+
A `while let` loop is semantically identical to a `while` loop but in place of a
3506+
condition expression it expects a refutable let statement. If the value of the
3507+
expression on the right hand side of the let statement matches the pattern, the
3508+
loop body block executes and control returns to the pattern matching statement.
3509+
Otherwise, the while expression completes.
3510+
34973511
### Return expressions
34983512

34993513
```{.ebnf .gram}

src/librustc/diagnostics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,6 @@ register_diagnostics!(
145145
E0161,
146146
E0162,
147147
E0163,
148-
E0164
148+
E0164,
149+
E0165
149150
)

src/librustc/lint/builtin.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,8 @@ impl LintPass for UnnecessaryParens {
10821082
ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
10831083
ast::ExprMatch(ref head, _, source) => match source {
10841084
ast::MatchNormal => (head, "`match` head expression", true),
1085-
ast::MatchIfLetDesugar => (head, "`if let` head expression", true)
1085+
ast::MatchIfLetDesugar => (head, "`if let` head expression", true),
1086+
ast::MatchWhileLetDesugar => (head, "`while let` head expression", true),
10861087
},
10871088
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
10881089
ast::ExprAssign(_, ref value) => (value, "assigned value", false),

src/librustc/middle/cfg/construct.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
259259
expr_exit
260260
}
261261

262+
ast::ExprWhileLet(..) => {
263+
self.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
264+
}
265+
262266
ast::ExprForLoop(ref pat, ref head, ref body, _) => {
263267
//
264268
// [pred]

src/librustc/middle/check_match.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -261,20 +261,32 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[(Vec<P<Pat>>, Option<&Expr>)], source
261261

262262
match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
263263
NotUseful => {
264-
if source == MatchIfLetDesugar {
265-
if printed_if_let_err {
266-
// we already printed an irrefutable if-let pattern error.
267-
// We don't want two, that's just confusing.
268-
} else {
264+
match source {
265+
MatchIfLetDesugar => {
266+
if printed_if_let_err {
267+
// we already printed an irrefutable if-let pattern error.
268+
// We don't want two, that's just confusing.
269+
} else {
270+
// find the first arm pattern so we can use its span
271+
let &(ref first_arm_pats, _) = &arms[0];
272+
let first_pat = first_arm_pats.get(0);
273+
let span = first_pat.span;
274+
span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern");
275+
printed_if_let_err = true;
276+
}
277+
},
278+
279+
MatchWhileLetDesugar => {
269280
// find the first arm pattern so we can use its span
270281
let &(ref first_arm_pats, _) = &arms[0];
271282
let first_pat = first_arm_pats.get(0);
272283
let span = first_pat.span;
273-
span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern");
274-
printed_if_let_err = true;
275-
}
276-
} else {
277-
span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern");
284+
span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern");
285+
},
286+
287+
MatchNormal => {
288+
span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern")
289+
},
278290
}
279291
}
280292
Useful => (),

src/librustc/middle/expr_use_visitor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
429429
self.walk_block(&**blk);
430430
}
431431

432+
ast::ExprWhileLet(..) => {
433+
self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
434+
}
435+
432436
ast::ExprForLoop(ref pat, ref head, ref blk, _) => {
433437
// The pattern lives as long as the block.
434438
debug!("walk_expr for loop case: blk id={}", blk.id);

src/librustc/middle/liveness.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,9 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
484484
ExprIfLet(..) => {
485485
ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
486486
}
487+
ExprWhileLet(..) => {
488+
ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
489+
}
487490
ExprForLoop(ref pat, _, _, _) => {
488491
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
489492
debug!("adding local variable {} from for loop with bm {:?}",
@@ -1022,6 +1025,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
10221025
self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ)
10231026
}
10241027

1028+
ExprWhileLet(..) => {
1029+
self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
1030+
}
1031+
10251032
ExprForLoop(ref pat, ref head, ref blk, _) => {
10261033
let ln = self.propagate_through_loop(expr, ForLoop(&**pat), &**blk, succ);
10271034
self.propagate_through_expr(&**head, ln)
@@ -1480,6 +1487,9 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
14801487
ExprIfLet(..) => {
14811488
this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
14821489
}
1490+
ExprWhileLet(..) => {
1491+
this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
1492+
}
14831493
}
14841494
}
14851495

src/librustc/middle/mem_categorization.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
530530
ast::ExprIfLet(..) => {
531531
self.tcx().sess.span_bug(expr.span, "non-desugared ExprIfLet");
532532
}
533+
ast::ExprWhileLet(..) => {
534+
self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
535+
}
533536
}
534537
}
535538

src/librustc/middle/trans/debuginfo.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3496,6 +3496,11 @@ fn populate_scope_map(cx: &CrateContext,
34963496
})
34973497
}
34983498

3499+
ast::ExprWhileLet(..) => {
3500+
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
3501+
Found unexpanded while-let.");
3502+
}
3503+
34993504
ast::ExprForLoop(ref pattern, ref head, ref body, _) => {
35003505
walk_expr(cx, &**head, scope_stack, scope_map);
35013506

src/librustc/middle/ty.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3605,6 +3605,9 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
36053605
ast::ExprIfLet(..) => {
36063606
tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
36073607
}
3608+
ast::ExprWhileLet(..) => {
3609+
tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3610+
}
36083611

36093612
ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
36103613
RvalueDpsExpr

0 commit comments

Comments
 (0)