]>
git.proxmox.com Git - rustc.git/blob - vendor/chalk-ir/src/fold/shift.rs
1 //! Shifting of debruijn indices
5 /// Methods for converting debruijn indices to move values into or out
7 pub trait Shift
<I
: Interner
>: TypeFoldable
<I
> {
8 /// Shifts this term in one level of binders.
9 fn shifted_in(self, interner
: I
) -> Self;
11 /// Shifts a term valid at `outer_binder` so that it is
12 /// valid at the innermost binder. See [`DebruijnIndex::shifted_in_from`]
13 /// for a detailed explanation.
14 fn shifted_in_from(self, interner
: I
, source_binder
: DebruijnIndex
) -> Self;
16 /// Shifts this term out one level of binders.
17 fn shifted_out(self, interner
: I
) -> Fallible
<Self>;
19 /// Shifts a term valid at the innermost binder so that it is
20 /// valid at `outer_binder`. See [`DebruijnIndex::shifted_out_to`]
21 /// for a detailed explanation.
22 fn shifted_out_to(self, interner
: I
, target_binder
: DebruijnIndex
) -> Fallible
<Self>;
25 impl<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
)
30 fn shifted_in_from(self, interner
: I
, source_binder
: DebruijnIndex
) -> T
{
36 DebruijnIndex
::INNERMOST
,
41 fn shifted_out_to(self, interner
: I
, target_binder
: DebruijnIndex
) -> Fallible
<T
> {
47 DebruijnIndex
::INNERMOST
,
51 fn shifted_out(self, interner
: I
) -> Fallible
<Self> {
52 self.shifted_out_to(interner
, DebruijnIndex
::ONE
)
56 /// A folder that adjusts debruijn indices by a certain amount.
57 #[derive(FallibleTypeFolder)]
58 struct Shifter
<I
: Interner
> {
59 source_binder
: DebruijnIndex
,
63 impl<I
: Interner
> Shifter
<I
> {
64 /// Given a free variable at `depth`, shifts that depth to `depth
65 /// + self.adjustment`, and then wraps *that* within the internal
67 fn adjust(&self, bound_var
: BoundVar
, outer_binder
: DebruijnIndex
) -> BoundVar
{
69 .shifted_in_from(self.source_binder
)
70 .shifted_in_from(outer_binder
)
74 impl<I
: Interner
> TypeFolder
<I
> for Shifter
<I
> {
75 fn as_dyn(&mut self) -> &mut dyn TypeFolder
<I
> {
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))
84 fn fold_free_var_lifetime(
87 outer_binder
: DebruijnIndex
,
89 LifetimeData
::<I
>::BoundVar(self.adjust(bound_var
, outer_binder
))
90 .intern(TypeFolder
::interner(self))
93 fn fold_free_var_const(
97 outer_binder
: DebruijnIndex
,
99 // const types don't have free variables, so we can skip folding `ty`
100 self.adjust(bound_var
, outer_binder
)
101 .to_const(TypeFolder
::interner(self), ty
)
104 fn interner(&self) -> I
{
109 //---------------------------------------------------------------------------
111 /// A shifter that reduces debruijn indices -- in other words, which lifts a value
112 /// *out* from binders. Consider this example:
114 struct DownShifter
<I
> {
115 target_binder
: DebruijnIndex
,
119 impl<I
> DownShifter
<I
> {
120 /// Given a reference to a free variable at depth `depth`
121 /// (appearing within `binders` internal binders), attempts to
122 /// lift that free variable out from `adjustment` levels of
123 /// binders (i.e., convert it to depth `depth -
124 /// self.adjustment`). If the free variable is bound by one of
125 /// those internal binders (i.e., `depth < self.adjustment`) the
126 /// this will fail with `Err`. Otherwise, returns the variable at
127 /// this new depth (but adjusted to appear within `binders`).
128 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
),
136 impl<I
: Interner
> FallibleTypeFolder
<I
> for DownShifter
<I
> {
137 type Error
= NoSolution
;
139 fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder
<I
, Error
= Self::Error
> {
143 fn try_fold_free_var_ty(
146 outer_binder
: DebruijnIndex
,
147 ) -> Fallible
<Ty
<I
>> {
148 Ok(TyKind
::<I
>::BoundVar(self.adjust(bound_var
, outer_binder
)?
).intern(self.interner()))
151 fn try_fold_free_var_lifetime(
154 outer_binder
: DebruijnIndex
,
155 ) -> Fallible
<Lifetime
<I
>> {
157 LifetimeData
::<I
>::BoundVar(self.adjust(bound_var
, outer_binder
)?
)
158 .intern(self.interner()),
162 fn try_fold_free_var_const(
166 outer_binder
: DebruijnIndex
,
167 ) -> Fallible
<Const
<I
>> {
168 // const types don't have free variables, so we can skip folding `ty`
170 .adjust(bound_var
, outer_binder
)?
171 .to_const(self.interner(), ty
))
174 fn interner(&self) -> I
{