Skip to content

Commit c83c1a5

Browse files
authored
Merge pull request #21335 from ChayimFriedman2/tupled-closure
internal: Store closures with "tupled" inputs
2 parents c8d3e3a + 7e515fc commit c83c1a5

10 files changed

Lines changed: 99 additions & 120 deletions

File tree

crates/hir-ty/src/display.rs

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,37 +1383,30 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
13831383
}
13841384
_ => (),
13851385
}
1386-
let sig = substs
1387-
.split_closure_args_untupled()
1388-
.closure_sig_as_fn_ptr_ty
1389-
.callable_sig(interner);
1390-
if let Some(sig) = sig {
1391-
let sig = sig.skip_binder();
1392-
let InternedClosure(def, _) = db.lookup_intern_closure(id);
1393-
let infer = InferenceResult::for_body(db, def);
1394-
let (_, kind) = infer.closure_info(id);
1395-
match f.closure_style {
1396-
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
1397-
ClosureStyle::RANotation => write!(f, "|")?,
1398-
_ => unreachable!(),
1399-
}
1400-
if sig.inputs().is_empty() {
1401-
} else if f.should_truncate() {
1402-
write!(f, "{TYPE_HINT_TRUNCATION}")?;
1403-
} else {
1404-
f.write_joined(sig.inputs(), ", ")?;
1405-
};
1406-
match f.closure_style {
1407-
ClosureStyle::ImplFn => write!(f, ")")?,
1408-
ClosureStyle::RANotation => write!(f, "|")?,
1409-
_ => unreachable!(),
1410-
}
1411-
if f.closure_style == ClosureStyle::RANotation || !sig.output().is_unit() {
1412-
write!(f, " -> ")?;
1413-
sig.output().hir_fmt(f)?;
1414-
}
1386+
let sig = interner.signature_unclosure(substs.as_closure().sig(), Safety::Safe);
1387+
let sig = sig.skip_binder();
1388+
let InternedClosure(def, _) = db.lookup_intern_closure(id);
1389+
let infer = InferenceResult::for_body(db, def);
1390+
let (_, kind) = infer.closure_info(id);
1391+
match f.closure_style {
1392+
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
1393+
ClosureStyle::RANotation => write!(f, "|")?,
1394+
_ => unreachable!(),
1395+
}
1396+
if sig.inputs().is_empty() {
1397+
} else if f.should_truncate() {
1398+
write!(f, "{TYPE_HINT_TRUNCATION}")?;
14151399
} else {
1416-
write!(f, "{{closure}}")?;
1400+
f.write_joined(sig.inputs(), ", ")?;
1401+
};
1402+
match f.closure_style {
1403+
ClosureStyle::ImplFn => write!(f, ")")?,
1404+
ClosureStyle::RANotation => write!(f, "|")?,
1405+
_ => unreachable!(),
1406+
}
1407+
if f.closure_style == ClosureStyle::RANotation || !sig.output().is_unit() {
1408+
write!(f, " -> ")?;
1409+
sig.output().hir_fmt(f)?;
14171410
}
14181411
}
14191412
TyKind::CoroutineClosure(id, args) => {

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ impl<'db> InferenceContext<'_, 'db> {
6868
let ClosureSignatures { bound_sig, liberated_sig } =
6969
self.sig_of_closure(arg_types, ret_type, expected_sig);
7070
let body_ret_ty = bound_sig.output().skip_binder();
71-
let sig_ty = Ty::new_fn_ptr(interner, bound_sig);
7271

7372
let parent_args = GenericArgs::identity_for_item(interner, self.generic_def.into());
7473
// FIXME: Make this an infer var and infer it later.
@@ -117,6 +116,16 @@ impl<'db> InferenceContext<'_, 'db> {
117116
}
118117
None => {}
119118
};
119+
let sig = bound_sig.map_bound(|sig| {
120+
interner.mk_fn_sig(
121+
[Ty::new_tup(interner, sig.inputs())],
122+
sig.output(),
123+
sig.c_variadic,
124+
sig.safety,
125+
sig.abi,
126+
)
127+
});
128+
let sig_ty = Ty::new_fn_ptr(interner, sig);
120129
// FIXME: Infer the kind later if needed.
121130
let parts = ClosureArgsParts {
122131
parent_args: parent_args.as_slice(),

crates/hir-ty/src/infer/closure/analysis.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use hir_def::{
1515
};
1616
use rustc_ast_ir::Mutability;
1717
use rustc_hash::{FxHashMap, FxHashSet};
18-
use rustc_type_ir::inherent::{IntoKind, Ty as _};
18+
use rustc_type_ir::inherent::{GenericArgs as _, IntoKind, Ty as _};
1919
use smallvec::{SmallVec, smallvec};
2020
use stdx::{format_to, never};
2121
use syntax::utils::is_raw_identifier;
@@ -103,7 +103,7 @@ impl CapturedItem {
103103

104104
pub fn ty<'db>(&self, db: &'db dyn HirDatabase, subst: GenericArgs<'db>) -> Ty<'db> {
105105
let interner = DbInterner::new_no_crate(db);
106-
self.ty.get().instantiate(interner, subst.split_closure_args_untupled().parent_args)
106+
self.ty.get().instantiate(interner, subst.as_closure().parent_args())
107107
}
108108

109109
pub fn kind(&self) -> CaptureKind {

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ use rustc_type_ir::{
4646
BoundVar, DebruijnIndex, TyVid, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
4747
TypeVisitableExt,
4848
error::TypeError,
49-
inherent::{Const as _, GenericArg as _, IntoKind, Safety, SliceLike, Ty as _},
49+
inherent::{
50+
Const as _, GenericArg as _, GenericArgs as _, IntoKind, Safety as _, SliceLike, Ty as _,
51+
},
5052
};
5153
use smallvec::{SmallVec, smallvec};
5254
use tracing::{debug, instrument};
@@ -63,6 +65,7 @@ use crate::{
6365
Canonical, ClauseKind, CoercePredicate, Const, ConstKind, DbInterner, ErrorGuaranteed,
6466
GenericArgs, ParamEnv, PolyFnSig, PredicateKind, Region, RegionKind, TraitRef, Ty, TyKind,
6567
TypingMode,
68+
abi::Safety,
6669
infer::{
6770
DbInternerInferExt, InferCtxt, InferOk, InferResult,
6871
relate::RelateResult,
@@ -921,10 +924,8 @@ where
921924
// or
922925
// `unsafe fn(arg0,arg1,...) -> _`
923926
let safety = hdr.safety;
924-
let closure_sig = args_a.closure_sig_untupled().map_bound(|mut sig| {
925-
sig.safety = hdr.safety;
926-
sig
927-
});
927+
let closure_sig =
928+
self.interner().signature_unclosure(args_a.as_closure().sig(), safety);
928929
let pointer_ty = Ty::new_fn_ptr(self.interner(), closure_sig);
929930
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
930931
self.unify_and(
@@ -1125,23 +1126,28 @@ impl<'db> InferenceContext<'_, 'db> {
11251126
}
11261127
(TyKind::Closure(_, args), TyKind::FnDef(..)) => {
11271128
let b_sig = new_ty.fn_sig(self.table.interner());
1128-
let a_sig = args.closure_sig_untupled().map_bound(|mut sig| {
1129-
sig.safety = b_sig.safety();
1130-
sig
1131-
});
1129+
let a_sig = self
1130+
.interner()
1131+
.signature_unclosure(args.as_closure().sig(), b_sig.safety());
11321132
(Some(a_sig), Some(b_sig))
11331133
}
11341134
(TyKind::FnDef(..), TyKind::Closure(_, args)) => {
11351135
let a_sig = prev_ty.fn_sig(self.table.interner());
1136-
let b_sig = args.closure_sig_untupled().map_bound(|mut sig| {
1137-
sig.safety = a_sig.safety();
1138-
sig
1139-
});
1136+
let b_sig = self
1137+
.interner()
1138+
.signature_unclosure(args.as_closure().sig(), a_sig.safety());
11401139
(Some(a_sig), Some(b_sig))
11411140
}
1142-
(TyKind::Closure(_, args_a), TyKind::Closure(_, args_b)) => {
1143-
(Some(args_a.closure_sig_untupled()), Some(args_b.closure_sig_untupled()))
1144-
}
1141+
(TyKind::Closure(_, args_a), TyKind::Closure(_, args_b)) => (
1142+
Some(
1143+
self.interner()
1144+
.signature_unclosure(args_a.as_closure().sig(), Safety::Safe),
1145+
),
1146+
Some(
1147+
self.interner()
1148+
.signature_unclosure(args_b.as_closure().sig(), Safety::Safe),
1149+
),
1150+
),
11451151
_ => (None, None),
11461152
}
11471153
}

crates/hir-ty/src/layout.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ use rustc_abi::{
1414
TargetDataLayout, WrappingRange,
1515
};
1616
use rustc_index::IndexVec;
17-
use rustc_type_ir::{FloatTy, IntTy, UintTy, inherent::IntoKind};
17+
use rustc_type_ir::{
18+
FloatTy, IntTy, UintTy,
19+
inherent::{GenericArgs as _, IntoKind},
20+
};
1821
use triomphe::Arc;
1922

2023
use crate::{
@@ -335,10 +338,7 @@ pub fn layout_of_ty_query(
335338
let fields = captures
336339
.iter()
337340
.map(|it| {
338-
let ty = it
339-
.ty
340-
.get()
341-
.instantiate(interner, args.split_closure_args_untupled().parent_args);
341+
let ty = it.ty.get().instantiate(interner, args.as_closure().parent_args());
342342
db.layout_of_ty(ty.store(), trait_env.clone())
343343
})
344344
.collect::<Result<Vec<_>, _>>()?;

crates/hir-ty/src/mir/borrowck.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::iter;
88
use hir_def::{DefWithBodyId, HasModule};
99
use la_arena::ArenaMap;
1010
use rustc_hash::FxHashMap;
11+
use rustc_type_ir::inherent::GenericArgs as _;
1112
use stdx::never;
1213
use triomphe::Arc;
1314

@@ -123,7 +124,7 @@ fn make_fetch_closure_field<'db>(
123124
let InternedClosure(def, _) = db.lookup_intern_closure(c);
124125
let infer = InferenceResult::for_body(db, def);
125126
let (captures, _) = infer.closure_info(c);
126-
let parent_subst = subst.split_closure_args_untupled().parent_args;
127+
let parent_subst = subst.as_closure().parent_args();
127128
let interner = DbInterner::new_no_crate(db);
128129
captures.get(f).expect("broken closure field").ty.get().instantiate(interner, parent_subst)
129130
}

crates/hir-ty/src/mir/eval.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_ast_ir::Mutability;
2727
use rustc_hash::{FxHashMap, FxHashSet};
2828
use rustc_type_ir::{
2929
AliasTyKind,
30-
inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _},
30+
inherent::{AdtDef, GenericArgs as _, IntoKind, Region as _, SliceLike, Ty as _},
3131
};
3232
use span::FileId;
3333
use stdx::never;
@@ -731,7 +731,7 @@ impl<'db> Evaluator<'db> {
731731
let InternedClosure(def, _) = self.db.lookup_intern_closure(c);
732732
let infer = InferenceResult::for_body(self.db, def);
733733
let (captures, _) = infer.closure_info(c);
734-
let parent_subst = subst.split_closure_args_untupled().parent_args;
734+
let parent_subst = subst.as_closure().parent_args();
735735
captures
736736
.get(f)
737737
.expect("broken closure field")
@@ -2771,7 +2771,7 @@ impl<'db> Evaluator<'db> {
27712771
TyKind::Closure(closure, subst) => self.exec_closure(
27722772
closure.0,
27732773
func_data,
2774-
GenericArgs::new_from_slice(subst.split_closure_args_untupled().parent_args),
2774+
GenericArgs::new_from_slice(subst.as_closure().parent_args()),
27752775
destination,
27762776
&args[1..],
27772777
locals,

crates/hir-ty/src/mir/lower.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use hir_expand::name::Name;
1919
use la_arena::ArenaMap;
2020
use rustc_apfloat::Float;
2121
use rustc_hash::FxHashMap;
22-
use rustc_type_ir::inherent::{Const as _, IntoKind, Ty as _};
22+
use rustc_type_ir::inherent::{Const as _, GenericArgs as _, IntoKind, Ty as _};
2323
use span::{Edition, FileId};
2424
use syntax::TextRange;
2525
use triomphe::Arc;
@@ -44,6 +44,7 @@ use crate::{
4444
next_solver::{
4545
Const, DbInterner, ParamConst, ParamEnv, Region, StoredGenericArgs, StoredTy, TyKind,
4646
TypingMode, UnevaluatedConst,
47+
abi::Safety,
4748
infer::{DbInternerInferExt, InferCtxt},
4849
},
4950
traits::FnTrait,
@@ -2138,11 +2139,7 @@ pub fn mir_body_for_closure_query<'db>(
21382139
.store(),
21392140
});
21402141
ctx.result.param_locals.push(closure_local);
2141-
let Some(sig) =
2142-
substs.split_closure_args_untupled().closure_sig_as_fn_ptr_ty.callable_sig(ctx.interner())
2143-
else {
2144-
implementation_error!("closure has not callable sig");
2145-
};
2142+
let sig = ctx.interner().signature_unclosure(substs.as_closure().sig(), Safety::Safe);
21462143
let resolver_guard = ctx.resolver.update_to_inner_scope(db, owner, expr);
21472144
let current = ctx.lower_params_and_bindings(
21482145
args.iter().zip(sig.skip_binder().inputs().iter()).map(|(it, y)| (*it, *y)),

crates/hir-ty/src/next_solver/generic_arg.rs

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,21 @@ use std::{hint::unreachable_unchecked, marker::PhantomData, ptr::NonNull};
1111
use hir_def::{GenericDefId, GenericParamId};
1212
use intern::InternedRef;
1313
use rustc_type_ir::{
14-
ClosureArgs, ConstVid, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, FnSigTys,
15-
GenericTypeVisitable, Interner, TyKind, TyVid, TypeFoldable, TypeFolder, TypeVisitable,
16-
TypeVisitor, Variance,
14+
ClosureArgs, ConstVid, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder,
15+
GenericTypeVisitable, Interner, TyVid, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
16+
Variance,
1717
inherent::{GenericArg as _, GenericsOf, IntoKind, SliceLike, Term as _, Ty as _},
1818
relate::{Relate, VarianceDiagInfo},
1919
walk::TypeWalker,
2020
};
2121
use smallvec::SmallVec;
2222

2323
use crate::next_solver::{
24-
ConstInterned, PolyFnSig, RegionInterned, TyInterned, impl_foldable_for_interned_slice,
25-
interned_slice,
24+
ConstInterned, RegionInterned, TyInterned, impl_foldable_for_interned_slice, interned_slice,
2625
};
2726

2827
use super::{
29-
Const, DbInterner, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId, Ty, Tys,
28+
Const, DbInterner, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, SolverDefId, Ty,
3029
generics::Generics,
3130
};
3231

@@ -566,33 +565,6 @@ impl<'db> GenericArgs<'db> {
566565
}
567566
}
568567

569-
pub fn closure_sig_untupled(self) -> PolyFnSig<'db> {
570-
let TyKind::FnPtr(inputs_and_output, hdr) =
571-
self.split_closure_args_untupled().closure_sig_as_fn_ptr_ty.kind()
572-
else {
573-
unreachable!("not a function pointer")
574-
};
575-
inputs_and_output.with(hdr)
576-
}
577-
578-
/// A "sensible" `.split_closure_args()`, where the arguments are not in a tuple.
579-
pub fn split_closure_args_untupled(self) -> rustc_type_ir::ClosureArgsParts<DbInterner<'db>> {
580-
// FIXME: should use `ClosureSubst` when possible
581-
match self.as_slice() {
582-
[parent_args @ .., closure_kind_ty, sig_ty, tupled_upvars_ty] => {
583-
rustc_type_ir::ClosureArgsParts {
584-
parent_args,
585-
closure_sig_as_fn_ptr_ty: sig_ty.expect_ty(),
586-
closure_kind_ty: closure_kind_ty.expect_ty(),
587-
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
588-
}
589-
}
590-
_ => {
591-
unreachable!("unexpected closure sig");
592-
}
593-
}
594-
}
595-
596568
pub fn types(self) -> impl Iterator<Item = Ty<'db>> {
597569
self.iter().filter_map(|it| it.as_type())
598570
}
@@ -688,27 +660,9 @@ impl<'db> rustc_type_ir::inherent::GenericArgs<DbInterner<'db>> for GenericArgs<
688660
// FIXME: should use `ClosureSubst` when possible
689661
match self.as_slice() {
690662
[parent_args @ .., closure_kind_ty, sig_ty, tupled_upvars_ty] => {
691-
let interner = DbInterner::conjure();
692-
// This is stupid, but the next solver expects the first input to actually be a tuple
693-
let sig_ty = match sig_ty.expect_ty().kind() {
694-
TyKind::FnPtr(sig_tys, header) => Ty::new(
695-
interner,
696-
TyKind::FnPtr(
697-
sig_tys.map_bound(|s| {
698-
let inputs = Ty::new_tup(interner, s.inputs());
699-
let output = s.output();
700-
FnSigTys {
701-
inputs_and_output: Tys::new_from_slice(&[inputs, output]),
702-
}
703-
}),
704-
header,
705-
),
706-
),
707-
_ => unreachable!("sig_ty should be last"),
708-
};
709663
rustc_type_ir::ClosureArgsParts {
710664
parent_args,
711-
closure_sig_as_fn_ptr_ty: sig_ty,
665+
closure_sig_as_fn_ptr_ty: sig_ty.expect_ty(),
712666
closure_kind_ty: closure_kind_ty.expect_ty(),
713667
tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
714668
}

0 commit comments

Comments
 (0)