Skip to content

Commit 7e515fc

Browse files
Store closures with "tupled" inputs
And remove it when needed, the opposite of what was previously, where we stored without a tuple and tupled for the solver (because it requires that). Because this is what rustc does, and generally, the closer we follow rustc, the easier our lives become. The weird name `signature_unclosure()` also comes from rustc.
1 parent 9581ba4 commit 7e515fc

File tree

10 files changed

+99
-120
lines changed

10 files changed

+99
-120
lines changed

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)