Skip to content

Commit 7262824

Browse files
authored
Rollup merge of rust-lang#51731 - varkor:closure-array-break-length, r=estebank
Fix ICEs when using continue as an array length inside closures (inside loop conditions) Fixes rust-lang#51707. Fixes rust-lang#51708. r? @estebank
2 parents b71f6df + c3d6ee9 commit 7262824

File tree

9 files changed

+87
-31
lines changed

9 files changed

+87
-31
lines changed

src/librustc/hir/lowering.rs

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

35623572
// Transform `async |x: u8| -> X { ... }` into
35633573
// `|x: u8| future_from_generator(|| -> X { ... })`
3564-
let outer_decl = FnDecl {
3565-
inputs: decl.inputs.clone(),
3566-
output: FunctionRetTy::Default(fn_decl_span),
3567-
variadic: false,
3568-
};
35693574
let body_id = this.lower_body(Some(&outer_decl), |this| {
35703575
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
35713576
Some(&**ty)
@@ -3579,12 +3584,17 @@ impl<'a> LoweringContext<'a> {
35793584
});
35803585
hir::ExprClosure(
35813586
this.lower_capture_clause(capture_clause),
3582-
this.lower_fn_decl(&outer_decl, None, false, false),
3587+
fn_decl,
35833588
body_id,
35843589
fn_decl_span,
35853590
None,
35863591
)
3587-
} else {
3592+
})
3593+
} else {
3594+
// Lower outside new scope to preserve `is_in_loop_condition`.
3595+
let fn_decl = self.lower_fn_decl(decl, None, false, false);
3596+
3597+
self.with_new_scopes(|this| {
35883598
let mut is_generator = false;
35893599
let body_id = this.lower_body(Some(decl), |this| {
35903600
let e = this.lower_expr(body);
@@ -3618,13 +3628,13 @@ impl<'a> LoweringContext<'a> {
36183628
};
36193629
hir::ExprClosure(
36203630
this.lower_capture_clause(capture_clause),
3621-
this.lower_fn_decl(decl, None, false, false),
3631+
fn_decl,
36223632
body_id,
36233633
fn_decl_span,
36243634
generator_option,
36253635
)
3626-
}
3627-
})
3636+
})
3637+
}
36283638
}
36293639
ExprKind::Block(ref blk, opt_label) => {
36303640
hir::ExprBlock(self.lower_block(blk,

src/librustc_mir/build/scope.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,12 +540,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
540540
// ==============
541541
/// Finds the breakable scope for a given label. This is used for
542542
/// resolving `break` and `continue`.
543-
pub fn find_breakable_scope(&mut self,
543+
pub fn find_breakable_scope(&self,
544544
span: Span,
545545
label: region::Scope)
546-
-> &mut BreakableScope<'tcx> {
546+
-> &BreakableScope<'tcx> {
547547
// find the loop-scope with the correct id
548-
self.breakable_scopes.iter_mut()
548+
self.breakable_scopes.iter()
549549
.rev()
550550
.filter(|breakable_scope| breakable_scope.region_scope == label)
551551
.next()

src/librustc_typeck/check/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3846,7 +3846,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
38463846
}
38473847

38483848
}
3849-
hir::ExprContinue(_) => { tcx.types.never }
3849+
hir::ExprContinue(destination) => {
3850+
if let Ok(_) = destination.target_id {
3851+
tcx.types.never
3852+
} else {
3853+
// There was an error, make typecheck fail
3854+
tcx.types.err
3855+
}
3856+
}
38503857
hir::ExprRet(ref expr_opt) => {
38513858
if self.ret_coercion.is_none() {
38523859
struct_span_err!(self.tcx.sess, expr.span, E0572,

src/test/mir-opt/end_region_6.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,17 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
6868
// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19s D]) -> i32 {
6969
// let mut _0: i32;
7070
// ...
71-
// let _2: &'15_0rs D;
71+
// let _2: &'16_0rs D;
7272
// ...
7373
// let mut _3: i32;
7474
// bb0: {
7575
// StorageLive(_2);
76-
// _2 = &'15_0rs (*(_1.0: &'19s D));
76+
// _2 = &'16_0rs (*(_1.0: &'19s D));
7777
// StorageLive(_3);
7878
// _3 = ((*_2).0: i32);
7979
// _0 = move _3;
8080
// StorageDead(_3);
81-
// EndRegion('15_0rs);
81+
// EndRegion('16_0rs);
8282
// StorageDead(_2);
8383
// return;
8484
// }

src/test/mir-opt/end_region_7.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,17 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
7676
// fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 {
7777
// let mut _0: i32;
7878
// ...
79-
// let _2: &'15_0rs D;
79+
// let _2: &'16_0rs D;
8080
// ...
8181
// let mut _3: i32;
8282
// bb0: {
8383
// StorageLive(_2);
84-
// _2 = &'15_0rs (_1.0: D);
84+
// _2 = &'16_0rs (_1.0: D);
8585
// StorageLive(_3);
8686
// _3 = ((*_2).0: i32);
8787
// _0 = move _3;
8888
// StorageDead(_3);
89-
// EndRegion('15_0rs);
89+
// EndRegion('16_0rs);
9090
// StorageDead(_2);
9191
// drop(_1) -> [return: bb2, unwind: bb1];
9292
// }

src/test/mir-opt/validate_1.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ fn main() {
6464
// bb0: {
6565
// Validate(Acquire, [_1: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrEnv) [closure@NodeId(50)], _2: &ReFree(DefId(0/1:11 ~ validate_1[317d]::main[0]::{{closure}}[0]), BrAnon(0)) mut i32]);
6666
// StorageLive(_3);
67-
// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 }))), [(*_2): i32]);
67+
// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 }))), [(*_2): i32]);
6868
// _3 = &ReErased (*_2);
69-
// Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 })) (imm)]);
69+
// Validate(Acquire, [(*_3): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })) (imm)]);
7070
// StorageLive(_4);
7171
// _4 = (*_3);
7272
// _0 = move _4;
7373
// StorageDead(_4);
74-
// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 })));
74+
// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(25), first_statement_index: 0 })));
7575
// StorageDead(_3);
7676
// return;
7777
// }

src/test/mir-opt/validate_5.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ fn main() {
5353
// StorageLive(_3);
5454
// StorageLive(_4);
5555
// StorageLive(_5);
56-
// Validate(Suspend(ReScope(Node(ItemLocalId(9)))), [(*_2): i32]);
56+
// Validate(Suspend(ReScope(Node(ItemLocalId(12)))), [(*_2): i32]);
5757
// _5 = &ReErased mut (*_2);
58-
// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(9)))]);
58+
// Validate(Acquire, [(*_5): i32/ReScope(Node(ItemLocalId(12)))]);
5959
// _4 = move _5 as *mut i32 (Misc);
6060
// _3 = move _4;
61-
// EndRegion(ReScope(Node(ItemLocalId(9))));
61+
// EndRegion(ReScope(Node(ItemLocalId(12))));
6262
// StorageDead(_4);
6363
// StorageDead(_5);
6464
// Validate(Release, [_0: bool, _3: *mut i32]);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
|_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
13+
14+
while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label
15+
16+
while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0268]: `continue` outside of loop
2+
--> $DIR/closure-array-break-length.rs:12:13
3+
|
4+
LL | |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop
5+
| ^^^^^^^^ cannot break outside of a loop
6+
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[E0590]: `break` or `continue` with no label in the condition of a `while` loop
14+
--> $DIR/closure-array-break-length.rs:16:19
15+
|
16+
LL | while |_: [_; break]| {} {} //~ ERROR: `break` or `continue` with no label
17+
| ^^^^^ unlabeled `break` in the condition of a `while` loop
18+
19+
error: aborting due to 3 previous errors
20+
21+
Some errors occurred: E0268, E0590.
22+
For more information about an error, try `rustc --explain E0268`.

0 commit comments

Comments
 (0)