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
Lukas Wirth 12 days ago
parent bcc9863 · parent 872df04 · commit a9c0ce4
-rw-r--r--crates/hir-ty/src/infer.rs44
-rw-r--r--crates/hir-ty/src/infer/closure.rs16
-rw-r--r--crates/hir-ty/src/infer/closure/analysis.rs5
-rw-r--r--crates/hir-ty/src/next_solver/binder.rs34
-rw-r--r--crates/hir-ty/src/next_solver/generic_arg.rs42
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs29
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs26
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]