From 6c51ec96bb5b6679645be1651d4ff1d079412af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 2 Sep 2020 00:00:00 +0000 Subject: [PATCH] inliner: Avoid query cycles when optimizing generators The HIR Id trick is insufficient to prevent query cycles when optimizing generators, since merely requesting a layout of a generator also computes its `optimized_mir`. Make no attempts to inline functions into generators within the same crate to avoid query cycles. --- compiler/rustc_mir/src/transform/inline.rs | 10 ++++++++-- src/test/mir-opt/inline/inline-async.rs | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/test/mir-opt/inline/inline-async.rs diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index 315d4fa9d477d..428f4e138c7f9 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -107,8 +107,14 @@ impl Inliner<'tcx> { // Avoid a cycle here by only using `optimized_mir` only if we have // a lower `HirId` than the callee. This ensures that the callee will // not inline us. This trick only works without incremental compilation. - // So don't do it if that is enabled. - if !self.tcx.dep_graph.is_fully_enabled() && self_hir_id < callee_hir_id { + // So don't do it if that is enabled. Also avoid inlining into generators, + // since their `optimized_mir` is used for layout computation, which can + // create a cycle, even when no attempt is made to inline the function + // in the other direction. + if !self.tcx.dep_graph.is_fully_enabled() + && self_hir_id < callee_hir_id + && caller_body.generator_kind.is_none() + { self.tcx.optimized_mir(callsite.callee) } else { continue; diff --git a/src/test/mir-opt/inline/inline-async.rs b/src/test/mir-opt/inline/inline-async.rs new file mode 100644 index 0000000000000..5c838159b986c --- /dev/null +++ b/src/test/mir-opt/inline/inline-async.rs @@ -0,0 +1,18 @@ +// Checks that inliner doesn't introduce cycles when optimizing generators. +// The outcome of optimization is not verfied, just the absence of the cycle. +// Regression test for #76181. +// +// edition:2018 + +#![crate_type = "lib"] + +pub struct S; + +impl S { + pub async fn g(&mut self) { + self.h(); + } + pub fn h(&mut self) { + let _ = self.g(); + } +}