@@ -420,6 +420,25 @@ impl<'tcx> TyCtxt<'tcx> {
420420 Some ( ty:: AsyncDestructor { future, ctor } )
421421 }
422422
423+ /// Returns async drop glue morphology for a definition. To get async drop
424+ /// glue morphology for a type see [`Ty::async_drop_glue_morphology`].
425+ //
426+ // FIXME: consider making this a query
427+ pub fn async_drop_glue_morphology ( self , did : DefId ) -> AsyncDropGlueMorphology {
428+ let ty: Ty < ' tcx > = self . type_of ( did) . instantiate_identity ( ) ;
429+
430+ // Async drop glue morphology is an internal detail, so reveal_all probably
431+ // should be fine
432+ let param_env = ty:: ParamEnv :: reveal_all ( ) ;
433+ if ty. needs_async_drop ( self , param_env) {
434+ AsyncDropGlueMorphology :: Custom
435+ } else if ty. needs_drop ( self , param_env) {
436+ AsyncDropGlueMorphology :: DeferredDropInPlace
437+ } else {
438+ AsyncDropGlueMorphology :: Noop
439+ }
440+ }
441+
423442 /// Returns the set of types that are required to be alive in
424443 /// order to run the destructor of `def` (see RFCs 769 and
425444 /// 1238).
@@ -1176,6 +1195,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for WeakAliasTypeExpander<'tcx> {
11761195 }
11771196}
11781197
1198+ /// Indicates the form of `AsyncDestruct::Destructor`. Used to simplify async
1199+ /// drop glue for types not using async drop.
1200+ #[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
1201+ pub enum AsyncDropGlueMorphology {
1202+ /// Async destructor simply does nothing
1203+ Noop ,
1204+ /// Async destructor simply runs `drop_in_place`
1205+ DeferredDropInPlace ,
1206+ /// Async destructor has custom logic
1207+ Custom ,
1208+ }
1209+
11791210impl < ' tcx > Ty < ' tcx > {
11801211 /// Returns the `Size` for primitive types (bool, uint, int, char, float).
11811212 pub fn primitive_size ( self , tcx : TyCtxt < ' tcx > ) -> Size {
@@ -1342,27 +1373,16 @@ impl<'tcx> Ty<'tcx> {
13421373 }
13431374 }
13441375
1345- /// Checks whether values of this type `T` implement has noop async destructor.
1376+ /// Get morphology of the async drop glue, needed for types which do not
1377+ /// use async drop. To get async drop glue morphology for a definition see
1378+ /// [`TyCtxt::async_drop_glue_morphology`]. Used for `AsyncDestruct::Destructor`
1379+ /// type construction.
13461380 //
1347- // FIXME: implement optimization to make ADTs, which do not need drop,
1348- // to skip fields or to have noop async destructor, use `needs_(async_)drop`
1349- pub fn is_async_destructor_noop (
1350- self ,
1351- tcx : TyCtxt < ' tcx > ,
1352- param_env : ty:: ParamEnv < ' tcx > ,
1353- ) -> bool {
1354- // TODO: check on the most generic version of your type
1355- self . is_async_destructor_trivially_noop ( )
1356- || self . needs_async_drop ( tcx, param_env)
1357- || self . needs_drop ( tcx, param_env)
1358- }
1359-
1360- /// Fast path helper for testing if a type has noop async destructor.
1361- ///
1362- /// Returning `true` means the type is known to have noop async destructor
1363- /// implementation. Returning `true` means nothing -- could be
1364- /// `Drop`, might not be.
1365- fn is_async_destructor_trivially_noop ( self ) -> bool {
1381+ // FIXME: implement optimization to not instantiate a certain morphology of
1382+ // async drop glue too soon to allow per type optimizations, see array case
1383+ // for more info. Perhaps then remove this method and use `needs_(async_)drop`
1384+ // instead.
1385+ pub fn async_drop_glue_morphology ( self , tcx : TyCtxt < ' tcx > ) -> AsyncDropGlueMorphology {
13661386 match self . kind ( ) {
13671387 ty:: Int ( _)
13681388 | ty:: Uint ( _)
@@ -1374,37 +1394,43 @@ impl<'tcx> Ty<'tcx> {
13741394 | ty:: Ref ( ..)
13751395 | ty:: RawPtr ( ..)
13761396 | ty:: FnDef ( ..)
1377- | ty:: FnPtr ( _) => true ,
1378- ty:: Tuple ( tys) => tys. is_empty ( ) ,
1379- ty:: Adt ( adt_def, _) => adt_def. is_manually_drop ( ) ,
1380- ty:: Bool => todo ! ( ) ,
1381- ty:: Char => todo ! ( ) ,
1382- ty:: Int ( _) => todo ! ( ) ,
1383- ty:: Uint ( _) => todo ! ( ) ,
1384- ty:: Float ( _) => todo ! ( ) ,
1385- ty:: Adt ( _, _) => todo ! ( ) ,
1386- ty:: Foreign ( _) => todo ! ( ) ,
1387- ty:: Str => todo ! ( ) ,
1388- ty:: Array ( _, _) => todo ! ( ) ,
1389- ty:: Pat ( _, _) => todo ! ( ) ,
1390- ty:: Slice ( _) => todo ! ( ) ,
1391- ty:: RawPtr ( _, _) => todo ! ( ) ,
1392- ty:: Ref ( _, _, _) => todo ! ( ) ,
1393- ty:: FnDef ( _, _) => todo ! ( ) ,
1394- ty:: FnPtr ( _) => todo ! ( ) ,
1395- ty:: Dynamic ( _, _, _) => todo ! ( ) ,
1396- ty:: Closure ( _, _) => todo ! ( ) ,
1397- ty:: CoroutineClosure ( _, _) => todo ! ( ) ,
1398- ty:: Coroutine ( _, _) => todo ! ( ) ,
1399- ty:: CoroutineWitness ( _, _) => todo ! ( ) ,
1400- ty:: Never => todo ! ( ) ,
1401- ty:: Tuple ( _) => todo ! ( ) ,
1402- ty:: Alias ( _, _) => todo ! ( ) ,
1403- ty:: Param ( _) => todo ! ( ) ,
1404- ty:: Bound ( _, _) => todo ! ( ) ,
1405- ty:: Placeholder ( _) => todo ! ( ) ,
1406- ty:: Infer ( _) => todo ! ( ) ,
1407- ty:: Error ( _) => todo ! ( ) ,
1397+ | ty:: FnPtr ( _)
1398+ | ty:: Infer ( ty:: FreshIntTy ( _) )
1399+ | ty:: Infer ( ty:: FreshFloatTy ( _) ) => AsyncDropGlueMorphology :: Noop ,
1400+
1401+ ty:: Tuple ( tys) if tys. is_empty ( ) => AsyncDropGlueMorphology :: Noop ,
1402+ ty:: Adt ( adt_def, _) if adt_def. is_manually_drop ( ) => AsyncDropGlueMorphology :: Noop ,
1403+
1404+ // Foreign types can never have destructors.
1405+ ty:: Foreign ( _) => AsyncDropGlueMorphology :: Noop ,
1406+
1407+ // FIXME: implement dynamic types async drops
1408+ ty:: Error ( _) | ty:: Dynamic ( ..) => AsyncDropGlueMorphology :: DeferredDropInPlace ,
1409+
1410+ ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Slice ( _) => {
1411+ // Assume worst-case scenario, because we can instantiate async
1412+ // destructors in different orders:
1413+ //
1414+ // 1. Instantiate [T; N] with T = String and N = 0
1415+ // 2. Instantiate <[String; 0] as AsyncDestruct>::Destructor
1416+ //
1417+ // And viceversa, thus we cannot rely on String not using async
1418+ // drop or array having zero (0) elements
1419+ AsyncDropGlueMorphology :: Custom
1420+ }
1421+ ty:: Pat ( ty, _) => ty. async_drop_glue_morphology ( tcx) ,
1422+
1423+ ty:: Adt ( adt_def, _) => tcx. async_drop_glue_morphology ( adt_def. did ( ) ) ,
1424+
1425+ ty:: Closure ( did, _)
1426+ | ty:: CoroutineClosure ( did, _)
1427+ | ty:: Coroutine ( did, _)
1428+ | ty:: CoroutineWitness ( did, _) => tcx. async_drop_glue_morphology ( * did) ,
1429+
1430+ ty:: Alias ( ..) | ty:: Param ( _) | ty:: Bound ( ..) | ty:: Placeholder ( ..) | ty:: Infer ( _) => {
1431+ // No specifics, but would usually mean forwarding async drop glue
1432+ AsyncDropGlueMorphology :: Custom
1433+ }
14081434 }
14091435 }
14101436
@@ -1451,7 +1477,11 @@ impl<'tcx> Ty<'tcx> {
14511477 /// (Note that this implies that if `ty` has an async destructor attached,
14521478 /// then `needs_async_drop` will definitely return `true` for `ty`.)
14531479 ///
1454- /// Note that this method is used to check eligible types in unions.
1480+ /// When constructing `AsyncDestruct::Destructor` type, use
1481+ /// [`Ty::async_drop_glue_morphology`] instead.
1482+ //
1483+ // FIXME(zetanumbers): Note that this method is used to check eligible types
1484+ // in unions.
14551485 #[ inline]
14561486 pub fn needs_async_drop ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> bool {
14571487 // Avoid querying in simple cases.
@@ -1647,10 +1677,13 @@ impl<'tcx> ExplicitSelf<'tcx> {
16471677 }
16481678}
16491679
1650- // FIXME(zetanumbers): make specifying asyncness explicit
16511680/// Returns a list of types such that the given type needs drop if and only if
16521681/// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
16531682/// this type always needs drop.
1683+ //
1684+ // FIXME(zetanumbers): consider replacing this with only
1685+ // `needs_drop_components_with_async`
1686+ #[ inline]
16541687pub fn needs_drop_components < ' tcx > (
16551688 tcx : TyCtxt < ' tcx > ,
16561689 ty : Ty < ' tcx > ,
0 commit comments