@@ -286,33 +286,38 @@ impl<'a> InferenceContext<'a> {
286
286
} )
287
287
. intern ( Interner ) ;
288
288
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 ( ) ;
304
305
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 ) ;
307
308
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 ) ;
314
318
315
- ( closure_ty, None )
319
+ ( Some ( closure_id) , closure_ty, None )
320
+ }
316
321
} ;
317
322
318
323
// Eagerly try to relate the closure type with the expected
@@ -321,7 +326,7 @@ impl<'a> InferenceContext<'a> {
321
326
self . deduce_closure_type_from_expectations ( tgt_expr, & ty, & sig_ty, expected) ;
322
327
323
328
// 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) {
325
330
self . infer_top_pat ( * arg_pat, & arg_ty) ;
326
331
}
327
332
@@ -333,16 +338,47 @@ impl<'a> InferenceContext<'a> {
333
338
let prev_resume_yield_tys =
334
339
mem:: replace ( & mut self . resume_yield_tys , resume_yield_tys) ;
335
340
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
+ } ;
339
357
340
358
self . diverges = prev_diverges;
341
359
self . return_ty = prev_ret_ty;
342
360
self . return_coercion = prev_ret_coercion;
343
361
self . resume_yield_tys = prev_resume_yield_tys;
344
362
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
+ }
346
382
}
347
383
Expr :: Call { callee, args, .. } => {
348
384
let callee_ty = self . infer_expr ( * callee, & Expectation :: none ( ) ) ;
0 commit comments