Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/closure.rs')
-rw-r--r--crates/hir-ty/src/infer/closure.rs95
1 files changed, 75 insertions, 20 deletions
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 2637ed6b3e..06f8307eb0 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -11,8 +11,9 @@ use hir_def::{
type_ref::TypeRefId,
};
use rustc_type_ir::{
- ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, Interner, TypeSuperVisitable,
- TypeVisitable, TypeVisitableExt, TypeVisitor,
+ ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs,
+ CoroutineClosureArgsParts, Interner, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+ TypeVisitor,
inherent::{BoundExistentialPredicates, GenericArgs as _, IntoKind, SliceLike, Ty as _},
};
use tracing::debug;
@@ -22,11 +23,12 @@ use crate::{
db::{InternedClosure, InternedCoroutine},
infer::{BreakableKind, Diverges, coerce::CoerceMany},
next_solver::{
- AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArgs, PolyFnSig,
- PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, Ty, TyKind,
+ AliasTy, Binder, BoundRegionKind, BoundVarKind, BoundVarKinds, ClauseKind, DbInterner,
+ ErrorGuaranteed, FnSig, GenericArgs, PolyFnSig, PolyProjectionPredicate, Predicate,
+ PredicateKind, SolverDefId, Ty, TyKind,
abi::Safety,
infer::{
- BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult,
+ BoundRegionConversionTime, InferOk, InferResult,
traits::{ObligationCause, PredicateObligations},
},
util::explicit_item_bounds,
@@ -72,6 +74,8 @@ impl<'db> InferenceContext<'_, 'db> {
let sig_ty = Ty::new_fn_ptr(interner, bound_sig);
let parent_args = GenericArgs::identity_for_item(interner, self.generic_def.into());
+ // FIXME: Make this an infer var and infer it later.
+ let tupled_upvars_ty = self.types.unit;
let (id, ty, resume_yield_tys) = match closure_kind {
ClosureKind::Coroutine(_) => {
let yield_ty = self.table.next_ty_var();
@@ -80,11 +84,11 @@ impl<'db> InferenceContext<'_, 'db> {
// FIXME: Infer the upvars later.
let parts = CoroutineArgsParts {
parent_args,
- kind_ty: Ty::new_unit(interner),
+ kind_ty: self.types.unit,
resume_ty,
yield_ty,
return_ty: body_ret_ty,
- tupled_upvars_ty: Ty::new_unit(interner),
+ tupled_upvars_ty,
};
let coroutine_id =
@@ -97,9 +101,7 @@ impl<'db> InferenceContext<'_, 'db> {
(None, coroutine_ty, Some((resume_ty, yield_ty)))
}
- // FIXME(next-solver): `ClosureKind::Async` should really be a separate arm that creates a `CoroutineClosure`.
- // But for now we treat it as a closure.
- ClosureKind::Closure | ClosureKind::Async => {
+ ClosureKind::Closure => {
let closure_id = self.db.intern_closure(InternedClosure(self.owner, tgt_expr));
match expected_kind {
Some(kind) => {
@@ -117,7 +119,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
None => {}
};
- // FIXME: Infer the kind and the upvars later when needed.
+ // FIXME: Infer the kind later if needed.
let parts = ClosureArgsParts {
parent_args,
closure_kind_ty: Ty::from_closure_kind(
@@ -125,7 +127,7 @@ impl<'db> InferenceContext<'_, 'db> {
expected_kind.unwrap_or(rustc_type_ir::ClosureKind::Fn),
),
closure_sig_as_fn_ptr_ty: sig_ty,
- tupled_upvars_ty: Ty::new_unit(interner),
+ tupled_upvars_ty,
};
let closure_ty = Ty::new_closure(
interner,
@@ -136,6 +138,61 @@ impl<'db> InferenceContext<'_, 'db> {
self.add_current_closure_dependency(closure_id);
(Some(closure_id), closure_ty, None)
}
+ ClosureKind::Async => {
+ // async closures always return the type ascribed after the `->` (if present),
+ // and yield `()`.
+ let bound_return_ty = bound_sig.skip_binder().output();
+ let bound_yield_ty = self.types.unit;
+ // rustc uses a special lang item type for the resume ty. I don't believe this can cause us problems.
+ let resume_ty = self.types.unit;
+
+ // FIXME: Infer the kind later if needed.
+ let closure_kind_ty = Ty::from_closure_kind(
+ interner,
+ expected_kind.unwrap_or(rustc_type_ir::ClosureKind::Fn),
+ );
+
+ // FIXME: Infer captures later.
+ // `for<'env> fn() -> ()`, for no captures.
+ let coroutine_captures_by_ref_ty = Ty::new_fn_ptr(
+ interner,
+ Binder::bind_with_vars(
+ interner.mk_fn_sig([], self.types.unit, false, Safety::Safe, FnAbi::Rust),
+ BoundVarKinds::new_from_iter(
+ interner,
+ [BoundVarKind::Region(BoundRegionKind::ClosureEnv)],
+ ),
+ ),
+ );
+ let closure_args = CoroutineClosureArgs::new(
+ interner,
+ CoroutineClosureArgsParts {
+ parent_args,
+ closure_kind_ty,
+ signature_parts_ty: Ty::new_fn_ptr(
+ interner,
+ bound_sig.map_bound(|sig| {
+ interner.mk_fn_sig(
+ [
+ resume_ty,
+ Ty::new_tup_from_iter(interner, sig.inputs().iter()),
+ ],
+ Ty::new_tup(interner, &[bound_yield_ty, bound_return_ty]),
+ sig.c_variadic,
+ sig.safety,
+ sig.abi,
+ )
+ }),
+ ),
+ tupled_upvars_ty,
+ coroutine_captures_by_ref_ty,
+ },
+ );
+
+ let coroutine_id =
+ self.db.intern_coroutine(InternedCoroutine(self.owner, tgt_expr)).into();
+ (None, Ty::new_coroutine_closure(interner, coroutine_id, closure_args.args), None)
+ }
};
// Now go through the argument patterns
@@ -307,7 +364,7 @@ impl<'db> InferenceContext<'_, 'db> {
.table
.infer_ctxt
.at(&ObligationCause::new(), self.table.trait_env.env)
- .eq(DefineOpaqueTypes::Yes, inferred_fnptr_sig, generalized_fnptr_sig)
+ .eq(inferred_fnptr_sig, generalized_fnptr_sig)
.map(|infer_ok| self.table.register_infer_ok(infer_ok));
let resolved_sig =
@@ -692,18 +749,16 @@ impl<'db> InferenceContext<'_, 'db> {
let InferOk { value: (), obligations } = table
.infer_ctxt
.at(&cause, table.trait_env.env)
- .eq(DefineOpaqueTypes::Yes, expected_ty, supplied_ty)?;
+ .eq(expected_ty, supplied_ty)?;
all_obligations.extend(obligations);
}
let supplied_output_ty = supplied_sig.output();
let cause = ObligationCause::new();
- let InferOk { value: (), obligations } =
- table.infer_ctxt.at(&cause, table.trait_env.env).eq(
- DefineOpaqueTypes::Yes,
- expected_sigs.liberated_sig.output(),
- supplied_output_ty,
- )?;
+ let InferOk { value: (), obligations } = table
+ .infer_ctxt
+ .at(&cause, table.trait_env.env)
+ .eq(expected_sigs.liberated_sig.output(), supplied_output_ty)?;
all_obligations.extend(obligations);
let inputs = supplied_sig