@@ -1170,7 +1170,7 @@ fn build_async_destructor_ctor_shim<'tcx>(
1170
1170
| ty:: Ref ( _, _, _)
1171
1171
| ty:: FnDef ( _, _)
1172
1172
| ty:: FnPtr ( _)
1173
- | ty:: Never
1173
+ | ty:: Never => GlueStrategy :: Empty ,
1174
1174
} ;
1175
1175
1176
1176
let return_bb;
@@ -1607,6 +1607,227 @@ fn build_async_destructor_ctor_shim<'tcx>(
1607
1607
new_body ( source, blocks, locals, sig. inputs ( ) . len ( ) , span)
1608
1608
}
1609
1609
1610
+ const ASYNC_DESTRUCTOR_CTOR_ARG_COUNT : usize = 1 ;
1611
+
1612
+ struct AsyncDestructorCtorShimBuilder < ' tcx > {
1613
+ tcx : TyCtxt < ' tcx > ,
1614
+ def_id : DefId ,
1615
+ self_ty : Ty < ' tcx > ,
1616
+ span : Span ,
1617
+ source_info : SourceInfo ,
1618
+
1619
+ stack : Vec < ( Local , Ty < ' tcx > ) > ,
1620
+ last_bb : BasicBlock ,
1621
+
1622
+ locals : IndexVec < Local , LocalDecl < ' tcx > > ,
1623
+ bbs : IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
1624
+
1625
+ // Cached stuff
1626
+ chain_combinator : Option < ( DefId , EarlyBinder < Ty < ' tcx > > ) > ,
1627
+ ready_unit : Option < ( DefId , Ty < ' tcx > ) > ,
1628
+ }
1629
+
1630
+ impl < ' tcx > AsyncDestructorCtorShimBuilder < ' tcx > {
1631
+ fn new ( tcx : TyCtxt < ' tcx > , def_id : DefId , self_ty : Ty < ' tcx > ) -> Self {
1632
+ let span = tcx. def_span ( def_id) ;
1633
+ let Some ( sig) = tcx. fn_sig ( def_id) . instantiate ( tcx, & [ self_ty. into ( ) ] ) . no_bound_vars ( )
1634
+ else {
1635
+ span_bug ! ( span, "async_drop_in_place_raw with bound vars for `{self_ty}`" ) ;
1636
+ } ;
1637
+
1638
+ let source_info = SourceInfo :: outermost ( span) ;
1639
+
1640
+ debug_assert_eq ! ( sig. inputs( ) . len( ) , ASYNC_DESTRUCTOR_CTOR_ARG_COUNT ) ;
1641
+ let locals = local_decls_for_sig ( & sig, span) ;
1642
+
1643
+ AsyncDestructorCtorShimBuilder {
1644
+ tcx,
1645
+ def_id,
1646
+ self_ty,
1647
+ span,
1648
+ source_info,
1649
+
1650
+ stack : Vec :: new ( ) ,
1651
+ last_bb : BasicBlock :: new ( 0 ) ,
1652
+
1653
+ locals,
1654
+ bbs : IndexVec :: from ( [ BasicBlockData :: new ( None ) ] ) ,
1655
+
1656
+ chain_combinator : None ,
1657
+ ready_unit : None ,
1658
+ }
1659
+ }
1660
+
1661
+ fn put_self ( & mut self ) {
1662
+ let last_bb = & mut self . bbs [ self . last_bb ] ;
1663
+ debug_assert ! ( last_bb. terminator. is_none( ) ) ;
1664
+
1665
+ let self_ptr = Local :: new ( 1 ) ;
1666
+ // We need to create a new local to be able to "consume" it with
1667
+ // a combinator
1668
+ let local = self . locals . push ( self . locals [ self_ptr] . clone ( ) ) ;
1669
+ last_bb. statements . extend_from_slice ( & [
1670
+ Statement { source_info : self . source_info , kind : StatementKind :: StorageLive ( local) } ,
1671
+ Statement {
1672
+ source_info : self . source_info ,
1673
+ kind : StatementKind :: Assign ( Box :: new ( (
1674
+ local. into ( ) ,
1675
+ Rvalue :: Use ( Operand :: Copy ( self_ptr. into ( ) ) ) ,
1676
+ ) ) ) ,
1677
+ } ,
1678
+ ] ) ;
1679
+
1680
+ // We use pointee types so that they are used for instantiation
1681
+ // of combinators
1682
+ self . stack . push ( ( local, self . self_ty ) ) ;
1683
+ }
1684
+
1685
+ fn put_field ( & mut self , field : FieldIdx , ty : Ty < ' tcx > ) {
1686
+ let last_bb = & mut self . bbs [ self . last_bb ] ;
1687
+ debug_assert ! ( last_bb. terminator. is_none( ) ) ;
1688
+
1689
+ // We need to create a new local to be able to "consume" it with
1690
+ // a combinator
1691
+ let local = self . locals . push ( LocalDecl :: with_source_info ( ty, self . source_info ) ) ;
1692
+ let self_ptr = Local :: new ( 1 ) ;
1693
+ last_bb. statements . extend_from_slice ( & [
1694
+ Statement { source_info : self . source_info , kind : StatementKind :: StorageLive ( local) } ,
1695
+ Statement {
1696
+ source_info : self . source_info ,
1697
+ kind : StatementKind :: Assign ( Box :: new ( (
1698
+ local. into ( ) ,
1699
+ Rvalue :: AddressOf (
1700
+ Mutability :: Mut ,
1701
+ self . tcx . mk_place_field (
1702
+ self . tcx . mk_place_deref ( self_ptr. into ( ) ) ,
1703
+ field,
1704
+ ty,
1705
+ ) ,
1706
+ ) ,
1707
+ ) ) ) ,
1708
+ } ,
1709
+ ] ) ;
1710
+
1711
+ // We use pointee types so that they are used for instantiation
1712
+ // of combinators
1713
+ self . stack . push ( ( local, ty) ) ;
1714
+ }
1715
+
1716
+ fn ready_unit ( & mut self ) {
1717
+ let tcx = self . tcx ;
1718
+ let ( function, ty) = * self . ready_unit . get_or_insert_with ( || {
1719
+ (
1720
+ tcx. require_lang_item ( LangItem :: FutureReadyUnitCtor , Some ( self . span ) ) ,
1721
+ tcx. type_of ( tcx. require_lang_item ( LangItem :: FutureReadyUnit , Some ( self . span ) ) )
1722
+ . instantiate_identity ( ) ,
1723
+ )
1724
+ } ) ;
1725
+ self . apply_combinator :: < 0 , _ > ( function, |_, _| ty)
1726
+ }
1727
+
1728
+ fn chain ( & mut self ) {
1729
+ let tcx = self . tcx ;
1730
+ let ( function, ty) = * self . chain_combinator . get_or_insert_with ( || {
1731
+ (
1732
+ tcx. require_lang_item ( LangItem :: FutureChainCtor , Some ( self . span ) ) ,
1733
+ tcx. type_of ( tcx. require_lang_item ( LangItem :: FutureChain , Some ( self . span ) ) ) ,
1734
+ )
1735
+ } ) ;
1736
+ self . apply_combinator :: < 2 , _ > ( function, |tcx, args| ty. instantiate ( tcx, args) )
1737
+ }
1738
+
1739
+ fn return_ ( mut self ) -> Body < ' tcx > {
1740
+ let last_bb = & mut self . bbs [ self . last_bb ] ;
1741
+ debug_assert ! ( last_bb. terminator. is_none( ) ) ;
1742
+
1743
+ let & [ ( output_local, _) ] = self . stack . as_slice ( ) else {
1744
+ span_bug ! (
1745
+ self . span,
1746
+ "async destructor ctor shim builder finished with invalid number of stack items: expected 1 found {}" ,
1747
+ self . stack. len( ) ,
1748
+ )
1749
+ } ;
1750
+ let return_local = Local :: new ( 0 ) ;
1751
+
1752
+ last_bb. statements . extend_from_slice ( & [
1753
+ Statement {
1754
+ source_info : self . source_info ,
1755
+ kind : StatementKind :: Assign ( Box :: new ( (
1756
+ return_local. into ( ) ,
1757
+ Rvalue :: Use ( Operand :: Move ( output_local. into ( ) ) ) ,
1758
+ ) ) ) ,
1759
+ } ,
1760
+ Statement {
1761
+ source_info : self . source_info ,
1762
+ kind : StatementKind :: StorageDead ( output_local) ,
1763
+ } ,
1764
+ ] ) ;
1765
+ last_bb. terminator =
1766
+ Some ( Terminator { source_info : self . source_info , kind : TerminatorKind :: Return } ) ;
1767
+
1768
+ let source = MirSource :: from_instance ( ty:: InstanceDef :: AsyncDropGlueCtorShim (
1769
+ self . def_id ,
1770
+ self . self_ty ,
1771
+ ) ) ;
1772
+ new_body ( source, self . bbs , self . locals , ASYNC_DESTRUCTOR_CTOR_ARG_COUNT , self . span )
1773
+ }
1774
+
1775
+ fn apply_combinator < const ARITY : usize , F > ( & mut self , function : DefId , mut ty_combinator : F )
1776
+ where
1777
+ F : FnMut ( TyCtxt < ' tcx > , & [ ty:: GenericArg < ' tcx > ] ) -> Ty < ' tcx > ,
1778
+ {
1779
+ let operands = self
1780
+ . stack
1781
+ . last_chunk :: < ARITY > ( )
1782
+ . expect ( "async destructor ctor shim combinator tried to consume too many items" ) ;
1783
+
1784
+ let generic_args = operands. each_ref ( ) . map ( |& ( _, t) | t. into ( ) ) ;
1785
+ let dest_ty = ty_combinator ( self . tcx , & generic_args) ;
1786
+
1787
+ let target = self . bbs . push ( BasicBlockData {
1788
+ statements : {
1789
+ let mut stmts = Vec :: with_capacity ( ARITY + 1 ) ;
1790
+ stmts. extend ( operands. iter ( ) . map ( |& ( l, _) | Statement {
1791
+ source_info : self . source_info ,
1792
+ kind : StatementKind :: StorageDead ( l) ,
1793
+ } ) ) ;
1794
+ stmts
1795
+ } ,
1796
+ terminator : None ,
1797
+ is_cleanup : false ,
1798
+ } ) ;
1799
+
1800
+ let args =
1801
+ operands. iter ( ) . map ( |& ( l, _) | respan ( self . span , Operand :: Move ( l. into ( ) ) ) ) . collect ( ) ;
1802
+ let dest =
1803
+ self . locals . push ( LocalDecl :: with_source_info ( dest_ty, self . source_info ) . immutable ( ) ) ;
1804
+
1805
+ let last_bb = & mut self . bbs [ self . last_bb ] ;
1806
+ debug_assert ! ( last_bb. terminator. is_none( ) ) ;
1807
+ last_bb. statements . push ( Statement {
1808
+ source_info : self . source_info ,
1809
+ kind : StatementKind :: StorageLive ( dest) ,
1810
+ } ) ;
1811
+ last_bb. terminator = Some ( Terminator {
1812
+ source_info : self . source_info ,
1813
+ kind : TerminatorKind :: Call {
1814
+ func : Operand :: function_handle ( self . tcx , function, generic_args, self . span ) ,
1815
+ args,
1816
+ destination : dest. into ( ) ,
1817
+ target : Some ( target) ,
1818
+ // TODO: Figure out unwind (even tho they shouldn't panic?)
1819
+ unwind : UnwindAction :: Continue ,
1820
+ call_source : CallSource :: Misc ,
1821
+ fn_span : self . span ,
1822
+ } ,
1823
+ } ) ;
1824
+
1825
+ drop ( self . stack . drain ( self . stack . len ( ) - ARITY ..) ) ;
1826
+ self . stack . push ( ( dest, dest_ty) ) ;
1827
+ self . last_bb = target;
1828
+ }
1829
+ }
1830
+
1610
1831
fn build_construct_coroutine_by_move_shim < ' tcx > (
1611
1832
tcx : TyCtxt < ' tcx > ,
1612
1833
coroutine_closure_def_id : DefId ,
0 commit comments