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::, _>>()?; 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> { - // 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> { self.iter().filter_map(|it| it.as_type()) } @@ -688,27 +660,9 @@ impl<'db> rustc_type_ir::inherent::GenericArgs> 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> 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) + }) + } +}