@@ -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,26 +84,79 @@ 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 ) ,
159
+ span : expr_span ,
106
160
} ) ;
107
161
108
162
match closure. kind {
@@ -111,8 +165,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
111
165
// Tuple up the arguments and insert the resulting function type into
112
166
// the `closures` table.
113
167
let sig = bound_sig. map_bound ( |sig| {
114
- self . tcx . mk_fn_sig (
115
- [ Ty :: new_tup ( self . tcx , sig. inputs ( ) ) ] ,
168
+ tcx. mk_fn_sig (
169
+ [ Ty :: new_tup ( tcx, sig. inputs ( ) ) ] ,
116
170
sig. output ( ) ,
117
171
sig. c_variadic ,
118
172
sig. unsafety ,
@@ -123,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
123
177
debug ! ( ?sig, ?opt_kind) ;
124
178
125
179
let closure_kind_ty = match opt_kind {
126
- Some ( kind) => Ty :: from_closure_kind ( self . tcx , kind) ,
180
+ Some ( kind) => Ty :: from_closure_kind ( tcx, kind) ,
127
181
128
182
// Create a type variable (for now) to represent the closure kind.
129
183
// It will be unified during the upvar inference phase (`upvar.rs`)
@@ -135,16 +189,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
135
189
} ;
136
190
137
191
let closure_args = ty:: ClosureArgs :: new (
138
- self . tcx ,
192
+ tcx,
139
193
ty:: ClosureArgsParts {
140
194
parent_args,
141
195
closure_kind_ty,
142
- closure_sig_as_fn_ptr_ty : Ty :: new_fn_ptr ( self . tcx , sig) ,
196
+ closure_sig_as_fn_ptr_ty : Ty :: new_fn_ptr ( tcx, sig) ,
143
197
tupled_upvars_ty,
144
198
} ,
145
199
) ;
146
200
147
- Ty :: new_closure ( self . tcx , expr_def_id. to_def_id ( ) , closure_args. args )
201
+ Ty :: new_closure ( tcx, expr_def_id. to_def_id ( ) , closure_args. args )
148
202
}
149
203
hir:: ClosureKind :: Coroutine ( _) => {
150
204
let Some ( CoroutineTypes { resume_ty, yield_ty } ) = coroutine_types else {
@@ -161,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
161
215
) ) ;
162
216
163
217
let coroutine_args = ty:: CoroutineArgs :: new (
164
- self . tcx ,
218
+ tcx,
165
219
ty:: CoroutineArgsParts {
166
220
parent_args,
167
221
resume_ty,
@@ -172,7 +226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
172
226
} ,
173
227
) ;
174
228
175
- Ty :: new_coroutine ( self . tcx , expr_def_id. to_def_id ( ) , coroutine_args. args )
229
+ Ty :: new_coroutine ( tcx, expr_def_id. to_def_id ( ) , coroutine_args. args )
176
230
}
177
231
}
178
232
}
0 commit comments