Skip to content

Commit

Permalink
Fix type-inference regression in #112225
Browse files Browse the repository at this point in the history
The type inference of argument-position closures and async blocks
regressed in 1.70 as the evaluation order of async blocks changed, as
they are not implicitly wrapped in an identity-function anymore.

Fixes #112225 by making sure the evaluation order stays the same as it
used to.
  • Loading branch information
Swatinem committed Jun 4, 2023
1 parent 9eee230 commit 75b557a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 1 deletion.
11 changes: 10 additions & 1 deletion compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
continue;
}

let is_closure = matches!(arg.kind, ExprKind::Closure { .. });
// For this check, we do *not* want to treat async generator closures (async blocks)
// as proper closures. Doing so would regress type inference when feeding
// the return value of an argument-position async block to an argument-position
// closure wrapped in a block.
// See <https://github.com/rust-lang/rust/issues/112225>.
let is_closure = if let ExprKind::Closure(closure) = arg.kind {
!tcx.generator_is_async(closure.def_id.to_def_id())
} else {
false
};
if is_closure != check_closures {
continue;
}
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/async-await/issues/issue-112225-1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// check-pass
// edition:2021

use core::future::Future;

fn main() {
do_async(async { (0,) }, {
// closure must be inside block
|info| println!("{:?}", info.0)
});
}

fn do_async<R, Fut, F>(_tokio_fut: Fut, _glib_closure: F)
where
Fut: Future<Output = R>,
F: FnOnce(R),
{
}
20 changes: 20 additions & 0 deletions tests/ui/async-await/issues/issue-112225-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// edition:2021

// With the current compiler logic, we cannot have both the `112225-1` case,
// and this `112225-2` case working, as the type inference depends on the evaluation
// order, and there is some explicit ordering going on.
// See the `check_closures` part in `FnCtxt::check_argument_types`.
// The `112225-1` case was a regression in real world code, whereas the `112225-2`
// case never used to work prior to 1.70.

use core::future::Future;

fn main() {
let x = Default::default();
//~^ ERROR: type annotations needed
do_async(
async { x.0; },
{ || { let _: &(i32,) = &x; } },
);
}
fn do_async<Fut, T>(_fut: Fut, _val: T, ) {}
17 changes: 17 additions & 0 deletions tests/ui/async-await/issues/issue-112225-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0282]: type annotations needed
--> $DIR/issue-112225-2.rs:13:9
|
LL | let x = Default::default();
| ^
...
LL | async { x.0; },
| - type must be known at this point
|
help: consider giving `x` an explicit type
|
LL | let x: /* Type */ = Default::default();
| ++++++++++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0282`.

0 comments on commit 75b557a

Please sign in to comment.