Skip to content

Commit 2a6bdd1

Browse files
committed
fix: Fix return type of async closures.
1 parent d9e462f commit 2a6bdd1

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

crates/hir-def/src/body/lower.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ impl ExprCollector<'_> {
466466
arg_types: arg_types.into(),
467467
ret_type,
468468
body,
469+
is_async: e.async_token().is_some(),
469470
},
470471
syntax_ptr,
471472
)

crates/hir-def/src/expr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ pub enum Expr {
196196
arg_types: Box<[Option<Interned<TypeRef>>]>,
197197
ret_type: Option<Interned<TypeRef>>,
198198
body: ExprId,
199+
is_async: bool,
199200
},
200201
Tuple {
201202
exprs: Box<[ExprId]>,

crates/hir-ty/src/infer/expr.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl<'a> InferenceContext<'a> {
218218
self.diverges = Diverges::Maybe;
219219
TyBuilder::unit()
220220
}
221-
Expr::Closure { body, args, ret_type, arg_types } => {
221+
Expr::Closure { body, args, ret_type, arg_types, is_async } => {
222222
assert_eq!(args.len(), arg_types.len());
223223

224224
let mut sig_tys = Vec::new();
@@ -262,19 +262,44 @@ impl<'a> InferenceContext<'a> {
262262
);
263263

264264
// Now go through the argument patterns
265-
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
265+
for (arg_pat, arg_ty) in args.iter().zip(&sig_tys) {
266266
self.infer_pat(*arg_pat, &arg_ty, BindingMode::default());
267267
}
268268

269269
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
270270
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
271271

272-
self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
272+
let inner_ty = self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
273+
274+
let inner_ty = if *is_async {
275+
// Use the first type parameter as the output type of future.
276+
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
277+
let impl_trait_id =
278+
crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
279+
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
280+
TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, inner_ty))
281+
.intern(Interner)
282+
} else {
283+
inner_ty
284+
};
273285

274286
self.diverges = prev_diverges;
275287
self.return_ty = prev_ret_ty;
276288

277-
closure_ty
289+
sig_tys.pop();
290+
sig_tys.push(inner_ty);
291+
292+
let sig_ty = TyKind::Function(FnPointer {
293+
num_binders: 0,
294+
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
295+
substitution: FnSubst(
296+
Substitution::from_iter(Interner, sig_tys.clone()).shifted_in(Interner),
297+
),
298+
})
299+
.intern(Interner);
300+
301+
TyKind::Closure(closure_id, Substitution::from1(Interner, sig_ty.clone()))
302+
.intern(Interner)
278303
}
279304
Expr::Call { callee, args, .. } => {
280305
let callee_ty = self.infer_expr(*callee, &Expectation::none());

0 commit comments

Comments
 (0)