Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs')
-rw-r--r--crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs96
1 files changed, 80 insertions, 16 deletions
diff --git a/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs b/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
index 6c7a87ef52..6360291071 100644
--- a/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
+++ b/crates/hir-ty/src/next_solver/infer/canonical/instantiate.rs
@@ -6,24 +6,15 @@
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-use crate::next_solver::BoundConst;
use crate::next_solver::{
- AliasTy, Binder, BoundRegion, BoundTy, Canonical, CanonicalVarValues, Const, DbInterner, Goal,
- ParamEnv, Predicate, PredicateKind, Region, Ty, TyKind,
- fold::FnMutDelegate,
- infer::{
- DefineOpaqueTypes, InferCtxt, TypeTrace,
- traits::{Obligation, PredicateObligations},
- },
+ BoundConst, BoundRegion, BoundTy, Canonical, CanonicalVarValues, Clauses, Const, ConstKind,
+ DbInterner, GenericArg, Predicate, Region, RegionKind, Ty, TyKind, fold::FnMutDelegate,
};
+use rustc_hash::FxHashMap;
use rustc_type_ir::{
- AliasRelationDirection, AliasTyKind, BoundVar, GenericArgKind, InferTy, TypeFoldable, Upcast,
- Variance,
- inherent::{IntoKind, SliceLike},
- relate::{
- Relate, TypeRelation, VarianceDiagInfo,
- combine::{super_combine_consts, super_combine_tys},
- },
+ BoundVarIndexKind, GenericArgKind, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
+ TypeVisitableExt,
+ inherent::{GenericArg as _, IntoKind, SliceLike},
};
pub trait CanonicalExt<'db, V> {
@@ -102,6 +93,79 @@ where
},
};
- tcx.replace_escaping_bound_vars_uncached(value, delegate)
+ let value = tcx.replace_escaping_bound_vars_uncached(value, delegate);
+ value.fold_with(&mut CanonicalInstantiator {
+ tcx,
+ var_values: var_values.var_values.as_slice(),
+ cache: Default::default(),
+ })
+ }
+}
+
+/// Replaces the bound vars in a canonical binder with var values.
+struct CanonicalInstantiator<'db, 'a> {
+ tcx: DbInterner<'db>,
+
+ // The values that the bound vars are being instantiated with.
+ var_values: &'a [GenericArg<'db>],
+
+ // Because we use `BoundVarIndexKind::Canonical`, we can cache
+ // based only on the entire ty, not worrying about a `DebruijnIndex`
+ cache: FxHashMap<Ty<'db>, Ty<'db>>,
+}
+
+impl<'db, 'a> TypeFolder<DbInterner<'db>> for CanonicalInstantiator<'db, 'a> {
+ fn cx(&self) -> DbInterner<'db> {
+ self.tcx
+ }
+
+ fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
+ match t.kind() {
+ TyKind::Bound(BoundVarIndexKind::Canonical, bound_ty) => {
+ self.var_values[bound_ty.var.as_usize()].expect_ty()
+ }
+ _ => {
+ if !t.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) {
+ t
+ } else if let Some(&t) = self.cache.get(&t) {
+ t
+ } else {
+ let res = t.super_fold_with(self);
+ assert!(self.cache.insert(t, res).is_none());
+ res
+ }
+ }
+ }
+ }
+
+ fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
+ match r.kind() {
+ RegionKind::ReBound(BoundVarIndexKind::Canonical, br) => {
+ self.var_values[br.var.as_usize()].expect_region()
+ }
+ _ => r,
+ }
+ }
+
+ fn fold_const(&mut self, ct: Const<'db>) -> Const<'db> {
+ match ct.kind() {
+ ConstKind::Bound(BoundVarIndexKind::Canonical, bound_const) => {
+ self.var_values[bound_const.var.as_usize()].expect_const()
+ }
+ _ => ct.super_fold_with(self),
+ }
+ }
+
+ fn fold_predicate(&mut self, p: Predicate<'db>) -> Predicate<'db> {
+ if p.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) { p.super_fold_with(self) } else { p }
+ }
+
+ fn fold_clauses(&mut self, c: Clauses<'db>) -> Clauses<'db> {
+ if !c.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) {
+ return c;
+ }
+
+ // FIXME: We might need cache here for perf like rustc
+ c.super_fold_with(self)
}
}