Unnamed repository; edit this file 'description' to name the repository.
Store liberated closure sigs in InferenceResult
We (will) need them in later stages, e.g. MIR building.
Chayim Refael Friedman 12 days ago
parent bec6681 · commit 872df04
-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]