@@ -72,7 +72,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7272 opt_kind : Option < ty:: ClosureKind > ,
7373 expected_sig : Option < ExpectedSig < ' tcx > > ,
7474 ) -> Ty < ' tcx > {
75- let body = self . tcx . hir ( ) . body ( closure. body ) ;
75+ let tcx = self . tcx ;
76+ let body = tcx. hir ( ) . body ( closure. body ) ;
7677
7778 trace ! ( "decl = {:#?}" , closure. fn_decl) ;
7879 let expr_def_id = closure. def_id ;
@@ -83,81 +84,151 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8384
8485 debug ! ( ?bound_sig, ?liberated_sig) ;
8586
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+
86142 let mut fcx = FnCtxt :: new ( self , self . param_env , closure. def_id ) ;
87- let coroutine_types = check_fn (
143+ check_fn (
88144 & mut fcx,
89145 liberated_sig,
146+ coroutine_types,
90147 closure. fn_decl ,
91148 expr_def_id,
92149 body,
93- Some ( closure. kind ) ,
94150 // Closure "rust-call" ABI doesn't support unsized params
95151 false ,
96152 ) ;
97153
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 ( ) ) ) ;
102156
103157 let tupled_upvars_ty = self . next_root_ty_var ( TypeVariableOrigin {
104158 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,
134160 } ) ;
135161
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+ } ) ;
140176
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+ ) ;
149200
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+ ) ;
159228
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+ }
161232 }
162233
163234 /// Given the expected type, figures out what it can about this closure we
0 commit comments