]> git.proxmox.com Git - rustc.git/blob - vendor/chalk-ir-0.14.0/src/fold/subst.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / vendor / chalk-ir-0.14.0 / src / fold / subst.rs
1 use super::*;
2 use crate::fold::shift::Shift;
3
4 pub struct Subst<'s, 'i, I: Interner> {
5 /// Values to substitute. A reference to a free variable with
6 /// index `i` will be mapped to `parameters[i]` -- if `i >
7 /// parameters.len()`, then we will leave the variable untouched.
8 parameters: &'s [GenericArg<I>],
9 interner: &'i I,
10 }
11
12 impl<I: Interner> Subst<'_, '_, I> {
13 pub fn apply<T: Fold<I, I>>(
14 interner: &I,
15 parameters: &[GenericArg<I>],
16 value: &T,
17 ) -> T::Result {
18 value
19 .fold_with(
20 &mut Subst {
21 parameters,
22 interner,
23 },
24 DebruijnIndex::INNERMOST,
25 )
26 .unwrap()
27 }
28 }
29
30 impl<'i, I: Interner> Folder<'i, I> for Subst<'_, 'i, I> {
31 fn as_dyn(&mut self) -> &mut dyn Folder<'i, I> {
32 self
33 }
34
35 /// We are eliminating one binder, but binders outside of that get preserved.
36 ///
37 /// So e.g. consider this:
38 ///
39 /// ```notrust
40 /// for<A, B> { for<C> { [A, C] } }
41 /// // ^ the binder we are substituing with `[u32]`
42 /// ```
43 ///
44 /// Here, `A` would be `^1.0` and `C` would be `^0.0`. We will replace `^0.0` with the
45 /// 0th index from the list (`u32`). We will convert `^1.0` (A) to `^0.0` -- i.e., shift
46 /// it **out** of one level of binder (the `for<C>` binder we are eliminating).
47 ///
48 /// This gives us as a result:
49 ///
50 /// ```notrust
51 /// for<A, B> { [A, u32] }
52 /// ^ represented as `^0.0`
53 /// ```
54 fn fold_free_var_ty(
55 &mut self,
56 bound_var: BoundVar,
57 outer_binder: DebruijnIndex,
58 ) -> Fallible<Ty<I>> {
59 if let Some(index) = bound_var.index_if_innermost() {
60 match self.parameters[index].data(self.interner()) {
61 GenericArgData::Ty(t) => Ok(t.shifted_in_from(self.interner(), outer_binder)),
62 _ => panic!("mismatched kinds in substitution"),
63 }
64 } else {
65 Ok(bound_var
66 .shifted_out()
67 .expect("cannot fail because this is not the innermost")
68 .shifted_in_from(outer_binder)
69 .to_ty(self.interner()))
70 }
71 }
72
73 /// see `fold_free_var_ty`
74 fn fold_free_var_lifetime(
75 &mut self,
76 bound_var: BoundVar,
77 outer_binder: DebruijnIndex,
78 ) -> Fallible<Lifetime<I>> {
79 if let Some(index) = bound_var.index_if_innermost() {
80 match self.parameters[index].data(self.interner()) {
81 GenericArgData::Lifetime(l) => Ok(l.shifted_in_from(self.interner(), outer_binder)),
82 _ => panic!("mismatched kinds in substitution"),
83 }
84 } else {
85 Ok(bound_var
86 .shifted_out()
87 .unwrap()
88 .shifted_in_from(outer_binder)
89 .to_lifetime(self.interner()))
90 }
91 }
92
93 /// see `fold_free_var_ty`
94 fn fold_free_var_const(
95 &mut self,
96 ty: &Ty<I>,
97 bound_var: BoundVar,
98 outer_binder: DebruijnIndex,
99 ) -> Fallible<Const<I>> {
100 if let Some(index) = bound_var.index_if_innermost() {
101 match self.parameters[index].data(self.interner()) {
102 GenericArgData::Const(c) => Ok(c.shifted_in_from(self.interner(), outer_binder)),
103 _ => panic!("mismatched kinds in substitution"),
104 }
105 } else {
106 Ok(bound_var
107 .shifted_out()
108 .unwrap()
109 .shifted_in_from(outer_binder)
110 .to_const(self.interner(), ty.clone()))
111 }
112 }
113
114 fn interner(&self) -> &'i I {
115 self.interner
116 }
117
118 fn target_interner(&self) -> &'i I {
119 self.interner()
120 }
121 }