1 //! This module contains code to substitute new values into a
2 //! `Canonical<'tcx, T>`.
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].
7 //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
9 use crate::infer
::canonical
::{Canonical, CanonicalVarValues}
;
10 use rustc_middle
::ty
::fold
::{FnMutDelegate, TypeFoldable}
;
11 use rustc_middle
::ty
::subst
::GenericArgKind
;
12 use rustc_middle
::ty
::{self, TyCtxt}
;
14 pub(super) trait CanonicalExt
<'tcx
, V
> {
15 /// Instantiate the wrapped value, replacing each canonical value
16 /// with the value given in `var_values`.
17 fn substitute(&self, tcx
: TyCtxt
<'tcx
>, var_values
: &CanonicalVarValues
<'tcx
>) -> V
19 V
: TypeFoldable
<'tcx
>;
21 /// Allows one to apply a substitute to some subset of
22 /// `self.value`. Invoke `projection_fn` with `self.value` to get
23 /// a value V that is expressed in terms of the same canonical
24 /// variables bound in `self` (usually this extracts from subset
25 /// of `self`). Apply the substitution `var_values` to this value
26 /// V, replacing each of the canonical variables.
27 fn substitute_projected
<T
>(
30 var_values
: &CanonicalVarValues
<'tcx
>,
31 projection_fn
: impl FnOnce(&V
) -> T
,
34 T
: TypeFoldable
<'tcx
>;
37 impl<'tcx
, V
> CanonicalExt
<'tcx
, V
> for Canonical
<'tcx
, V
> {
38 fn substitute(&self, tcx
: TyCtxt
<'tcx
>, var_values
: &CanonicalVarValues
<'tcx
>) -> V
40 V
: TypeFoldable
<'tcx
>,
42 self.substitute_projected(tcx
, var_values
, |value
| value
.clone())
45 fn substitute_projected
<T
>(
48 var_values
: &CanonicalVarValues
<'tcx
>,
49 projection_fn
: impl FnOnce(&V
) -> T
,
52 T
: TypeFoldable
<'tcx
>,
54 assert_eq
!(self.variables
.len(), var_values
.len());
55 let value
= projection_fn(&self.value
);
56 substitute_value(tcx
, var_values
, value
)
60 /// Substitute the values from `var_values` into `value`. `var_values`
61 /// must be values for the set of canonical variables that appear in
63 pub(super) fn substitute_value
<'tcx
, T
>(
65 var_values
: &CanonicalVarValues
<'tcx
>,
69 T
: TypeFoldable
<'tcx
>,
71 if var_values
.var_values
.is_empty() {
74 let delegate
= FnMutDelegate
{
75 regions
: |br
: ty
::BoundRegion
| match var_values
.var_values
[br
.var
].unpack() {
76 GenericArgKind
::Lifetime(l
) => l
,
77 r
=> bug
!("{:?} is a region but value is {:?}", br
, r
),
79 types
: |bound_ty
: ty
::BoundTy
| match var_values
.var_values
[bound_ty
.var
].unpack() {
80 GenericArgKind
::Type(ty
) => ty
,
81 r
=> bug
!("{:?} is a type but value is {:?}", bound_ty
, r
),
83 consts
: |bound_ct
: ty
::BoundVar
, _
| match var_values
.var_values
[bound_ct
].unpack() {
84 GenericArgKind
::Const(ct
) => ct
,
85 c
=> bug
!("{:?} is a const but value is {:?}", bound_ct
, c
),
89 tcx
.replace_escaping_bound_vars_uncached(value
, delegate
)