From d2e10d5cc60eab699f7ae0f11fe5be4c7ccf1b53 Mon Sep 17 00:00:00 2001 From: bors Date: Thu, 16 Sep 2021 16:46:02 +0000 Subject: [PATCH] Auto merge of #88979 - tmiasko:no-remove-zsts-in-generators, r=oli-obk Disable RemoveZsts in generators to avoid query cycles Querying layout of a generator requires its optimized MIR. Thus computing layout during MIR optimization of a generator might create a query cycle. Disable RemoveZsts in generators to avoid the issue (similar approach is used in ConstProp transform already). Fixes #88972. --- compiler/rustc_mir/src/transform/remove_zsts.rs | 4 ++++ src/test/ui/mir/remove-zsts-query-cycle.rs | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/mir/remove-zsts-query-cycle.rs diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir/src/transform/remove_zsts.rs index 03277b1b2e0be..5876ac22c66a7 100644 --- a/compiler/rustc_mir/src/transform/remove_zsts.rs +++ b/compiler/rustc_mir/src/transform/remove_zsts.rs @@ -9,6 +9,10 @@ pub struct RemoveZsts; impl<'tcx> MirPass<'tcx> for RemoveZsts { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // Avoid query cycles (generators require optimized MIR for layout). + if tcx.type_of(body.source.def_id()).is_generator() { + return; + } let param_env = tcx.param_env(body.source.def_id()); let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); for block in basic_blocks.iter_mut() { diff --git a/src/test/ui/mir/remove-zsts-query-cycle.rs b/src/test/ui/mir/remove-zsts-query-cycle.rs new file mode 100644 index 0000000000000..8f93c6cadff5a --- /dev/null +++ b/src/test/ui/mir/remove-zsts-query-cycle.rs @@ -0,0 +1,16 @@ +// Regression test for #88972. Used to cause a query cycle: +// optimized mir -> remove zsts -> layout of a generator -> optimized mir. +// +// edition:2018 +// compile-flags: --crate-type=lib +// build-pass + +pub async fn listen() -> Result<(), std::io::Error> { + let f = do_async(); + std::mem::forget(f); + Ok(()) +} + +pub async fn do_async() { + listen().await.unwrap() +}