@@ -39,6 +39,7 @@ use rustc_hir::LangItem;
39
39
use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , DocLinkResMap , LifetimeRes , Res } ;
40
40
use rustc_hir:: def_id:: { CrateNum , DefId , DefIdMap , LocalDefId , LocalDefIdMap } ;
41
41
use rustc_index:: IndexVec ;
42
+ use rustc_index:: bit_set:: BitMatrix ;
42
43
use rustc_macros:: {
43
44
Decodable , Encodable , HashStable , TyDecodable , TyEncodable , TypeFoldable , TypeVisitable ,
44
45
extension,
@@ -103,7 +104,7 @@ pub use self::visit::*;
103
104
use crate :: error:: { OpaqueHiddenTypeMismatch , TypeMismatchReason } ;
104
105
use crate :: metadata:: ModChild ;
105
106
use crate :: middle:: privacy:: EffectiveVisibilities ;
106
- use crate :: mir:: { Body , CoroutineLayout } ;
107
+ use crate :: mir:: { Body , CoroutineLayout , CoroutineSavedLocal , CoroutineSavedTy , SourceInfo } ;
107
108
use crate :: query:: { IntoQueryParam , Providers } ;
108
109
use crate :: ty;
109
110
use crate :: ty:: codec:: { TyDecoder , TyEncoder } ;
@@ -1702,9 +1703,8 @@ impl<'tcx> TyCtxt<'tcx> {
1702
1703
| ty:: InstanceKind :: CloneShim ( ..)
1703
1704
| ty:: InstanceKind :: ThreadLocalShim ( ..)
1704
1705
| ty:: InstanceKind :: FnPtrAddrShim ( ..)
1705
- | ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..) => self . mir_shims ( instance) ,
1706
- // async drop glue should be processed specifically, as a templated coroutine
1707
- ty:: InstanceKind :: AsyncDropGlue ( _, _ty) => todo ! ( ) ,
1706
+ | ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..)
1707
+ | ty:: InstanceKind :: AsyncDropGlue ( ..) => self . mir_shims ( instance) ,
1708
1708
}
1709
1709
}
1710
1710
@@ -1820,16 +1820,17 @@ impl<'tcx> TyCtxt<'tcx> {
1820
1820
self . def_kind ( trait_def_id) == DefKind :: TraitAlias
1821
1821
}
1822
1822
1823
- /// Returns layout of a coroutine. Layout might be unavailable if the
1823
+ /// Returns layout of a non-templated coroutine. Layout might be unavailable if the
1824
1824
/// coroutine is tainted by errors.
1825
1825
///
1826
1826
/// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
1827
1827
/// e.g. `args.as_coroutine().kind_ty()`.
1828
- pub fn coroutine_layout (
1828
+ pub fn ordinary_coroutine_layout (
1829
1829
self ,
1830
1830
def_id : DefId ,
1831
1831
coroutine_kind_ty : Ty < ' tcx > ,
1832
1832
) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1833
+ debug_assert_ne ! ( Some ( def_id) , self . lang_items( ) . async_drop_in_place_poll_fn( ) ) ;
1833
1834
let mir = self . optimized_mir ( def_id) ;
1834
1835
// Regular coroutine
1835
1836
if coroutine_kind_ty. is_unit ( ) {
@@ -1859,6 +1860,68 @@ impl<'tcx> TyCtxt<'tcx> {
1859
1860
}
1860
1861
}
1861
1862
1863
+ /// Returns layout of a templated coroutine. Layout might be unavailable if the
1864
+ /// coroutine is tainted by errors. Atm, the only templated coroutine is
1865
+ /// `async_drop_in_place<T>::{closure}` returned from `async fn async_drop_in_place<T>(..)`.
1866
+ pub fn templated_coroutine_layout ( self , ty : Ty < ' tcx > ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1867
+ self . lang_items ( ) . async_drop_in_place_poll_fn ( ) . and_then ( |def_id| {
1868
+ self . mir_shims ( InstanceKind :: AsyncDropGlue ( def_id, ty) ) . coroutine_layout_raw ( )
1869
+ } )
1870
+ }
1871
+
1872
+ /// Returns layout of a templated (or not) coroutine. Layout might be unavailable if the
1873
+ /// coroutine is tainted by errors.
1874
+ pub fn coroutine_layout (
1875
+ self ,
1876
+ def_id : DefId ,
1877
+ args : GenericArgsRef < ' tcx > ,
1878
+ ) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1879
+ if Some ( def_id) == self . lang_items ( ) . async_drop_in_place_poll_fn ( ) {
1880
+ fn find_impl_coroutine < ' tcx > ( tcx : TyCtxt < ' tcx > , mut cor_ty : Ty < ' tcx > ) -> Ty < ' tcx > {
1881
+ let mut ty = cor_ty;
1882
+ loop {
1883
+ if let ty:: Coroutine ( def_id, args) = ty. kind ( ) {
1884
+ cor_ty = ty;
1885
+ if tcx. is_templated_coroutine ( * def_id) {
1886
+ ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1887
+ continue ;
1888
+ } else {
1889
+ return cor_ty;
1890
+ }
1891
+ } else {
1892
+ return cor_ty;
1893
+ }
1894
+ }
1895
+ }
1896
+ // layout of `async_drop_in_place<T>::{closure}` in case,
1897
+ // when T is a coroutine, contains this internal coroutine's ref
1898
+ let arg_cor_ty = args. first ( ) . unwrap ( ) . expect_ty ( ) ;
1899
+ if arg_cor_ty. is_coroutine ( ) {
1900
+ let impl_cor_ty = find_impl_coroutine ( self , arg_cor_ty) ;
1901
+ let impl_ref = Ty :: new_mut_ref ( self , self . lifetimes . re_static , impl_cor_ty) ;
1902
+ let span = self . def_span ( def_id) ;
1903
+ let source_info = SourceInfo :: outermost ( span) ;
1904
+ let proxy_layout = CoroutineLayout {
1905
+ field_tys : [ CoroutineSavedTy {
1906
+ ty : impl_ref,
1907
+ source_info,
1908
+ ignore_for_traits : true ,
1909
+ } ]
1910
+ . into ( ) ,
1911
+ field_names : [ None ] . into ( ) ,
1912
+ variant_fields : [ IndexVec :: from ( [ CoroutineSavedLocal :: ZERO ] ) ] . into ( ) ,
1913
+ variant_source_info : [ source_info] . into ( ) ,
1914
+ storage_conflicts : BitMatrix :: new ( 1 , 1 ) ,
1915
+ } ;
1916
+ return Some ( self . arena . alloc ( proxy_layout) ) ;
1917
+ } else {
1918
+ self . templated_coroutine_layout ( Ty :: new_coroutine ( self , def_id, args) )
1919
+ }
1920
+ } else {
1921
+ self . ordinary_coroutine_layout ( def_id, args. as_coroutine ( ) . kind_ty ( ) )
1922
+ }
1923
+ }
1924
+
1862
1925
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
1863
1926
/// If it implements no trait, returns `None`.
1864
1927
pub fn trait_id_of_impl ( self , def_id : DefId ) -> Option < DefId > {
0 commit comments