Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22945 from ChayimFriedman2/liberated-sigs
internal: Store liberated closure sigs in InferenceResult
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 44 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/closure.rs | 16 | ||||
| -rw-r--r-- | crates/hir-ty/src/infer/closure/analysis.rs | 5 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/binder.rs | 34 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/generic_arg.rs | 42 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/interner.rs | 29 | ||||
| -rw-r--r-- | crates/hir-ty/src/next_solver/ty.rs | 26 |
7 files changed, 115 insertions, 81 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index bd00da84ca..c838fcc3a7 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -99,7 +99,7 @@ use crate::{ }, method_resolution::CandidateId, next_solver::{ - AliasTy, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, + AliasTy, Const, ConstKind, DbInterner, ErrorGuaranteed, GenericArgs, Region, StoredFnSig, StoredGenericArg, StoredGenericArgs, StoredTy, StoredTys, Term, Ty, TyKind, Tys, abi::Safety, infer::{InferCtxt, ObligationInspector, traits::ObligationCause}, @@ -820,7 +820,7 @@ pub struct InferenceResult<'db> { defined_anon_consts: ThinVec<AnonConstId<'db>>, } -#[derive(Clone, PartialEq, Eq, Debug, Default)] +#[derive(Clone, PartialEq, Eq, Debug)] pub struct ClosureData { /// Tracks the minimum captures required for a closure; /// see `MinCaptureInformationMap` for more details. @@ -849,6 +849,42 @@ pub struct ClosureData { /// information on `t` in order to create place `t.0` and `t.1`. We can solve this /// issue by fake reading `t`. pub fake_reads: Box<[(Place, FakeReadCause, SmallVec<[CaptureSourceStack; 2]>)]>, + + /// For each fn, records the "liberated" types of its arguments + /// and return type. Liberated means that all bound regions + /// (including late-bound regions) are replaced with free + /// equivalents. This table is not used in codegen (since regions + /// are erased there) and hence is not serialized to metadata. + /// + /// This table also contains the "revealed" values for any `impl Trait` + /// that appear in the signature and whose values are being inferred + /// by this function. + /// + /// # Example + /// + /// ```rust + /// # use std::fmt::Debug; + /// fn foo(x: &u32) -> impl Debug { *x } + /// ``` + /// + /// The function signature here would be: + /// + /// ```ignore (illustrative) + /// for<'a> fn(&'a u32) -> Foo + /// ``` + /// + /// where `Foo` is an opaque type created for this function. + /// + /// + /// The *liberated* form of this would be + /// + /// ```ignore (illustrative) + /// fn(&'a u32) -> u32 + /// ``` + /// + /// Note that `'a` is not bound (it would be an `ReLateParam`) and + /// that the `Foo` opaque type is replaced by its hidden type. + pub liberated_sig: StoredFnSig, } /// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`. @@ -1677,7 +1713,7 @@ impl<'db> InferenceContext<'db> { } pat_adjustments.shrink_to_fit(); for closure_data in closures_data.values_mut() { - let ClosureData { min_captures, fake_reads } = closure_data; + let ClosureData { min_captures, fake_reads, liberated_sig } = closure_data; let dummy_place = || Place { base_ty: types.types.error.store(), base: closure::analysis::expr_use_visitor::PlaceBase::Rvalue, @@ -1706,6 +1742,8 @@ impl<'db> InferenceContext<'db> { min_capture.shrink_to_fit(); } min_captures.shrink_to_fit(); + + resolver.resolve_completely(liberated_sig); } closures_data.shrink_to_fit(); *tuple_field_access_types = tuple_field_accesses_rev diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs index e2948a81ac..9af182fc49 100644 --- a/crates/hir-ty/src/infer/closure.rs +++ b/crates/hir-ty/src/infer/closure.rs @@ -9,6 +9,7 @@ use hir_def::{ hir::{ClosureKind, CoroutineKind, CoroutineSource, ExprId, PatId}, type_ref::TypeRefId, }; +use indexmap::IndexMap; use rustc_abi::ExternAbi; use rustc_type_ir::{ AliasTyKind, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, @@ -21,11 +22,11 @@ use tracing::{debug, instrument}; use crate::{ Span, db::{InternedClosure, InternedClosureId, InternedCoroutineClosureId, InternedCoroutineId}, - infer::{BreakableKind, Diverges, coerce::CoerceMany, pat::PatOrigin}, + infer::{BreakableKind, ClosureData, Diverges, coerce::CoerceMany, pat::PatOrigin}, next_solver::{ AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArg, PolyFnSig, - PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, TermId, Ty, TyKind, - Unnormalized, + PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, StoredFnSig, TermId, Ty, + TyKind, Unnormalized, abi::Safety, infer::{ BoundRegionConversionTime, InferOk, InferResult, @@ -303,6 +304,15 @@ impl<'db> InferenceContext<'db> { } }; + self.result.closures_data.insert( + closure_expr, + ClosureData { + liberated_sig: StoredFnSig::new(liberated_sig), + fake_reads: Box::default(), + min_captures: IndexMap::default(), + }, + ); + // Now go through the argument patterns for (arg_pat, arg_ty) in args.iter().zip(liberated_sig.inputs()) { self.infer_top_pat(*arg_pat, *arg_ty, PatOrigin::Param); diff --git a/crates/hir-ty/src/infer/closure/analysis.rs b/crates/hir-ty/src/infer/closure/analysis.rs index 38e634eb7d..0c24b82d1b 100644 --- a/crates/hir-ty/src/infer/closure/analysis.rs +++ b/crates/hir-ty/src/infer/closure/analysis.rs @@ -515,7 +515,7 @@ impl<'db> InferenceContext<'db> { let fake_reads = delegate.fake_reads; - self.result.closures_data.entry(closure_expr_id).or_default().fake_reads = + self.result.closures_data.get_mut(&closure_expr_id).unwrap().fake_reads = fake_reads.into_boxed_slice(); // If we are also inferred the closure kind here, @@ -730,8 +730,7 @@ impl<'db> InferenceContext<'db> { return; } - let mut closure_data = - self.result.closures_data.remove(&closure_def_id).unwrap_or_default(); + let mut closure_data = self.result.closures_data.remove(&closure_def_id).unwrap(); let root_var_min_capture_list = &mut closure_data.min_captures; let mut dedup_sources_scratch = FxHashMap::default(); diff --git a/crates/hir-ty/src/next_solver/binder.rs b/crates/hir-ty/src/next_solver/binder.rs index 9585cced6b..351d0c4cda 100644 --- a/crates/hir-ty/src/next_solver/binder.rs +++ b/crates/hir-ty/src/next_solver/binder.rs @@ -71,17 +71,33 @@ impl StoredEarlyBinder<StoredTraitRef> { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StoredPolyFnSig { bound_vars: StoredBoundVarKinds, - inputs_and_output: StoredTys, - fn_sig_kind: FnSigKind<'static>, + sig: StoredFnSig, } impl StoredPolyFnSig { #[inline] pub fn new(sig: PolyFnSig<'_>) -> Self { let bound_vars = sig.bound_vars().store(); - let sig = sig.skip_binder(); + Self { bound_vars, sig: StoredFnSig::new(sig.skip_binder()) } + } + + #[inline] + pub fn get(&self) -> PolyFnSig<'_> { + Binder::bind_with_vars(self.sig.get(), self.bound_vars.as_ref()) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable)] +pub struct StoredFnSig { + inputs_and_output: StoredTys, + #[type_visitable(ignore)] + fn_sig_kind: FnSigKind<'static>, +} + +impl StoredFnSig { + #[inline] + pub fn new(sig: FnSig<'_>) -> Self { Self { - bound_vars, inputs_and_output: sig.inputs_and_output.store(), fn_sig_kind: FnSigKind::new( sig.fn_sig_kind.abi(), @@ -92,14 +108,8 @@ impl StoredPolyFnSig { } #[inline] - pub fn get(&self) -> PolyFnSig<'_> { - Binder::bind_with_vars( - FnSig { - inputs_and_output: self.inputs_and_output.as_ref(), - fn_sig_kind: self.fn_sig_kind, - }, - self.bound_vars.as_ref(), - ) + pub fn get(&self) -> FnSig<'_> { + FnSig { inputs_and_output: self.inputs_and_output.as_ref(), fn_sig_kind: self.fn_sig_kind } } } diff --git a/crates/hir-ty/src/next_solver/generic_arg.rs b/crates/hir-ty/src/next_solver/generic_arg.rs index 22b34b379d..483811f9e6 100644 --- a/crates/hir-ty/src/next_solver/generic_arg.rs +++ b/crates/hir-ty/src/next_solver/generic_arg.rs @@ -21,7 +21,8 @@ use rustc_type_ir::{ }; use crate::next_solver::{ - ConstInterned, RegionInterned, TyInterned, impl_foldable_for_interned_slice, interned_slice, + ConstInterned, RegionInterned, TyInterned, impl_foldable_for_interned_slice, + impl_foldable_for_stored_type, interned_slice, }; use super::{ @@ -194,24 +195,7 @@ impl std::fmt::Debug for StoredGenericArg { } } -impl<'db> TypeVisitable<DbInterner<'db>> for StoredGenericArg { - fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result { - self.as_ref().visit_with(visitor) - } -} - -impl<'db> TypeFoldable<DbInterner<'db>> for StoredGenericArg { - fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>( - self, - folder: &mut F, - ) -> Result<Self, F::Error> { - Ok(self.as_ref().try_fold_with(folder)?.store()) - } - - fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { - self.as_ref().fold_with(folder).store() - } -} +impl_foldable_for_stored_type!(StoredGenericArg); #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct GenericArg<'db> { @@ -473,28 +457,10 @@ interned_slice!( GenericArg<'static>, ); impl_foldable_for_interned_slice!(GenericArgs); +impl_foldable_for_stored_type!(StoredGenericArgs); impl<'db> rustc_type_ir::inherent::GenericArg<DbInterner<'db>> for GenericArg<'db> {} -impl<'db> TypeVisitable<DbInterner<'db>> for StoredGenericArgs { - fn visit_with<V: TypeVisitor<DbInterner<'db>>>(&self, visitor: &mut V) -> V::Result { - self.as_ref().visit_with(visitor) - } -} - -impl<'db> TypeFoldable<DbInterner<'db>> for StoredGenericArgs { - fn try_fold_with<F: FallibleTypeFolder<DbInterner<'db>>>( - self, - folder: &mut F, - ) -> Result<Self, F::Error> { - Ok(self.as_ref().try_fold_with(folder)?.store()) - } - - fn fold_with<F: TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { - self.as_ref().fold_with(folder).store() - } -} - trait GenericArgsBuilder<'db>: AsRef<[GenericArg<'db>]> { fn push(&mut self, arg: GenericArg<'db>); } diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs index dc30c1e582..7554ca6bcd 100644 --- a/crates/hir-ty/src/next_solver/interner.rs +++ b/crates/hir-ty/src/next_solver/interner.rs @@ -265,6 +265,35 @@ macro_rules! impl_foldable_for_interned_slice { } pub(crate) use impl_foldable_for_interned_slice; +macro_rules! impl_foldable_for_stored_type { + ($name:ident) => { + impl<'db> ::rustc_type_ir::TypeVisitable<DbInterner<'db>> for $name { + fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( + &self, + visitor: &mut V, + ) -> V::Result { + self.as_ref().visit_with(visitor) + } + } + + impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for $name { + fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(self.as_ref().try_fold_with(folder)?.store()) + } + fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>( + self, + folder: &mut F, + ) -> Self { + self.as_ref().fold_with(folder).store() + } + } + }; +} +pub(crate) use impl_foldable_for_stored_type; + macro_rules! impl_stored_interned { ( $storage:ident, $name:ident, $stored_name:ident $(,)? ) => { #[derive(Clone, PartialEq, Eq, Hash)] diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs index 05f559c034..36c18ed772 100644 --- a/crates/hir-ty/src/next_solver/ty.rs +++ b/crates/hir-ty/src/next_solver/ty.rs @@ -33,7 +33,8 @@ use crate::{ CoroutineClosureIdWrapper, CoroutineIdWrapper, FnSig, GenericArgKind, PolyFnSig, Predicate, Region, TraitRef, TypeAliasIdWrapper, Unnormalized, abi::Safety, - impl_foldable_for_interned_slice, impl_stored_interned, interned_slice, + impl_foldable_for_interned_slice, impl_foldable_for_stored_type, impl_stored_interned, + interned_slice, util::{CoroutineArgsExt, IntegerTypeExt}, }, }; @@ -61,6 +62,7 @@ pub(super) struct TyInterned(WithCachedTypeInfo<TyKind<'static>>); impl_internable!(gc; TyInterned); impl_stored_interned!(TyInterned, Ty, StoredTy); +impl_foldable_for_stored_type!(StoredTy); const _: () = { const fn is_copy<T: Copy>() {} @@ -894,15 +896,6 @@ impl<'db> TypeVisitable<DbInterner<'db>> for Ty<'db> { } } -impl<'db> TypeVisitable<DbInterner<'db>> for StoredTy { - fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( - &self, - visitor: &mut V, - ) -> V::Result { - self.as_ref().visit_with(visitor) - } -} - impl<'db> TypeSuperVisitable<DbInterner<'db>> for Ty<'db> { fn super_visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( &self, @@ -969,18 +962,6 @@ impl<'db> TypeFoldable<DbInterner<'db>> for Ty<'db> { } } -impl<'db> TypeFoldable<DbInterner<'db>> for StoredTy { - fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( - self, - folder: &mut F, - ) -> Result<Self, F::Error> { - Ok(self.as_ref().try_fold_with(folder)?.store()) - } - fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { - self.as_ref().fold_with(folder).store() - } -} - impl<'db> TypeSuperFoldable<DbInterner<'db>> for Ty<'db> { fn try_super_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( self, @@ -1422,6 +1403,7 @@ impl<'db> rustc_type_ir::inherent::Ty<DbInterner<'db>> for Ty<'db> { interned_slice!(TysStorage, Tys, StoredTys, tys, Ty<'db>, Ty<'static>); impl_foldable_for_interned_slice!(Tys); +impl_foldable_for_stored_type!(StoredTys); impl<'db> Tys<'db> { #[inline] |