]>
git.proxmox.com Git - rustc.git/blob - vendor/chalk-ir-0.14.0/src/fold/shift.rs
4 /// Methods for converting debruijn indices to move values into or out
6 pub trait Shift
<I
: Interner
>: Fold
<I
, I
> {
7 /// Shifts this term in one level of binders.
8 fn shifted_in(&self, interner
: &I
) -> Self::Result
;
10 /// Shifts a term valid at `outer_binder` so that it is
11 /// valid at the innermost binder. See [`DebruijnIndex::shifted_in_from`]
12 /// for a detailed explanation.
13 fn shifted_in_from(&self, interner
: &I
, source_binder
: DebruijnIndex
) -> Self::Result
;
15 /// Shifts this term out one level of binders.
16 fn shifted_out(&self, interner
: &I
) -> Fallible
<Self::Result
>;
18 /// Shifts a term valid at the innermost binder so that it is
19 /// valid at `outer_binder`. See [`DebruijnIndex::shifted_out_to`]
20 /// for a detailed explanation.
21 fn shifted_out_to(&self, interner
: &I
, target_binder
: DebruijnIndex
) -> Fallible
<Self::Result
>;
24 impl<T
: Fold
<I
, I
>, I
: Interner
> Shift
<I
> for T
{
25 fn shifted_in(&self, interner
: &I
) -> Self::Result
{
26 self.shifted_in_from(interner
, DebruijnIndex
::ONE
)
29 fn shifted_in_from(&self, interner
: &I
, source_binder
: DebruijnIndex
) -> T
::Result
{
35 DebruijnIndex
::INNERMOST
,
40 fn shifted_out_to(&self, interner
: &I
, target_binder
: DebruijnIndex
) -> Fallible
<T
::Result
> {
46 DebruijnIndex
::INNERMOST
,
50 fn shifted_out(&self, interner
: &I
) -> Fallible
<Self::Result
> {
51 self.shifted_out_to(interner
, DebruijnIndex
::ONE
)
55 /// A folder that adjusts debruijn indices by a certain amount.
56 struct Shifter
<'i
, I
> {
57 source_binder
: DebruijnIndex
,
61 impl<I
> Shifter
<'_
, I
> {
62 /// Given a free variable at `depth`, shifts that depth to `depth
63 /// + self.adjustment`, and then wraps *that* within the internal
65 fn adjust(&self, bound_var
: BoundVar
, outer_binder
: DebruijnIndex
) -> BoundVar
{
67 .shifted_in_from(self.source_binder
)
68 .shifted_in_from(outer_binder
)
72 impl<'i
, I
: Interner
> Folder
<'i
, I
> for Shifter
<'i
, I
> {
73 fn as_dyn(&mut self) -> &mut dyn Folder
<'i
, I
> {
80 outer_binder
: DebruijnIndex
,
81 ) -> Fallible
<Ty
<I
>> {
82 Ok(TyData
::<I
>::BoundVar(self.adjust(bound_var
, outer_binder
)).intern(self.interner()))
85 fn fold_free_var_lifetime(
88 outer_binder
: DebruijnIndex
,
89 ) -> Fallible
<Lifetime
<I
>> {
91 LifetimeData
::<I
>::BoundVar(self.adjust(bound_var
, outer_binder
))
92 .intern(self.interner()),
96 fn fold_free_var_const(
100 outer_binder
: DebruijnIndex
,
101 ) -> Fallible
<Const
<I
>> {
102 // const types don't have free variables, so we can skip folding `ty`
104 .adjust(bound_var
, outer_binder
)
105 .to_const(self.interner(), ty
.clone()))
108 fn interner(&self) -> &'i I
{
112 fn target_interner(&self) -> &'i I
{
117 //---------------------------------------------------------------------------
119 /// A shifter that reduces debruijn indices -- in other words, which lifts a value
120 /// *out* from binders. Consider this example:
122 struct DownShifter
<'i
, I
> {
123 target_binder
: DebruijnIndex
,
127 impl<I
> DownShifter
<'_
, I
> {
128 /// Given a reference to a free variable at depth `depth`
129 /// (appearing within `binders` internal binders), attempts to
130 /// lift that free variable out from `adjustment` levels of
131 /// binders (i.e., convert it to depth `depth -
132 /// self.adjustment`). If the free variable is bound by one of
133 /// those internal binders (i.e., `depth < self.adjustment`) the
134 /// this will fail with `Err`. Otherwise, returns the variable at
135 /// this new depth (but adjusted to appear within `binders`).
136 fn adjust(&self, bound_var
: BoundVar
, outer_binder
: DebruijnIndex
) -> Fallible
<BoundVar
> {
137 match bound_var
.shifted_out_to(self.target_binder
) {
138 Some(bound_var1
) => Ok(bound_var1
.shifted_in_from(outer_binder
)),
139 None
=> Err(NoSolution
),
144 impl<'i
, I
: Interner
> Folder
<'i
, I
> for DownShifter
<'i
, I
> {
145 fn as_dyn(&mut self) -> &mut dyn Folder
<'i
, I
> {
152 outer_binder
: DebruijnIndex
,
153 ) -> Fallible
<Ty
<I
>> {
154 Ok(TyData
::<I
>::BoundVar(self.adjust(bound_var
, outer_binder
)?
).intern(self.interner()))
157 fn fold_free_var_lifetime(
160 outer_binder
: DebruijnIndex
,
161 ) -> Fallible
<Lifetime
<I
>> {
163 LifetimeData
::<I
>::BoundVar(self.adjust(bound_var
, outer_binder
)?
)
164 .intern(self.interner()),
168 fn fold_free_var_const(
172 outer_binder
: DebruijnIndex
,
173 ) -> Fallible
<Const
<I
>> {
174 // const types don't have free variables, so we can skip folding `ty`
176 .adjust(bound_var
, outer_binder
)?
177 .to_const(self.interner(), ty
.clone()))
180 fn interner(&self) -> &'i I
{
184 fn target_interner(&self) -> &'i I
{