@@ -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