From 24a4650889e83ffc67000dd89595170d365bf5ea Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 21 Apr 2021 01:10:19 -0400 Subject: [PATCH 1/3] Enforce that `closure: 'a` requires that `closure_ret_ty: 'a` holds RFC 1214 allows us to infer that `>::Out: 'a` holds, so long as `T: 'a, P0: 'a, ..., PN: 'a` all hold. In order for this to be sound, we must ensure that whenever we need to prove `T: 'a` for some concrete type `T`, we also ensure that any type which could appear in the output type for an impl also outlives `'a` However, we failed to enforce this for closures. Specifically, we allowed `closure: 'a` to hold without requiring that `closure_ret_ty: 'a` also holds. Since `closure_ret_ty` appears in the output of the `FnOnce` impl for closures, it was possible to extend a lifetime by causing rustc to assume that the closure return type outlived a lifetime based on the fact that the closure itself outlived a lifetime. This commit includes the closure return type as one of the 'components' used when computing outlives requirements. To minimize the extent of this breaking change, we do *not* include the arguments of the closure as 'components'. Doing so is still sound, but introduces an inconsistency with function pointers (which do treat their arguments as 'components') Several uses of closures in libcore needed to be adjusted, all of them involving returning a closure via an `impl Fn` opaque type. In all cases, we needed to add extra lifetime bounds to generic parameters that ended up in the return type `R` of `impl Fn() -> R`. --- .../src/infer/outlives/components.rs | 29 ++++++++++++-- library/core/src/iter/adapters/enumerate.rs | 2 +- library/core/src/iter/adapters/filter.rs | 2 +- library/core/src/iter/adapters/filter_map.rs | 8 ++-- library/core/src/iter/adapters/flatten.rs | 16 ++++---- library/core/src/iter/adapters/inspect.rs | 2 +- library/core/src/iter/adapters/map.rs | 2 +- library/core/src/iter/adapters/scan.rs | 2 +- library/core/src/iter/adapters/take.rs | 2 +- library/core/src/iter/adapters/take_while.rs | 2 +- library/core/src/iter/traits/iterator.rs | 2 +- .../issue-84366-closure-outlives-ret.rs | 37 +++++++++++++++++ .../issue-84366-closure-outlives-ret.stderr | 17 ++++++++ .../issue-84366-generator-outlives-return.rs | 40 +++++++++++++++++++ ...sue-84366-generator-outlives-return.stderr | 17 ++++++++ .../issue-84366-generator-outlives-yield.rs | 40 +++++++++++++++++++ ...ssue-84366-generator-outlives-yield.stderr | 17 ++++++++ 17 files changed, 213 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/closures/issue-84366-closure-outlives-ret.rs create mode 100644 src/test/ui/closures/issue-84366-closure-outlives-ret.stderr create mode 100644 src/test/ui/generator/issue-84366-generator-outlives-return.rs create mode 100644 src/test/ui/generator/issue-84366-generator-outlives-return.stderr create mode 100644 src/test/ui/generator/issue-84366-generator-outlives-yield.rs create mode 100644 src/test/ui/generator/issue-84366-generator-outlives-yield.stderr diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 14ee9f0519010..e869525db2f3b 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -101,14 +101,35 @@ fn compute_components<'tcx>( } ty::Closure(_, ref substs) => { - let tupled_ty = substs.as_closure().tupled_upvars_ty(); - compute_components(tcx, tupled_ty, out, visited); + let closure_substs = substs.as_closure(); + compute_components(tcx, closure_substs.tupled_upvars_ty(), out, visited); + // Subtle: The return type of a closure can be used in a projection + // of the form `::Output`. Per the RFC 1214 rules + // for projections, we can use `closure: 'a` to conclude that + // `::Output: 'a` holds. In order for this to be sound, + // we must enforce that requiring `closure: 'a` also requires that. + // the return type of the closure outlive `a`. + // We do not require that any of the closure's *argument* types outlive 'a + // - this is sound, because there is no rule that would allow us to conclide + // anything about the argument types from the fact that `closure: 'a` holds + // (the arguments of a closure do not appear in the output type of a trait impl + // for any trait implemented for a closure). + // This is inconsistent with function pointers, which require that all of their + // argument types (as well as the return type) outlive `'a` in order for + // `fn(A, B) -> R : ' a` to hold. It would be a breaking change to enforce this for + // closuers, and is not required for soundness. + // + // Note: The 'skip_binder()' call here matches the way we handle fn substs + // via `walk_shallow`, which also skips binders. + compute_components(tcx, closure_substs.sig().output().skip_binder(), out, visited); } ty::Generator(_, ref substs, _) => { // Same as the closure case - let tupled_ty = substs.as_generator().tupled_upvars_ty(); - compute_components(tcx, tupled_ty, out, visited); + let generator_substs = substs.as_generator(); + compute_components(tcx, generator_substs.tupled_upvars_ty(), out, visited); + compute_components(tcx, generator_substs.yield_ty(), out, visited); + compute_components(tcx, generator_substs.return_ty(), out, visited); // We ignore regions in the generator interior as we don't // want these to affect region inference diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 14a126951115c..1cfc91c0c73ed 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -76,7 +76,7 @@ where R: Try, { #[inline] - fn enumerate<'a, T, Acc, R>( + fn enumerate<'a, T, Acc, R: 'a>( count: &'a mut usize, mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index a0afaa326ad63..7edcecf5d75d2 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -37,7 +37,7 @@ fn filter_fold( move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } } -fn filter_try_fold<'a, T, Acc, R: Try>( +fn filter_try_fold<'a, T, Acc, R: Try + 'a>( predicate: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index e0d665c9e12ba..04b9f548be865 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -39,7 +39,7 @@ fn filter_map_fold( } } -fn filter_map_try_fold<'a, T, B, Acc, R: Try>( +fn filter_map_try_fold<'a, T, B, Acc, R: Try + 'a>( f: &'a mut impl FnMut(T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -94,9 +94,9 @@ where #[inline] fn next_back(&mut self) -> Option { #[inline] - fn find( - f: &mut impl FnMut(T) -> Option, - ) -> impl FnMut((), T) -> ControlFlow + '_ { + fn find<'a, T, B: 'a>( + f: &'a mut impl FnMut(T) -> Option, + ) -> impl FnMut((), T) -> ControlFlow + 'a { move |(), x| match f(x) { Some(x) => ControlFlow::Break(x), None => ControlFlow::CONTINUE, diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 307016c269099..388338b33e321 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -334,9 +334,9 @@ where Fold: FnMut(Acc, U) -> Acc, { #[inline] - fn flatten( - fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc, - ) -> impl FnMut(Acc, T) -> Acc + '_ { + fn flatten<'a, T: IntoIterator, Acc: 'a>( + fold: &'a mut impl FnMut(Acc, T::IntoIter) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc + 'a { move |acc, iter| fold(acc, iter.into_iter()) } @@ -365,7 +365,7 @@ where R: Try, { #[inline] - fn flatten<'a, T: IntoIterator, Acc, R: Try>( + fn flatten<'a, T: IntoIterator, Acc, R: Try + 'a>( frontiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R, ) -> impl FnMut(Acc, T) -> R + 'a { @@ -403,9 +403,9 @@ where Fold: FnMut(Acc, U) -> Acc, { #[inline] - fn flatten( - fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc, - ) -> impl FnMut(Acc, T) -> Acc + '_ { + fn flatten<'a, T: IntoIterator, Acc: 'a>( + fold: &'a mut impl FnMut(Acc, T::IntoIter) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc + 'a { move |acc, iter| fold(acc, iter.into_iter()) } @@ -434,7 +434,7 @@ where R: Try, { #[inline] - fn flatten<'a, T: IntoIterator, Acc, R: Try>( + fn flatten<'a, T: IntoIterator, Acc, R: Try + 'a>( backiter: &'a mut Option, fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R, ) -> impl FnMut(Acc, T) -> R + 'a { diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 19839fdfe5bc3..23e90c3dfabda 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -54,7 +54,7 @@ fn inspect_fold( } } -fn inspect_try_fold<'a, T, Acc, R>( +fn inspect_try_fold<'a, T, Acc, R: 'a>( f: &'a mut impl FnMut(&T), mut fold: impl FnMut(Acc, T) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 9e25dbe462c91..479141531b619 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -84,7 +84,7 @@ fn map_fold( move |acc, elt| g(acc, f(elt)) } -fn map_try_fold<'a, T, B, Acc, R>( +fn map_try_fold<'a, T, B, Acc, R: 'a>( f: &'a mut impl FnMut(T) -> B, mut g: impl FnMut(Acc, B) -> R + 'a, ) -> impl FnMut(Acc, T) -> R + 'a { diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 80bfd2231241b..6f893783cb450 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -58,7 +58,7 @@ where Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - fn scan<'a, T, St, B, Acc, R: Try>( + fn scan<'a, T, St, B, Acc: 'a, R: Try + 'a>( state: &'a mut St, f: &'a mut impl FnMut(&mut St, T) -> Option, mut fold: impl FnMut(Acc, B) -> R + 'a, diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 2962e0104d11d..d70667aae9ac3 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -79,7 +79,7 @@ where Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - fn check<'a, T, Acc, R: Try>( + fn check<'a, T, Acc: 'a, R: Try + 'a>( n: &'a mut usize, mut fold: impl FnMut(Acc, T) -> R + 'a, ) -> impl FnMut(Acc, T) -> ControlFlow + 'a { diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index ded216da952a3..62908665460b5 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -70,7 +70,7 @@ where Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - fn check<'a, T, Acc, R: Try>( + fn check<'a, T, Acc: 'a, R: Try + 'a>( flag: &'a mut bool, p: &'a mut impl FnMut(&T) -> bool, mut fold: impl FnMut(Acc, T) -> R + 'a, diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index f6e6732b0e391..b9b1979cb4b37 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3848,7 +3848,7 @@ where F: FnMut(A::Item, B::Item) -> ControlFlow, { #[inline] - fn compare<'a, B, X, T>( + fn compare<'a, B, X, T: 'a>( b: &'a mut B, mut f: impl FnMut(X, B::Item) -> ControlFlow + 'a, ) -> impl FnMut(X) -> ControlFlow> + 'a diff --git a/src/test/ui/closures/issue-84366-closure-outlives-ret.rs b/src/test/ui/closures/issue-84366-closure-outlives-ret.rs new file mode 100644 index 0000000000000..6f610a130f366 --- /dev/null +++ b/src/test/ui/closures/issue-84366-closure-outlives-ret.rs @@ -0,0 +1,37 @@ +// Regression test for issue #84366 +// Ensures that proving `closure: 'a` requires that +// we prove `closure_ret_type: 'a` + +use std::fmt; +trait Trait { + type Associated; +} + +impl R> Trait for F { + type Associated = R; +} + +fn static_transfers_to_associated( + _: &T, + x: T::Associated, +) -> Box +where + T::Associated: fmt::Display, +{ + Box::new(x) // T::Associated: 'static follows from T: 'static +} + +fn make_static_displayable<'a>(s: &'a str) -> Box { + let f = || -> &'a str { "" }; + // problem is: the closure type of `f` is 'static + static_transfers_to_associated(&f, s) //~ ERROR borrowed data escapes +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = make_static_displayable(&x); + } + println!("{}", d); +} diff --git a/src/test/ui/closures/issue-84366-closure-outlives-ret.stderr b/src/test/ui/closures/issue-84366-closure-outlives-ret.stderr new file mode 100644 index 0000000000000..07656b7d917e0 --- /dev/null +++ b/src/test/ui/closures/issue-84366-closure-outlives-ret.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-84366-closure-outlives-ret.rs:27:5 + | +LL | fn make_static_displayable<'a>(s: &'a str) -> Box { + | -- - `s` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | static_transfers_to_associated(&f, s) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `s` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/generator/issue-84366-generator-outlives-return.rs b/src/test/ui/generator/issue-84366-generator-outlives-return.rs new file mode 100644 index 0000000000000..ee01257156b80 --- /dev/null +++ b/src/test/ui/generator/issue-84366-generator-outlives-return.rs @@ -0,0 +1,40 @@ +// A version of issue #84366, but involving generator return types instead of closures + +#![feature(generators)] +#![feature(generator_trait)] + +use std::fmt; +use std::ops::Generator; + +trait Trait { + type Associated; +} + +impl> Trait for F { + type Associated = R; +} + +fn static_transfers_to_associated( + _: &T, + x: T::Associated, +) -> Box +where + T::Associated: fmt::Display, +{ + Box::new(x) // T::Associated: 'static follows from T: 'static +} + +fn make_static_displayable<'a>(s: &'a str) -> Box { + let f = || { yield ""; "" }; + // problem is: the closure type of `f` is 'static + static_transfers_to_associated(&f, s) //~ ERROR borrowed data escapes +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = make_static_displayable(&x); + } + println!("{}", d); +} diff --git a/src/test/ui/generator/issue-84366-generator-outlives-return.stderr b/src/test/ui/generator/issue-84366-generator-outlives-return.stderr new file mode 100644 index 0000000000000..ce198b1db0df4 --- /dev/null +++ b/src/test/ui/generator/issue-84366-generator-outlives-return.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-84366-generator-outlives-return.rs:30:5 + | +LL | fn make_static_displayable<'a>(s: &'a str) -> Box { + | -- - `s` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | static_transfers_to_associated(&f, s) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `s` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/generator/issue-84366-generator-outlives-yield.rs b/src/test/ui/generator/issue-84366-generator-outlives-yield.rs new file mode 100644 index 0000000000000..7f274140ed8df --- /dev/null +++ b/src/test/ui/generator/issue-84366-generator-outlives-yield.rs @@ -0,0 +1,40 @@ +// A version of issue #84366, but involving generators instead of closures + +#![feature(generators)] +#![feature(generator_trait)] + +use std::fmt; +use std::ops::Generator; + +trait Trait { + type Associated; +} + +impl> Trait for F { + type Associated = R; +} + +fn static_transfers_to_associated( + _: &T, + x: T::Associated, +) -> Box +where + T::Associated: fmt::Display, +{ + Box::new(x) // T::Associated: 'static follows from T: 'static +} + +fn make_static_displayable<'a>(s: &'a str) -> Box { + let f = || { yield ""; "" }; + // problem is: the closure type of `f` is 'static + static_transfers_to_associated(&f, s) //~ ERROR borrowed data escapes +} + +fn main() { + let d; + { + let x = "Hello World".to_string(); + d = make_static_displayable(&x); + } + println!("{}", d); +} diff --git a/src/test/ui/generator/issue-84366-generator-outlives-yield.stderr b/src/test/ui/generator/issue-84366-generator-outlives-yield.stderr new file mode 100644 index 0000000000000..05d27a449ff3d --- /dev/null +++ b/src/test/ui/generator/issue-84366-generator-outlives-yield.stderr @@ -0,0 +1,17 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-84366-generator-outlives-yield.rs:30:5 + | +LL | fn make_static_displayable<'a>(s: &'a str) -> Box { + | -- - `s` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | static_transfers_to_associated(&f, s) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `s` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. From 1541392400a6556f6d1660b90e8eb9dd512133b2 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 3 Oct 2022 22:01:48 -0500 Subject: [PATCH 2/3] Fix closure return type lifetimes in rustc itself --- compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 4abc00cefb68f..61056fab3ed75 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -108,7 +108,7 @@ pub struct InlineAsmCtxt<'a, 'tcx> { get_operand_ty: Box) -> Ty<'tcx> + 'a>, } -impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { +impl<'a, 'tcx: 'a> InlineAsmCtxt<'a, 'tcx> { pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { InlineAsmCtxt { tcx, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 441dc3c7e888c..d0751be8dbe19 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -335,7 +335,7 @@ pub struct InferCtxt<'tcx> { universe: Cell, normalize_fn_sig_for_diagnostic: - Option, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, + Option, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'tcx>>, } /// See the `error_reporting` module for more details. @@ -552,7 +552,7 @@ pub struct InferCtxtBuilder<'tcx> { defining_use_anchor: DefiningAnchor, considering_regions: bool, normalize_fn_sig_for_diagnostic: - Option, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, + Option, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'tcx>>, } pub trait TyCtxtInferExt<'tcx> { @@ -589,7 +589,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { pub fn with_normalize_fn_sig_for_diagnostic( mut self, - fun: Lrc, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>, + fun: Lrc, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'tcx>, ) -> Self { self.normalize_fn_sig_for_diagnostic = Some(fun); self From 70cec5d274a3651935979d196865b47d9eb6fb86 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 7 Oct 2022 15:37:02 -0500 Subject: [PATCH 3/3] [DO NOT MERGE] [CRATER] Only enable when CARGO_PRIMARY_PACKAGE is set --- .../rustc_infer/src/infer/outlives/components.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index e869525db2f3b..ae9281ff2643e 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -121,15 +121,22 @@ fn compute_components<'tcx>( // // Note: The 'skip_binder()' call here matches the way we handle fn substs // via `walk_shallow`, which also skips binders. - compute_components(tcx, closure_substs.sig().output().skip_binder(), out, visited); + + // Hack - try to get a more accurate count on Crater by skipping this + // when checking dependencies. + if std::env::var("CARGO_PRIMARY_PACKAGE").is_ok() { + compute_components(tcx, closure_substs.sig().output().skip_binder(), out, visited); + } } ty::Generator(_, ref substs, _) => { // Same as the closure case let generator_substs = substs.as_generator(); compute_components(tcx, generator_substs.tupled_upvars_ty(), out, visited); - compute_components(tcx, generator_substs.yield_ty(), out, visited); - compute_components(tcx, generator_substs.return_ty(), out, visited); + if std::env::var("CARGO_PKG_NAME").ok().as_deref() != Some("tokio-util") { + compute_components(tcx, generator_substs.yield_ty(), out, visited); + compute_components(tcx, generator_substs.return_ty(), out, visited); + } // We ignore regions in the generator interior as we don't // want these to affect region inference