1use crate::*;
4
5pub trait Shift<I: Interner>: TypeFoldable<I> {
8 fn shifted_in(self, interner: I) -> Self;
10
11 fn shifted_in_from(self, interner: I, source_binder: DebruijnIndex) -> Self;
15
16 fn shifted_out(self, interner: I) -> Fallible<Self>;
18
19 fn shifted_out_to(self, interner: I, target_binder: DebruijnIndex) -> Fallible<Self>;
23}
24
25impl<T: TypeFoldable<I>, I: Interner> Shift<I> for T {
26 fn shifted_in(self, interner: I) -> Self {
27 self.shifted_in_from(interner, DebruijnIndex::ONE)
28 }
29
30 fn shifted_in_from(self, interner: I, source_binder: DebruijnIndex) -> T {
31 self.try_fold_with(
32 &mut Shifter {
33 source_binder,
34 interner,
35 },
36 DebruijnIndex::INNERMOST,
37 )
38 .unwrap()
39 }
40
41 fn shifted_out_to(self, interner: I, target_binder: DebruijnIndex) -> Fallible<T> {
42 self.try_fold_with(
43 &mut DownShifter {
44 target_binder,
45 interner,
46 },
47 DebruijnIndex::INNERMOST,
48 )
49 }
50
51 fn shifted_out(self, interner: I) -> Fallible<Self> {
52 self.shifted_out_to(interner, DebruijnIndex::ONE)
53 }
54}
55
56#[derive(FallibleTypeFolder)]
58struct Shifter<I: Interner> {
59 source_binder: DebruijnIndex,
60 interner: I,
61}
62
63impl<I: Interner> Shifter<I> {
64 fn adjust(&self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> BoundVar {
68 bound_var
69 .shifted_in_from(self.source_binder)
70 .shifted_in_from(outer_binder)
71 }
72}
73
74impl<I: Interner> TypeFolder<I> for Shifter<I> {
75 fn as_dyn(&mut self) -> &mut dyn TypeFolder<I> {
76 self
77 }
78
79 fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty<I> {
80 TyKind::<I>::BoundVar(self.adjust(bound_var, outer_binder))
81 .intern(TypeFolder::interner(self))
82 }
83
84 fn fold_free_var_lifetime(
85 &mut self,
86 bound_var: BoundVar,
87 outer_binder: DebruijnIndex,
88 ) -> Lifetime<I> {
89 LifetimeData::<I>::BoundVar(self.adjust(bound_var, outer_binder))
90 .intern(TypeFolder::interner(self))
91 }
92
93 fn fold_free_var_const(
94 &mut self,
95 ty: Ty<I>,
96 bound_var: BoundVar,
97 outer_binder: DebruijnIndex,
98 ) -> Const<I> {
99 self.adjust(bound_var, outer_binder)
101 .to_const(TypeFolder::interner(self), ty)
102 }
103
104 fn interner(&self) -> I {
105 self.interner
106 }
107}
108
109struct DownShifter<I> {
115 target_binder: DebruijnIndex,
116 interner: I,
117}
118
119impl<I> DownShifter<I> {
120 fn adjust(&self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Fallible<BoundVar> {
129 match bound_var.shifted_out_to(self.target_binder) {
130 Some(bound_var1) => Ok(bound_var1.shifted_in_from(outer_binder)),
131 None => Err(NoSolution),
132 }
133 }
134}
135
136impl<I: Interner> FallibleTypeFolder<I> for DownShifter<I> {
137 type Error = NoSolution;
138
139 fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<I, Error = Self::Error> {
140 self
141 }
142
143 fn try_fold_free_var_ty(
144 &mut self,
145 bound_var: BoundVar,
146 outer_binder: DebruijnIndex,
147 ) -> Fallible<Ty<I>> {
148 Ok(TyKind::<I>::BoundVar(self.adjust(bound_var, outer_binder)?).intern(self.interner()))
149 }
150
151 fn try_fold_free_var_lifetime(
152 &mut self,
153 bound_var: BoundVar,
154 outer_binder: DebruijnIndex,
155 ) -> Fallible<Lifetime<I>> {
156 Ok(
157 LifetimeData::<I>::BoundVar(self.adjust(bound_var, outer_binder)?)
158 .intern(self.interner()),
159 )
160 }
161
162 fn try_fold_free_var_const(
163 &mut self,
164 ty: Ty<I>,
165 bound_var: BoundVar,
166 outer_binder: DebruijnIndex,
167 ) -> Fallible<Const<I>> {
168 Ok(self
170 .adjust(bound_var, outer_binder)?
171 .to_const(self.interner(), ty))
172 }
173
174 fn interner(&self) -> I {
175 self.interner
176 }
177}