1
Fork 0

Rollup merge of #91975 - cjgillot:noinline-generator, r=jackh726

Move generator check earlier in inlining.

Inlining into generator may create references to other generators. For instance, inlining `Pin::<&mut from_generator::GenFuture<[generator1]>>::new_unchecked` into `generator2`. This cross reference can then create cycles when computing inlining for `generator1`.

In order to avoid this kind of surprises, we forbid all inlining into generators, and rely on LLVM to do the right thing. The existing `remove-zst-query-cycle` already ICEs in inline-mir mode, so we use it as test.

Split from #91743.
This commit is contained in:
Matthias Krüger 2021-12-18 08:16:30 +01:00 committed by GitHub
commit 816cda7e1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 12 additions and 19 deletions

View file

@ -68,6 +68,12 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
if body.source.promoted.is_some() {
return false;
}
// 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 body.generator.is_some() {
return false;
}
let mut this = Inliner {
tcx,
@ -202,14 +208,6 @@ impl<'tcx> Inliner<'tcx> {
if let Some(callee_def_id) = callee.def_id().as_local() {
let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
// 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 caller_body.generator.is_some() {
return Err("local generator (query cycle avoidance)");
}
// Avoid a cycle here by only using `instance_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.