This commit is contained in:
Lukas Wirth 2023-03-15 13:49:57 +01:00
parent af175ddcdc
commit 3bf07a5f04
3 changed files with 52 additions and 71 deletions

View File

@ -360,8 +360,14 @@ fn print_expr(&mut self, expr: ExprId) {
w!(self, "]"); w!(self, "]");
} }
Expr::Closure { args, arg_types, ret_type, body, closure_kind } => { Expr::Closure { args, arg_types, ret_type, body, closure_kind } => {
if let ClosureKind::Generator(Movability::Static) = closure_kind { match closure_kind {
w!(self, "static "); ClosureKind::Generator(Movability::Static) => {
w!(self, "static ");
}
ClosureKind::Async => {
w!(self, "async ");
}
_ => (),
} }
w!(self, "|"); w!(self, "|");
for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() { for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
@ -375,20 +381,9 @@ fn print_expr(&mut self, expr: ExprId) {
} }
} }
w!(self, "|"); w!(self, "|");
match (ret_type, closure_kind) { if let Some(ret_ty) = ret_type {
(Some(ret_ty), ClosureKind::Async) => { w!(self, " -> ");
w!(self, " -> impl Future<Output = "); self.print_type_ref(ret_ty);
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}}>");
}
(None, _) => {}
} }
self.whitespace(); self.whitespace();
self.print_expr(*body); self.print_expr(*body);

View File

@ -275,7 +275,23 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
Some(type_ref) => self.make_ty(type_ref), Some(type_ref) => self.make_ty(type_ref),
None => self.table.new_type_var(), None => self.table.new_type_var(),
}; };
sig_tys.push(ret_ty.clone()); if let ClosureKind::Async = closure_kind {
// 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();
sig_tys.push(
TyKind::OpaqueType(
opaque_ty_id,
Substitution::from1(Interner, ret_ty.clone()),
)
.intern(Interner),
);
} else {
sig_tys.push(ret_ty.clone());
}
let sig_ty = TyKind::Function(FnPointer { let sig_ty = TyKind::Function(FnPointer {
num_binders: 0, num_binders: 0,
sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
@ -286,7 +302,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
}) })
.intern(Interner); .intern(Interner);
let (closure_id, ty, resume_yield_tys) = match closure_kind { let (ty, resume_yield_tys) = match closure_kind {
ClosureKind::Generator(_) => { ClosureKind::Generator(_) => {
// FIXME: report error when there are more than 1 parameter. // FIXME: report error when there are more than 1 parameter.
let resume_ty = match sig_tys.first() { let resume_ty = match sig_tys.first() {
@ -306,9 +322,9 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
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);
(None, generator_ty, Some((resume_ty, yield_ty))) (generator_ty, Some((resume_ty, yield_ty)))
} }
ClosureKind::Async | ClosureKind::Closure => { ClosureKind::Closure | ClosureKind::Async => {
let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
let closure_ty = TyKind::Closure( let closure_ty = TyKind::Closure(
closure_id, closure_id,
@ -316,7 +332,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
) )
.intern(Interner); .intern(Interner);
(Some(closure_id), closure_ty, None) (closure_ty, None)
} }
}; };
@ -338,47 +354,16 @@ 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);
let (breaks, ()) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| { this.infer_return(*body);
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;
sig_tys.pop(); ty
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());

View File

@ -533,29 +533,30 @@ fn tuple_struct_with_fn() {
r#" r#"
struct S(fn(u32) -> u64); struct S(fn(u32) -> u64);
fn test() -> u64 { fn test() -> u64 {
let a = S(|i| 2*i); let a = S(|i| 2*i as u64);
let b = a.0(4); let b = a.0(4);
a.0(2) a.0(2)
}"#, }"#,
expect![[r#" expect![[r#"
43..101 '{ ...0(2) }': u64 43..108 '{ ...0(2) }': u64
53..54 'a': S 53..54 'a': S
57..58 'S': S(fn(u32) -> u64) -> S 57..58 'S': S(fn(u32) -> u64) -> S
57..67 'S(|i| 2*i)': S 57..74 'S(|i| ...s u64)': S
59..66 '|i| 2*i': |u32| -> u64 59..73 '|i| 2*i as u64': |u32| -> u64
60..61 'i': u32 60..61 'i': u32
63..64 '2': u32 63..64 '2': u64
63..66 '2*i': u32 63..73 '2*i as u64': u64
65..66 'i': u32 65..66 'i': u32
77..78 'b': u64 65..73 'i as u64': u64
81..82 'a': S 84..85 'b': u64
81..84 'a.0': fn(u32) -> u64 88..89 'a': S
81..87 'a.0(4)': u64 88..91 'a.0': fn(u32) -> u64
85..86 '4': u32 88..94 'a.0(4)': u64
93..94 'a': S 92..93 '4': u32
93..96 'a.0': fn(u32) -> u64 100..101 'a': S
93..99 'a.0(2)': u64 100..103 'a.0': fn(u32) -> u64
97..98 '2': u32 100..106 'a.0(2)': u64
104..105 '2': u32
"#]], "#]],
); );
} }