@@ -98,6 +98,7 @@ fn fn_sig_for_fn_abi<'tcx>(
98
98
)
99
99
}
100
100
ty:: Coroutine ( did, args, _) => {
101
+ let coroutine_kind = tcx. coroutine_kind ( did) . unwrap ( ) ;
101
102
let sig = args. as_coroutine ( ) . poly_sig ( ) ;
102
103
103
104
let bound_vars = tcx. mk_bound_variable_kinds_from_iter (
@@ -112,74 +113,83 @@ fn fn_sig_for_fn_abi<'tcx>(
112
113
let pin_did = tcx. require_lang_item ( LangItem :: Pin , None ) ;
113
114
let pin_adt_ref = tcx. adt_def ( pin_did) ;
114
115
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
+ }
121
125
} ;
122
126
123
127
let sig = sig. skip_binder ( ) ;
124
128
// The `FnSig` and the `ret_ty` here is for a coroutines main
125
129
// `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) ;
160
157
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)
172
159
}
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
+ }
173
181
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
+ }
183
193
} ;
184
194
185
195
let fn_sig = if let Some ( resume_ty) = resume_ty {
0 commit comments