parent
1787c14e72
commit
6746a08b44
@ -499,6 +499,8 @@ fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
|
|||||||
Movability::Movable
|
Movability::Movable
|
||||||
};
|
};
|
||||||
ClosureKind::Generator(movability)
|
ClosureKind::Generator(movability)
|
||||||
|
} else if e.async_token().is_some() {
|
||||||
|
ClosureKind::Async
|
||||||
} else {
|
} else {
|
||||||
ClosureKind::Closure
|
ClosureKind::Closure
|
||||||
};
|
};
|
||||||
|
@ -375,9 +375,20 @@ fn print_expr(&mut self, expr: ExprId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
w!(self, "|");
|
w!(self, "|");
|
||||||
if let Some(ret_ty) = ret_type {
|
match (ret_type, closure_kind) {
|
||||||
w!(self, " -> ");
|
(Some(ret_ty), ClosureKind::Async) => {
|
||||||
self.print_type_ref(ret_ty);
|
w!(self, " -> impl Future<Output = ");
|
||||||
|
self.print_type_ref(ret_ty);
|
||||||
|
w!(self, ">");
|
||||||
|
}
|
||||||
|
(Some(ret_ty), _) => {
|
||||||
|
w!(self, " -> ");
|
||||||
|
self.print_type_ref(ret_ty);
|
||||||
|
}
|
||||||
|
(None, ClosureKind::Async) => {
|
||||||
|
w!(self, " -> impl Future<Output = {{unknown}}>"); // FIXME(zachs18): {unknown} or ()?
|
||||||
|
}
|
||||||
|
(None, _) => {}
|
||||||
}
|
}
|
||||||
self.whitespace();
|
self.whitespace();
|
||||||
self.print_expr(*body);
|
self.print_expr(*body);
|
||||||
|
@ -245,6 +245,7 @@ pub enum Expr {
|
|||||||
pub enum ClosureKind {
|
pub enum ClosureKind {
|
||||||
Closure,
|
Closure,
|
||||||
Generator(Movability),
|
Generator(Movability),
|
||||||
|
Async,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
@ -286,33 +286,38 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
|||||||
})
|
})
|
||||||
.intern(Interner);
|
.intern(Interner);
|
||||||
|
|
||||||
let (ty, resume_yield_tys) = if matches!(closure_kind, ClosureKind::Generator(_)) {
|
let (closure_id, ty, resume_yield_tys) = match closure_kind {
|
||||||
// FIXME: report error when there are more than 1 parameter.
|
ClosureKind::Generator(_) => {
|
||||||
let resume_ty = match sig_tys.first() {
|
// FIXME: report error when there are more than 1 parameter.
|
||||||
// When `sig_tys.len() == 1` the first type is the return type, not the
|
let resume_ty = match sig_tys.first() {
|
||||||
// first parameter type.
|
// When `sig_tys.len() == 1` the first type is the return type, not the
|
||||||
Some(ty) if sig_tys.len() > 1 => ty.clone(),
|
// first parameter type.
|
||||||
_ => self.result.standard_types.unit.clone(),
|
Some(ty) if sig_tys.len() > 1 => ty.clone(),
|
||||||
};
|
_ => self.result.standard_types.unit.clone(),
|
||||||
let yield_ty = self.table.new_type_var();
|
};
|
||||||
|
let yield_ty = self.table.new_type_var();
|
||||||
|
|
||||||
let subst = TyBuilder::subst_for_generator(self.db, self.owner)
|
let subst = TyBuilder::subst_for_generator(self.db, self.owner)
|
||||||
.push(resume_ty.clone())
|
.push(resume_ty.clone())
|
||||||
.push(yield_ty.clone())
|
.push(yield_ty.clone())
|
||||||
.push(ret_ty.clone())
|
.push(ret_ty.clone())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let generator_id = self.db.intern_generator((self.owner, tgt_expr)).into();
|
let generator_id = self.db.intern_generator((self.owner, tgt_expr)).into();
|
||||||
let generator_ty = TyKind::Generator(generator_id, subst).intern(Interner);
|
let generator_ty = TyKind::Generator(generator_id, subst).intern(Interner);
|
||||||
|
|
||||||
(generator_ty, Some((resume_ty, yield_ty)))
|
(None, generator_ty, Some((resume_ty, yield_ty)))
|
||||||
} else {
|
}
|
||||||
let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
|
ClosureKind::Async | ClosureKind::Closure => {
|
||||||
let closure_ty =
|
let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
|
||||||
TyKind::Closure(closure_id, Substitution::from1(Interner, sig_ty.clone()))
|
let closure_ty = TyKind::Closure(
|
||||||
.intern(Interner);
|
closure_id,
|
||||||
|
Substitution::from1(Interner, sig_ty.clone()),
|
||||||
|
)
|
||||||
|
.intern(Interner);
|
||||||
|
|
||||||
(closure_ty, None)
|
(Some(closure_id), closure_ty, None)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Eagerly try to relate the closure type with the expected
|
// Eagerly try to relate the closure type with the expected
|
||||||
@ -321,7 +326,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
|||||||
self.deduce_closure_type_from_expectations(tgt_expr, &ty, &sig_ty, expected);
|
self.deduce_closure_type_from_expectations(tgt_expr, &ty, &sig_ty, expected);
|
||||||
|
|
||||||
// Now go through the argument patterns
|
// Now go through the argument patterns
|
||||||
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
|
for (arg_pat, arg_ty) in args.iter().zip(&sig_tys) {
|
||||||
self.infer_top_pat(*arg_pat, &arg_ty);
|
self.infer_top_pat(*arg_pat, &arg_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,16 +338,47 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
|||||||
let prev_resume_yield_tys =
|
let prev_resume_yield_tys =
|
||||||
mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
|
mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
|
||||||
|
|
||||||
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
|
let (breaks, ()) =
|
||||||
this.infer_return(*body);
|
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
|
||||||
});
|
this.infer_return(*body);
|
||||||
|
});
|
||||||
|
|
||||||
|
let inner_ty = if matches!(closure_kind, ClosureKind::Async) {
|
||||||
|
// Use the first type parameter as the output type of future.
|
||||||
|
// existential type AsyncBlockImplTrait<InnerType>: Future<Output = InnerType>
|
||||||
|
let impl_trait_id =
|
||||||
|
crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
|
||||||
|
let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
|
||||||
|
TyKind::OpaqueType(opaque_ty_id, Substitution::from1(Interner, ret_ty.clone()))
|
||||||
|
.intern(Interner)
|
||||||
|
} else {
|
||||||
|
ret_ty.clone()
|
||||||
|
};
|
||||||
|
|
||||||
self.diverges = prev_diverges;
|
self.diverges = prev_diverges;
|
||||||
self.return_ty = prev_ret_ty;
|
self.return_ty = prev_ret_ty;
|
||||||
self.return_coercion = prev_ret_coercion;
|
self.return_coercion = prev_ret_coercion;
|
||||||
self.resume_yield_tys = prev_resume_yield_tys;
|
self.resume_yield_tys = prev_resume_yield_tys;
|
||||||
|
|
||||||
ty
|
sig_tys.pop();
|
||||||
|
sig_tys.push(inner_ty);
|
||||||
|
|
||||||
|
let sig_ty = TyKind::Function(FnPointer {
|
||||||
|
num_binders: 0,
|
||||||
|
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
|
||||||
|
substitution: FnSubst(
|
||||||
|
Substitution::from_iter(Interner, sig_tys.clone()).shifted_in(Interner),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.intern(Interner);
|
||||||
|
|
||||||
|
match closure_id {
|
||||||
|
Some(closure_id) => {
|
||||||
|
TyKind::Closure(closure_id, Substitution::from1(Interner, sig_ty.clone()))
|
||||||
|
.intern(Interner)
|
||||||
|
}
|
||||||
|
None => ty,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expr::Call { callee, args, .. } => {
|
Expr::Call { callee, args, .. } => {
|
||||||
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
||||||
|
Loading…
Reference in New Issue
Block a user