Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lower closure prototype after its body. #81249

Merged
merged 1 commit into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`.