@@ -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 {
@@ -1341,27 +1372,16 @@ impl<'tcx> Ty<'tcx> {
13411372 }
13421373 }
13431374
1344- /// Checks whether values of this type `T` implement has noop async destructor.
1375+ /// Get morphology of the async drop glue, needed for types which do not
1376+ /// use async drop. To get async drop glue morphology for a definition see
1377+ /// [`TyCtxt::async_drop_glue_morphology`]. Used for `AsyncDestruct::Destructor`
1378+ /// type construction.
13451379 //
1346- // FIXME: implement optimization to make ADTs, which do not need drop,
1347- // to skip fields or to have noop async destructor, use `needs_(async_)drop`
1348- pub fn is_async_destructor_noop (
1349- self ,
1350- tcx : TyCtxt < ' tcx > ,
1351- param_env : ty:: ParamEnv < ' tcx > ,
1352- ) -> bool {
1353- // TODO: check on the most generic version of your type
1354- self . is_async_destructor_trivially_noop ( )
1355- || self . needs_async_drop ( tcx, param_env)
1356- || self . needs_drop ( tcx, param_env)
1357- }
1358-
1359- /// Fast path helper for testing if a type has noop async destructor.
1360- ///
1361- /// Returning `true` means the type is known to have noop async destructor
1362- /// implementation. Returning `true` means nothing -- could be
1363- /// `Drop`, might not be.
1364- fn is_async_destructor_trivially_noop ( self ) -> bool {
1380+ // FIXME: implement optimization to not instantiate a certain morphology of
1381+ // async drop glue too soon to allow per type optimizations, see array case
1382+ // for more info. Perhaps then remove this method and use `needs_(async_)drop`
1383+ // instead.
1384+ pub fn async_drop_glue_morphology ( self , tcx : TyCtxt < ' tcx > ) -> AsyncDropGlueMorphology {
13651385 match self . kind ( ) {
13661386 ty:: Int ( _)
13671387 | ty:: Uint ( _)
@@ -1373,37 +1393,43 @@ impl<'tcx> Ty<'tcx> {
13731393 | ty:: Ref ( ..)
13741394 | ty:: RawPtr ( ..)
13751395 | ty:: FnDef ( ..)
1376- | ty:: FnPtr ( _) => true ,
1377- ty:: Tuple ( tys) => tys. is_empty ( ) ,
1378- ty:: Adt ( adt_def, _) => adt_def. is_manually_drop ( ) ,
1379- ty:: Bool => todo ! ( ) ,
1380- ty:: Char => todo ! ( ) ,
1381- ty:: Int ( _) => todo ! ( ) ,
1382- ty:: Uint ( _) => todo ! ( ) ,
1383- ty:: Float ( _) => todo ! ( ) ,
1384- ty:: Adt ( _, _) => todo ! ( ) ,
1385- ty:: Foreign ( _) => todo ! ( ) ,
1386- ty:: Str => todo ! ( ) ,
1387- ty:: Array ( _, _) => todo ! ( ) ,
1388- ty:: Pat ( _, _) => todo ! ( ) ,
1389- ty:: Slice ( _) => todo ! ( ) ,
1390- ty:: RawPtr ( _, _) => todo ! ( ) ,
1391- ty:: Ref ( _, _, _) => todo ! ( ) ,
1392- ty:: FnDef ( _, _) => todo ! ( ) ,
1393- ty:: FnPtr ( _) => todo ! ( ) ,
1394- ty:: Dynamic ( _, _, _) => todo ! ( ) ,
1395- ty:: Closure ( _, _) => todo ! ( ) ,
1396- ty:: CoroutineClosure ( _, _) => todo ! ( ) ,
1397- ty:: Coroutine ( _, _) => todo ! ( ) ,
1398- ty:: CoroutineWitness ( _, _) => todo ! ( ) ,
1399- ty:: Never => todo ! ( ) ,
1400- ty:: Tuple ( _) => todo ! ( ) ,
1401- ty:: Alias ( _, _) => todo ! ( ) ,
1402- ty:: Param ( _) => todo ! ( ) ,
1403- ty:: Bound ( _, _) => todo ! ( ) ,
1404- ty:: Placeholder ( _) => todo ! ( ) ,
1405- ty:: Infer ( _) => todo ! ( ) ,
1406- ty:: Error ( _) => todo ! ( ) ,
1396+ | ty:: FnPtr ( _)
1397+ | ty:: Infer ( ty:: FreshIntTy ( _) )
1398+ | ty:: Infer ( ty:: FreshFloatTy ( _) ) => AsyncDropGlueMorphology :: Noop ,
1399+
1400+ ty:: Tuple ( tys) if tys. is_empty ( ) => AsyncDropGlueMorphology :: Noop ,
1401+ ty:: Adt ( adt_def, _) if adt_def. is_manually_drop ( ) => AsyncDropGlueMorphology :: Noop ,
1402+
1403+ // Foreign types can never have destructors.
1404+ ty:: Foreign ( _) => AsyncDropGlueMorphology :: Noop ,
1405+
1406+ // FIXME: implement dynamic types async drops
1407+ ty:: Error ( _) | ty:: Dynamic ( ..) => AsyncDropGlueMorphology :: DeferredDropInPlace ,
1408+
1409+ ty:: Tuple ( _) | ty:: Array ( _, _) | ty:: Slice ( _) => {
1410+ // Assume worst-case scenario, because we can instantiate async
1411+ // destructors in different orders:
1412+ //
1413+ // 1. Instantiate [T; N] with T = String and N = 0
1414+ // 2. Instantiate <[String; 0] as AsyncDestruct>::Destructor
1415+ //
1416+ // And viceversa, thus we cannot rely on String not using async
1417+ // drop or array having zero (0) elements
1418+ AsyncDropGlueMorphology :: Custom
1419+ }
1420+ ty:: Pat ( ty, _) => ty. async_drop_glue_morphology ( tcx) ,
1421+
1422+ ty:: Adt ( adt_def, _) => tcx. async_drop_glue_morphology ( adt_def. did ( ) ) ,
1423+
1424+ ty:: Closure ( did, _)
1425+ | ty:: CoroutineClosure ( did, _)
1426+ | ty:: Coroutine ( did, _)
1427+ | ty:: CoroutineWitness ( did, _) => tcx. async_drop_glue_morphology ( * did) ,
1428+
1429+ ty:: Alias ( ..) | ty:: Param ( _) | ty:: Bound ( ..) | ty:: Placeholder ( ..) | ty:: Infer ( _) => {
1430+ // No specifics, but would usually mean forwarding async drop glue
1431+ AsyncDropGlueMorphology :: Custom
1432+ }
14071433 }
14081434 }
14091435
@@ -1450,7 +1476,11 @@ impl<'tcx> Ty<'tcx> {
14501476 /// (Note that this implies that if `ty` has an async destructor attached,
14511477 /// then `needs_async_drop` will definitely return `true` for `ty`.)
14521478 ///
1453- /// Note that this method is used to check eligible types in unions.
1479+ /// When constructing `AsyncDestruct::Destructor` type, use
1480+ /// [`Ty::async_drop_glue_morphology`] instead.
1481+ //
1482+ // FIXME(zetanumbers): Note that this method is used to check eligible types
1483+ // in unions.
14541484 #[ inline]
14551485 pub fn needs_async_drop ( self , tcx : TyCtxt < ' tcx > , param_env : ty:: ParamEnv < ' tcx > ) -> bool {
14561486 // Avoid querying in simple cases.
@@ -1646,10 +1676,13 @@ impl<'tcx> ExplicitSelf<'tcx> {
16461676 }
16471677}
16481678
1649- // FIXME(zetanumbers): make specifying asyncness explicit
16501679/// Returns a list of types such that the given type needs drop if and only if
16511680/// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
16521681/// this type always needs drop.
1682+ //
1683+ // FIXME(zetanumbers): consider replacing this with only
1684+ // `needs_drop_components_with_async`
1685+ #[ inline]
16531686pub fn needs_drop_components < ' tcx > (
16541687 tcx : TyCtxt < ' tcx > ,
16551688 ty : Ty < ' tcx > ,
0 commit comments