Skip to content

Commit

Permalink
Lower closure prototype after its body.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjgillot committed Jan 21, 2021
1 parent c5a96fb commit 3f42abe
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 13 deletions.
31 changes: 18 additions & 13 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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(
Expand Down Expand Up @@ -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!(
Expand Down Expand Up @@ -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.
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/closures/local-type-mix.rs
Original file line number Diff line number Diff line change
@@ -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
51 changes: 51 additions & 0 deletions src/test/ui/closures/local-type-mix.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 3f42abe

Please sign in to comment.