@@ -281,14 +281,14 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
281281 if place. local == ty:: CAPTURE_STRUCT_LOCAL
282282 && let Some ( ( & mir:: ProjectionElem :: Field ( idx, _) , projection) ) =
283283 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 ) ) =
285285 self . field_remapping . get ( & idx)
286286 {
287287 // As noted before, if the parent closure captures a field by value, and
288288 // the child captures a field by ref, then for the by-move body we're
289289 // 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 {
292292 let Some ( ( mir:: ProjectionElem :: Deref , projection) ) = projection. split_first ( )
293293 else {
294294 bug ! (
@@ -302,20 +302,18 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
302302 projection
303303 } ;
304304
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+ } ) ;
319317
320318 // We start out with an adjusted field index (and ty), representing the
321319 // 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> {
326324 projection : self . tcx . mk_place_elems_from_iter (
327325 [ mir:: ProjectionElem :: Field ( remapped_idx, remapped_ty) ]
328326 . into_iter ( )
329- . chain ( additional_projections )
330- . chain ( final_deref . iter ( ) . copied ( ) ) ,
327+ . chain ( bridging_projections )
328+ . chain ( final_projections . iter ( ) . copied ( ) ) ,
331329 ) ,
332330 } ;
333331 }
0 commit comments