6969
7070use rustc_abi:: { FieldIdx , VariantIdx } ;
7171use rustc_data_structures:: steal:: Steal ;
72- use rustc_data_structures:: unord:: UnordMap ;
7372use rustc_hir as hir;
7473use rustc_hir:: def:: DefKind ;
7574use rustc_hir:: def_id:: { DefId , LocalDefId } ;
@@ -78,6 +77,16 @@ use rustc_middle::hir::place::{Projection, ProjectionKind};
7877use rustc_middle:: mir:: visit:: MutVisitor ;
7978use rustc_middle:: mir:: { self , dump_mir} ;
8079use rustc_middle:: ty:: { self , InstanceKind , Ty , TyCtxt , TypeVisitableExt } ;
80+ use rustc_type_ir:: data_structures:: IndexMap ;
81+
82+ struct CaptureInfo < ' tcx > {
83+ /// Field index of the capture in the parent coroutine structure
84+ remapped_idx : FieldIdx ,
85+ /// Type of the capture in the parent coroutine structure
86+ remapped_ty : Ty < ' tcx > ,
87+ peel_deref : bool ,
88+ bridging_projections : Vec < Projection < ' tcx > > ,
89+ }
8190
8291pub ( crate ) fn coroutine_by_move_body_def_id < ' tcx > (
8392 tcx : TyCtxt < ' tcx > ,
@@ -125,23 +134,27 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
125134 . tuple_fields ( )
126135 . len ( ) ;
127136
128- let field_remapping: UnordMap < _ , _ > = ty:: analyze_coroutine_closure_captures (
137+ let field_remapping: IndexMap < _ , _ > = ty:: analyze_coroutine_closure_captures (
129138 tcx. closure_captures ( parent_def_id) . iter ( ) . copied ( ) ,
130139 tcx. closure_captures ( coroutine_def_id) . iter ( ) . skip ( num_args) . copied ( ) ,
131140 |( parent_field_idx, parent_capture) , ( child_field_idx, child_capture) | {
132141 // Store this set of additional projections (fields and derefs).
133142 // We need to re-apply them later.
134- let mut child_precise_captures =
135- child_capture. place . projections [ parent_capture. place . projections . len ( ) ..] . to_vec ( ) ;
143+ let child_precise_captures = child_capture. place . projections
144+ [ parent_capture. place . projections . len ( ) ..]
145+ . iter ( )
146+ . copied ( ) ;
136147
137148 // If the parent capture is by-ref, then we need to apply an additional
138149 // deref before applying any further projections to this place.
139- if parent_capture. is_by_ref ( ) {
140- child_precise_captures. insert (
141- 0 ,
142- Projection { ty : parent_capture. place . ty ( ) , kind : ProjectionKind :: Deref } ,
143- ) ;
144- }
150+ let bridging_projections = if parent_capture. is_by_ref ( ) {
151+ [ Projection { ty : parent_capture. place . ty ( ) , kind : ProjectionKind :: Deref } ]
152+ . into_iter ( )
153+ . chain ( child_precise_captures)
154+ . collect ( )
155+ } else {
156+ child_precise_captures. collect ( )
157+ } ;
145158 // If the child capture is by-ref, then we need to apply a "ref"
146159 // projection (i.e. `&`) at the end. But wait! We don't have that
147160 // as a projection kind. So instead, we can apply its dual and
@@ -167,8 +180,8 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
167180
168181 // Finally, store the type of the parent's captured place. We need
169182 // this when building the field projection in the MIR body later on.
170- let mut parent_capture_ty = parent_capture. place . ty ( ) ;
171- parent_capture_ty = match parent_capture. info . capture_kind {
183+ let parent_capture_ty = parent_capture. place . ty ( ) ;
184+ let remapped_ty = match parent_capture. info . capture_kind {
172185 ty:: UpvarCapture :: ByValue | ty:: UpvarCapture :: ByUse => parent_capture_ty,
173186 ty:: UpvarCapture :: ByRef ( kind) => Ty :: new_ref (
174187 tcx,
@@ -180,18 +193,18 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
180193
181194 (
182195 FieldIdx :: from_usize ( child_field_idx + num_args) ,
183- (
184- FieldIdx :: from_usize ( parent_field_idx + num_args) ,
185- parent_capture_ty ,
196+ CaptureInfo {
197+ remapped_idx : FieldIdx :: from_usize ( parent_field_idx + num_args) ,
198+ remapped_ty ,
186199 peel_deref,
187- child_precise_captures ,
188- ) ,
200+ bridging_projections ,
201+ } ,
189202 )
190203 } ,
191204 )
192205 . collect ( ) ;
193206
194- if coroutine_kind == ty:: ClosureKind :: FnOnce {
207+ if matches ! ( coroutine_kind, ty:: ClosureKind :: FnOnce ) {
195208 assert_eq ! ( field_remapping. len( ) , tcx. closure_captures( parent_def_id) . len( ) ) ;
196209 // The by-move body is just the body :)
197210 return coroutine_def_id. to_def_id ( ) ;
@@ -210,6 +223,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
210223 ) ;
211224
212225 let mut by_move_body = body. clone ( ) ;
226+ dump_mir ( tcx, false , "built" , & "before" , & by_move_body, |_, _| Ok ( ( ) ) ) ;
213227 MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty } . visit_body ( & mut by_move_body) ;
214228
215229 // This will always be `{closure#1}`, since the original coroutine is `{closure#0}`.
@@ -240,7 +254,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
240254
241255struct MakeByMoveBody < ' tcx > {
242256 tcx : TyCtxt < ' tcx > ,
243- field_remapping : UnordMap < FieldIdx , ( FieldIdx , Ty < ' tcx > , bool , Vec < Projection < ' tcx > > ) > ,
257+ field_remapping : IndexMap < FieldIdx , CaptureInfo < ' tcx > > ,
244258 by_move_coroutine_ty : Ty < ' tcx > ,
245259}
246260
@@ -261,8 +275,12 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
261275 if place. local == ty:: CAPTURE_STRUCT_LOCAL
262276 && let Some ( ( & mir:: ProjectionElem :: Field ( idx, _) , projection) ) =
263277 place. projection . split_first ( )
264- && let Some ( & ( remapped_idx, remapped_ty, peel_deref, ref bridging_projections) ) =
265- self . field_remapping . get ( & idx)
278+ && let Some ( & CaptureInfo {
279+ remapped_idx,
280+ remapped_ty,
281+ peel_deref,
282+ ref bridging_projections,
283+ } ) = self . field_remapping . get ( & idx)
266284 {
267285 // As noted before, if the parent closure captures a field by value, and
268286 // the child captures a field by ref, then for the by-move body we're
0 commit comments