@@ -162,35 +162,7 @@ impl<'a> InferenceContext<'a> {
162162 . 1
163163 }
164164 Expr :: Async { id, statements, tail } => {
165- let ret_ty = self . table . new_type_var ( ) ;
166- let prev_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
167- let prev_ret_ty = mem:: replace ( & mut self . return_ty , ret_ty. clone ( ) ) ;
168- let prev_ret_coercion =
169- mem:: replace ( & mut self . return_coercion , Some ( CoerceMany :: new ( ret_ty. clone ( ) ) ) ) ;
170-
171- let ( _, inner_ty) =
172- self . with_breakable_ctx ( BreakableKind :: Border , None , None , |this| {
173- this. infer_block (
174- tgt_expr,
175- * id,
176- statements,
177- * tail,
178- None ,
179- & Expectation :: has_type ( ret_ty) ,
180- )
181- } ) ;
182-
183- self . diverges = prev_diverges;
184- self . return_ty = prev_ret_ty;
185- self . return_coercion = prev_ret_coercion;
186-
187- // Use the first type parameter as the output type of future.
188- // existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
189- let impl_trait_id =
190- crate :: ImplTraitId :: AsyncBlockTypeImplTrait ( self . owner , tgt_expr) ;
191- let opaque_ty_id = self . db . intern_impl_trait_id ( impl_trait_id) . into ( ) ;
192- TyKind :: OpaqueType ( opaque_ty_id, Substitution :: from1 ( Interner , inner_ty) )
193- . intern ( Interner )
165+ self . infer_async_block ( tgt_expr, id, statements, tail)
194166 }
195167 & Expr :: Loop { body, label } => {
196168 // FIXME: should be:
@@ -260,18 +232,7 @@ impl<'a> InferenceContext<'a> {
260232 None => self . table . new_type_var ( ) ,
261233 } ;
262234 if let ClosureKind :: Async = closure_kind {
263- // Use the first type parameter as the output type of future.
264- // existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
265- let impl_trait_id =
266- crate :: ImplTraitId :: AsyncBlockTypeImplTrait ( self . owner , * body) ;
267- let opaque_ty_id = self . db . intern_impl_trait_id ( impl_trait_id) . into ( ) ;
268- sig_tys. push (
269- TyKind :: OpaqueType (
270- opaque_ty_id,
271- Substitution :: from1 ( Interner , ret_ty. clone ( ) ) ,
272- )
273- . intern ( Interner ) ,
274- ) ;
235+ sig_tys. push ( self . lower_async_block_type_impl_trait ( ret_ty. clone ( ) , * body) ) ;
275236 } else {
276237 sig_tys. push ( ret_ty. clone ( ) ) ;
277238 }
@@ -332,6 +293,7 @@ impl<'a> InferenceContext<'a> {
332293
333294 // FIXME: lift these out into a struct
334295 let prev_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
296+ let prev_is_async_fn = mem:: replace ( & mut self . is_async_fn , false ) ;
335297 let prev_ret_ty = mem:: replace ( & mut self . return_ty , ret_ty. clone ( ) ) ;
336298 let prev_ret_coercion =
337299 mem:: replace ( & mut self . return_coercion , Some ( CoerceMany :: new ( ret_ty) ) ) ;
@@ -345,6 +307,7 @@ impl<'a> InferenceContext<'a> {
345307 self . diverges = prev_diverges;
346308 self . return_ty = prev_ret_ty;
347309 self . return_coercion = prev_ret_coercion;
310+ self . is_async_fn = prev_is_async_fn;
348311 self . resume_yield_tys = prev_resume_yield_tys;
349312
350313 ty
@@ -900,6 +863,42 @@ impl<'a> InferenceContext<'a> {
900863 ty
901864 }
902865
866+ fn infer_async_block (
867+ & mut self ,
868+ tgt_expr : ExprId ,
869+ id : & Option < BlockId > ,
870+ statements : & [ Statement ] ,
871+ tail : & Option < ExprId > ,
872+ ) -> Ty {
873+ let ret_ty = self . table . new_type_var ( ) ;
874+ let prev_diverges = mem:: replace ( & mut self . diverges , Diverges :: Maybe ) ;
875+ let prev_ret_ty = mem:: replace ( & mut self . return_ty , ret_ty. clone ( ) ) ;
876+ let prev_ret_coercion =
877+ mem:: replace ( & mut self . return_coercion , Some ( CoerceMany :: new ( ret_ty. clone ( ) ) ) ) ;
878+
879+ let ( _, inner_ty) = self . with_breakable_ctx ( BreakableKind :: Border , None , None , |this| {
880+ this. infer_block ( tgt_expr, * id, statements, * tail, None , & Expectation :: has_type ( ret_ty) )
881+ } ) ;
882+
883+ self . diverges = prev_diverges;
884+ self . return_ty = prev_ret_ty;
885+ self . return_coercion = prev_ret_coercion;
886+
887+ self . lower_async_block_type_impl_trait ( inner_ty, tgt_expr)
888+ }
889+
890+ pub ( crate ) fn lower_async_block_type_impl_trait (
891+ & mut self ,
892+ inner_ty : Ty ,
893+ tgt_expr : ExprId ,
894+ ) -> Ty {
895+ // Use the first type parameter as the output type of future.
896+ // existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
897+ let impl_trait_id = crate :: ImplTraitId :: AsyncBlockTypeImplTrait ( self . owner , tgt_expr) ;
898+ let opaque_ty_id = self . db . intern_impl_trait_id ( impl_trait_id) . into ( ) ;
899+ TyKind :: OpaqueType ( opaque_ty_id, Substitution :: from1 ( Interner , inner_ty) ) . intern ( Interner )
900+ }
901+
903902 fn infer_expr_array (
904903 & mut self ,
905904 array : & Array ,
@@ -964,7 +963,11 @@ impl<'a> InferenceContext<'a> {
964963 . as_mut ( )
965964 . expect ( "infer_return called outside function body" )
966965 . expected_ty ( ) ;
967- let return_expr_ty = self . infer_expr_inner ( expr, & Expectation :: HasType ( ret_ty) ) ;
966+ let return_expr_ty = if self . is_async_fn {
967+ self . infer_async_block ( expr, & None , & [ ] , & Some ( expr) )
968+ } else {
969+ self . infer_expr_inner ( expr, & Expectation :: HasType ( ret_ty) )
970+ } ;
968971 let mut coerce_many = self . return_coercion . take ( ) . unwrap ( ) ;
969972 coerce_many. coerce ( self , Some ( expr) , & return_expr_ty) ;
970973 self . return_coercion = Some ( coerce_many) ;
0 commit comments