From: varkor Date: Sat, 23 Jun 2018 12:12:15 +0000 (+0100) Subject: Fix an ICE with continue inside a closure inside a loop condition X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=4efd5c75a8d03b9ad2b5d7de3d58eb342428844d;p=rust.git Fix an ICE with continue inside a closure inside a loop condition --- 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 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { 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 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { // 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 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { }); 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 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr { }; 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`.