@@ -331,7 +331,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
331
331
) ,
332
332
ExprKind :: Try ( sub_expr) => self . lower_expr_try ( e. span , sub_expr) ,
333
333
334
- ExprKind :: Paren ( _) | ExprKind :: ForLoop { .. } => {
334
+ ExprKind :: Paren ( _) | ExprKind :: ForLoop { .. } => {
335
335
unreachable ! ( "already handled" )
336
336
}
337
337
@@ -784,6 +784,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
784
784
/// }
785
785
/// ```
786
786
fn lower_expr_await ( & mut self , await_kw_span : Span , expr : & Expr ) -> hir:: ExprKind < ' hir > {
787
+ let expr = self . lower_expr_mut ( expr) ;
788
+ self . make_lowered_await ( await_kw_span, & expr)
789
+ }
790
+
791
+ /// Takes an expr that has already been lowered and generates a desugared await loop around it
792
+ fn make_lowered_await (
793
+ & mut self ,
794
+ await_kw_span : Span ,
795
+ expr : & hir:: Expr < ' hir > ,
796
+ ) -> hir:: ExprKind < ' hir > {
787
797
let full_span = expr. span . to ( await_kw_span) ;
788
798
match self . coroutine_kind {
789
799
Some ( hir:: CoroutineKind :: Async ( _) ) => { }
@@ -800,7 +810,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
800
810
full_span,
801
811
Some ( self . allow_gen_future . clone ( ) ) ,
802
812
) ;
803
- let expr = self . lower_expr_mut ( expr) ;
804
813
let expr_hir_id = expr. hir_id ;
805
814
806
815
// Note that the name of this binding must not be changed to something else because
@@ -924,7 +933,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
924
933
let into_future_expr = self . expr_call_lang_item_fn (
925
934
span,
926
935
hir:: LangItem :: IntoFutureIntoFuture ,
927
- arena_vec ! [ self ; expr] ,
936
+ arena_vec ! [ self ; * expr] ,
928
937
) ;
929
938
930
939
// match <into_future_expr> {
@@ -1554,7 +1563,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
1554
1563
head : & Expr ,
1555
1564
body : & Block ,
1556
1565
opt_label : Option < Label > ,
1557
- _is_await : bool ,
1566
+ is_await : bool ,
1558
1567
) -> hir:: Expr < ' hir > {
1559
1568
let head = self . lower_expr_mut ( head) ;
1560
1569
let pat = self . lower_pat ( pat) ;
@@ -1583,15 +1592,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
1583
1592
let ( iter_pat, iter_pat_nid) =
1584
1593
self . pat_ident_binding_mode ( head_span, iter, hir:: BindingAnnotation :: MUT ) ;
1585
1594
1586
- // `match Iterator::next(&mut iter) { ... }`
1587
1595
let match_expr = {
1588
1596
let iter = self . expr_ident ( head_span, iter, iter_pat_nid) ;
1589
- let ref_mut_iter = self . expr_mut_addr_of ( head_span, iter) ;
1590
- let next_expr = self . expr_call_lang_item_fn (
1591
- head_span,
1592
- hir:: LangItem :: IteratorNext ,
1593
- arena_vec ! [ self ; ref_mut_iter] ,
1594
- ) ;
1597
+ let next_expr = if is_await {
1598
+ // `async_iter_next(unsafe { Pin::new_unchecked(&mut iter) }).await`
1599
+ let future = self . expr_mut_addr_of ( head_span, iter) ;
1600
+ let future = self . arena . alloc ( self . expr_call_lang_item_fn_mut (
1601
+ head_span,
1602
+ hir:: LangItem :: PinNewUnchecked ,
1603
+ arena_vec ! [ self ; future] ,
1604
+ ) ) ;
1605
+ let future = self . expr_unsafe ( future) ;
1606
+ let future = self . expr_call_lang_item_fn (
1607
+ head_span,
1608
+ hir:: LangItem :: AsyncIterNext ,
1609
+ arena_vec ! [ self ; future] ,
1610
+ ) ;
1611
+ let kind = self . make_lowered_await ( head_span, future) ;
1612
+ self . arena . alloc ( hir:: Expr { hir_id : self . next_id ( ) , kind, span : head_span } )
1613
+ } else {
1614
+ // `match Iterator::next(&mut iter) { ... }`
1615
+ let ref_mut_iter = self . expr_mut_addr_of ( head_span, iter) ;
1616
+ self . expr_call_lang_item_fn (
1617
+ head_span,
1618
+ hir:: LangItem :: IteratorNext ,
1619
+ arena_vec ! [ self ; ref_mut_iter] ,
1620
+ )
1621
+ } ;
1595
1622
let arms = arena_vec ! [ self ; none_arm, some_arm] ;
1596
1623
1597
1624
self . expr_match ( head_span, next_expr, arms, hir:: MatchSource :: ForLoopDesugar )
@@ -1613,8 +1640,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
1613
1640
// `mut iter => { ... }`
1614
1641
let iter_arm = self . arm ( iter_pat, loop_expr) ;
1615
1642
1616
- // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1617
- let into_iter_expr = {
1643
+ let into_iter_expr = if is_await {
1644
+ // `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
1645
+ let iter = self . expr_call_lang_item_fn (
1646
+ head_span,
1647
+ hir:: LangItem :: IntoAsyncIterIntoIter ,
1648
+ arena_vec ! [ self ; head] ,
1649
+ ) ;
1650
+ self . arena . alloc ( self . expr_mut_addr_of ( head_span, iter) )
1651
+ } else {
1652
+ // `::std::iter::IntoIterator::into_iter(<head>)`
1618
1653
self . expr_call_lang_item_fn (
1619
1654
head_span,
1620
1655
hir:: LangItem :: IntoIterIntoIter ,
0 commit comments