about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-02-13 15:29:50 +0000
committerMichael Goulet <michael@errs.io>2024-03-19 16:59:23 -0400
commit05116c5c30dea6895fb65fe31b6f2dd0f1198b51 (patch)
tree2b749122abce71572f775b3aba670e61ff3c74c2 /compiler/rustc_ty_utils
parente760daa6a729b3d52a38804e9766f7d89dc27357 (diff)
downloadrust-05116c5c30dea6895fb65fe31b6f2dd0f1198b51.tar.gz
rust-05116c5c30dea6895fb65fe31b6f2dd0f1198b51.zip
Only split by-ref/by-move futures for async closures
Diffstat (limited to 'compiler/rustc_ty_utils')
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs18
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs33
2 files changed, 22 insertions, 29 deletions
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index a5328baadb5..7d54083fbd5 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -102,6 +102,7 @@ fn fn_sig_for_fn_abi<'tcx>(
             )
         }
         ty::CoroutineClosure(def_id, args) => {
+            let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args);
             let sig = args.as_coroutine_closure().coroutine_closure_sig();
             let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
                 sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
@@ -111,18 +112,17 @@ fn fn_sig_for_fn_abi<'tcx>(
                 kind: ty::BoundRegionKind::BrEnv,
             };
             let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
-
             // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`,
             // 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.
-            let mut kind = args.as_coroutine_closure().kind();
-            if let InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } = instance.def {
-                kind = target_kind;
+            let mut coroutine_kind = args.as_coroutine_closure().kind();
+
+            if let InstanceDef::ConstructCoroutineInClosureShim { .. } = instance.def {
+                coroutine_kind = ty::ClosureKind::FnOnce;
             }
 
-            let env_ty =
-                tcx.closure_env_ty(Ty::new_coroutine_closure(tcx, def_id, args), kind, env_region);
+            let env_ty = tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region);
 
             let sig = sig.skip_binder();
             ty::Binder::bind_with_vars(
@@ -132,7 +132,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                         tcx,
                         args.as_coroutine_closure().parent_args(),
                         tcx.coroutine_for_closure(def_id),
-                        kind,
+                        coroutine_kind,
                         env_region,
                         args.as_coroutine_closure().tupled_upvars_ty(),
                         args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
@@ -161,7 +161,7 @@ fn fn_sig_for_fn_abi<'tcx>(
             // 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 {
+            if let InstanceDef::CoroutineKindShim { .. } = instance.def {
                 // Grab the parent coroutine-closure. It has the same args for the purposes
                 // of instantiation, so this will be okay to do.
                 let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx
@@ -181,7 +181,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                             tcx,
                             coroutine_closure_args.parent_args(),
                             did,
-                            target_kind,
+                            ty::ClosureKind::FnOnce,
                             tcx.lifetimes.re_erased,
                             coroutine_closure_args.tupled_upvars_ty(),
                             coroutine_closure_args.coroutine_captures_by_ref_ty(),
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 2816bcc888b..c2ea89f4c29 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -282,7 +282,6 @@ fn resolve_associated_item<'tcx>(
                             Some(Instance {
                                 def: ty::InstanceDef::ConstructCoroutineInClosureShim {
                                     coroutine_closure_def_id,
-                                    target_kind: ty::ClosureKind::FnOnce,
                                 },
                                 args,
                             })
@@ -297,25 +296,19 @@ fn resolve_associated_item<'tcx>(
             {
                 match *rcvr_args.type_at(0).kind() {
                     ty::CoroutineClosure(coroutine_closure_def_id, args) => {
-                        match (target_kind, args.as_coroutine_closure().kind()) {
-                            (ClosureKind::FnOnce | ClosureKind::FnMut, ClosureKind::Fn)
-                            | (ClosureKind::FnOnce, ClosureKind::FnMut) => {
-                                // If we're computing `AsyncFnOnce`/`AsyncFnMut` for a by-ref closure,
-                                // or `AsyncFnOnce` for a by-mut closure, then construct a new body that
-                                // has the right return types.
-                                //
-                                // Specifically, `AsyncFnMut` for a by-ref coroutine-closure just needs
-                                // to have its input and output types fixed (`&mut self` and returning
-                                // `i16` coroutine kind).
-                                Some(Instance {
-                                    def: ty::InstanceDef::ConstructCoroutineInClosureShim {
-                                        coroutine_closure_def_id,
-                                        target_kind,
-                                    },
-                                    args,
-                                })
-                            }
-                            _ => Some(Instance::new(coroutine_closure_def_id, args)),
+                        if target_kind == ClosureKind::FnOnce
+                            && args.as_coroutine_closure().kind() != ClosureKind::FnOnce
+                        {
+                            // If we're computing `AsyncFnOnce` for a by-ref closure then
+                            // construct a new body that has the right return types.
+                            Some(Instance {
+                                def: ty::InstanceDef::ConstructCoroutineInClosureShim {
+                                    coroutine_closure_def_id,
+                                },
+                                args,
+                            })
+                        } else {
+                            Some(Instance::new(coroutine_closure_def_id, args))
                         }
                     }
                     ty::Closure(closure_def_id, args) => {