@@ -35,6 +35,7 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
3535use 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 } ;
38+ use rustc_index:: bit_set:: BitMatrix ;
3839use rustc_index:: IndexVec ;
3940use rustc_macros:: {
4041 extension, Decodable , Encodable , HashStable , TyDecodable , TyEncodable , TypeFoldable ,
@@ -109,7 +110,7 @@ pub use self::IntVarValue::*;
109110use crate :: error:: { OpaqueHiddenTypeMismatch , TypeMismatchReason } ;
110111use crate :: metadata:: ModChild ;
111112use crate :: middle:: privacy:: EffectiveVisibilities ;
112- use crate :: mir:: { Body , CoroutineLayout } ;
113+ use crate :: mir:: { Body , CoroutineLayout , CoroutineSavedLocal , CoroutineSavedTy , SourceInfo } ;
113114use crate :: query:: Providers ;
114115use crate :: traits:: { self , Reveal } ;
115116use crate :: ty;
@@ -1764,7 +1765,7 @@ impl<'tcx> TyCtxt<'tcx> {
17641765 | ty:: InstanceKind :: FnPtrAddrShim ( ..)
17651766 | ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..) => self . mir_shims ( instance) ,
17661767 // async drop glue should be processed specifically, as a templated coroutine
1767- ty:: InstanceKind :: AsyncDropGlue ( _, _ty ) => todo ! ( ) ,
1768+ ty:: InstanceKind :: AsyncDropGlue ( _, ty ) => self . templated_optimized_mir ( ty ) ,
17681769 }
17691770 }
17701771
@@ -1844,16 +1845,17 @@ impl<'tcx> TyCtxt<'tcx> {
18441845 self . def_kind ( trait_def_id) == DefKind :: TraitAlias
18451846 }
18461847
1847- /// Returns layout of a coroutine. Layout might be unavailable if the
1848+ /// Returns layout of a non-templated coroutine. Layout might be unavailable if the
18481849 /// coroutine is tainted by errors.
18491850 ///
18501851 /// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
18511852 /// e.g. `args.as_coroutine().kind_ty()`.
1852- pub fn coroutine_layout (
1853+ pub fn ordinary_coroutine_layout (
18531854 self ,
18541855 def_id : DefId ,
18551856 coroutine_kind_ty : Ty < ' tcx > ,
18561857 ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1858+ debug_assert_ne ! ( Some ( def_id) , self . lang_items( ) . async_drop_in_place_poll_fn( ) ) ;
18571859 let mir = self . optimized_mir ( def_id) ;
18581860 // Regular coroutine
18591861 if coroutine_kind_ty. is_unit ( ) {
@@ -1882,6 +1884,66 @@ impl<'tcx> TyCtxt<'tcx> {
18821884 }
18831885 }
18841886
1887+ /// Returns layout of a templated coroutine. Layout might be unavailable if the
1888+ /// coroutine is tainted by errors. Atm, the only templated coroutine is
1889+ /// `async_drop_in_place<T>::{closure}` returned from `async fn async_drop_in_place<T>(..)`.
1890+ pub fn templated_coroutine_layout ( self , ty : Ty < ' tcx > ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1891+ self . templated_optimized_mir ( ty) . coroutine_layout_raw ( )
1892+ }
1893+
1894+ /// Returns layout of a templated (or not) coroutine. Layout might be unavailable if the
1895+ /// coroutine is tainted by errors.
1896+ pub fn coroutine_layout (
1897+ self ,
1898+ def_id : DefId ,
1899+ args : GenericArgsRef < ' tcx > ,
1900+ ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1901+ if Some ( def_id) == self . lang_items ( ) . async_drop_in_place_poll_fn ( ) {
1902+ fn find_impl_coroutine < ' tcx > ( tcx : TyCtxt < ' tcx > , mut cor_ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1903+ let mut ty = cor_ty;
1904+ loop {
1905+ if let ty:: Coroutine ( def_id, args) = ty. kind ( ) {
1906+ cor_ty = ty;
1907+ if tcx. is_templated_coroutine ( * def_id) {
1908+ ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1909+ continue ;
1910+ } else {
1911+ return cor_ty;
1912+ }
1913+ } else {
1914+ return cor_ty;
1915+ }
1916+ }
1917+ }
1918+ // layout of `async_drop_in_place<T>::{closure}` in case,
1919+ // when T is a coroutine, contains this internal coroutine's ref
1920+ let arg_cor_ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1921+ if arg_cor_ty. is_coroutine ( ) {
1922+ let impl_cor_ty = find_impl_coroutine ( self , arg_cor_ty) ;
1923+ let impl_ref = Ty :: new_mut_ref ( self , self . lifetimes . re_static , impl_cor_ty) ;
1924+ let span = self . def_span ( def_id) ;
1925+ let source_info = SourceInfo :: outermost ( span) ;
1926+ let proxy_layout = CoroutineLayout {
1927+ field_tys : [ CoroutineSavedTy {
1928+ ty : impl_ref,
1929+ source_info,
1930+ ignore_for_traits : true ,
1931+ } ]
1932+ . into ( ) ,
1933+ field_names : [ None ] . into ( ) ,
1934+ variant_fields : [ IndexVec :: from ( [ CoroutineSavedLocal :: ZERO ] ) ] . into ( ) ,
1935+ variant_source_info : [ source_info] . into ( ) ,
1936+ storage_conflicts : BitMatrix :: new ( 1 , 1 ) ,
1937+ } ;
1938+ return Some ( self . arena . alloc ( proxy_layout) ) ;
1939+ } else {
1940+ self . templated_coroutine_layout ( Ty :: new_coroutine ( self , def_id, args) )
1941+ }
1942+ } else {
1943+ self . ordinary_coroutine_layout ( def_id, args. as_coroutine ( ) . kind_ty ( ) )
1944+ }
1945+ }
1946+
18851947 /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
18861948 /// If it implements no trait, returns `None`.
18871949 pub fn trait_id_of_impl ( self , def_id : DefId ) -> Option < DefId > {
0 commit comments