@@ -72,7 +72,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
72
72
opt_kind : Option < ty:: ClosureKind > ,
73
73
expected_sig : Option < ExpectedSig < ' tcx > > ,
74
74
) -> Ty < ' tcx > {
75
- let body = self . tcx . hir ( ) . body ( closure. body ) ;
75
+ let tcx = self . tcx ;
76
+ let body = tcx. hir ( ) . body ( closure. body ) ;
76
77
77
78
trace ! ( "decl = {:#?}" , closure. fn_decl) ;
78
79
let expr_def_id = closure. def_id ;
@@ -83,81 +84,151 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
83
84
84
85
debug ! ( ?bound_sig, ?liberated_sig) ;
85
86
87
+ // FIXME: We could probably actually just unify this further --
88
+ // instead of having a `FnSig` and a `Option<CoroutineTypes>`,
89
+ // we can have a `ClosureSignature { Coroutine { .. }, Closure { .. } }`,
90
+ // similar to how `ty::GenSig` is a distinct data structure.
91
+ let coroutine_types = match closure. kind {
92
+ hir:: ClosureKind :: Closure => None ,
93
+ hir:: ClosureKind :: Coroutine ( kind) => {
94
+ let yield_ty = match kind {
95
+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Gen , _)
96
+ | hir:: CoroutineKind :: Coroutine ( _) => {
97
+ let yield_ty = self . next_ty_var ( TypeVariableOrigin {
98
+ kind : TypeVariableOriginKind :: TypeInference ,
99
+ span : expr_span,
100
+ } ) ;
101
+ self . require_type_is_sized ( yield_ty, expr_span, traits:: SizedYieldType ) ;
102
+ yield_ty
103
+ }
104
+ // HACK(-Ztrait-solver=next): In the *old* trait solver, we must eagerly
105
+ // guide inference on the yield type so that we can handle `AsyncIterator`
106
+ // in this block in projection correctly. In the new trait solver, it is
107
+ // not a problem.
108
+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: AsyncGen , _) => {
109
+ let yield_ty = self . next_ty_var ( TypeVariableOrigin {
110
+ kind : TypeVariableOriginKind :: TypeInference ,
111
+ span : expr_span,
112
+ } ) ;
113
+ self . require_type_is_sized ( yield_ty, expr_span, traits:: SizedYieldType ) ;
114
+
115
+ Ty :: new_adt (
116
+ tcx,
117
+ tcx. adt_def (
118
+ tcx. require_lang_item ( hir:: LangItem :: Poll , Some ( expr_span) ) ,
119
+ ) ,
120
+ tcx. mk_args ( & [ Ty :: new_adt (
121
+ tcx,
122
+ tcx. adt_def (
123
+ tcx. require_lang_item ( hir:: LangItem :: Option , Some ( expr_span) ) ,
124
+ ) ,
125
+ tcx. mk_args ( & [ yield_ty. into ( ) ] ) ,
126
+ )
127
+ . into ( ) ] ) ,
128
+ )
129
+ }
130
+ hir:: CoroutineKind :: Desugared ( hir:: CoroutineDesugaring :: Async , _) => {
131
+ tcx. types . unit
132
+ }
133
+ } ;
134
+
135
+ // Resume type defaults to `()` if the coroutine has no argument.
136
+ let resume_ty = liberated_sig. inputs ( ) . get ( 0 ) . copied ( ) . unwrap_or ( tcx. types . unit ) ;
137
+
138
+ Some ( CoroutineTypes { resume_ty, yield_ty } )
139
+ }
140
+ } ;
141
+
86
142
let mut fcx = FnCtxt :: new ( self , self . param_env , closure. def_id ) ;
87
- let coroutine_types = check_fn (
143
+ check_fn (
88
144
& mut fcx,
89
145
liberated_sig,
146
+ coroutine_types,
90
147
closure. fn_decl ,
91
148
expr_def_id,
92
149
body,
93
- Some ( closure. kind ) ,
94
150
// Closure "rust-call" ABI doesn't support unsized params
95
151
false ,
96
152
) ;
97
153
98
- let parent_args = GenericArgs :: identity_for_item (
99
- self . tcx ,
100
- self . tcx . typeck_root_def_id ( expr_def_id. to_def_id ( ) ) ,
101
- ) ;
154
+ let parent_args =
155
+ GenericArgs :: identity_for_item ( tcx, tcx. typeck_root_def_id ( expr_def_id. to_def_id ( ) ) ) ;
102
156
103
157
let tupled_upvars_ty = self . next_root_ty_var ( TypeVariableOrigin {
104
158
kind : TypeVariableOriginKind :: ClosureSynthetic ,
105
- span : self . tcx . def_span ( expr_def_id) ,
106
- } ) ;
107
-
108
- if let Some ( CoroutineTypes { resume_ty, yield_ty, interior } ) = coroutine_types {
109
- let coroutine_args = ty:: CoroutineArgs :: new (
110
- self . tcx ,
111
- ty:: CoroutineArgsParts {
112
- parent_args,
113
- resume_ty,
114
- yield_ty,
115
- return_ty : liberated_sig. output ( ) ,
116
- witness : interior,
117
- tupled_upvars_ty,
118
- } ,
119
- ) ;
120
-
121
- return Ty :: new_coroutine ( self . tcx , expr_def_id. to_def_id ( ) , coroutine_args. args ) ;
122
- }
123
-
124
- // Tuple up the arguments and insert the resulting function type into
125
- // the `closures` table.
126
- let sig = bound_sig. map_bound ( |sig| {
127
- self . tcx . mk_fn_sig (
128
- [ Ty :: new_tup ( self . tcx , sig. inputs ( ) ) ] ,
129
- sig. output ( ) ,
130
- sig. c_variadic ,
131
- sig. unsafety ,
132
- sig. abi ,
133
- )
159
+ span : expr_span,
134
160
} ) ;
135
161
136
- debug ! ( ?sig, ?opt_kind) ;
137
-
138
- let closure_kind_ty = match opt_kind {
139
- Some ( kind) => Ty :: from_closure_kind ( self . tcx , kind) ,
162
+ match closure. kind {
163
+ hir:: ClosureKind :: Closure => {
164
+ assert_eq ! ( coroutine_types, None ) ;
165
+ // Tuple up the arguments and insert the resulting function type into
166
+ // the `closures` table.
167
+ let sig = bound_sig. map_bound ( |sig| {
168
+ tcx. mk_fn_sig (
169
+ [ Ty :: new_tup ( tcx, sig. inputs ( ) ) ] ,
170
+ sig. output ( ) ,
171
+ sig. c_variadic ,
172
+ sig. unsafety ,
173
+ sig. abi ,
174
+ )
175
+ } ) ;
140
176
141
- // Create a type variable (for now) to represent the closure kind.
142
- // It will be unified during the upvar inference phase (`upvar.rs`)
143
- None => self . next_root_ty_var ( TypeVariableOrigin {
144
- // FIXME(eddyb) distinguish closure kind inference variables from the rest.
145
- kind : TypeVariableOriginKind :: ClosureSynthetic ,
146
- span : expr_span,
147
- } ) ,
148
- } ;
177
+ debug ! ( ?sig, ?opt_kind) ;
178
+
179
+ let closure_kind_ty = match opt_kind {
180
+ Some ( kind) => Ty :: from_closure_kind ( tcx, kind) ,
181
+
182
+ // Create a type variable (for now) to represent the closure kind.
183
+ // It will be unified during the upvar inference phase (`upvar.rs`)
184
+ None => self . next_root_ty_var ( TypeVariableOrigin {
185
+ // FIXME(eddyb) distinguish closure kind inference variables from the rest.
186
+ kind : TypeVariableOriginKind :: ClosureSynthetic ,
187
+ span : expr_span,
188
+ } ) ,
189
+ } ;
190
+
191
+ let closure_args = ty:: ClosureArgs :: new (
192
+ tcx,
193
+ ty:: ClosureArgsParts {
194
+ parent_args,
195
+ closure_kind_ty,
196
+ closure_sig_as_fn_ptr_ty : Ty :: new_fn_ptr ( tcx, sig) ,
197
+ tupled_upvars_ty,
198
+ } ,
199
+ ) ;
149
200
150
- let closure_args = ty:: ClosureArgs :: new (
151
- self . tcx ,
152
- ty:: ClosureArgsParts {
153
- parent_args,
154
- closure_kind_ty,
155
- closure_sig_as_fn_ptr_ty : Ty :: new_fn_ptr ( self . tcx , sig) ,
156
- tupled_upvars_ty,
157
- } ,
158
- ) ;
201
+ Ty :: new_closure ( tcx, expr_def_id. to_def_id ( ) , closure_args. args )
202
+ }
203
+ hir:: ClosureKind :: Coroutine ( _) => {
204
+ let Some ( CoroutineTypes { resume_ty, yield_ty } ) = coroutine_types else {
205
+ bug ! ( "expected coroutine to have yield/resume types" ) ;
206
+ } ;
207
+ let interior = fcx. next_ty_var ( TypeVariableOrigin {
208
+ kind : TypeVariableOriginKind :: MiscVariable ,
209
+ span : body. value . span ,
210
+ } ) ;
211
+ fcx. deferred_coroutine_interiors . borrow_mut ( ) . push ( (
212
+ expr_def_id,
213
+ body. id ( ) ,
214
+ interior,
215
+ ) ) ;
216
+
217
+ let coroutine_args = ty:: CoroutineArgs :: new (
218
+ tcx,
219
+ ty:: CoroutineArgsParts {
220
+ parent_args,
221
+ resume_ty,
222
+ yield_ty,
223
+ return_ty : liberated_sig. output ( ) ,
224
+ witness : interior,
225
+ tupled_upvars_ty,
226
+ } ,
227
+ ) ;
159
228
160
- Ty :: new_closure ( self . tcx , expr_def_id. to_def_id ( ) , closure_args. args )
229
+ Ty :: new_coroutine ( tcx, expr_def_id. to_def_id ( ) , coroutine_args. args )
230
+ }
231
+ }
161
232
}
162
233
163
234
/// Given the expected type, figures out what it can about this closure we
0 commit comments