@@ -98,6 +98,7 @@ fn fn_sig_for_fn_abi<'tcx>(
9898 )
9999 }
100100 ty:: Coroutine ( did, args, _) => {
101+ let coroutine_kind = tcx. coroutine_kind ( did) ;
101102 let sig = args. as_coroutine ( ) . poly_sig ( ) ;
102103
103104 let bound_vars = tcx. mk_bound_variable_kinds_from_iter (
@@ -112,74 +113,83 @@ fn fn_sig_for_fn_abi<'tcx>(
112113 let pin_did = tcx. require_lang_item ( LangItem :: Pin , None ) ;
113114 let pin_adt_ref = tcx. adt_def ( pin_did) ;
114115 let pin_args = tcx. mk_args ( & [ env_ty. into ( ) ] ) ;
115- let env_ty = if tcx. coroutine_is_gen ( did) {
116- // Iterator::next doesn't accept a pinned argument,
117- // unlike for all other coroutine kinds.
118- env_ty
119- } else {
120- Ty :: new_adt ( tcx, pin_adt_ref, pin_args)
116+ let env_ty = match coroutine_kind {
117+ hir:: CoroutineKind :: Gen ( _) => {
118+ // Iterator::next doesn't accept a pinned argument,
119+ // unlike for all other coroutine kinds.
120+ env_ty
121+ }
122+ hir:: CoroutineKind :: Async | hir:: CoroutineKind :: Coroutine => {
123+ Ty :: new_adt ( tcx, pin_adt_ref, pin_args)
124+ }
121125 } ;
122126
123127 let sig = sig. skip_binder ( ) ;
124128 // The `FnSig` and the `ret_ty` here is for a coroutines main
125129 // `Coroutine::resume(...) -> CoroutineState` function in case we
126- // have an ordinary coroutine, or the `Future::poll(...) -> Poll`
127- // function in case this is a special coroutine backing an async construct.
128- let ( resume_ty, ret_ty) = if tcx. coroutine_is_async ( did) {
129- // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
130- assert_eq ! ( sig. yield_ty, tcx. types. unit) ;
131-
132- let poll_did = tcx. require_lang_item ( LangItem :: Poll , None ) ;
133- let poll_adt_ref = tcx. adt_def ( poll_did) ;
134- let poll_args = tcx. mk_args ( & [ sig. return_ty . into ( ) ] ) ;
135- let ret_ty = Ty :: new_adt ( tcx, poll_adt_ref, poll_args) ;
136-
137- // We have to replace the `ResumeTy` that is used for type and borrow checking
138- // with `&mut Context<'_>` which is used in codegen.
139- #[ cfg( debug_assertions) ]
140- {
141- if let ty:: Adt ( resume_ty_adt, _) = sig. resume_ty . kind ( ) {
142- let expected_adt =
143- tcx. adt_def ( tcx. require_lang_item ( LangItem :: ResumeTy , None ) ) ;
144- assert_eq ! ( * resume_ty_adt, expected_adt) ;
145- } else {
146- panic ! ( "expected `ResumeTy`, found `{:?}`" , sig. resume_ty) ;
147- } ;
148- }
149- let context_mut_ref = Ty :: new_task_context ( tcx) ;
150-
151- ( Some ( context_mut_ref) , ret_ty)
152- } else if tcx. coroutine_is_gen ( did) {
153- // The signature should be `Iterator::next(_) -> Option<Yield>`
154- let option_did = tcx. require_lang_item ( LangItem :: Option , None ) ;
155- let option_adt_ref = tcx. adt_def ( option_did) ;
156- let option_args = tcx. mk_args ( & [ sig. yield_ty . into ( ) ] ) ;
157- let ret_ty = Ty :: new_adt ( tcx, option_adt_ref, option_args) ;
158-
159- assert_eq ! ( sig. return_ty, tcx. types. unit) ;
130+ // have an ordinary coroutine, the `Future::poll(...) -> Poll`
131+ // function in case this is a special coroutine backing an async construct
132+ // or the `Iterator::next(...) -> Option` function in case this is a
133+ // special coroutine backing a gen construct.
134+ let ( resume_ty, ret_ty) = match coroutine_kind {
135+ hir:: CoroutineKind :: Async ( _) => {
136+ // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
137+ assert_eq ! ( sig. yield_ty, tcx. types. unit) ;
138+
139+ let poll_did = tcx. require_lang_item ( LangItem :: Poll , None ) ;
140+ let poll_adt_ref = tcx. adt_def ( poll_did) ;
141+ let poll_args = tcx. mk_args ( & [ sig. return_ty . into ( ) ] ) ;
142+ let ret_ty = Ty :: new_adt ( tcx, poll_adt_ref, poll_args) ;
143+
144+ // We have to replace the `ResumeTy` that is used for type and borrow checking
145+ // with `&mut Context<'_>` which is used in codegen.
146+ #[ cfg( debug_assertions) ]
147+ {
148+ if let ty:: Adt ( resume_ty_adt, _) = sig. resume_ty . kind ( ) {
149+ let expected_adt =
150+ tcx. adt_def ( tcx. require_lang_item ( LangItem :: ResumeTy , None ) ) ;
151+ assert_eq ! ( * resume_ty_adt, expected_adt) ;
152+ } else {
153+ panic ! ( "expected `ResumeTy`, found `{:?}`" , sig. resume_ty) ;
154+ } ;
155+ }
156+ let context_mut_ref = Ty :: new_task_context ( tcx) ;
160157
161- // We have to replace the `ResumeTy` that is used for type and borrow checking
162- // with `()` which is used in codegen.
163- #[ cfg( debug_assertions) ]
164- {
165- if let ty:: Adt ( resume_ty_adt, _) = sig. resume_ty . kind ( ) {
166- let expected_adt =
167- tcx. adt_def ( tcx. require_lang_item ( LangItem :: ResumeTy , None ) ) ;
168- assert_eq ! ( * resume_ty_adt, expected_adt) ;
169- } else {
170- panic ! ( "expected `ResumeTy`, found `{:?}`" , sig. resume_ty) ;
171- } ;
158+ ( Some ( context_mut_ref) , ret_ty)
172159 }
160+ hir:: CoroutineKind :: Gen ( _) => {
161+ // The signature should be `Iterator::next(_) -> Option<Yield>`
162+ let option_did = tcx. require_lang_item ( LangItem :: Option , None ) ;
163+ let option_adt_ref = tcx. adt_def ( option_did) ;
164+ let option_args = tcx. mk_args ( & [ sig. yield_ty . into ( ) ] ) ;
165+ let ret_ty = Ty :: new_adt ( tcx, option_adt_ref, option_args) ;
166+
167+ assert_eq ! ( sig. return_ty, tcx. types. unit) ;
168+
169+ // We have to replace the `ResumeTy` that is used for type and borrow checking
170+ // with `()` which is used in codegen.
171+ #[ cfg( debug_assertions) ]
172+ {
173+ if let ty:: Adt ( resume_ty_adt, _) = sig. resume_ty . kind ( ) {
174+ let expected_adt =
175+ tcx. adt_def ( tcx. require_lang_item ( LangItem :: ResumeTy , None ) ) ;
176+ assert_eq ! ( * resume_ty_adt, expected_adt) ;
177+ } else {
178+ panic ! ( "expected `ResumeTy`, found `{:?}`" , sig. resume_ty) ;
179+ } ;
180+ }
173181
174- ( None , ret_ty)
175- } else {
176- // The signature should be `Coroutine::resume(_, Resume) -> CoroutineState<Yield, Return>`
177- let state_did = tcx. require_lang_item ( LangItem :: CoroutineState , None ) ;
178- let state_adt_ref = tcx. adt_def ( state_did) ;
179- let state_args = tcx. mk_args ( & [ sig. yield_ty . into ( ) , sig. return_ty . into ( ) ] ) ;
180- let ret_ty = Ty :: new_adt ( tcx, state_adt_ref, state_args) ;
181-
182- ( Some ( sig. resume_ty ) , ret_ty)
182+ ( None , ret_ty)
183+ }
184+ hir:: CoroutineKind :: Coroutine => {
185+ // The signature should be `Coroutine::resume(_, Resume) -> CoroutineState<Yield, Return>`
186+ let state_did = tcx. require_lang_item ( LangItem :: CoroutineState , None ) ;
187+ let state_adt_ref = tcx. adt_def ( state_did) ;
188+ let state_args = tcx. mk_args ( & [ sig. yield_ty . into ( ) , sig. return_ty . into ( ) ] ) ;
189+ let ret_ty = Ty :: new_adt ( tcx, state_adt_ref, state_args) ;
190+
191+ ( Some ( sig. resume_ty ) , ret_ty)
192+ }
183193 } ;
184194
185195 let fn_sig = if let Some ( resume_ty) = resume_ty {
0 commit comments