hir_ty/next_solver/infer/canonical/
instantiate.rs

1//! This module contains code to instantiate new values into a
2//! `Canonical<'tcx, T>`.
3//!
4//! For an overview of what canonicalization is and how it fits into
5//! rustc, check out the [chapter in the rustc dev guide][c].
6//!
7//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
8
9use crate::next_solver::BoundConst;
10use crate::next_solver::{
11    AliasTy, Binder, BoundRegion, BoundTy, Canonical, CanonicalVarValues, Const, DbInterner, Goal,
12    ParamEnv, Predicate, PredicateKind, Region, Ty, TyKind,
13    fold::FnMutDelegate,
14    infer::{
15        DefineOpaqueTypes, InferCtxt, TypeTrace,
16        traits::{Obligation, PredicateObligations},
17    },
18};
19use rustc_type_ir::{
20    AliasRelationDirection, AliasTyKind, BoundVar, GenericArgKind, InferTy, TypeFoldable, Upcast,
21    Variance,
22    inherent::{IntoKind, SliceLike},
23    relate::{
24        Relate, TypeRelation, VarianceDiagInfo,
25        combine::{super_combine_consts, super_combine_tys},
26    },
27};
28
29pub trait CanonicalExt<'db, V> {
30    fn instantiate(&self, tcx: DbInterner<'db>, var_values: &CanonicalVarValues<'db>) -> V
31    where
32        V: TypeFoldable<DbInterner<'db>>;
33    fn instantiate_projected<T>(
34        &self,
35        tcx: DbInterner<'db>,
36        var_values: &CanonicalVarValues<'db>,
37        projection_fn: impl FnOnce(&V) -> T,
38    ) -> T
39    where
40        T: TypeFoldable<DbInterner<'db>>;
41}
42
43/// FIXME(-Znext-solver): This or public because it is shared with the
44/// new trait solver implementation. We should deduplicate canonicalization.
45impl<'db, V> CanonicalExt<'db, V> for Canonical<'db, V> {
46    /// Instantiate the wrapped value, replacing each canonical value
47    /// with the value given in `var_values`.
48    fn instantiate(&self, tcx: DbInterner<'db>, var_values: &CanonicalVarValues<'db>) -> V
49    where
50        V: TypeFoldable<DbInterner<'db>>,
51    {
52        self.instantiate_projected(tcx, var_values, |value| value.clone())
53    }
54
55    /// Allows one to apply a instantiation to some subset of
56    /// `self.value`. Invoke `projection_fn` with `self.value` to get
57    /// a value V that is expressed in terms of the same canonical
58    /// variables bound in `self` (usually this extracts from subset
59    /// of `self`). Apply the instantiation `var_values` to this value
60    /// V, replacing each of the canonical variables.
61    fn instantiate_projected<T>(
62        &self,
63        tcx: DbInterner<'db>,
64        var_values: &CanonicalVarValues<'db>,
65        projection_fn: impl FnOnce(&V) -> T,
66    ) -> T
67    where
68        T: TypeFoldable<DbInterner<'db>>,
69    {
70        assert_eq!(self.variables.len(), var_values.len());
71        let value = projection_fn(&self.value);
72        instantiate_value(tcx, var_values, value)
73    }
74}
75
76/// Instantiate the values from `var_values` into `value`. `var_values`
77/// must be values for the set of canonical variables that appear in
78/// `value`.
79pub(super) fn instantiate_value<'db, T>(
80    tcx: DbInterner<'db>,
81    var_values: &CanonicalVarValues<'db>,
82    value: T,
83) -> T
84where
85    T: TypeFoldable<DbInterner<'db>>,
86{
87    if var_values.var_values.is_empty() {
88        value
89    } else {
90        let delegate = FnMutDelegate {
91            regions: &mut |br: BoundRegion| match var_values[br.var].kind() {
92                GenericArgKind::Lifetime(l) => l,
93                r => panic!("{br:?} is a region but value is {r:?}"),
94            },
95            types: &mut |bound_ty: BoundTy| match var_values[bound_ty.var].kind() {
96                GenericArgKind::Type(ty) => ty,
97                r => panic!("{bound_ty:?} is a type but value is {r:?}"),
98            },
99            consts: &mut |bound_ct: BoundConst| match var_values[bound_ct.var].kind() {
100                GenericArgKind::Const(ct) => ct,
101                c => panic!("{bound_ct:?} is a const but value is {c:?}"),
102            },
103        };
104
105        tcx.replace_escaping_bound_vars_uncached(value, delegate)
106    }
107}