@@ -36,6 +36,7 @@ use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
3636use  rustc_hir:: def:: { CtorKind ,  CtorOf ,  DefKind ,  DocLinkResMap ,  LifetimeRes ,  Res } ; 
3737use  rustc_hir:: def_id:: { CrateNum ,  DefId ,  DefIdMap ,  LocalDefId ,  LocalDefIdMap } ; 
3838use  rustc_hir:: LangItem ; 
39+ use  rustc_index:: bit_set:: BitMatrix ; 
3940use  rustc_index:: IndexVec ; 
4041use  rustc_macros:: { 
4142    extension,  Decodable ,  Encodable ,  HashStable ,  TyDecodable ,  TyEncodable ,  TypeFoldable , 
@@ -110,7 +111,7 @@ pub use self::IntVarValue::*;
110111use  crate :: error:: { OpaqueHiddenTypeMismatch ,  TypeMismatchReason } ; 
111112use  crate :: metadata:: ModChild ; 
112113use  crate :: middle:: privacy:: EffectiveVisibilities ; 
113- use  crate :: mir:: { Body ,  CoroutineLayout } ; 
114+ use  crate :: mir:: { Body ,  CoroutineLayout ,   CoroutineSavedLocal ,   CoroutineSavedTy ,   SourceInfo } ; 
114115use  crate :: query:: Providers ; 
115116use  crate :: traits:: { self ,  Reveal } ; 
116117use  crate :: ty; 
@@ -1771,7 +1772,7 @@ impl<'tcx> TyCtxt<'tcx> {
17711772            | ty:: InstanceKind :: FnPtrAddrShim ( ..) 
17721773            | ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..)  => self . mir_shims ( instance) , 
17731774            // async drop glue should be processed specifically, as a templated coroutine 
1774-             ty:: InstanceKind :: AsyncDropGlue ( _,  _ty )  => todo ! ( ) , 
1775+             ty:: InstanceKind :: AsyncDropGlue ( _,  ty )  => self . templated_optimized_mir ( ty ) , 
17751776        } 
17761777    } 
17771778
@@ -1851,16 +1852,17 @@ impl<'tcx> TyCtxt<'tcx> {
18511852        self . def_kind ( trait_def_id)  == DefKind :: TraitAlias 
18521853    } 
18531854
1854-     /// Returns layout of a coroutine. Layout might be unavailable if the 
1855+     /// Returns layout of a non-templated  coroutine. Layout might be unavailable if the 
18551856     /// coroutine is tainted by errors. 
18561857     /// 
18571858     /// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`, 
18581859     /// e.g. `args.as_coroutine().kind_ty()`. 
1859-      pub  fn  coroutine_layout ( 
1860+      pub  fn  ordinary_coroutine_layout ( 
18601861        self , 
18611862        def_id :  DefId , 
18621863        coroutine_kind_ty :  Ty < ' tcx > , 
18631864    )  -> Option < & ' tcx  CoroutineLayout < ' tcx > >  { 
1865+         debug_assert_ne ! ( Some ( def_id) ,  self . lang_items( ) . async_drop_in_place_poll_fn( ) ) ; 
18641866        let  mir = self . optimized_mir ( def_id) ; 
18651867        // Regular coroutine 
18661868        if  coroutine_kind_ty. is_unit ( )  { 
@@ -1890,6 +1892,66 @@ impl<'tcx> TyCtxt<'tcx> {
18901892        } 
18911893    } 
18921894
1895+     /// Returns layout of a templated coroutine. Layout might be unavailable if the 
1896+      /// coroutine is tainted by errors. Atm, the only templated coroutine is 
1897+      /// `async_drop_in_place<T>::{closure}` returned from `async fn async_drop_in_place<T>(..)`. 
1898+      pub  fn  templated_coroutine_layout ( self ,  ty :  Ty < ' tcx > )  -> Option < & ' tcx  CoroutineLayout < ' tcx > >  { 
1899+         self . templated_optimized_mir ( ty) . coroutine_layout_raw ( ) 
1900+     } 
1901+ 
1902+     /// Returns layout of a templated (or not) coroutine. Layout might be unavailable if the 
1903+      /// coroutine is tainted by errors. 
1904+      pub  fn  coroutine_layout ( 
1905+         self , 
1906+         def_id :  DefId , 
1907+         args :  GenericArgsRef < ' tcx > , 
1908+     )  -> Option < & ' tcx  CoroutineLayout < ' tcx > >  { 
1909+         if  Some ( def_id)  == self . lang_items ( ) . async_drop_in_place_poll_fn ( )  { 
1910+             fn  find_impl_coroutine < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  mut  cor_ty :  Ty < ' tcx > )  -> Ty < ' tcx >  { 
1911+                 let  mut  ty = cor_ty; 
1912+                 loop  { 
1913+                     if  let  ty:: Coroutine ( def_id,  args)  = ty. kind ( )  { 
1914+                         cor_ty = ty; 
1915+                         if  tcx. is_templated_coroutine ( * def_id)  { 
1916+                             ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ; 
1917+                             continue ; 
1918+                         }  else  { 
1919+                             return  cor_ty; 
1920+                         } 
1921+                     }  else  { 
1922+                         return  cor_ty; 
1923+                     } 
1924+                 } 
1925+             } 
1926+             // layout of `async_drop_in_place<T>::{closure}` in case, 
1927+             // when T is a coroutine, contains this internal coroutine's ref 
1928+             let  arg_cor_ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ; 
1929+             if  arg_cor_ty. is_coroutine ( )  { 
1930+                 let  impl_cor_ty = find_impl_coroutine ( self ,  arg_cor_ty) ; 
1931+                 let  impl_ref = Ty :: new_mut_ref ( self ,  self . lifetimes . re_static ,  impl_cor_ty) ; 
1932+                 let  span = self . def_span ( def_id) ; 
1933+                 let  source_info = SourceInfo :: outermost ( span) ; 
1934+                 let  proxy_layout = CoroutineLayout  { 
1935+                     field_tys :  [ CoroutineSavedTy  { 
1936+                         ty :  impl_ref, 
1937+                         source_info, 
1938+                         ignore_for_traits :  true , 
1939+                     } ] 
1940+                     . into ( ) , 
1941+                     field_names :  [ None ] . into ( ) , 
1942+                     variant_fields :  [ IndexVec :: from ( [ CoroutineSavedLocal :: ZERO ] ) ] . into ( ) , 
1943+                     variant_source_info :  [ source_info] . into ( ) , 
1944+                     storage_conflicts :  BitMatrix :: new ( 1 ,  1 ) , 
1945+                 } ; 
1946+                 return  Some ( self . arena . alloc ( proxy_layout) ) ; 
1947+             }  else  { 
1948+                 self . templated_coroutine_layout ( Ty :: new_coroutine ( self ,  def_id,  args) ) 
1949+             } 
1950+         }  else  { 
1951+             self . ordinary_coroutine_layout ( def_id,  args. as_coroutine ( ) . kind_ty ( ) ) 
1952+         } 
1953+     } 
1954+ 
18931955    /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. 
18941956     /// If it implements no trait, returns `None`. 
18951957     pub  fn  trait_id_of_impl ( self ,  def_id :  DefId )  -> Option < DefId >  { 
0 commit comments