Merge pull request #21335 from ChayimFriedman2/tupled-closure
internal: Store closures with "tupled" inputs
This commit is contained in:
commit
856cc543a3
10 changed files with 99 additions and 120 deletions
|
|
@ -1383,37 +1383,30 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
|
|||
}
|
||||
_ => (),
|
||||
}
|
||||
let sig = substs
|
||||
.split_closure_args_untupled()
|
||||
.closure_sig_as_fn_ptr_ty
|
||||
.callable_sig(interner);
|
||||
if let Some(sig) = sig {
|
||||
let sig = sig.skip_binder();
|
||||
let InternedClosure(def, _) = db.lookup_intern_closure(id);
|
||||
let infer = InferenceResult::for_body(db, def);
|
||||
let (_, kind) = infer.closure_info(id);
|
||||
match f.closure_style {
|
||||
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
|
||||
ClosureStyle::RANotation => write!(f, "|")?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if sig.inputs().is_empty() {
|
||||
} else if f.should_truncate() {
|
||||
write!(f, "{TYPE_HINT_TRUNCATION}")?;
|
||||
} else {
|
||||
f.write_joined(sig.inputs(), ", ")?;
|
||||
};
|
||||
match f.closure_style {
|
||||
ClosureStyle::ImplFn => write!(f, ")")?,
|
||||
ClosureStyle::RANotation => write!(f, "|")?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if f.closure_style == ClosureStyle::RANotation || !sig.output().is_unit() {
|
||||
write!(f, " -> ")?;
|
||||
sig.output().hir_fmt(f)?;
|
||||
}
|
||||
let sig = interner.signature_unclosure(substs.as_closure().sig(), Safety::Safe);
|
||||
let sig = sig.skip_binder();
|
||||
let InternedClosure(def, _) = db.lookup_intern_closure(id);
|
||||
let infer = InferenceResult::for_body(db, def);
|
||||
let (_, kind) = infer.closure_info(id);
|
||||
match f.closure_style {
|
||||
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
|
||||
ClosureStyle::RANotation => write!(f, "|")?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if sig.inputs().is_empty() {
|
||||
} else if f.should_truncate() {
|
||||
write!(f, "{TYPE_HINT_TRUNCATION}")?;
|
||||
} else {
|
||||
write!(f, "{{closure}}")?;
|
||||
f.write_joined(sig.inputs(), ", ")?;
|
||||
};
|
||||
match f.closure_style {
|
||||
ClosureStyle::ImplFn => write!(f, ")")?,
|
||||
ClosureStyle::RANotation => write!(f, "|")?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if f.closure_style == ClosureStyle::RANotation || !sig.output().is_unit() {
|
||||
write!(f, " -> ")?;
|
||||
sig.output().hir_fmt(f)?;
|
||||
}
|
||||
}
|
||||
TyKind::CoroutineClosure(id, args) => {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ impl<'db> InferenceContext<'_, 'db> {
|
|||
let ClosureSignatures { bound_sig, liberated_sig } =
|
||||
self.sig_of_closure(arg_types, ret_type, expected_sig);
|
||||
let body_ret_ty = bound_sig.output().skip_binder();
|
||||
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.
|
||||
|
|
@ -117,6 +116,16 @@ impl<'db> InferenceContext<'_, 'db> {
|
|||
}
|
||||
None => {}
|
||||
};
|
||||
let sig = bound_sig.map_bound(|sig| {
|
||||
interner.mk_fn_sig(
|
||||
[Ty::new_tup(interner, sig.inputs())],
|
||||
sig.output(),
|
||||
sig.c_variadic,
|
||||
sig.safety,
|
||||
sig.abi,
|
||||
)
|
||||
});
|
||||
let sig_ty = Ty::new_fn_ptr(interner, sig);
|
||||
// FIXME: Infer the kind later if needed.
|
||||
let parts = ClosureArgsParts {
|
||||
parent_args: parent_args.as_slice(),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use hir_def::{
|
|||
};
|
||||
use rustc_ast_ir::Mutability;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use rustc_type_ir::inherent::{IntoKind, Ty as _};
|
||||
use rustc_type_ir::inherent::{GenericArgs as _, IntoKind, Ty as _};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use stdx::{format_to, never};
|
||||
use syntax::utils::is_raw_identifier;
|
||||
|
|
@ -103,7 +103,7 @@ impl CapturedItem {
|
|||
|
||||
pub fn ty<'db>(&self, db: &'db dyn HirDatabase, subst: GenericArgs<'db>) -> Ty<'db> {
|
||||
let interner = DbInterner::new_no_crate(db);
|
||||
self.ty.get().instantiate(interner, subst.split_closure_args_untupled().parent_args)
|
||||
self.ty.get().instantiate(interner, subst.as_closure().parent_args())
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> CaptureKind {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ use rustc_type_ir::{
|
|||
BoundVar, DebruijnIndex, TyVid, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
error::TypeError,
|
||||
inherent::{Const as _, GenericArg as _, IntoKind, Safety, SliceLike, Ty as _},
|
||||
inherent::{
|
||||
Const as _, GenericArg as _, GenericArgs as _, IntoKind, Safety as _, SliceLike, Ty as _,
|
||||
},
|
||||
};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use tracing::{debug, instrument};
|
||||
|
|
@ -63,6 +65,7 @@ use crate::{
|
|||
Canonical, ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed,
|
||||
GenericArgs, ParamEnv, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind,
|
||||
TypingMode,
|
||||
abi::Safety,
|
||||
infer::{
|
||||
DbInternerInferExt, InferCtxt, InferOk, InferResult,
|
||||
relate::RelateResult,
|
||||
|
|
@ -921,10 +924,8 @@ where
|
|||
// or
|
||||
// `unsafe fn(arg0,arg1,...) -> _`
|
||||
let safety = hdr.safety;
|
||||
let closure_sig = args_a.closure_sig_untupled().map_bound(|mut sig| {
|
||||
sig.safety = hdr.safety;
|
||||
sig
|
||||
});
|
||||
let closure_sig =
|
||||
self.interner().signature_unclosure(args_a.as_closure().sig(), safety);
|
||||
let pointer_ty = Ty::new_fn_ptr(self.interner(), closure_sig);
|
||||
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
|
||||
self.unify_and(
|
||||
|
|
@ -1125,23 +1126,28 @@ impl<'db> InferenceContext<'_, 'db> {
|
|||
}
|
||||
(TyKind::Closure(_, args), TyKind::FnDef(..)) => {
|
||||
let b_sig = new_ty.fn_sig(self.table.interner());
|
||||
let a_sig = args.closure_sig_untupled().map_bound(|mut sig| {
|
||||
sig.safety = b_sig.safety();
|
||||
sig
|
||||
});
|
||||
let a_sig = self
|
||||
.interner()
|
||||
.signature_unclosure(args.as_closure().sig(), b_sig.safety());
|
||||
(Some(a_sig), Some(b_sig))
|
||||
}
|
||||
(TyKind::FnDef(..), TyKind::Closure(_, args)) => {
|
||||
let a_sig = prev_ty.fn_sig(self.table.interner());
|
||||
let b_sig = args.closure_sig_untupled().map_bound(|mut sig| {
|
||||
sig.safety = a_sig.safety();
|
||||
sig
|
||||
});
|
||||
let b_sig = self
|
||||
.interner()
|
||||
.signature_unclosure(args.as_closure().sig(), a_sig.safety());
|
||||
(Some(a_sig), Some(b_sig))
|
||||
}
|
||||
(TyKind::Closure(_, args_a), TyKind::Closure(_, args_b)) => {
|
||||
(Some(args_a.closure_sig_untupled()), Some(args_b.closure_sig_untupled()))
|
||||
}
|
||||
(TyKind::Closure(_, args_a), TyKind::Closure(_, args_b)) => (
|
||||
Some(
|
||||
self.interner()
|
||||
.signature_unclosure(args_a.as_closure().sig(), Safety::Safe),
|
||||
),
|
||||
Some(
|
||||
self.interner()
|
||||
.signature_unclosure(args_b.as_closure().sig(), Safety::Safe),
|
||||
),
|
||||
),
|
||||
_ => (None, None),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@ use rustc_abi::{
|
|||
TargetDataLayout, WrappingRange,
|
||||
};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_type_ir::{FloatTy, IntTy, UintTy, inherent::IntoKind};
|
||||
use rustc_type_ir::{
|
||||
FloatTy, IntTy, UintTy,
|
||||
inherent::{GenericArgs as _, IntoKind},
|
||||
};
|
||||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -335,10 +338,7 @@ pub fn layout_of_ty_query(
|
|||
let fields = captures
|
||||
.iter()
|
||||
.map(|it| {
|
||||
let ty = it
|
||||
.ty
|
||||
.get()
|
||||
.instantiate(interner, args.split_closure_args_untupled().parent_args);
|
||||
let ty = it.ty.get().instantiate(interner, args.as_closure().parent_args());
|
||||
db.layout_of_ty(ty.store(), trait_env.clone())
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use std::iter;
|
|||
use hir_def::{DefWithBodyId, HasModule};
|
||||
use la_arena::ArenaMap;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_type_ir::inherent::GenericArgs as _;
|
||||
use stdx::never;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
|
@ -123,7 +124,7 @@ fn make_fetch_closure_field<'db>(
|
|||
let InternedClosure(def, _) = db.lookup_intern_closure(c);
|
||||
let infer = InferenceResult::for_body(db, def);
|
||||
let (captures, _) = infer.closure_info(c);
|
||||
let parent_subst = subst.split_closure_args_untupled().parent_args;
|
||||
let parent_subst = subst.as_closure().parent_args();
|
||||
let interner = DbInterner::new_no_crate(db);
|
||||
captures.get(f).expect("broken closure field").ty.get().instantiate(interner, parent_subst)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use rustc_ast_ir::Mutability;
|
|||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use rustc_type_ir::{
|
||||
AliasTyKind,
|
||||
inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _},
|
||||
inherent::{AdtDef, GenericArgs as _, IntoKind, Region as _, SliceLike, Ty as _},
|
||||
};
|
||||
use span::FileId;
|
||||
use stdx::never;
|
||||
|
|
@ -731,7 +731,7 @@ impl<'db> Evaluator<'db> {
|
|||
let InternedClosure(def, _) = self.db.lookup_intern_closure(c);
|
||||
let infer = InferenceResult::for_body(self.db, def);
|
||||
let (captures, _) = infer.closure_info(c);
|
||||
let parent_subst = subst.split_closure_args_untupled().parent_args;
|
||||
let parent_subst = subst.as_closure().parent_args();
|
||||
captures
|
||||
.get(f)
|
||||
.expect("broken closure field")
|
||||
|
|
@ -2771,7 +2771,7 @@ impl<'db> Evaluator<'db> {
|
|||
TyKind::Closure(closure, subst) => self.exec_closure(
|
||||
closure.0,
|
||||
func_data,
|
||||
GenericArgs::new_from_slice(subst.split_closure_args_untupled().parent_args),
|
||||
GenericArgs::new_from_slice(subst.as_closure().parent_args()),
|
||||
destination,
|
||||
&args[1..],
|
||||
locals,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ use hir_expand::name::Name;
|
|||
use la_arena::ArenaMap;
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_type_ir::inherent::{Const as _, IntoKind, Ty as _};
|
||||
use rustc_type_ir::inherent::{Const as _, GenericArgs as _, IntoKind, Ty as _};
|
||||
use span::{Edition, FileId};
|
||||
use syntax::TextRange;
|
||||
use triomphe::Arc;
|
||||
|
|
@ -44,6 +44,7 @@ use crate::{
|
|||
next_solver::{
|
||||
Const, DbInterner, ParamConst, ParamEnv, Region, StoredGenericArgs, StoredTy, TyKind,
|
||||
TypingMode, UnevaluatedConst,
|
||||
abi::Safety,
|
||||
infer::{DbInternerInferExt, InferCtxt},
|
||||
},
|
||||
traits::FnTrait,
|
||||
|
|
@ -2138,11 +2139,7 @@ pub fn mir_body_for_closure_query<'db>(
|
|||
.store(),
|
||||
});
|
||||
ctx.result.param_locals.push(closure_local);
|
||||
let Some(sig) =
|
||||
substs.split_closure_args_untupled().closure_sig_as_fn_ptr_ty.callable_sig(ctx.interner())
|
||||
else {
|
||||
implementation_error!("closure has not callable sig");
|
||||
};
|
||||
let sig = ctx.interner().signature_unclosure(substs.as_closure().sig(), Safety::Safe);
|
||||
let resolver_guard = ctx.resolver.update_to_inner_scope(db, owner, expr);
|
||||
let current = ctx.lower_params_and_bindings(
|
||||
args.iter().zip(sig.skip_binder().inputs().iter()).map(|(it, y)| (*it, *y)),
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ use std::{hint::unreachable_unchecked, marker::PhantomData, ptr::NonNull};
|
|||
use hir_def::{GenericDefId, GenericParamId};
|
||||
use intern::InternedRef;
|
||||
use rustc_type_ir::{
|
||||
ClosureArgs, ConstVid, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, FnSigTys,
|
||||
GenericTypeVisitable, Interner, TyKind, TyVid, TypeFoldable, TypeFolder, TypeVisitable,
|
||||
TypeVisitor, Variance,
|
||||
ClosureArgs, ConstVid, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder,
|
||||
GenericTypeVisitable, Interner, TyVid, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
|
||||
Variance,
|
||||
inherent::{GenericArg as _, GenericsOf, IntoKind, SliceLike, Term as _, Ty as _},
|
||||
relate::{Relate, VarianceDiagInfo},
|
||||
walk::TypeWalker,
|
||||
|
|
@ -21,12 +21,11 @@ use rustc_type_ir::{
|
|||
use smallvec::SmallVec;
|
||||
|
||||
use crate::next_solver::{
|
||||
ConstInterned, PolyFnSig, RegionInterned, TyInterned, impl_foldable_for_interned_slice,
|
||||
interned_slice,
|
||||
ConstInterned, RegionInterned, TyInterned, impl_foldable_for_interned_slice, interned_slice,
|
||||
};
|
||||
|
||||
use super::{
|
||||
Const, DbInterner, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId, Ty, Tys,
|
||||
Const, DbInterner, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId, Ty,
|
||||
generics::Generics,
|
||||
};
|
||||
|
||||
|
|
@ -566,33 +565,6 @@ impl<'db> GenericArgs<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn closure_sig_untupled(self) -> PolyFnSig<'db> {
|
||||
let TyKind::FnPtr(inputs_and_output, hdr) =
|
||||
self.split_closure_args_untupled().closure_sig_as_fn_ptr_ty.kind()
|
||||
else {
|
||||
unreachable!("not a function pointer")
|
||||
};
|
||||
inputs_and_output.with(hdr)
|
||||
}
|
||||
|
||||
/// A "sensible" `.split_closure_args()`, where the arguments are not in a tuple.
|
||||
pub fn split_closure_args_untupled(self) -> rustc_type_ir::ClosureArgsParts<DbInterner<'db>> {
|
||||
// FIXME: should use `ClosureSubst` when possible
|
||||
match self.as_slice() {
|
||||
[parent_args @ .., closure_kind_ty, sig_ty, tupled_upvars_ty] => {
|
||||
rustc_type_ir::ClosureArgsParts {
|
||||
parent_args,
|
||||
closure_sig_as_fn_ptr_ty: sig_ty.expect_ty(),
|
||||
closure_kind_ty: closure_kind_ty.expect_ty(),
|
||||
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!("unexpected closure sig");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn types(self) -> impl Iterator<Item = Ty<'db>> {
|
||||
self.iter().filter_map(|it| it.as_type())
|
||||
}
|
||||
|
|
@ -688,27 +660,9 @@ impl<'db> rustc_type_ir::inherent::GenericArgs<DbInterner<'db>> for GenericArgs<
|
|||
// FIXME: should use `ClosureSubst` when possible
|
||||
match self.as_slice() {
|
||||
[parent_args @ .., closure_kind_ty, sig_ty, tupled_upvars_ty] => {
|
||||
let interner = DbInterner::conjure();
|
||||
// This is stupid, but the next solver expects the first input to actually be a tuple
|
||||
let sig_ty = match sig_ty.expect_ty().kind() {
|
||||
TyKind::FnPtr(sig_tys, header) => Ty::new(
|
||||
interner,
|
||||
TyKind::FnPtr(
|
||||
sig_tys.map_bound(|s| {
|
||||
let inputs = Ty::new_tup(interner, s.inputs());
|
||||
let output = s.output();
|
||||
FnSigTys {
|
||||
inputs_and_output: Tys::new_from_slice(&[inputs, output]),
|
||||
}
|
||||
}),
|
||||
header,
|
||||
),
|
||||
),
|
||||
_ => unreachable!("sig_ty should be last"),
|
||||
};
|
||||
rustc_type_ir::ClosureArgsParts {
|
||||
parent_args,
|
||||
closure_sig_as_fn_ptr_ty: sig_ty,
|
||||
closure_sig_as_fn_ptr_ty: sig_ty.expect_ty(),
|
||||
closure_kind_ty: closure_kind_ty.expect_ty(),
|
||||
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use rustc_type_ir::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
FnAbi,
|
||||
db::{HirDatabase, InternedCoroutine},
|
||||
lower::GenericPredicates,
|
||||
next_solver::{
|
||||
|
|
@ -495,10 +496,9 @@ impl<'db> Ty<'db> {
|
|||
Some(interner.fn_sig(callable).instantiate(interner, args))
|
||||
}
|
||||
TyKind::FnPtr(sig, hdr) => Some(sig.with(hdr)),
|
||||
TyKind::Closure(_, closure_args) => closure_args
|
||||
.split_closure_args_untupled()
|
||||
.closure_sig_as_fn_ptr_ty
|
||||
.callable_sig(interner),
|
||||
TyKind::Closure(_, closure_args) => {
|
||||
Some(interner.signature_unclosure(closure_args.as_closure().sig(), Safety::Safe))
|
||||
}
|
||||
TyKind::CoroutineClosure(coroutine_id, args) => {
|
||||
Some(args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
|
||||
let unit_ty = Ty::new_unit(interner);
|
||||
|
|
@ -1426,3 +1426,22 @@ impl<'db> PlaceholderLike<DbInterner<'db>> for PlaceholderTy {
|
|||
Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'db> DbInterner<'db> {
|
||||
/// Given a closure signature, returns an equivalent fn signature. Detuples
|
||||
/// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then
|
||||
/// you would get a `fn(u32, i32)`.
|
||||
/// `unsafety` determines the unsafety of the fn signature. If you pass
|
||||
/// `Safety::Unsafe` in the previous example, then you would get
|
||||
/// an `unsafe fn (u32, i32)`.
|
||||
/// It cannot convert a closure that requires unsafe.
|
||||
pub fn signature_unclosure(self, sig: PolyFnSig<'db>, safety: Safety) -> PolyFnSig<'db> {
|
||||
sig.map_bound(|s| {
|
||||
let params = match s.inputs()[0].kind() {
|
||||
TyKind::Tuple(params) => params,
|
||||
_ => panic!(),
|
||||
};
|
||||
self.mk_fn_sig(params, s.output(), s.c_variadic, safety, FnAbi::Rust)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue