Auto merge of #112266 - Swatinem:fix-async-block-inference, r=compiler-errors

Fix type-inference regression in #112225

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.

r? `@compiler-errors`

As this was a stable-to-stable regression, it might be worth to consider backporting. Although the workaround for this is trivial as well: Just wrap the async block in another block.
This commit is contained in:
bors 2023-06-04 22:21:42 +00:00
commit dcf3571c51
4 changed files with 65 additions and 1 deletions

View File

@ -362,7 +362,16 @@ pub(in super::super) fn check_argument_types(
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;
}

View File

@ -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),
{
}

View File

@ -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, ) {}

View File

@ -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`.