diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1b9ccbd850b..2470a8791e1 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -770,10 +770,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Expr, fn_decl_span: Span, ) -> hir::ExprKind<'hir> { - // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, false, None); - - self.with_new_scopes(move |this| { + let (body_id, generator_option) = self.with_new_scopes(move |this| { let prev = this.current_item; this.current_item = Some(fn_decl_span); let mut generator_kind = None; @@ -785,8 +782,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let generator_option = this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability); this.current_item = prev; - hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option) - }) + (body_id, generator_option) + }); + + // Lower outside new scope to preserve `is_in_loop_condition`. + let fn_decl = self.lower_fn_decl(decl, None, false, None); + + hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option) } fn generator_movability_for_fn( @@ -832,12 +834,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::ExprKind<'hir> { let outer_decl = FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - // 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, None); - self.with_new_scopes(move |this| { + let body_id = self.with_new_scopes(|this| { // FIXME(cramertj): allow `async` non-`move` closures with arguments. if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { struct_span_err!( @@ -868,8 +866,15 @@ impl<'hir> LoweringContext<'_, 'hir> { ); this.expr(fn_decl_span, async_body, ThinVec::new()) }); - hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None) - }) + body_id + }); + + // 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, None); + + hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None) } /// Destructure the LHS of complex assignments. diff --git a/src/test/ui/closures/local-type-mix.rs b/src/test/ui/closures/local-type-mix.rs new file mode 100644 index 00000000000..006e6f490f0 --- /dev/null +++ b/src/test/ui/closures/local-type-mix.rs @@ -0,0 +1,17 @@ +// Check that using the parameter name in its type does not ICE. +// edition:2018 + +#![feature(async_closure)] + +fn main() { + let _ = |x: x| x; //~ ERROR expected type + let _ = |x: bool| -> x { x }; //~ ERROR expected type + let _ = async move |x: x| x; //~ ERROR expected type + let _ = async move |x: bool| -> x { x }; //~ ERROR expected type +} + +fn foo(x: x) {} //~ ERROR expected type +fn foo_ret(x: bool) -> x {} //~ ERROR expected type + +async fn async_foo(x: x) {} //~ ERROR expected type +async fn async_foo_ret(x: bool) -> x {} //~ ERROR expected type diff --git a/src/test/ui/closures/local-type-mix.stderr b/src/test/ui/closures/local-type-mix.stderr new file mode 100644 index 00000000000..68c320a065d --- /dev/null +++ b/src/test/ui/closures/local-type-mix.stderr @@ -0,0 +1,51 @@ +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:7:17 + | +LL | let _ = |x: x| x; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:8:26 + | +LL | let _ = |x: bool| -> x { x }; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:9:28 + | +LL | let _ = async move |x: x| x; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:10:37 + | +LL | let _ = async move |x: bool| -> x { x }; + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:13:11 + | +LL | fn foo(x: x) {} + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:14:24 + | +LL | fn foo_ret(x: bool) -> x {} + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:16:23 + | +LL | async fn async_foo(x: x) {} + | ^ not a type + +error[E0573]: expected type, found local variable `x` + --> $DIR/local-type-mix.rs:17:36 + | +LL | async fn async_foo_ret(x: bool) -> x {} + | ^ not a type + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0573`.