Skip to content

Commit 4efd5c7

Browse files
committed
Fix an ICE with continue inside a closure inside a loop condition
1 parent f68ee0b commit 4efd5c7

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

src/librustc/hir/lowering.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3538,12 +3538,22 @@ impl<'a> LoweringContext<'a> {
35383538
this.expr_block(block, ThinVec::new())
35393539
})
35403540
})
3541-
},
3541+
}
35423542
ExprKind::Closure(
3543-
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span) =>
3544-
{
3545-
self.with_new_scopes(|this| {
3546-
if let IsAsync::Async(async_closure_node_id) = asyncness {
3543+
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
3544+
) => {
3545+
if let IsAsync::Async(async_closure_node_id) = asyncness {
3546+
let outer_decl = FnDecl {
3547+
inputs: decl.inputs.clone(),
3548+
output: FunctionRetTy::Default(fn_decl_span),
3549+
variadic: false,
3550+
};
3551+
// We need to lower the declaration outside the new scope, because we
3552+
// have to conserve the state of being inside a loop condition for the
3553+
// closure argument types.
3554+
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false);
3555+
3556+
self.with_new_scopes(|this| {
35473557
// FIXME(cramertj) allow `async` non-`move` closures with
35483558
if capture_clause == CaptureBy::Ref &&
35493559
!decl.inputs.is_empty()
@@ -3563,11 +3573,6 @@ impl<'a> LoweringContext<'a> {
35633573

35643574
// Transform `async |x: u8| -> X { ... }` into
35653575
// `|x: u8| future_from_generator(|| -> X { ... })`
3566-
let outer_decl = FnDecl {
3567-
inputs: decl.inputs.clone(),
3568-
output: FunctionRetTy::Default(fn_decl_span),
3569-
variadic: false,
3570-
};
35713576
let body_id = this.lower_body(Some(&outer_decl), |this| {
35723577
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
35733578
Some(&**ty)
@@ -3581,12 +3586,17 @@ impl<'a> LoweringContext<'a> {
35813586
});
35823587
hir::ExprClosure(
35833588
this.lower_capture_clause(capture_clause),
3584-
this.lower_fn_decl(&outer_decl, None, false, false),
3589+
fn_decl,
35853590
body_id,
35863591
fn_decl_span,
35873592
None,
35883593
)
3589-
} else {
3594+
})
3595+
} else {
3596+
// Lower outside new scope to preserve `is_in_loop_condition`.
3597+
let fn_decl = self.lower_fn_decl(decl, None, false, false);
3598+
3599+
self.with_new_scopes(|this| {
35903600
let mut is_generator = false;
35913601
let body_id = this.lower_body(Some(decl), |this| {
35923602
let e = this.lower_expr(body);
@@ -3620,13 +3630,13 @@ impl<'a> LoweringContext<'a> {
36203630
};
36213631
hir::ExprClosure(
36223632
this.lower_capture_clause(capture_clause),
3623-
this.lower_fn_decl(decl, None, false, false),
3633+
fn_decl,
36243634
body_id,
36253635
fn_decl_span,
36263636
generator_option,
36273637
)
3628-
}
3629-
})
3638+
})
3639+
}
36303640
}
36313641
ExprKind::Block(ref blk, opt_label) => {
36323642
hir::ExprBlock(self.lower_block(blk,

src/test/ui/closure-array-break-length.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@
1010

1111
fn main() {
1212
|_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
13+
14+
while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label
1315
}

src/test/ui/closure-array-break-length.stderr

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ error[E0268]: `continue` outside of loop
44
LL | |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
55
| ^^^^^^^^ cannot break outside of a loop
66

7-
error: aborting due to previous error
7+
error[E0590]: `break` or `continue` with no label in the condition of a `while` loop
8+
--> $DIR/closure-array-break-length.rs:14:19
9+
|
10+
LL | while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label
11+
| ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop
12+
13+
error: aborting due to 2 previous errors
814

9-
For more information about this error, try `rustc --explain E0268`.
15+
Some errors occurred: E0268, E0590.
16+
For more information about an error, try `rustc --explain E0268`.

0 commit comments

Comments
 (0)