diff options
| author | Arpad Borsos <swatinem@swatinem.de> | 2023-06-04 10:38:14 +0200 |
|---|---|---|
| committer | Arpad Borsos <swatinem@swatinem.de> | 2023-06-04 10:56:00 +0200 |
| commit | 75b557a2c416f997385a886b39e7ef7625073f5a (patch) | |
| tree | 0272e3eac75a52abfe30db85910883c2371d7502 | |
| parent | 9eee230cd0a56bfba3ce65121798d9f9f4341cdd (diff) | |
| download | rust-75b557a2c416f997385a886b39e7ef7625073f5a.tar.gz rust-75b557a2c416f997385a886b39e7ef7625073f5a.zip | |
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.
| -rw-r--r-- | compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 11 | ||||
| -rw-r--r-- | tests/ui/async-await/issues/issue-112225-1.rs | 18 | ||||
| -rw-r--r-- | tests/ui/async-await/issues/issue-112225-2.rs | 20 | ||||
| -rw-r--r-- | tests/ui/async-await/issues/issue-112225-2.stderr | 17 |
4 files changed, 65 insertions, 1 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 72c42f8e789..eba5c829e39 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -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; } diff --git a/tests/ui/async-await/issues/issue-112225-1.rs b/tests/ui/async-await/issues/issue-112225-1.rs new file mode 100644 index 00000000000..e28cbee214e --- /dev/null +++ b/tests/ui/async-await/issues/issue-112225-1.rs @@ -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), +{ +} diff --git a/tests/ui/async-await/issues/issue-112225-2.rs b/tests/ui/async-await/issues/issue-112225-2.rs new file mode 100644 index 00000000000..50fa1a79b6b --- /dev/null +++ b/tests/ui/async-await/issues/issue-112225-2.rs @@ -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, ) {} diff --git a/tests/ui/async-await/issues/issue-112225-2.stderr b/tests/ui/async-await/issues/issue-112225-2.stderr new file mode 100644 index 00000000000..5926a4f3995 --- /dev/null +++ b/tests/ui/async-await/issues/issue-112225-2.stderr @@ -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`. |
