@@ -12,6 +12,8 @@ use super::*;
1212use crate :: deref_separator:: deref_finder;
1313use crate :: patch:: MirPatch ;
1414
15+ const SELF_ARG : Local = Local :: arg ( 0 ) ;
16+
1517pub ( super ) fn build_async_destructor_ctor_shim < ' tcx > (
1618 tcx : TyCtxt < ' tcx > ,
1719 def_id : DefId ,
@@ -76,7 +78,7 @@ pub(super) fn build_async_drop_shim<'tcx>(
7678 let source_info = SourceInfo :: outermost ( span) ;
7779
7880 // The first argument (index 0) which will be local 1 (after the return value).
79- let coroutine_layout = Place :: from ( Local :: arg ( 0 ) ) ;
81+ let coroutine_layout = Place :: from ( SELF_ARG ) ;
8082 let coroutine_layout_dropee =
8183 tcx. mk_place_field ( coroutine_layout, FieldIdx :: new ( 0 ) , drop_ptr_ty) ;
8284
@@ -199,87 +201,85 @@ fn build_adrop_for_coroutine_shim<'tcx>(
199201 let ty:: Coroutine ( coroutine_def_id, impl_args) = impl_ty. kind ( ) else {
200202 bug ! ( "build_adrop_for_coroutine_shim not for coroutine impl type: ({:?})" , instance) ;
201203 } ;
202- let proxy_ref = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , proxy_ty) ;
203- // taking _1.0 (impl from Pin)
204- let pin_proxy_layout_local = Local :: new ( 1 ) ;
205204 let source_info = SourceInfo :: outermost ( span) ;
206- // converting `(_1: Pin<&mut CorLayout>, _2: &mut Context<'_>) -> Poll<()>`
207- // into `(_1: Pin<&mut ProxyLayout>, _2: &mut Context<'_>) -> Poll<()>`
208- // let mut _x: &mut CorLayout = &mut *_1.0.0;
209- // Replace old _1.0 accesses into _x accesses;
210205 let body = tcx. optimized_mir ( * coroutine_def_id) . future_drop_poll ( ) . unwrap ( ) ;
211206 let mut body: Body < ' tcx > =
212207 EarlyBinder :: bind ( body. clone ( ) ) . instantiate ( tcx, impl_args) . skip_norm_wip ( ) ;
213208 body. source . instance = instance;
214209 body. phase = MirPhase :: Runtime ( RuntimePhase :: Initial ) ;
215210 body. var_debug_info . clear ( ) ;
211+
212+ // converting `(_1: Pin<&mut CorLayout>, _2: &mut Context<'_>) -> Poll<()>`
213+ // into `(_1: Pin<&mut ProxyLayout>, _2: &mut Context<'_>) -> Poll<()>`
214+ // let mut _x: &mut CorLayout = &mut *_1.0.0;
215+ // Replace old _1.0 accesses into _x accesses;
216+ let proxy_ref = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , proxy_ty) ;
217+
216218 let pin_adt_ref = tcx. adt_def ( tcx. require_lang_item ( LangItem :: Pin , span) ) ;
217219 let args = tcx. mk_args ( & [ proxy_ref. into ( ) ] ) ;
218220 let pin_proxy_ref = Ty :: new_adt ( tcx, pin_adt_ref, args) ;
219221
220222 let cor_ref = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , impl_ty) ;
221-
222- let proxy_ref_local = body. local_decls . push ( LocalDecl :: new ( proxy_ref, span) ) ;
223223 let cor_ref_local = body. local_decls . push ( LocalDecl :: new ( cor_ref, span) ) ;
224224
225225 FixProxyFutureDropVisitor { tcx, replace_to : cor_ref_local } . visit_body ( & mut body) ;
226+
226227 // Now changing first arg from Pin<&mut ImplCoroutine> to Pin<&mut ProxyCoroutine>
227- body. local_decls [ pin_proxy_layout_local] = LocalDecl :: new ( pin_proxy_ref, span) ;
228-
229- {
230- let mut idx: usize = 0 ;
231- // _proxy = _1.0 : Pin<&mut ProxyLayout> ==> &mut ProxyLayout
232- let proxy_ref_place = Place :: from ( pin_proxy_layout_local)
233- . project_deeper ( & [ PlaceElem :: Field ( FieldIdx :: ZERO , proxy_ref) ] , tcx) ;
234- body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
235- idx,
236- Statement :: new (
237- source_info,
238- StatementKind :: Assign ( Box :: new ( (
239- Place :: from ( proxy_ref_local) ,
240- Rvalue :: Use ( Operand :: Copy ( proxy_ref_place) , WithRetag :: Yes ) ,
241- ) ) ) ,
242- ) ,
243- ) ;
244- idx += 1 ;
245-
246- // _cor_ref_tmp = (*(*_proxy).0).0...
247- let mut cor_ref_tmp_local = proxy_ref_local;
248- proxy_ty. find_async_drop_impl_coroutine ( tcx, |ty| {
249- if ty != proxy_ty {
250- let ty_ref = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , ty) ;
251- let impl_ptr_place = Place :: from ( cor_ref_tmp_local) . project_deeper (
252- & [ PlaceElem :: Deref , PlaceElem :: Field ( FieldIdx :: ZERO , ty_ref) ] ,
253- tcx,
254- ) ;
255- cor_ref_tmp_local = body. local_decls . push ( LocalDecl :: new ( ty_ref, span) ) ;
256- body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
257- idx,
258- Statement :: new (
259- source_info,
260- StatementKind :: Assign ( Box :: new ( (
261- Place :: from ( cor_ref_tmp_local) ,
262- Rvalue :: Use ( Operand :: Copy ( impl_ptr_place) , WithRetag :: Yes ) ,
263- ) ) ) ,
264- ) ,
265- ) ;
266- idx += 1 ;
267- }
268- } ) ;
228+ body. local_decls [ SELF_ARG ] = LocalDecl :: new ( pin_proxy_ref, span) ;
269229
270- // _cor_ref = cor_ref_tmp
271- body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
272- idx,
273- Statement :: new (
274- source_info,
275- StatementKind :: Assign ( Box :: new ( (
276- Place :: from ( cor_ref_local) ,
277- Rvalue :: Use ( Operand :: Move ( Place :: from ( cor_ref_tmp_local) ) , WithRetag :: Yes ) ,
278- ) ) ) ,
279- ) ,
280- ) ;
230+ // Build the projection to assign `cor_ref_local = _1.<projection>`.
231+ let mut pin_proxy_to_cor_projection = vec ! [
232+ // _1.0 : Pin<&mut ProxyLayout> ==> &mut ProxyLayout
233+ PlaceElem :: Field ( FieldIdx :: ZERO , proxy_ref) ,
234+ ] ;
235+
236+ // _cor_ref_tmp = (*(*_proxy).0).0...
237+ proxy_ty. find_async_drop_impl_coroutine ( tcx, |ty| {
238+ if ty != proxy_ty {
239+ let ty_ref = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , ty) ;
240+ pin_proxy_to_cor_projection. push ( PlaceElem :: Deref ) ;
241+ pin_proxy_to_cor_projection. push ( PlaceElem :: Field ( FieldIdx :: ZERO , ty_ref) ) ;
242+ }
243+ } ) ;
244+
245+ // _cor_ref = cor_ref_tmp
246+ let projected_pin = Place :: from ( SELF_ARG ) . project_deeper ( & pin_proxy_to_cor_projection, tcx) ;
247+ body. basic_blocks_mut ( ) [ START_BLOCK ] . statements . insert (
248+ 0 ,
249+ Statement :: new (
250+ source_info,
251+ StatementKind :: Assign ( Box :: new ( (
252+ Place :: from ( cor_ref_local) ,
253+ Rvalue :: Use ( Operand :: Move ( projected_pin) , WithRetag :: Yes ) ,
254+ ) ) ) ,
255+ ) ,
256+ ) ;
257+
258+ // We did not bother respectig deref separation, do it here.
259+ deref_finder ( tcx, & mut body, false ) ;
260+
261+ return body;
262+
263+ /// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> accesses
264+ struct FixProxyFutureDropVisitor < ' tcx > {
265+ tcx : TyCtxt < ' tcx > ,
266+ replace_to : Local ,
267+ }
268+
269+ impl < ' tcx > MutVisitor < ' tcx > for FixProxyFutureDropVisitor < ' tcx > {
270+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
271+ self . tcx
272+ }
273+
274+ fn visit_place ( & mut self , place : & mut Place < ' tcx > , _: PlaceContext , _: Location ) {
275+ if place. local == SELF_ARG
276+ && let Some ( ( first, rest) ) = place. projection . split_first ( )
277+ {
278+ assert ! ( matches!( first, ProjectionElem :: Field ( FieldIdx :: ZERO , _) ) ) ;
279+ * place = Place :: from ( self . replace_to ) . project_deeper ( rest, self . tcx ) ;
280+ }
281+ }
281282 }
282- body
283283}
284284
285285// When dropping async drop coroutine, we continue its execution.
@@ -294,9 +294,8 @@ fn build_adrop_for_adrop_shim<'tcx>(
294294 let source_info = SourceInfo :: outermost ( span) ;
295295 let proxy_ref = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , proxy_ty) ;
296296 // taking _1.0 (impl from Pin)
297- let pin_proxy_layout_local = Local :: new ( 1 ) ;
298- let proxy_ref_place = Place :: from ( pin_proxy_layout_local)
299- . project_deeper ( & [ PlaceElem :: Field ( FieldIdx :: ZERO , proxy_ref) ] , tcx) ;
297+ let proxy_ref_place =
298+ Place :: from ( SELF_ARG ) . project_deeper ( & [ PlaceElem :: Field ( FieldIdx :: ZERO , proxy_ref) ] , tcx) ;
300299 let cor_ref = Ty :: new_mut_ref ( tcx, tcx. lifetimes . re_erased , impl_ty) ;
301300
302301 // ret_ty = `Poll<()>`
0 commit comments