Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/display.rs53
-rw-r--r--crates/hir-ty/src/infer/closure.rs11
-rw-r--r--crates/hir-ty/src/infer/closure/analysis.rs4
-rw-r--r--crates/hir-ty/src/infer/coerce.rs38
-rw-r--r--crates/hir-ty/src/layout.rs10
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs3
-rw-r--r--crates/hir-ty/src/mir/eval.rs6
-rw-r--r--crates/hir-ty/src/mir/lower.rs9
-rw-r--r--crates/hir-ty/src/next_solver/generic_arg.rs58
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs27
10 files changed, 99 insertions, 120 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index b9e23464e9..0f989d6c58 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -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) => {
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 19ffa3a939..d1391ad24e 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -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(),
diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs
index 5b0360071d..6ae6f75525 100644
--- a/crates/hir-ty/src/infer/closure/analysis.rs
+++ b/crates/hir-ty/src/infer/closure/analysis.rs
@@ -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 {
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index bb9cb1c1ca..ec7dad0fa0 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -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),
}
}
diff --git a/crates/hir-ty/src/layout.rs b/crates/hir-ty/src/layout.rs
index b6ad3624ae..525100439f 100644
--- a/crates/hir-ty/src/layout.rs
+++ b/crates/hir-ty/src/layout.rs
@@ -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<_>, _>>()?;
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index 941b6c75bf..dece61a57d 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/crates/hir-ty/src/mir/borrowck.rs
@@ -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)
}
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index c7156bb11e..2d1368858b 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -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,
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index e8d42bed9f..762f91fb0d 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -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)),
diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs
index 9936e44321..72cf2f9f07 100644
--- a/crates/hir-ty/src/next_solver/generic_arg.rs
+++ b/crates/hir-ty/src/next_solver/generic_arg.rs
@@ -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(),
}
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index c89831bd40..030ba37015 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -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)
+ })
+ }
+}