@@ -7,9 +7,8 @@ use rustc_ast::*;
77use rustc_ast_pretty:: pprust:: expr_to_string;
88use rustc_data_structures:: stack:: ensure_sufficient_stack;
99use rustc_errors:: msg;
10- use rustc_hir as hir;
1110use rustc_hir:: def:: { DefKind , Res } ;
12- use rustc_hir:: { HirId , Target , find_attr} ;
11+ use rustc_hir:: { self as hir , HirId , LangItem , Target , find_attr} ;
1312use rustc_middle:: span_bug;
1413use rustc_middle:: ty:: TyCtxt ;
1514use rustc_session:: errors:: report_lit_error;
@@ -359,9 +358,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
359358 GenBlockKind :: Gen => hir:: CoroutineDesugaring :: Gen ,
360359 GenBlockKind :: AsyncGen => hir:: CoroutineDesugaring :: AsyncGen ,
361360 } ;
362- self . make_desugared_coroutine_expr (
361+ return self . make_desugared_coroutine_expr (
363362 * capture_clause,
364363 e. id ,
364+ expr_hir_id,
365365 None ,
366366 * decl_span,
367367 e. span ,
@@ -375,7 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
375375 expr
376376 } )
377377 } ,
378- )
378+ ) ;
379379 }
380380 ExprKind :: Block ( blk, opt_label) => {
381381 // Different from loops, label of block resolves to block id rather than
@@ -813,26 +813,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
813813 & mut self ,
814814 capture_clause : CaptureBy ,
815815 closure_node_id : NodeId ,
816+ closure_hir_id : HirId ,
816817 return_ty : Option < hir:: FnRetTy < ' hir > > ,
817818 fn_decl_span : Span ,
818819 span : Span ,
819820 desugaring_kind : hir:: CoroutineDesugaring ,
820821 coroutine_source : hir:: CoroutineSource ,
821822 body : impl FnOnce ( & mut Self ) -> hir:: Expr < ' hir > ,
822- ) -> hir:: ExprKind < ' hir > {
823+ ) -> hir:: Expr < ' hir > {
823824 let closure_def_id = self . local_def_id ( closure_node_id) ;
824825 let coroutine_kind = hir:: CoroutineKind :: Desugared ( desugaring_kind, coroutine_source) ;
825826
827+ let span = self . lower_span ( span) ;
828+ let unstable_span = self . mark_span_with_reason (
829+ DesugaringKind :: Async ,
830+ span,
831+ Some ( Arc :: clone ( & self . allow_gen_future ) ) ,
832+ ) ;
833+
826834 // The `async` desugaring takes a resume argument and maintains a `task_context`,
827835 // whereas a generator does not.
828836 let ( inputs, params, task_context) : ( & [ _ ] , & [ _ ] , _ ) = match desugaring_kind {
829837 hir:: CoroutineDesugaring :: Async | hir:: CoroutineDesugaring :: AsyncGen => {
830838 // Resume argument type: `ResumeTy`
831- let unstable_span = self . mark_span_with_reason (
832- DesugaringKind :: Async ,
833- self . lower_span ( span) ,
834- Some ( Arc :: clone ( & self . allow_gen_future ) ) ,
835- ) ;
836839 let resume_ty =
837840 self . make_lang_item_qpath ( hir:: LangItem :: ResumeTy , unstable_span, None ) ;
838841 let input_ty = hir:: Ty {
@@ -848,21 +851,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
848851 Ident :: with_dummy_span ( sym:: _task_context) ,
849852 hir:: BindingMode :: MUT ,
850853 ) ;
851- let param = hir:: Param {
852- hir_id : self . next_id ( ) ,
853- pat,
854- ty_span : self . lower_span ( span) ,
855- span : self . lower_span ( span) ,
856- } ;
854+ let param = hir:: Param { hir_id : self . next_id ( ) , pat, ty_span : span, span } ;
857855 let params = arena_vec ! [ self ; param] ;
858856
859857 ( inputs, params, Some ( task_context_hid) )
860858 }
861859 hir:: CoroutineDesugaring :: Gen => ( & [ ] , & [ ] , None ) ,
862860 } ;
863861
864- let output =
865- return_ty. unwrap_or_else ( || hir:: FnRetTy :: DefaultReturn ( self . lower_span ( span) ) ) ;
862+ let output = return_ty. unwrap_or_else ( || hir:: FnRetTy :: DefaultReturn ( span) ) ;
866863
867864 let fn_decl = self . arena . alloc ( hir:: FnDecl {
868865 inputs,
@@ -884,7 +881,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
884881 } ) ;
885882
886883 // `static |<_task_context?>| -> <return_ty> { <body> }`:
887- hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
884+ let coroutine_closure = hir:: ExprKind :: Closure ( self . arena . alloc ( hir:: Closure {
888885 def_id : closure_def_id,
889886 binder : hir:: ClosureBinder :: Default ,
890887 capture_clause : self . lower_capture_clause ( capture_clause) ,
@@ -896,7 +893,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
896893 kind : hir:: ClosureKind :: Coroutine ( coroutine_kind) ,
897894 constness : hir:: Constness :: NotConst ,
898895 explicit_captures : & [ ] ,
899- } ) )
896+ } ) ) ;
897+ let coroutine_closure = hir:: Expr { hir_id : closure_hir_id, kind : coroutine_closure, span } ;
898+
899+ let from_coroutine = match desugaring_kind {
900+ hir:: CoroutineDesugaring :: Async => LangItem :: FutureFromCoroutine ,
901+ hir:: CoroutineDesugaring :: AsyncGen => LangItem :: AsyncIteratorFromCoroutine ,
902+ hir:: CoroutineDesugaring :: Gen => LangItem :: IterFromCoroutine ,
903+ } ;
904+ self . expr_call_lang_item_fn_mut (
905+ unstable_span,
906+ from_coroutine,
907+ arena_vec ! [ self ; coroutine_closure] ,
908+ )
900909 }
901910
902911 /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to
@@ -949,19 +958,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
949958 /// }
950959 /// ```
951960 fn lower_expr_await ( & mut self , await_kw_span : Span , expr : & Expr ) -> hir:: ExprKind < ' hir > {
961+ let full_span = expr. span . to ( await_kw_span) ;
952962 let expr = self . arena . alloc ( self . lower_expr_mut ( expr) ) ;
953- self . make_lowered_await ( await_kw_span, expr, FutureKind :: Future )
963+ self . make_lowered_await ( await_kw_span, full_span , expr, FutureKind :: Future )
954964 }
955965
956966 /// Takes an expr that has already been lowered and generates a desugared await loop around it
957967 fn make_lowered_await (
958968 & mut self ,
959969 await_kw_span : Span ,
970+ // Pass the span separately, as `expr.span` may be a desugaring.
971+ full_span : Span ,
960972 expr : & ' hir hir:: Expr < ' hir > ,
961973 await_kind : FutureKind ,
962974 ) -> hir:: ExprKind < ' hir > {
963- let full_span = expr. span . to ( await_kw_span) ;
964-
965975 let is_async_gen = match self . coroutine_kind {
966976 Some ( hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , _) ) => false ,
967977 Some ( hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: AsyncGen , _) ) => true ,
@@ -972,19 +982,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
972982 // is not accidentally orphaned.
973983 let stmt_id = self . next_id ( ) ;
974984 let expr_err = self . expr (
975- expr . span ,
985+ full_span ,
976986 hir:: ExprKind :: Err ( self . dcx ( ) . emit_err ( AwaitOnlyInAsyncFnAndBlocks {
977987 await_kw_span,
978988 item_span : self . current_item ,
979989 } ) ) ,
980990 ) ;
981991 return hir:: ExprKind :: Block (
982992 self . block_all (
983- expr . span ,
993+ full_span ,
984994 arena_vec ! [ self ; hir:: Stmt {
985995 hir_id: stmt_id,
986996 kind: hir:: StmtKind :: Semi ( expr) ,
987- span: expr . span ,
997+ span: full_span ,
988998 } ] ,
989999 Some ( self . arena . alloc ( expr_err) ) ,
9901000 ) ,
@@ -1643,18 +1653,54 @@ impl<'hir> LoweringContext<'_, 'hir> {
16431653 . emit ( ) ;
16441654 }
16451655
1646- let is_async_gen = match self . coroutine_kind {
1647- Some ( hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Gen , _) ) => false ,
1648- Some ( hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: AsyncGen , _) ) => true ,
1649- Some ( hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , _) ) => {
1650- // Lower to a block `{ EXPR; <error> }` so that the awaited expr
1651- // is not accidentally orphaned.
1656+ let Some ( coroutine_kind) = self . coroutine_kind else {
1657+ let suggestion = self . current_item . map ( |s| s. shrink_to_lo ( ) ) ;
1658+ self . dcx ( ) . emit_err ( YieldInClosure { span, suggestion } ) ;
1659+ self . coroutine_kind = Some ( hir:: CoroutineKind :: Coroutine ( Movability :: Movable ) ) ;
1660+ return hir:: ExprKind :: Yield ( yielded, hir:: YieldSource :: Yield ) ;
1661+ } ;
1662+
1663+ match coroutine_kind {
1664+ // Raw and Gen coroutines, nothing to do.
1665+ hir:: CoroutineKind :: Coroutine ( _)
1666+ | hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Gen , _) => {
1667+ hir:: ExprKind :: Yield ( yielded, hir:: YieldSource :: Yield )
1668+ }
1669+ // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
1670+ // This ensures that we store our resumed `ResumeContext` correctly, and also that
1671+ // the apparent value of the `yield` expression is `()`.
1672+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: AsyncGen , _) => {
1673+ let desugar_span = self . mark_span_with_reason (
1674+ DesugaringKind :: Async ,
1675+ span,
1676+ Some ( Arc :: clone ( & self . allow_async_gen ) ) ,
1677+ ) ;
1678+ let wrapped_yielded = self . expr_call_lang_item_fn (
1679+ desugar_span,
1680+ hir:: LangItem :: AsyncGenReady ,
1681+ std:: slice:: from_ref ( yielded) ,
1682+ ) ;
1683+ let yield_expr = self . arena . alloc (
1684+ self . expr ( span, hir:: ExprKind :: Yield ( wrapped_yielded, hir:: YieldSource :: Yield ) ) ,
1685+ ) ;
1686+
1687+ let Some ( task_context_hid) = self . task_context else {
1688+ unreachable ! ( "use of `await` outside of an async context." ) ;
1689+ } ;
1690+ let task_context_ident = Ident :: with_dummy_span ( sym:: _task_context) ;
1691+ let lhs = self . expr_ident ( desugar_span, task_context_ident, task_context_hid) ;
1692+
1693+ hir:: ExprKind :: Assign ( lhs, yield_expr, self . lower_span ( span) )
1694+ }
1695+ // Lower to a block `{ EXPR; <error> }` so that the awaited expr
1696+ // is not accidentally orphaned.
1697+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , _) => {
16521698 let stmt_id = self . next_id ( ) ;
16531699 let expr_err = self . expr (
16541700 yielded. span ,
16551701 hir:: ExprKind :: Err ( self . dcx ( ) . emit_err ( AsyncCoroutinesNotSupported { span } ) ) ,
16561702 ) ;
1657- return hir:: ExprKind :: Block (
1703+ hir:: ExprKind :: Block (
16581704 self . block_all (
16591705 yielded. span ,
16601706 arena_vec ! [ self ; hir:: Stmt {
@@ -1665,45 +1711,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
16651711 Some ( self . arena . alloc ( expr_err) ) ,
16661712 ) ,
16671713 None ,
1668- ) ;
1669- }
1670- Some ( hir:: CoroutineKind :: Coroutine ( _) ) => false ,
1671- None => {
1672- let suggestion = self . current_item . map ( |s| s. shrink_to_lo ( ) ) ;
1673- self . dcx ( ) . emit_err ( YieldInClosure { span, suggestion } ) ;
1674- self . coroutine_kind = Some ( hir:: CoroutineKind :: Coroutine ( Movability :: Movable ) ) ;
1675-
1676- false
1714+ )
16771715 }
1678- } ;
1679-
1680- if is_async_gen {
1681- // `yield $expr` is transformed into `task_context = yield async_gen_ready($expr)`.
1682- // This ensures that we store our resumed `ResumeContext` correctly, and also that
1683- // the apparent value of the `yield` expression is `()`.
1684- let desugar_span = self . mark_span_with_reason (
1685- DesugaringKind :: Async ,
1686- span,
1687- Some ( Arc :: clone ( & self . allow_async_gen ) ) ,
1688- ) ;
1689- let wrapped_yielded = self . expr_call_lang_item_fn (
1690- desugar_span,
1691- hir:: LangItem :: AsyncGenReady ,
1692- std:: slice:: from_ref ( yielded) ,
1693- ) ;
1694- let yield_expr = self . arena . alloc (
1695- self . expr ( span, hir:: ExprKind :: Yield ( wrapped_yielded, hir:: YieldSource :: Yield ) ) ,
1696- ) ;
1697-
1698- let Some ( task_context_hid) = self . task_context else {
1699- unreachable ! ( "use of `await` outside of an async context." ) ;
1700- } ;
1701- let task_context_ident = Ident :: with_dummy_span ( sym:: _task_context) ;
1702- let lhs = self . expr_ident ( desugar_span, task_context_ident, task_context_hid) ;
1703-
1704- hir:: ExprKind :: Assign ( lhs, yield_expr, self . lower_span ( span) )
1705- } else {
1706- hir:: ExprKind :: Yield ( yielded, hir:: YieldSource :: Yield )
17071716 }
17081717 }
17091718
@@ -1798,7 +1807,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
17981807 ) ) ;
17991808 // `unsafe { ... }`
18001809 let iter = self . arena . alloc ( self . expr_unsafe ( head_span, iter) ) ;
1801- let kind = self . make_lowered_await ( head_span, iter, FutureKind :: AsyncIterator ) ;
1810+ let kind = self . make_lowered_await (
1811+ head_span,
1812+ head_span,
1813+ iter,
1814+ FutureKind :: AsyncIterator ,
1815+ ) ;
18021816 self . arena . alloc ( hir:: Expr { hir_id : self . next_id ( ) , kind, span : head_span } )
18031817 }
18041818 } ;
0 commit comments