@@ -36,6 +36,7 @@ use rustc_errors::{Diag, ErrorGuaranteed, StashKey};
36
36
use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , DocLinkResMap , LifetimeRes , Res } ;
37
37
use rustc_hir:: def_id:: { CrateNum , DefId , DefIdMap , LocalDefId , LocalDefIdMap } ;
38
38
use rustc_hir:: LangItem ;
39
+ use rustc_index:: bit_set:: BitMatrix ;
39
40
use rustc_index:: IndexVec ;
40
41
use rustc_macros:: {
41
42
extension, Decodable , Encodable , HashStable , TyDecodable , TyEncodable , TypeFoldable ,
@@ -110,7 +111,7 @@ pub use self::IntVarValue::*;
110
111
use crate :: error:: { OpaqueHiddenTypeMismatch , TypeMismatchReason } ;
111
112
use crate :: metadata:: ModChild ;
112
113
use crate :: middle:: privacy:: EffectiveVisibilities ;
113
- use crate :: mir:: { Body , CoroutineLayout } ;
114
+ use crate :: mir:: { Body , CoroutineLayout , CoroutineSavedLocal , CoroutineSavedTy , SourceInfo } ;
114
115
use crate :: query:: Providers ;
115
116
use crate :: traits:: { self , Reveal } ;
116
117
use crate :: ty;
@@ -1771,7 +1772,7 @@ impl<'tcx> TyCtxt<'tcx> {
1771
1772
| ty:: InstanceKind :: FnPtrAddrShim ( ..)
1772
1773
| ty:: InstanceKind :: AsyncDropGlueCtorShim ( ..) => self . mir_shims ( instance) ,
1773
1774
// 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 ) ,
1775
1776
}
1776
1777
}
1777
1778
@@ -1851,16 +1852,17 @@ impl<'tcx> TyCtxt<'tcx> {
1851
1852
self . def_kind ( trait_def_id) == DefKind :: TraitAlias
1852
1853
}
1853
1854
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
1855
1856
/// coroutine is tainted by errors.
1856
1857
///
1857
1858
/// Takes `coroutine_kind` which can be acquired from the `CoroutineArgs::kind_ty`,
1858
1859
/// e.g. `args.as_coroutine().kind_ty()`.
1859
- pub fn coroutine_layout (
1860
+ pub fn ordinary_coroutine_layout (
1860
1861
self ,
1861
1862
def_id : DefId ,
1862
1863
coroutine_kind_ty : Ty < ' tcx > ,
1863
1864
) -> Option < & ' tcx CoroutineLayout < ' tcx > > {
1865
+ debug_assert_ne ! ( Some ( def_id) , self . lang_items( ) . async_drop_in_place_poll_fn( ) ) ;
1864
1866
let mir = self . optimized_mir ( def_id) ;
1865
1867
// Regular coroutine
1866
1868
if coroutine_kind_ty. is_unit ( ) {
@@ -1890,6 +1892,66 @@ impl<'tcx> TyCtxt<'tcx> {
1890
1892
}
1891
1893
}
1892
1894
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
+
1893
1955
/// Given the `DefId` of an impl, returns the `DefId` of the trait it implements.
1894
1956
/// If it implements no trait, returns `None`.
1895
1957
pub fn trait_id_of_impl ( self , def_id : DefId ) -> Option < DefId > {
0 commit comments