@@ -39,6 +39,7 @@ use rustc_hir::LangItem;
3939use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , DocLinkResMap , LifetimeRes , Res } ;
4040use rustc_hir:: def_id:: { CrateNum , DefId , DefIdMap , LocalDefId , LocalDefIdMap } ;
4141use rustc_index:: IndexVec ;
42+ use rustc_index:: bit_set:: BitMatrix ;
4243use rustc_macros:: {
4344 Decodable , Encodable , HashStable , TyDecodable , TyEncodable , TypeFoldable , TypeVisitable ,
4445 extension,
@@ -103,7 +104,7 @@ pub use self::visit::*;
103104use crate :: error:: { OpaqueHiddenTypeMismatch , TypeMismatchReason } ;
104105use crate :: metadata:: ModChild ;
105106use crate :: middle:: privacy:: EffectiveVisibilities ;
106- use crate :: mir:: { Body , CoroutineLayout } ;
107+ use crate :: mir:: { Body , CoroutineLayout , CoroutineSavedLocal , CoroutineSavedTy , SourceInfo } ;
107108use crate :: query:: { IntoQueryParam , Providers } ;
108109use crate :: ty;
109110use crate :: ty:: codec:: { TyDecoder , TyEncoder } ;
@@ -1721,9 +1722,8 @@ impl<'tcx> TyCtxt<'tcx> {
17211722 | ty:: InstanceKind :: CloneShim ( ..)
17221723 | ty:: InstanceKind :: ThreadLocalShim ( ..)
17231724 | ty:: InstanceKind :: FnPtrAddrShim ( ..)
1724- | ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..) => self . mir_shims ( instance) ,
1725- // async drop glue should be processed specifically, as a templated coroutine
1726- ty:: InstanceKind :: AsyncDropGlue ( _, _ty) => todo ! ( ) ,
1725+ | ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..)
1726+ | ty:: InstanceKind :: AsyncDropGlue ( ..) => self . mir_shims ( instance) ,
17271727 }
17281728 }
17291729
@@ -1839,16 +1839,17 @@ impl<'tcx> TyCtxt<'tcx> {
18391839 self . def_kind ( trait_def_id) == DefKind :: TraitAlias
18401840 }
18411841
1842- /// Returns layout of a coroutine. Layout might be unavailable if the
1842+ /// Returns layout of a non-templated coroutine. Layout might be unavailable if the
18431843 /// coroutine is tainted by errors.
18441844 ///
18451845 /// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
18461846 /// e.g. `args.as_coroutine().kind_ty()`.
1847- pub fn coroutine_layout (
1847+ pub fn ordinary_coroutine_layout (
18481848 self ,
18491849 def_id : DefId ,
18501850 coroutine_kind_ty : Ty < ' tcx > ,
18511851 ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1852+ debug_assert_ne ! ( Some ( def_id) , self . lang_items( ) . async_drop_in_place_poll_fn( ) ) ;
18521853 let mir = self . optimized_mir ( def_id) ;
18531854 // Regular coroutine
18541855 if coroutine_kind_ty. is_unit ( ) {
@@ -1878,6 +1879,68 @@ impl<'tcx> TyCtxt<'tcx> {
18781879 }
18791880 }
18801881
1882+ /// Returns layout of a templated coroutine. Layout might be unavailable if the
1883+ /// coroutine is tainted by errors. Atm, the only templated coroutine is
1884+ /// `async_drop_in_place<T>::{closure}` returned from `async fn async_drop_in_place<T>(..)`.
1885+ pub fn templated_coroutine_layout ( self , ty : Ty < ' tcx > ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1886+ self . lang_items ( ) . async_drop_in_place_poll_fn ( ) . and_then ( |def_id| {
1887+ self . mir_shims ( InstanceKind :: AsyncDropGlue ( def_id, ty) ) . coroutine_layout_raw ( )
1888+ } )
1889+ }
1890+
1891+ /// Returns layout of a templated (or not) coroutine. Layout might be unavailable if the
1892+ /// coroutine is tainted by errors.
1893+ pub fn coroutine_layout (
1894+ self ,
1895+ def_id : DefId ,
1896+ args : GenericArgsRef < ' tcx > ,
1897+ ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1898+ if Some ( def_id) == self . lang_items ( ) . async_drop_in_place_poll_fn ( ) {
1899+ fn find_impl_coroutine < ' tcx > ( tcx : TyCtxt < ' tcx > , mut cor_ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1900+ let mut ty = cor_ty;
1901+ loop {
1902+ if let ty:: Coroutine ( def_id, args) = ty. kind ( ) {
1903+ cor_ty = ty;
1904+ if tcx. is_templated_coroutine ( * def_id) {
1905+ ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1906+ continue ;
1907+ } else {
1908+ return cor_ty;
1909+ }
1910+ } else {
1911+ return cor_ty;
1912+ }
1913+ }
1914+ }
1915+ // layout of `async_drop_in_place<T>::{closure}` in case,
1916+ // when T is a coroutine, contains this internal coroutine's ref
1917+ let arg_cor_ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1918+ if arg_cor_ty. is_coroutine ( ) {
1919+ let impl_cor_ty = find_impl_coroutine ( self , arg_cor_ty) ;
1920+ let impl_ref = Ty :: new_mut_ref ( self , self . lifetimes . re_static , impl_cor_ty) ;
1921+ let span = self . def_span ( def_id) ;
1922+ let source_info = SourceInfo :: outermost ( span) ;
1923+ let proxy_layout = CoroutineLayout {
1924+ field_tys : [ CoroutineSavedTy {
1925+ ty : impl_ref,
1926+ source_info,
1927+ ignore_for_traits : true ,
1928+ } ]
1929+ . into ( ) ,
1930+ field_names : [ None ] . into ( ) ,
1931+ variant_fields : [ IndexVec :: from ( [ CoroutineSavedLocal :: ZERO ] ) ] . into ( ) ,
1932+ variant_source_info : [ source_info] . into ( ) ,
1933+ storage_conflicts : BitMatrix :: new ( 1 , 1 ) ,
1934+ } ;
1935+ return Some ( self . arena . alloc ( proxy_layout) ) ;
1936+ } else {
1937+ self . templated_coroutine_layout ( Ty :: new_coroutine ( self , def_id, args) )
1938+ }
1939+ } else {
1940+ self . ordinary_coroutine_layout ( def_id, args. as_coroutine ( ) . kind_ty ( ) )
1941+ }
1942+ }
1943+
18811944 /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
18821945 /// If it implements no trait, returns `None`.
18831946 pub fn trait_id_of_impl ( self , def_id : DefId ) -> Option < DefId > {
0 commit comments