@@ -281,14 +281,14 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
281
281
if place.local == ty::CAPTURE_STRUCT_LOCAL
282
282
&& let Some((&mir::ProjectionElem::Field(idx, _), projection)) =
283
283
place.projection.split_first()
284
- && let Some(&(remapped_idx, remapped_ty, needs_deref, additional_projections )) =
284
+ && let Some(&(remapped_idx, remapped_ty, needs_deref, bridging_projections )) =
285
285
self.field_remapping.get(&idx)
286
286
{
287
287
// As noted before, if the parent closure captures a field by value, and
288
288
// the child captures a field by ref, then for the by-move body we're
289
289
// generating, we also are taking that field by value. Peel off a deref,
290
- // since a layer of reffing has now become redundant.
291
- let final_deref = if needs_deref {
290
+ // since a layer of ref'ing has now become redundant.
291
+ let final_projections = if needs_deref {
292
292
let Some((mir::ProjectionElem::Deref, projection)) = projection.split_first()
293
293
else {
294
294
bug!(
@@ -302,20 +302,18 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
302
302
projection
303
303
};
304
304
305
- // The only thing that should be left is a deref, if the parent captured
306
- // an upvar by-ref.
307
- std::assert_matches::assert_matches!(final_deref, [] | [mir::ProjectionElem::Deref]);
308
-
309
- // For all of the additional projections that come out of precise capturing,
310
- // re-apply these projections.
311
- let additional_projections =
312
- additional_projections.iter().map(|elem| match elem.kind {
313
- ProjectionKind::Deref => mir::ProjectionElem::Deref,
314
- ProjectionKind::Field(idx, VariantIdx::ZERO) => {
315
- mir::ProjectionElem::Field(idx, elem.ty)
316
- }
317
- _ => unreachable!("precise captures only through fields and derefs"),
318
- });
305
+ // These projections are applied in order to "bridge" the local that we are
306
+ // currently transforming *from* the old upvar that the by-ref coroutine used
307
+ // to capture *to* the upvar of the parent coroutine-closure. For example, if
308
+ // the parent captures `&s` but the child captures `&(s.field)`, then we will
309
+ // apply a field projection.
310
+ let bridging_projections = bridging_projections.iter().map(|elem| match elem.kind {
311
+ ProjectionKind::Deref => mir::ProjectionElem::Deref,
312
+ ProjectionKind::Field(idx, VariantIdx::ZERO) => {
313
+ mir::ProjectionElem::Field(idx, elem.ty)
314
+ }
315
+ _ => unreachable!("precise captures only through fields and derefs"),
316
+ });
319
317
320
318
// We start out with an adjusted field index (and ty), representing the
321
319
// upvar that we get from our parent closure. We apply any of the additional
@@ -326,8 +324,8 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
326
324
projection: self.tcx.mk_place_elems_from_iter(
327
325
[mir::ProjectionElem::Field(remapped_idx, remapped_ty)]
328
326
.into_iter()
329
- .chain(additional_projections )
330
- .chain(final_deref .iter().copied()),
327
+ .chain(bridging_projections )
328
+ .chain(final_projections .iter().copied()),
331
329
),
332
330
};
333
331
}
0 commit comments