diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 7b95b4d03a6..0542ef4ecf9 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -145,8 +145,6 @@ fn fn_sig_for_fn_abi<'tcx>( ) } ty::Coroutine(did, args) => { - // FIXME(async_closures): This isn't right for `CoroutineKindShim`. - let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); @@ -157,6 +155,40 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; + + let mut ty = ty; + // When this `Closure` comes from a `CoroutineKindShim`, + // make sure we respect the `target_kind` in that shim. + // FIXME(async_closures): This shouldn't be needed, and we should be populating + // a separate def-id for these bodies. + if let InstanceDef::CoroutineKindShim { target_kind, .. } = instance.def { + // Grab the parent coroutine-closure. It has the same args for the purposes + // of substitution, so this will be okay to do. + let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx + .instantiate_and_normalize_erasing_regions( + args, + param_env, + tcx.type_of(tcx.parent(did)), + ) + .kind() + else { + bug!("CoroutineKindShim comes from calling a coroutine-closure"); + }; + let coroutine_closure_args = coroutine_closure_args.as_coroutine_closure(); + ty = tcx.instantiate_bound_regions_with_erased( + coroutine_closure_args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine_given_kind_and_upvars( + tcx, + coroutine_closure_args.parent_args(), + did, + target_kind, + tcx.lifetimes.re_erased, + coroutine_closure_args.tupled_upvars_ty(), + coroutine_closure_args.coroutine_captures_by_ref_ty(), + ) + }), + ); + } let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr deleted file mode 100644 index 48917e8b23f..00000000000 --- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), [i16, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_mut_for_async_fn[3241]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>.See . diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr deleted file mode 100644 index 978a5a653f9..00000000000 --- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_codegen_ssa::mir::locals Unexpected initial operand type: expected std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), [i32, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>, found std::pin::Pin<&ReErased mut Coroutine(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), [i8, std::future::ResumeTy, (), (), CoroutineWitness(DefId(0:8 ~ async_fn_once_for_async_fn[6cdf]::main::{closure#0}::{closure#0}::{closure#0}), []), ()])>.See .