diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 575aab47ac750..a4c1066ee8e92 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -87,7 +87,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.tcx(),
ty::CoroutineArgsParts {
parent_args: args.parent_args(),
- kind_ty: Ty::from_closure_kind(self.tcx(), args.kind()),
+ kind_ty: Ty::from_coroutine_closure_kind(self.tcx(), args.kind()),
return_ty: user_provided_sig.output(),
tupled_upvars_ty,
// For async closures, none of these can be annotated, so just fill
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 9a500fa712bf3..0e75a47683dcc 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -184,16 +184,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind: TypeVariableOriginKind::TypeInference,
span: callee_expr.span,
});
+ // We may actually receive a coroutine back whose kind is different
+ // from the closure that this dispatched from. This is because when
+ // we have no captures, we automatically implement `FnOnce`. This
+ // impl forces the closure kind to `FnOnce` i.e. `u8`.
+ let kind_ty = self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span: callee_expr.span,
+ });
let call_sig = self.tcx.mk_fn_sig(
[coroutine_closure_sig.tupled_inputs_ty],
coroutine_closure_sig.to_coroutine(
self.tcx,
closure_args.parent_args(),
- // Inherit the kind ty of the closure, since we're calling this
- // coroutine with the most relaxed `AsyncFn*` trait that we can.
- // We don't necessarily need to do this here, but it saves us
- // computing one more infer var that will get constrained later.
- closure_args.kind_ty(),
+ kind_ty,
self.tcx.coroutine_for_closure(def_id),
tupled_upvars_ty,
),
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 4bea4bb3e8262..6e30cb0224535 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -262,6 +262,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
},
);
+ let coroutine_kind_ty = self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::ClosureSynthetic,
+ span: expr_span,
+ });
let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::ClosureSynthetic,
span: expr_span,
@@ -279,7 +283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sig.to_coroutine(
tcx,
parent_args,
- closure_kind_ty,
+ coroutine_kind_ty,
tcx.coroutine_for_closure(expr_def_id),
coroutine_upvars_ty,
)
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index be14f5bf0d8b5..b71e88a15799c 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -410,7 +410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.demand_eqtype(
span,
coroutine_args.as_coroutine().kind_ty(),
- Ty::from_closure_kind(self.tcx, closure_kind),
+ Ty::from_coroutine_closure_kind(self.tcx, closure_kind),
);
}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index d57ffc0f8b5c5..984d4687ef8b4 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -278,13 +278,6 @@ pub struct CoroutineInfo<'tcx> {
/// using `run_passes`.
pub by_move_body: Option
>,
- /// The body of the coroutine, modified to take its upvars by mutable ref rather than by
- /// immutable ref.
- ///
- /// FIXME(async_closures): This is literally the same body as the parent body. Find a better
- /// way to represent the by-mut signature (or cap the closure-kind of the coroutine).
- pub by_mut_body: Option>,
-
/// The layout of a coroutine. This field is populated after the state transform pass.
pub coroutine_layout: Option>,
@@ -305,7 +298,6 @@ impl<'tcx> CoroutineInfo<'tcx> {
yield_ty: Some(yield_ty),
resume_ty: Some(resume_ty),
by_move_body: None,
- by_mut_body: None,
coroutine_drop: None,
coroutine_layout: None,
}
@@ -628,10 +620,6 @@ impl<'tcx> Body<'tcx> {
self.coroutine.as_ref()?.by_move_body.as_ref()
}
- pub fn coroutine_by_mut_body(&self) -> Option<&Body<'tcx>> {
- self.coroutine.as_ref()?.by_mut_body.as_ref()
- }
-
#[inline]
pub fn coroutine_kind(&self) -> Option {
self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind)
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 845b17175505d..be960669ff4d0 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -345,8 +345,11 @@ macro_rules! make_mir_visitor {
ty::InstanceDef::Virtual(_def_id, _) |
ty::InstanceDef::ThreadLocalShim(_def_id) |
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
- ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, target_kind: _ } |
- ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id, target_kind: _ } |
+ ty::InstanceDef::ConstructCoroutineInClosureShim {
+ coroutine_closure_def_id: _def_id,
+ receiver_by_ref: _,
+ } |
+ ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id } |
ty::InstanceDef::DropGlue(_def_id, None) => {}
ty::InstanceDef::FnPtrShim(_def_id, ty) |
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 814c3629b08fa..4748e961019e1 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -90,15 +90,19 @@ pub enum InstanceDef<'tcx> {
/// and dispatch to the `FnMut::call_mut` instance for the closure.
ClosureOnceShim { call_once: DefId, track_caller: bool },
- /// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once` or
- /// `<[Fn coroutine-closure] as FnMut>::call_mut`.
+ /// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once`
///
/// The body generated here differs significantly from the `ClosureOnceShim`,
/// since we need to generate a distinct coroutine type that will move the
/// closure's upvars *out* of the closure.
ConstructCoroutineInClosureShim {
coroutine_closure_def_id: DefId,
- target_kind: ty::ClosureKind,
+ // Whether the generated MIR body takes the coroutine by-ref. This is
+ // because the signature of `<{async fn} as FnMut>::call_mut` is:
+ // `fn(&mut self, args: A) -> ::Output`, that is to say
+ // that it returns the `FnOnce`-flavored coroutine but takes the closure
+ // by mut ref (and similarly for `Fn::call`).
+ receiver_by_ref: bool,
},
/// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce`
@@ -107,7 +111,7 @@ pub enum InstanceDef<'tcx> {
///
/// This will select the body that is produced by the `ByMoveBody` transform, and thus
/// take and use all of its upvars by-move rather than by-ref.
- CoroutineKindShim { coroutine_def_id: DefId, target_kind: ty::ClosureKind },
+ CoroutineKindShim { coroutine_def_id: DefId },
/// Compiler-generated accessor for thread locals which returns a reference to the thread local
/// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking
@@ -192,9 +196,9 @@ impl<'tcx> InstanceDef<'tcx> {
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
| ty::InstanceDef::ConstructCoroutineInClosureShim {
coroutine_closure_def_id: def_id,
- target_kind: _,
+ receiver_by_ref: _,
}
- | ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id, target_kind: _ }
+ | ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id }
| InstanceDef::DropGlue(def_id, _)
| InstanceDef::CloneShim(def_id, _)
| InstanceDef::FnPtrAddrShim(def_id, _) => def_id,
@@ -651,10 +655,7 @@ impl<'tcx> Instance<'tcx> {
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
} else {
Some(Instance {
- def: ty::InstanceDef::CoroutineKindShim {
- coroutine_def_id,
- target_kind: args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
- },
+ def: ty::InstanceDef::CoroutineKindShim { coroutine_def_id },
args,
})
}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 540936d7d8a6f..6e0a9eb86dde7 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -483,7 +483,7 @@ impl<'tcx> CoroutineClosureSignature<'tcx> {
self.to_coroutine(
tcx,
parent_args,
- Ty::from_closure_kind(tcx, goal_kind),
+ Ty::from_coroutine_closure_kind(tcx, goal_kind),
coroutine_def_id,
tupled_upvars_ty,
)
@@ -2456,6 +2456,25 @@ impl<'tcx> Ty<'tcx> {
}
}
+ /// Like [`Ty::to_opt_closure_kind`], but it caps the "maximum" closure kind
+ /// to `FnMut`. This is because although we have three capability states,
+ /// `AsyncFn`/`AsyncFnMut`/`AsyncFnOnce`, we only need to distinguish two coroutine
+ /// bodies: by-ref and by-value.
+ ///
+ /// See the definition of `AsyncFn` and `AsyncFnMut` and the `CallRefFuture`
+ /// associated type for why we don't distinguish [`ty::ClosureKind::Fn`] and
+ /// [`ty::ClosureKind::FnMut`] for the purpose of the generated MIR bodies.
+ ///
+ /// This method should be used when constructing a `Coroutine` out of a
+ /// `CoroutineClosure`, when the `Coroutine`'s `kind` field is being populated
+ /// directly from the `CoroutineClosure`'s `kind`.
+ pub fn from_coroutine_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
+ match kind {
+ ty::ClosureKind::Fn | ty::ClosureKind::FnMut => tcx.types.i16,
+ ty::ClosureKind::FnOnce => tcx.types.i32,
+ }
+ }
+
/// Fast path helper for testing if a type is `Sized`.
///
/// Returning true means the type is known to be sized. Returning
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index e40f4520671bb..000b96ee8016f 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -67,45 +67,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
by_move_body.source = mir::MirSource {
instance: InstanceDef::CoroutineKindShim {
coroutine_def_id: coroutine_def_id.to_def_id(),
- target_kind: ty::ClosureKind::FnOnce,
},
promoted: None,
};
body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body);
-
- // If this is coming from an `AsyncFn` coroutine-closure, we must also create a by-mut body.
- // This is actually just a copy of the by-ref body, but with a different self type.
- // FIXME(async_closures): We could probably unify this with the by-ref body somehow.
- if coroutine_kind == ty::ClosureKind::Fn {
- let by_mut_coroutine_ty = Ty::new_coroutine(
- tcx,
- coroutine_def_id.to_def_id(),
- ty::CoroutineArgs::new(
- tcx,
- ty::CoroutineArgsParts {
- parent_args: args.as_coroutine().parent_args(),
- kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnMut),
- resume_ty: args.as_coroutine().resume_ty(),
- yield_ty: args.as_coroutine().yield_ty(),
- return_ty: args.as_coroutine().return_ty(),
- witness: args.as_coroutine().witness(),
- tupled_upvars_ty: args.as_coroutine().tupled_upvars_ty(),
- },
- )
- .args,
- );
- let mut by_mut_body = body.clone();
- by_mut_body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty = by_mut_coroutine_ty;
- dump_mir(tcx, false, "coroutine_by_mut", &0, &by_mut_body, |_, _| Ok(()));
- by_mut_body.source = mir::MirSource {
- instance: InstanceDef::CoroutineKindShim {
- coroutine_def_id: coroutine_def_id.to_def_id(),
- target_kind: ty::ClosureKind::FnMut,
- },
- promoted: None,
- };
- body.coroutine.as_mut().unwrap().by_mut_body = Some(by_mut_body);
- }
}
}
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 77478cc741d39..17a1c3c715797 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -186,9 +186,6 @@ fn run_passes_inner<'tcx>(
if let Some(by_move_body) = coroutine.by_move_body.as_mut() {
run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each);
}
- if let Some(by_mut_body) = coroutine.by_mut_body.as_mut() {
- run_passes_inner(tcx, by_mut_body, passes, phase_change, validate_each);
- }
}
}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 733e2f93b2535..28b502e8cabe5 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -3,8 +3,8 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::*;
use rustc_middle::query::Providers;
+use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt};
-use rustc_middle::ty::{GenericArgs, CAPTURE_STRUCT_LOCAL};
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_index::{Idx, IndexVec};
@@ -72,37 +72,12 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
ty::InstanceDef::ConstructCoroutineInClosureShim {
coroutine_closure_def_id,
- target_kind,
- } => match target_kind {
- ty::ClosureKind::Fn => unreachable!("shouldn't be building shim for Fn"),
- ty::ClosureKind::FnMut => {
- // No need to optimize the body, it has already been optimized
- // since we steal it from the `AsyncFn::call` body and just fix
- // the return type.
- return build_construct_coroutine_by_mut_shim(tcx, coroutine_closure_def_id);
- }
- ty::ClosureKind::FnOnce => {
- build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id)
- }
- },
+ receiver_by_ref,
+ } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref),
- ty::InstanceDef::CoroutineKindShim { coroutine_def_id, target_kind } => match target_kind {
- ty::ClosureKind::Fn => unreachable!(),
- ty::ClosureKind::FnMut => {
- return tcx
- .optimized_mir(coroutine_def_id)
- .coroutine_by_mut_body()
- .unwrap()
- .clone();
- }
- ty::ClosureKind::FnOnce => {
- return tcx
- .optimized_mir(coroutine_def_id)
- .coroutine_by_move_body()
- .unwrap()
- .clone();
- }
- },
+ ty::InstanceDef::CoroutineKindShim { coroutine_def_id } => {
+ return tcx.optimized_mir(coroutine_def_id).coroutine_by_move_body().unwrap().clone();
+ }
ty::InstanceDef::DropGlue(def_id, ty) => {
// FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
@@ -123,21 +98,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() {
coroutine_body.coroutine_drop().unwrap()
} else {
- match args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() {
- ty::ClosureKind::Fn => {
- unreachable!()
- }
- ty::ClosureKind::FnMut => coroutine_body
- .coroutine_by_mut_body()
- .unwrap()
- .coroutine_drop()
- .unwrap(),
- ty::ClosureKind::FnOnce => coroutine_body
- .coroutine_by_move_body()
- .unwrap()
- .coroutine_drop()
- .unwrap(),
- }
+ assert_eq!(
+ args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
+ ty::ClosureKind::FnOnce
+ );
+ coroutine_body.coroutine_by_move_body().unwrap().coroutine_drop().unwrap()
};
let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
@@ -1051,12 +1016,26 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t
fn build_construct_coroutine_by_move_shim<'tcx>(
tcx: TyCtxt<'tcx>,
coroutine_closure_def_id: DefId,
+ receiver_by_ref: bool,
) -> Body<'tcx> {
- let self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity();
+ let mut self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity();
let ty::CoroutineClosure(_, args) = *self_ty.kind() else {
bug!();
};
+ // We use `*mut Self` here because we only need to emit an ABI-compatible shim body,
+ // rather than match the signature exactly.
+ //
+ // The self type here is a coroutine-closure, not a coroutine, and we never read from
+ // it because it never has any captures, because this is only true in the Fn/FnMut
+ // implementation, not the AsyncFn/AsyncFnMut implementation, which is implemented only
+ // if the coroutine-closure has no captures.
+ if receiver_by_ref {
+ // Triple-check that there's no captures here.
+ assert_eq!(args.as_coroutine_closure().tupled_upvars_ty(), tcx.types.unit);
+ self_ty = Ty::new_mut_ptr(tcx, self_ty);
+ }
+
let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
tcx.mk_fn_sig(
[self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()),
@@ -1112,49 +1091,19 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
let source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim {
coroutine_closure_def_id,
- target_kind: ty::ClosureKind::FnOnce,
+ receiver_by_ref,
});
let body =
new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span);
- dump_mir(tcx, false, "coroutine_closure_by_move", &0, &body, |_, _| Ok(()));
-
- body
-}
-
-fn build_construct_coroutine_by_mut_shim<'tcx>(
- tcx: TyCtxt<'tcx>,
- coroutine_closure_def_id: DefId,
-) -> Body<'tcx> {
- let mut body = tcx.optimized_mir(coroutine_closure_def_id).clone();
- let coroutine_closure_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity();
- let ty::CoroutineClosure(_, args) = *coroutine_closure_ty.kind() else {
- bug!();
- };
- let args = args.as_coroutine_closure();
-
- body.local_decls[RETURN_PLACE].ty =
- tcx.instantiate_bound_regions_with_erased(args.coroutine_closure_sig().map_bound(|sig| {
- sig.to_coroutine_given_kind_and_upvars(
- tcx,
- args.parent_args(),
- tcx.coroutine_for_closure(coroutine_closure_def_id),
- ty::ClosureKind::FnMut,
- tcx.lifetimes.re_erased,
- args.tupled_upvars_ty(),
- args.coroutine_captures_by_ref_ty(),
- )
- }));
- body.local_decls[CAPTURE_STRUCT_LOCAL].ty =
- Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_closure_ty);
-
- body.source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim {
- coroutine_closure_def_id,
- target_kind: ty::ClosureKind::FnMut,
- });
-
- body.pass_count = 0;
- dump_mir(tcx, false, "coroutine_closure_by_mut", &0, &body, |_, _| Ok(()));
+ dump_mir(
+ tcx,
+ false,
+ if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" },
+ &0,
+ &body,
+ |_, _| Ok(()),
+ );
body
}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 63b950a2803c4..8b911a41a112f 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -166,9 +166,8 @@ symbols! {
Break,
C,
CStr,
- CallFuture,
- CallMutFuture,
CallOnceFuture,
+ CallRefFuture,
Capture,
Center,
Cleanup,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 83e920e2f8ee4..1c62ce2d214b7 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -76,16 +76,10 @@ pub(super) fn mangle<'tcx>(
}
// FIXME(async_closures): This shouldn't be needed when we fix
// `Instance::ty`/`Instance::def_id`.
- ty::InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. }
- | ty::InstanceDef::CoroutineKindShim { target_kind, .. } => match target_kind {
- ty::ClosureKind::Fn => unreachable!(),
- ty::ClosureKind::FnMut => {
- printer.write_str("{{fn-mut-shim}}").unwrap();
- }
- ty::ClosureKind::FnOnce => {
- printer.write_str("{{fn-once-shim}}").unwrap();
- }
- },
+ ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
+ | ty::InstanceDef::CoroutineKindShim { .. } => {
+ printer.write_str("{{fn-once-shim}}").unwrap();
+ }
_ => {}
}
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index f1b1b4ed2bb84..6bc375512ac57 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -46,12 +46,8 @@ pub(super) fn mangle<'tcx>(
ty::InstanceDef::VTableShim(_) => Some("vtable"),
ty::InstanceDef::ReifyShim(_) => Some("reify"),
- ty::InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. }
- | ty::InstanceDef::CoroutineKindShim { target_kind, .. } => match target_kind {
- ty::ClosureKind::Fn => unreachable!(),
- ty::ClosureKind::FnMut => Some("fn_mut"),
- ty::ClosureKind::FnOnce => Some("fn_once"),
- },
+ ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
+ | ty::InstanceDef::CoroutineKindShim { .. } => Some("fn_once"),
_ => None,
};
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index d24bec5a766b9..85bb6338daff9 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -414,7 +414,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
),
output_coroutine_ty.into(),
),
- sym::CallMutFuture | sym::CallFuture => (
+ sym::CallRefFuture => (
ty::AliasTy::new(
tcx,
goal.predicate.def_id(),
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 6756b5dec2318..12371155303f9 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1726,7 +1726,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
let sig = args.coroutine_closure_sig().skip_binder();
let term = match item_name {
- sym::CallOnceFuture | sym::CallMutFuture | sym::CallFuture => {
+ sym::CallOnceFuture | sym::CallRefFuture => {
if let Some(closure_kind) = kind_ty.to_opt_closure_kind() {
if !closure_kind.extends(goal_kind) {
bug!("we should not be confirming if the closure kind is not met");
@@ -1787,7 +1787,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
obligation.predicate.def_id,
[self_ty, sig.tupled_inputs_ty],
),
- sym::CallMutFuture | sym::CallFuture => ty::AliasTy::new(
+ sym::CallRefFuture => ty::AliasTy::new(
tcx,
obligation.predicate.def_id,
[ty::GenericArg::from(self_ty), sig.tupled_inputs_ty.into(), env_region.into()],
@@ -1803,7 +1803,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
let sig = bound_sig.skip_binder();
let term = match item_name {
- sym::CallOnceFuture | sym::CallMutFuture | sym::CallFuture => sig.output(),
+ sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
sym::Output => {
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
let future_output_def_id = tcx
@@ -1822,7 +1822,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
obligation.predicate.def_id,
[self_ty, Ty::new_tup(tcx, sig.inputs())],
),
- sym::CallMutFuture | sym::CallFuture => ty::AliasTy::new(
+ sym::CallRefFuture => ty::AliasTy::new(
tcx,
obligation.predicate.def_id,
[
@@ -1842,7 +1842,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
let sig = bound_sig.skip_binder();
let term = match item_name {
- sym::CallOnceFuture | sym::CallMutFuture | sym::CallFuture => sig.output(),
+ sym::CallOnceFuture | sym::CallRefFuture => sig.output(),
sym::Output => {
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
let future_output_def_id = tcx
@@ -1859,7 +1859,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
sym::CallOnceFuture | sym::Output => {
ty::AliasTy::new(tcx, obligation.predicate.def_id, [self_ty, sig.inputs()[0]])
}
- sym::CallMutFuture | sym::CallFuture => ty::AliasTy::new(
+ sym::CallRefFuture => ty::AliasTy::new(
tcx,
obligation.predicate.def_id,
[ty::GenericArg::from(self_ty), sig.inputs()[0].into(), env_region.into()],
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index a5328baadb5fc..baf4de768c562 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,24 @@ 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();
let env_ty =
- tcx.closure_env_ty(Ty::new_coroutine_closure(tcx, def_id, args), kind, env_region);
+ if let InstanceDef::ConstructCoroutineInClosureShim { receiver_by_ref, .. } =
+ instance.def
+ {
+ coroutine_kind = ty::ClosureKind::FnOnce;
+
+ // Implementations of `FnMut` and `Fn` for coroutine-closures
+ // still take their receiver by ref.
+ if receiver_by_ref { Ty::new_mut_ptr(tcx, coroutine_ty) } else { coroutine_ty }
+ } else {
+ tcx.closure_env_ty(coroutine_ty, coroutine_kind, env_region)
+ };
let sig = sig.skip_binder();
ty::Binder::bind_with_vars(
@@ -132,7 +139,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 +168,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 +188,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 2816bcc888b0c..a8f9afb87dd7d 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -282,7 +282,7 @@ fn resolve_associated_item<'tcx>(
Some(Instance {
def: ty::InstanceDef::ConstructCoroutineInClosureShim {
coroutine_closure_def_id,
- target_kind: ty::ClosureKind::FnOnce,
+ receiver_by_ref: target_kind != ty::ClosureKind::FnOnce,
},
args,
})
@@ -297,25 +297,20 @@ 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,
+ receiver_by_ref: false,
+ },
+ args,
+ })
+ } else {
+ Some(Instance::new(coroutine_closure_def_id, args))
}
}
ty::Closure(closure_def_id, args) => {
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index f47fe560b07a2..cfaf533088a27 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -2042,18 +2042,16 @@ impl + ?Sized, A: Allocator> AsyncFnOnce
#[unstable(feature = "async_fn_traits", issue = "none")]
impl + ?Sized, A: Allocator> AsyncFnMut for Box {
- type CallMutFuture<'a> = F::CallMutFuture<'a> where Self: 'a;
+ type CallRefFuture<'a> = F::CallRefFuture<'a> where Self: 'a;
- extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallMutFuture<'_> {
+ extern "rust-call" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_> {
F::async_call_mut(self, args)
}
}
#[unstable(feature = "async_fn_traits", issue = "none")]
impl + ?Sized, A: Allocator> AsyncFn for Box {
- type CallFuture<'a> = F::CallFuture<'a> where Self: 'a;
-
- extern "rust-call" fn async_call(&self, args: Args) -> Self::CallFuture<'_> {
+ extern "rust-call" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_> {
F::async_call(self, args)
}
}
diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs
index d6b06ffb7fc0f..6c8a0daf6f35b 100644
--- a/library/core/src/ops/async_function.rs
+++ b/library/core/src/ops/async_function.rs
@@ -10,15 +10,9 @@ use crate::marker::Tuple;
#[must_use = "async closures are lazy and do nothing unless called"]
#[lang = "async_fn"]
pub trait AsyncFn: AsyncFnMut {
- /// Future returned by [`AsyncFn::async_call`].
- #[unstable(feature = "async_fn_traits", issue = "none")]
- type CallFuture<'a>: Future