@@ -37,6 +37,7 @@ use rustc_hir::LangItem;
3737use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , DocLinkResMap , LifetimeRes , Res } ;
3838use rustc_hir:: def_id:: { CrateNum , DefId , DefIdMap , LocalDefId , LocalDefIdMap } ;
3939use rustc_index:: IndexVec ;
40+ use rustc_index:: bit_set:: BitMatrix ;
4041use rustc_macros:: {
4142 Decodable , Encodable , HashStable , TyDecodable , TyEncodable , TypeFoldable , TypeVisitable ,
4243 extension,
@@ -100,7 +101,7 @@ pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeV
100101use crate :: error:: { OpaqueHiddenTypeMismatch , TypeMismatchReason } ;
101102use crate :: metadata:: ModChild ;
102103use crate :: middle:: privacy:: EffectiveVisibilities ;
103- use crate :: mir:: { Body , CoroutineLayout } ;
104+ use crate :: mir:: { Body , CoroutineLayout , CoroutineSavedLocal , CoroutineSavedTy , SourceInfo } ;
104105use crate :: query:: { IntoQueryParam , Providers } ;
105106use crate :: ty;
106107pub use crate :: ty:: diagnostics:: * ;
@@ -1742,7 +1743,7 @@ impl<'tcx> TyCtxt<'tcx> {
17421743 | ty:: InstanceKind :: FnPtrAddrShim ( ..)
17431744 | ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..) => self . mir_shims ( instance) ,
17441745 // async drop glue should be processed specifically, as a templated coroutine
1745- ty:: InstanceKind :: AsyncDropGlue ( _, _ty ) => todo ! ( ) ,
1746+ ty:: InstanceKind :: AsyncDropGlue ( _, ty ) => self . templated_optimized_mir ( ty ) ,
17461747 }
17471748 }
17481749
@@ -1853,16 +1854,17 @@ impl<'tcx> TyCtxt<'tcx> {
18531854 self . def_kind ( trait_def_id) == DefKind :: TraitAlias
18541855 }
18551856
1856- /// Returns layout of a coroutine. Layout might be unavailable if the
1857+ /// Returns layout of a non-templated coroutine. Layout might be unavailable if the
18571858 /// coroutine is tainted by errors.
18581859 ///
18591860 /// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
18601861 /// e.g. `args.as_coroutine().kind_ty()`.
1861- pub fn coroutine_layout (
1862+ pub fn ordinary_coroutine_layout (
18621863 self ,
18631864 def_id : DefId ,
18641865 coroutine_kind_ty : Ty < ' tcx > ,
18651866 ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1867+ debug_assert_ne ! ( Some ( def_id) , self . lang_items( ) . async_drop_in_place_poll_fn( ) ) ;
18661868 let mir = self . optimized_mir ( def_id) ;
18671869 // Regular coroutine
18681870 if coroutine_kind_ty. is_unit ( ) {
@@ -1892,6 +1894,66 @@ impl<'tcx> TyCtxt<'tcx> {
18921894 }
18931895 }
18941896
1897+ /// Returns layout of a templated coroutine. Layout might be unavailable if the
1898+ /// coroutine is tainted by errors. Atm, the only templated coroutine is
1899+ /// `async_drop_in_place<T>::{closure}` returned from `async fn async_drop_in_place<T>(..)`.
1900+ pub fn templated_coroutine_layout ( self , ty : Ty < ' tcx > ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1901+ self . templated_optimized_mir ( ty) . coroutine_layout_raw ( )
1902+ }
1903+
1904+ /// Returns layout of a templated (or not) coroutine. Layout might be unavailable if the
1905+ /// coroutine is tainted by errors.
1906+ pub fn coroutine_layout (
1907+ self ,
1908+ def_id : DefId ,
1909+ args : GenericArgsRef < ' tcx > ,
1910+ ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1911+ if Some ( def_id) == self . lang_items ( ) . async_drop_in_place_poll_fn ( ) {
1912+ fn find_impl_coroutine < ' tcx > ( tcx : TyCtxt < ' tcx > , mut cor_ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1913+ let mut ty = cor_ty;
1914+ loop {
1915+ if let ty:: Coroutine ( def_id, args) = ty. kind ( ) {
1916+ cor_ty = ty;
1917+ if tcx. is_templated_coroutine ( * def_id) {
1918+ ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1919+ continue ;
1920+ } else {
1921+ return cor_ty;
1922+ }
1923+ } else {
1924+ return cor_ty;
1925+ }
1926+ }
1927+ }
1928+ // layout of `async_drop_in_place<T>::{closure}` in case,
1929+ // when T is a coroutine, contains this internal coroutine's ref
1930+ let arg_cor_ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1931+ if arg_cor_ty. is_coroutine ( ) {
1932+ let impl_cor_ty = find_impl_coroutine ( self , arg_cor_ty) ;
1933+ let impl_ref = Ty :: new_mut_ref ( self , self . lifetimes . re_static , impl_cor_ty) ;
1934+ let span = self . def_span ( def_id) ;
1935+ let source_info = SourceInfo :: outermost ( span) ;
1936+ let proxy_layout = CoroutineLayout {
1937+ field_tys : [ CoroutineSavedTy {
1938+ ty : impl_ref,
1939+ source_info,
1940+ ignore_for_traits : true ,
1941+ } ]
1942+ . into ( ) ,
1943+ field_names : [ None ] . into ( ) ,
1944+ variant_fields : [ IndexVec :: from ( [ CoroutineSavedLocal :: ZERO ] ) ] . into ( ) ,
1945+ variant_source_info : [ source_info] . into ( ) ,
1946+ storage_conflicts : BitMatrix :: new ( 1 , 1 ) ,
1947+ } ;
1948+ return Some ( self . arena . alloc ( proxy_layout) ) ;
1949+ } else {
1950+ self . templated_coroutine_layout ( Ty :: new_coroutine ( self , def_id, args) )
1951+ }
1952+ } else {
1953+ self . ordinary_coroutine_layout ( def_id, args. as_coroutine ( ) . kind_ty ( ) )
1954+ }
1955+ }
1956+
18951957 /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
18961958 /// If it implements no trait, returns `None`.
18971959 pub fn trait_id_of_impl ( self , def_id : DefId ) -> Option < DefId > {
0 commit comments