@@ -286,33 +286,38 @@ impl<'a> InferenceContext<'a> {
286286 } )
287287 . intern ( Interner ) ;
288288
289- let ( ty, resume_yield_tys) = if matches ! ( closure_kind, ClosureKind :: Generator ( _) ) {
290- // FIXME: report error when there are more than 1 parameter.
291- let resume_ty = match sig_tys. first ( ) {
292- // When `sig_tys.len() == 1` the first type is the return type, not the
293- // first parameter type.
294- Some ( ty) if sig_tys. len ( ) > 1 => ty. clone ( ) ,
295- _ => self . result . standard_types . unit . clone ( ) ,
296- } ;
297- let yield_ty = self . table . new_type_var ( ) ;
298-
299- let subst = TyBuilder :: subst_for_generator ( self . db , self . owner )
300- . push ( resume_ty. clone ( ) )
301- . push ( yield_ty. clone ( ) )
302- . push ( ret_ty. clone ( ) )
303- . build ( ) ;
289+ let ( closure_id, ty, resume_yield_tys) = match closure_kind {
290+ ClosureKind :: Generator ( _) => {
291+ // FIXME: report error when there are more than 1 parameter.
292+ let resume_ty = match sig_tys. first ( ) {
293+ // When `sig_tys.len() == 1` the first type is the return type, not the
294+ // first parameter type.
295+ Some ( ty) if sig_tys. len ( ) > 1 => ty. clone ( ) ,
296+ _ => self . result . standard_types . unit . clone ( ) ,
297+ } ;
298+ let yield_ty = self . table . new_type_var ( ) ;
299+
300+ let subst = TyBuilder :: subst_for_generator ( self . db , self . owner )
301+ . push ( resume_ty. clone ( ) )
302+ . push ( yield_ty. clone ( ) )
303+ . push ( ret_ty. clone ( ) )
304+ . build ( ) ;
304305
305- let generator_id = self . db . intern_generator ( ( self . owner , tgt_expr) ) . into ( ) ;
306- let generator_ty = TyKind :: Generator ( generator_id, subst) . intern ( Interner ) ;
306+ let generator_id = self . db . intern_generator ( ( self . owner , tgt_expr) ) . into ( ) ;
307+ let generator_ty = TyKind :: Generator ( generator_id, subst) . intern ( Interner ) ;
307308
308- ( generator_ty, Some ( ( resume_ty, yield_ty) ) )
309- } else {
310- let closure_id = self . db . intern_closure ( ( self . owner , tgt_expr) ) . into ( ) ;
311- let closure_ty =
312- TyKind :: Closure ( closure_id, Substitution :: from1 ( Interner , sig_ty. clone ( ) ) )
313- . intern ( Interner ) ;
309+ ( None , generator_ty, Some ( ( resume_ty, yield_ty) ) )
310+ }
311+ ClosureKind :: Async | ClosureKind :: Closure => {
312+ let closure_id = self . db . intern_closure ( ( self . owner , tgt_expr) ) . into ( ) ;
313+ let closure_ty = TyKind :: Closure (
314+ closure_id,
315+ Substitution :: from1 ( Interner , sig_ty. clone ( ) ) ,
316+ )
317+ . intern ( Interner ) ;
314318
315- ( closure_ty, None )
319+ ( Some ( closure_id) , closure_ty, None )
320+ }
316321 } ;
317322
318323 // Eagerly try to relate the closure type with the expected
@@ -321,7 +326,7 @@ impl<'a> InferenceContext<'a> {
321326 self . deduce_closure_type_from_expectations ( tgt_expr, & ty, & sig_ty, expected) ;
322327
323328 // Now go through the argument patterns
324- for ( arg_pat, arg_ty) in args. iter ( ) . zip ( sig_tys) {
329+ for ( arg_pat, arg_ty) in args. iter ( ) . zip ( & sig_tys) {
325330 self . infer_top_pat ( * arg_pat, & arg_ty) ;
326331 }
327332
@@ -333,16 +338,47 @@ impl<'a> InferenceContext<'a> {
333338 let prev_resume_yield_tys =
334339 mem:: replace ( & mut self . resume_yield_tys , resume_yield_tys) ;
335340
336- self . with_breakable_ctx ( BreakableKind :: Border , None , None , |this| {
337- this. infer_return ( * body) ;
338- } ) ;
341+ let ( breaks, ( ) ) =
342+ self . with_breakable_ctx ( BreakableKind :: Border , None , None , |this| {
343+ this. infer_return ( * body) ;
344+ } ) ;
345+
346+ let inner_ty = if matches ! ( closure_kind, ClosureKind :: Async ) {
347+ // Use the first type parameter as the output type of future.
348+ // existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
349+ let impl_trait_id =
350+ crate :: ImplTraitId :: AsyncBlockTypeImplTrait ( self . owner , * body) ;
351+ let opaque_ty_id = self . db . intern_impl_trait_id ( impl_trait_id) . into ( ) ;
352+ TyKind :: OpaqueType ( opaque_ty_id, Substitution :: from1 ( Interner , ret_ty. clone ( ) ) )
353+ . intern ( Interner )
354+ } else {
355+ ret_ty. clone ( )
356+ } ;
339357
340358 self . diverges = prev_diverges;
341359 self . return_ty = prev_ret_ty;
342360 self . return_coercion = prev_ret_coercion;
343361 self . resume_yield_tys = prev_resume_yield_tys;
344362
345- ty
363+ sig_tys. pop ( ) ;
364+ sig_tys. push ( inner_ty) ;
365+
366+ let sig_ty = TyKind :: Function ( FnPointer {
367+ num_binders : 0 ,
368+ sig : FnSig { abi : ( ) , safety : chalk_ir:: Safety :: Safe , variadic : false } ,
369+ substitution : FnSubst (
370+ Substitution :: from_iter ( Interner , sig_tys. clone ( ) ) . shifted_in ( Interner ) ,
371+ ) ,
372+ } )
373+ . intern ( Interner ) ;
374+
375+ match closure_id {
376+ Some ( closure_id) => {
377+ TyKind :: Closure ( closure_id, Substitution :: from1 ( Interner , sig_ty. clone ( ) ) )
378+ . intern ( Interner )
379+ }
380+ None => ty,
381+ }
346382 }
347383 Expr :: Call { callee, args, .. } => {
348384 let callee_ty = self . infer_expr ( * callee, & Expectation :: none ( ) ) ;
0 commit comments