diff options
| author | varkor <github@varkor.com> | 2018-06-23 13:12:15 +0100 |
|---|---|---|
| committer | varkor <github@varkor.com> | 2018-06-23 18:00:47 +0100 |
| commit | 4efd5c75a8d03b9ad2b5d7de3d58eb342428844d (patch) | |
| tree | 0aed3c0ed29656fd3776340493824d9516fd4336 | |
| parent | f68ee0b4e14a8a7e50587bf9752fc1aa72297770 (diff) | |
| download | rust-4efd5c75a8d03b9ad2b5d7de3d58eb342428844d.tar.gz rust-4efd5c75a8d03b9ad2b5d7de3d58eb342428844d.zip | |
Fix an ICE with continue inside a closure inside a loop condition
| -rw-r--r-- | src/librustc/hir/lowering.rs | 40 | ||||
| -rw-r--r-- | src/test/ui/closure-array-break-length.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/closure-array-break-length.stderr | 11 |
3 files changed, 36 insertions, 17 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 02e9415fd8e..13e033e67fc 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3538,12 +3538,22 @@ impl<'a> LoweringContext<'a> { this.expr_block(block, ThinVec::new()) }) }) - }, + } ExprKind::Closure( - capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span) => - { - self.with_new_scopes(|this| { - if let IsAsync::Async(async_closure_node_id) = asyncness { + capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span + ) => { + if let IsAsync::Async(async_closure_node_id) = asyncness { + let outer_decl = FnDecl { + inputs: decl.inputs.clone(), + output: FunctionRetTy::Default(fn_decl_span), + variadic: false, + }; + // We need to lower the declaration outside the new scope, because we + // have to conserve the state of being inside a loop condition for the + // closure argument types. + let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false); + + self.with_new_scopes(|this| { // FIXME(cramertj) allow `async` non-`move` closures with if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() @@ -3563,11 +3573,6 @@ impl<'a> LoweringContext<'a> { // Transform `async |x: u8| -> X { ... }` into // `|x: u8| future_from_generator(|| -> X { ... })` - let outer_decl = FnDecl { - inputs: decl.inputs.clone(), - output: FunctionRetTy::Default(fn_decl_span), - variadic: false, - }; let body_id = this.lower_body(Some(&outer_decl), |this| { let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output { Some(&**ty) @@ -3581,12 +3586,17 @@ impl<'a> LoweringContext<'a> { }); hir::ExprClosure( this.lower_capture_clause(capture_clause), - this.lower_fn_decl(&outer_decl, None, false, false), + fn_decl, body_id, fn_decl_span, None, ) - } else { + }) + } else { + // Lower outside new scope to preserve `is_in_loop_condition`. + let fn_decl = self.lower_fn_decl(decl, None, false, false); + + self.with_new_scopes(|this| { let mut is_generator = false; let body_id = this.lower_body(Some(decl), |this| { let e = this.lower_expr(body); @@ -3620,13 +3630,13 @@ impl<'a> LoweringContext<'a> { }; hir::ExprClosure( this.lower_capture_clause(capture_clause), - this.lower_fn_decl(decl, None, false, false), + fn_decl, body_id, fn_decl_span, generator_option, ) - } - }) + }) + } } ExprKind::Block(ref blk, opt_label) => { hir::ExprBlock(self.lower_block(blk, diff --git a/src/test/ui/closure-array-break-length.rs b/src/test/ui/closure-array-break-length.rs index 67feed38b6c..4b0e941a3ce 100644 --- a/src/test/ui/closure-array-break-length.rs +++ b/src/test/ui/closure-array-break-length.rs @@ -10,4 +10,6 @@ fn main() { |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop + + while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label } diff --git a/src/test/ui/closure-array-break-length.stderr b/src/test/ui/closure-array-break-length.stderr index a1e28e84ced..7cedcb254d6 100644 --- a/src/test/ui/closure-array-break-length.stderr +++ b/src/test/ui/closure-array-break-length.stderr @@ -4,6 +4,13 @@ error[E0268]: `continue` outside of loop LL | |_: [_; continue]| {}; //~ ERROR: `continue` outside of loop | ^^^^^^^^ cannot break outside of a loop -error: aborting due to previous error +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/closure-array-break-length.rs:14:19 + | +LL | while |_: [_; continue]| {} {} //~ ERROR: `break` or `continue` with no label + | ^^^^^^^^ unlabeled `continue` in the condition of a `while` loop + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0268`. +Some errors occurred: E0268, E0590. +For more information about an error, try `rustc --explain E0268`. |
