Skip to content

Commit b40b710

Browse files
Cap closure kind, get rid of by_mut_body
1 parent 4a2fe44 commit b40b710

File tree

20 files changed

+62
-190
lines changed

20 files changed

+62
-190
lines changed

compiler/rustc_borrowck/src/type_check/input_output.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
8888
self.tcx(),
8989
ty::CoroutineArgsParts {
9090
parent_args: args.parent_args(),
91-
kind_ty: Ty::from_closure_kind(self.tcx(), args.kind()),
91+
kind_ty: Ty::from_closure_kind(self.tcx(), args.kind().cap_for_coroutine()),
9292
return_ty: user_provided_sig.output(),
9393
tupled_upvars_ty,
9494
// For async closures, none of these can be annotated, so just fill

compiler/rustc_borrowck/src/universal_regions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
755755
tcx,
756756
args.as_coroutine_closure().parent_args(),
757757
tcx.coroutine_for_closure(def_id),
758-
closure_kind,
758+
closure_kind.cap_for_coroutine(),
759759
env_region,
760760
args.as_coroutine_closure().tupled_upvars_ty(),
761761
args.as_coroutine_closure().coroutine_captures_by_ref_ty(),

compiler/rustc_hir_typeck/src/callee.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -183,16 +183,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
183183
kind: TypeVariableOriginKind::TypeInference,
184184
span: callee_expr.span,
185185
});
186+
// We may actually receive a coroutine back whose kind is different
187+
// from the closure that this dispatched from. This is because when
188+
// we have no captures, we automatically implement `FnOnce`. This
189+
// impl forces the closure kind to `FnOnce` i.e. `u8`.
190+
let kind_ty = self.next_ty_var(TypeVariableOrigin {
191+
kind: TypeVariableOriginKind::TypeInference,
192+
span: callee_expr.span,
193+
});
186194
let call_sig = self.tcx.mk_fn_sig(
187195
[coroutine_closure_sig.tupled_inputs_ty],
188196
coroutine_closure_sig.to_coroutine(
189197
self.tcx,
190198
closure_args.parent_args(),
191-
// Inherit the kind ty of the closure, since we're calling this
192-
// coroutine with the most relaxed `AsyncFn*` trait that we can.
193-
// We don't necessarily need to do this here, but it saves us
194-
// computing one more infer var that will get constrained later.
195-
closure_args.kind_ty(),
199+
kind_ty,
196200
self.tcx.coroutine_for_closure(def_id),
197201
tupled_upvars_ty,
198202
),

compiler/rustc_hir_typeck/src/closure.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
261261
},
262262
);
263263

264+
let coroutine_kind_ty = self.next_ty_var(TypeVariableOrigin {
265+
// FIXME(eddyb) distinguish closure kind inference variables from the rest.
266+
kind: TypeVariableOriginKind::ClosureSynthetic,
267+
span: expr_span,
268+
});
264269
let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin {
265270
kind: TypeVariableOriginKind::ClosureSynthetic,
266271
span: expr_span,
@@ -278,7 +283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
278283
sig.to_coroutine(
279284
tcx,
280285
parent_args,
281-
closure_kind_ty,
286+
coroutine_kind_ty,
282287
tcx.coroutine_for_closure(expr_def_id),
283288
coroutine_upvars_ty,
284289
)

compiler/rustc_hir_typeck/src/upvar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
410410
self.demand_eqtype(
411411
span,
412412
coroutine_args.as_coroutine().kind_ty(),
413-
Ty::from_closure_kind(self.tcx, closure_kind),
413+
Ty::from_closure_kind(self.tcx, closure_kind.cap_for_coroutine()),
414414
);
415415
}
416416

compiler/rustc_middle/src/mir/mod.rs

-12
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,6 @@ pub struct CoroutineInfo<'tcx> {
274274
/// using `run_passes`.
275275
pub by_move_body: Option<Body<'tcx>>,
276276

277-
/// The body of the coroutine, modified to take its upvars by mutable ref rather than by
278-
/// immutable ref.
279-
///
280-
/// FIXME(async_closures): This is literally the same body as the parent body. Find a better
281-
/// way to represent the by-mut signature (or cap the closure-kind of the coroutine).
282-
pub by_mut_body: Option<Body<'tcx>>,
283-
284277
/// The layout of a coroutine. This field is populated after the state transform pass.
285278
pub coroutine_layout: Option<CoroutineLayout<'tcx>>,
286279

@@ -301,7 +294,6 @@ impl<'tcx> CoroutineInfo<'tcx> {
301294
yield_ty: Some(yield_ty),
302295
resume_ty: Some(resume_ty),
303296
by_move_body: None,
304-
by_mut_body: None,
305297
coroutine_drop: None,
306298
coroutine_layout: None,
307299
}
@@ -616,10 +608,6 @@ impl<'tcx> Body<'tcx> {
616608
self.coroutine.as_ref()?.by_move_body.as_ref()
617609
}
618610

619-
pub fn coroutine_by_mut_body(&self) -> Option<&Body<'tcx>> {
620-
self.coroutine.as_ref()?.by_mut_body.as_ref()
621-
}
622-
623611
#[inline]
624612
pub fn coroutine_kind(&self) -> Option<CoroutineKind> {
625613
self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind)

compiler/rustc_middle/src/mir/visit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,8 @@ macro_rules! make_mir_visitor {
345345
ty::InstanceDef::Virtual(_def_id, _) |
346346
ty::InstanceDef::ThreadLocalShim(_def_id) |
347347
ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
348-
ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, target_kind: _ } |
349-
ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id, target_kind: _ } |
348+
ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id } |
349+
ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id } |
350350
ty::InstanceDef::DropGlue(_def_id, None) => {}
351351

352352
ty::InstanceDef::FnPtrShim(_def_id, ty) |

compiler/rustc_middle/src/ty/instance.rs

+5-13
Original file line numberDiff line numberDiff line change
@@ -90,24 +90,20 @@ pub enum InstanceDef<'tcx> {
9090
/// and dispatch to the `FnMut::call_mut` instance for the closure.
9191
ClosureOnceShim { call_once: DefId, track_caller: bool },
9292

93-
/// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once` or
94-
/// `<[Fn coroutine-closure] as FnMut>::call_mut`.
93+
/// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once`
9594
///
9695
/// The body generated here differs significantly from the `ClosureOnceShim`,
9796
/// since we need to generate a distinct coroutine type that will move the
9897
/// closure's upvars *out* of the closure.
99-
ConstructCoroutineInClosureShim {
100-
coroutine_closure_def_id: DefId,
101-
target_kind: ty::ClosureKind,
102-
},
98+
ConstructCoroutineInClosureShim { coroutine_closure_def_id: DefId },
10399

104100
/// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce`
105101
/// is called on a coroutine-closure whose closure kind greater than `FnOnce`, or
106102
/// similarly for `AsyncFnMut`.
107103
///
108104
/// This will select the body that is produced by the `ByMoveBody` transform, and thus
109105
/// take and use all of its upvars by-move rather than by-ref.
110-
CoroutineKindShim { coroutine_def_id: DefId, target_kind: ty::ClosureKind },
106+
CoroutineKindShim { coroutine_def_id: DefId },
111107

112108
/// Compiler-generated accessor for thread locals which returns a reference to the thread local
113109
/// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking
@@ -192,9 +188,8 @@ impl<'tcx> InstanceDef<'tcx> {
192188
| InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
193189
| ty::InstanceDef::ConstructCoroutineInClosureShim {
194190
coroutine_closure_def_id: def_id,
195-
target_kind: _,
196191
}
197-
| ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id, target_kind: _ }
192+
| ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id }
198193
| InstanceDef::DropGlue(def_id, _)
199194
| InstanceDef::CloneShim(def_id, _)
200195
| InstanceDef::FnPtrAddrShim(def_id, _) => def_id,
@@ -654,10 +649,7 @@ impl<'tcx> Instance<'tcx> {
654649
Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
655650
} else {
656651
Some(Instance {
657-
def: ty::InstanceDef::CoroutineKindShim {
658-
coroutine_def_id,
659-
target_kind: args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
660-
},
652+
def: ty::InstanceDef::CoroutineKindShim { coroutine_def_id },
661653
args,
662654
})
663655
}

compiler/rustc_middle/src/ty/sty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ impl<'tcx> CoroutineClosureSignature<'tcx> {
485485
self.to_coroutine(
486486
tcx,
487487
parent_args,
488-
Ty::from_closure_kind(tcx, goal_kind),
488+
Ty::from_closure_kind(tcx, goal_kind.cap_for_coroutine()),
489489
coroutine_def_id,
490490
tupled_upvars_ty,
491491
)

compiler/rustc_mir_transform/src/coroutine/by_move_body.rs

-35
Original file line numberDiff line numberDiff line change
@@ -64,45 +64,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
6464
by_move_body.source = mir::MirSource {
6565
instance: InstanceDef::CoroutineKindShim {
6666
coroutine_def_id: coroutine_def_id.to_def_id(),
67-
target_kind: ty::ClosureKind::FnOnce,
6867
},
6968
promoted: None,
7069
};
7170
body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body);
72-
73-
// If this is coming from an `AsyncFn` coroutine-closure, we must also create a by-mut body.
74-
// This is actually just a copy of the by-ref body, but with a different self type.
75-
// FIXME(async_closures): We could probably unify this with the by-ref body somehow.
76-
if coroutine_kind == ty::ClosureKind::Fn {
77-
let by_mut_coroutine_ty = Ty::new_coroutine(
78-
tcx,
79-
coroutine_def_id.to_def_id(),
80-
ty::CoroutineArgs::new(
81-
tcx,
82-
ty::CoroutineArgsParts {
83-
parent_args: args.as_coroutine().parent_args(),
84-
kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnMut),
85-
resume_ty: args.as_coroutine().resume_ty(),
86-
yield_ty: args.as_coroutine().yield_ty(),
87-
return_ty: args.as_coroutine().return_ty(),
88-
witness: args.as_coroutine().witness(),
89-
tupled_upvars_ty: args.as_coroutine().tupled_upvars_ty(),
90-
},
91-
)
92-
.args,
93-
);
94-
let mut by_mut_body = body.clone();
95-
by_mut_body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty = by_mut_coroutine_ty;
96-
dump_mir(tcx, false, "coroutine_by_mut", &0, &by_mut_body, |_, _| Ok(()));
97-
by_mut_body.source = mir::MirSource {
98-
instance: InstanceDef::CoroutineKindShim {
99-
coroutine_def_id: coroutine_def_id.to_def_id(),
100-
target_kind: ty::ClosureKind::FnMut,
101-
},
102-
promoted: None,
103-
};
104-
body.coroutine.as_mut().unwrap().by_mut_body = Some(by_mut_body);
105-
}
10671
}
10772
}
10873

compiler/rustc_mir_transform/src/pass_manager.rs

-3
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,6 @@ fn run_passes_inner<'tcx>(
194194
if let Some(by_move_body) = coroutine.by_move_body.as_mut() {
195195
run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each);
196196
}
197-
if let Some(by_mut_body) = coroutine.by_mut_body.as_mut() {
198-
run_passes_inner(tcx, by_mut_body, passes, phase_change, validate_each);
199-
}
200197
}
201198
}
202199

compiler/rustc_mir_transform/src/shim.rs

+12-86
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use rustc_hir::def_id::DefId;
33
use rustc_hir::lang_items::LangItem;
44
use rustc_middle::mir::*;
55
use rustc_middle::query::Providers;
6+
use rustc_middle::ty::GenericArgs;
67
use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt};
7-
use rustc_middle::ty::{GenericArgs, CAPTURE_STRUCT_LOCAL};
88
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
99

1010
use rustc_index::{Idx, IndexVec};
@@ -66,39 +66,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
6666
build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
6767
}
6868

69-
ty::InstanceDef::ConstructCoroutineInClosureShim {
70-
coroutine_closure_def_id,
71-
target_kind,
72-
} => match target_kind {
73-
ty::ClosureKind::Fn => unreachable!("shouldn't be building shim for Fn"),
74-
ty::ClosureKind::FnMut => {
75-
// No need to optimize the body, it has already been optimized
76-
// since we steal it from the `AsyncFn::call` body and just fix
77-
// the return type.
78-
return build_construct_coroutine_by_mut_shim(tcx, coroutine_closure_def_id);
79-
}
80-
ty::ClosureKind::FnOnce => {
81-
build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id)
82-
}
83-
},
69+
ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id } => {
70+
build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id)
71+
}
8472

85-
ty::InstanceDef::CoroutineKindShim { coroutine_def_id, target_kind } => match target_kind {
86-
ty::ClosureKind::Fn => unreachable!(),
87-
ty::ClosureKind::FnMut => {
88-
return tcx
89-
.optimized_mir(coroutine_def_id)
90-
.coroutine_by_mut_body()
91-
.unwrap()
92-
.clone();
93-
}
94-
ty::ClosureKind::FnOnce => {
95-
return tcx
96-
.optimized_mir(coroutine_def_id)
97-
.coroutine_by_move_body()
98-
.unwrap()
99-
.clone();
100-
}
101-
},
73+
ty::InstanceDef::CoroutineKindShim { coroutine_def_id } => {
74+
return tcx.optimized_mir(coroutine_def_id).coroutine_by_move_body().unwrap().clone();
75+
}
10276

10377
ty::InstanceDef::DropGlue(def_id, ty) => {
10478
// FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
@@ -119,21 +93,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
11993
let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() {
12094
coroutine_body.coroutine_drop().unwrap()
12195
} else {
122-
match args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() {
123-
ty::ClosureKind::Fn => {
124-
unreachable!()
125-
}
126-
ty::ClosureKind::FnMut => coroutine_body
127-
.coroutine_by_mut_body()
128-
.unwrap()
129-
.coroutine_drop()
130-
.unwrap(),
131-
ty::ClosureKind::FnOnce => coroutine_body
132-
.coroutine_by_move_body()
133-
.unwrap()
134-
.coroutine_drop()
135-
.unwrap(),
136-
}
96+
assert_eq!(
97+
args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
98+
ty::ClosureKind::FnOnce
99+
);
100+
coroutine_body.coroutine_by_move_body().unwrap().coroutine_drop().unwrap()
137101
};
138102

139103
let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
@@ -1111,7 +1075,6 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
11111075

11121076
let source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim {
11131077
coroutine_closure_def_id,
1114-
target_kind: ty::ClosureKind::FnOnce,
11151078
});
11161079

11171080
let body =
@@ -1120,40 +1083,3 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
11201083

11211084
body
11221085
}
1123-
1124-
fn build_construct_coroutine_by_mut_shim<'tcx>(
1125-
tcx: TyCtxt<'tcx>,
1126-
coroutine_closure_def_id: DefId,
1127-
) -> Body<'tcx> {
1128-
let mut body = tcx.optimized_mir(coroutine_closure_def_id).clone();
1129-
let coroutine_closure_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity();
1130-
let ty::CoroutineClosure(_, args) = *coroutine_closure_ty.kind() else {
1131-
bug!();
1132-
};
1133-
let args = args.as_coroutine_closure();
1134-
1135-
body.local_decls[RETURN_PLACE].ty =
1136-
tcx.instantiate_bound_regions_with_erased(args.coroutine_closure_sig().map_bound(|sig| {
1137-
sig.to_coroutine_given_kind_and_upvars(
1138-
tcx,
1139-
args.parent_args(),
1140-
tcx.coroutine_for_closure(coroutine_closure_def_id),
1141-
ty::ClosureKind::FnMut,
1142-
tcx.lifetimes.re_erased,
1143-
args.tupled_upvars_ty(),
1144-
args.coroutine_captures_by_ref_ty(),
1145-
)
1146-
}));
1147-
body.local_decls[CAPTURE_STRUCT_LOCAL].ty =
1148-
Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_closure_ty);
1149-
1150-
body.source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim {
1151-
coroutine_closure_def_id,
1152-
target_kind: ty::ClosureKind::FnMut,
1153-
});
1154-
1155-
body.pass_count = 0;
1156-
dump_mir(tcx, false, "coroutine_closure_by_mut", &0, &body, |_, _| Ok(()));
1157-
1158-
body
1159-
}

compiler/rustc_symbol_mangling/src/legacy.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,10 @@ pub(super) fn mangle<'tcx>(
7676
}
7777
// FIXME(async_closures): This shouldn't be needed when we fix
7878
// `Instance::ty`/`Instance::def_id`.
79-
ty::InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. }
80-
| ty::InstanceDef::CoroutineKindShim { target_kind, .. } => match target_kind {
81-
ty::ClosureKind::Fn => unreachable!(),
82-
ty::ClosureKind::FnMut => {
83-
printer.write_str("{{fn-mut-shim}}").unwrap();
84-
}
85-
ty::ClosureKind::FnOnce => {
86-
printer.write_str("{{fn-once-shim}}").unwrap();
87-
}
88-
},
79+
ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
80+
| ty::InstanceDef::CoroutineKindShim { .. } => {
81+
printer.write_str("{{fn-once-shim}}").unwrap();
82+
}
8983
_ => {}
9084
}
9185

0 commit comments

Comments
 (0)