diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-09-07 23:30:13 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-07 23:30:13 +0200 |
| commit | 7b7f2f7f74522da174910f650e737aa80cc5705e (patch) | |
| tree | 207f62a4761529d2df807cdc5332e4a3081f7f6d | |
| parent | 37523d2a59b4dd210ae6f938c3f05dae0ddb3571 (diff) | |
| parent | 384aed834cd83bdd0e93a2ef5690d3e44bf15856 (diff) | |
| download | rust-7b7f2f7f74522da174910f650e737aa80cc5705e.tar.gz rust-7b7f2f7f74522da174910f650e737aa80cc5705e.zip | |
Rollup merge of #129847 - compiler-errors:async-cycle, r=davidtwco
Do not call query to compute coroutine layout for synthetic body of async closure There is code in the MIR validator that attempts to prevent query cycles when inlining a coroutine into itself, and will use the coroutine layout directly from the body when it detects that's the same coroutine as the one that's being validated. After #128506, this logic didn't take into account the fact that the coroutine def id will differ if it's the "by-move body" of an async closure. This PR implements that. Fixes #129811
| -rw-r--r-- | compiler/rustc_mir_transform/src/validate.rs | 13 | ||||
| -rw-r--r-- | tests/ui/async-await/async-closures/validate-synthetic-body.rs | 19 |
2 files changed, 31 insertions, 1 deletions
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 69e2592e82c..e515dfc5ea5 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1,6 +1,7 @@ //! Validates the MIR to ensure that invariants are upheld. use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_hir as hir; use rustc_hir::LangItem; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -714,7 +715,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // since we may be in the process of computing this MIR in the // first place. let layout = if def_id == self.caller_body.source.def_id() { - // FIXME: This is not right for async closures. + self.caller_body.coroutine_layout_raw() + } else if let Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Closure, + )) = self.tcx.coroutine_kind(def_id) + && let ty::ClosureKind::FnOnce = + args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() + && self.caller_body.source.def_id() + == self.tcx.coroutine_by_move_body_def_id(def_id) + { + // Same if this is the by-move body of a coroutine-closure. self.caller_body.coroutine_layout_raw() } else { self.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty()) diff --git a/tests/ui/async-await/async-closures/validate-synthetic-body.rs b/tests/ui/async-await/async-closures/validate-synthetic-body.rs new file mode 100644 index 00000000000..67e683ac08a --- /dev/null +++ b/tests/ui/async-await/async-closures/validate-synthetic-body.rs @@ -0,0 +1,19 @@ +//@ check-pass +//@ edition: 2021 + +#![feature(async_closure)] + +// Make sure that we don't hit a query cycle when validating +// the by-move coroutine body for an async closure. + +use std::future::Future; + +async fn test<Fut: Future>(operation: impl Fn() -> Fut) { + operation().await; +} + +pub async fn orchestrate_simple_crud() { + test(async || async {}.await).await; +} + +fn main() {} |
