@@ -337,7 +337,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
337337 ) ,
338338 ExprKind :: Try ( sub_expr) => self . lower_expr_try ( e. span , sub_expr) ,
339339
340- ExprKind :: Paren ( _) | ExprKind :: ForLoop { .. } => {
340+ ExprKind :: Paren ( _) | ExprKind :: ForLoop { .. } => {
341341 unreachable ! ( "already handled" )
342342 }
343343
@@ -871,6 +871,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
871871 /// }
872872 /// ```
873873 fn lower_expr_await ( & mut self , await_kw_span : Span , expr : & Expr ) -> hir:: ExprKind < ' hir > {
874+ let expr = self . lower_expr_mut ( expr) ;
875+ self . make_lowered_await ( await_kw_span, & expr)
876+ }
877+
878+ /// Takes an expr that has already been lowered and generates a desugared await loop around it
879+ fn make_lowered_await (
880+ & mut self ,
881+ await_kw_span : Span ,
882+ expr : & hir:: Expr < ' hir > ,
883+ ) -> hir:: ExprKind < ' hir > {
874884 let full_span = expr. span . to ( await_kw_span) ;
875885
876886 let is_async_gen = match self . coroutine_kind {
@@ -890,7 +900,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
890900 full_span,
891901 Some ( self . allow_gen_future . clone ( ) ) ,
892902 ) ;
893- let expr = self . lower_expr_mut ( expr) ;
894903 let expr_hir_id = expr. hir_id ;
895904
896905 // Note that the name of this binding must not be changed to something else because
@@ -1021,7 +1030,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10211030 let into_future_expr = self . expr_call_lang_item_fn (
10221031 span,
10231032 hir:: LangItem :: IntoFutureIntoFuture ,
1024- arena_vec ! [ self ; expr] ,
1033+ arena_vec ! [ self ; * expr] ,
10251034 ) ;
10261035
10271036 // match <into_future_expr> {
@@ -1670,7 +1679,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
16701679 head : & Expr ,
16711680 body : & Block ,
16721681 opt_label : Option < Label > ,
1673- _is_await : bool ,
1682+ is_await : bool ,
16741683 ) -> hir:: Expr < ' hir > {
16751684 let head = self . lower_expr_mut ( head) ;
16761685 let pat = self . lower_pat ( pat) ;
@@ -1699,15 +1708,33 @@ impl<'hir> LoweringContext<'_, 'hir> {
16991708 let ( iter_pat, iter_pat_nid) =
17001709 self . pat_ident_binding_mode ( head_span, iter, hir:: BindingAnnotation :: MUT ) ;
17011710
1702- // `match Iterator::next(&mut iter) { ... }`
17031711 let match_expr = {
17041712 let iter = self . expr_ident ( head_span, iter, iter_pat_nid) ;
1705- let ref_mut_iter = self . expr_mut_addr_of ( head_span, iter) ;
1706- let next_expr = self . expr_call_lang_item_fn (
1707- head_span,
1708- hir:: LangItem :: IteratorNext ,
1709- arena_vec ! [ self ; ref_mut_iter] ,
1710- ) ;
1713+ let next_expr = if is_await {
1714+ // `async_iter_next(unsafe { Pin::new_unchecked(&mut iter) }).await`
1715+ let future = self . expr_mut_addr_of ( head_span, iter) ;
1716+ let future = self . arena . alloc ( self . expr_call_lang_item_fn_mut (
1717+ head_span,
1718+ hir:: LangItem :: PinNewUnchecked ,
1719+ arena_vec ! [ self ; future] ,
1720+ ) ) ;
1721+ let future = self . expr_unsafe ( future) ;
1722+ let future = self . expr_call_lang_item_fn (
1723+ head_span,
1724+ hir:: LangItem :: AsyncIterNext ,
1725+ arena_vec ! [ self ; future] ,
1726+ ) ;
1727+ let kind = self . make_lowered_await ( head_span, future) ;
1728+ self . arena . alloc ( hir:: Expr { hir_id : self . next_id ( ) , kind, span : head_span } )
1729+ } else {
1730+ // `match Iterator::next(&mut iter) { ... }`
1731+ let ref_mut_iter = self . expr_mut_addr_of ( head_span, iter) ;
1732+ self . expr_call_lang_item_fn (
1733+ head_span,
1734+ hir:: LangItem :: IteratorNext ,
1735+ arena_vec ! [ self ; ref_mut_iter] ,
1736+ )
1737+ } ;
17111738 let arms = arena_vec ! [ self ; none_arm, some_arm] ;
17121739
17131740 self . expr_match ( head_span, next_expr, arms, hir:: MatchSource :: ForLoopDesugar )
@@ -1729,8 +1756,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
17291756 // `mut iter => { ... }`
17301757 let iter_arm = self . arm ( iter_pat, loop_expr) ;
17311758
1732- // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
1733- let into_iter_expr = {
1759+ let into_iter_expr = if is_await {
1760+ // `::core::async_iter::IntoAsyncIterator::into_async_iter(<head>)`
1761+ let iter = self . expr_call_lang_item_fn (
1762+ head_span,
1763+ hir:: LangItem :: IntoAsyncIterIntoIter ,
1764+ arena_vec ! [ self ; head] ,
1765+ ) ;
1766+ self . arena . alloc ( self . expr_mut_addr_of ( head_span, iter) )
1767+ } else {
1768+ // `::std::iter::IntoIterator::into_iter(<head>)`
17341769 self . expr_call_lang_item_fn (
17351770 head_span,
17361771 hir:: LangItem :: IntoIterIntoIter ,
0 commit comments