[−][src]Trait chalk_ir::fold::Folder
A "folder" is a transformer that can be used to make a copy of
some term -- that is, some bit of IR, such as a Goal
-- with
certain changes applied. The idea is that it contains methods that
let you swap types/lifetimes for new types/lifetimes; meanwhile,
each bit of IR implements the Fold
trait which, given a
Folder
, will reconstruct itself, invoking the folder's methods
to transform each of the types/lifetimes embedded within.
Interners
The Folder trait has two type parameters, I
and TI
:
I
is the "source interner" that we are folding fromTI
is the "target interner" that we are folding into
Often, both are the same.
Usage patterns
Substituting for free variables
Most of the time, though, we are not interested in adjust arbitrary types/lifetimes, but rather just free variables (even more often, just free existential variables) that appear within the term.
For this reason, the Folder
trait extends two other traits that
contain methods that are invoked when just those particular
In particular, folders can intercept references to free variables (either existentially or universally quantified) and replace them with other types/lifetimes as appropriate.
To create a folder F
, one never implements Folder
directly, but instead
implements one of each of these three sub-traits:
FreeVarFolder
-- foldsBoundVar
instances that appear free in the term being folded (useDefaultFreeVarFolder
to ignore/forbid these altogether)InferenceFolder
-- folds existentialInferenceVar
instances that appear in the term being folded (useDefaultInferenceFolder
to ignore/forbid these altogether)PlaceholderFolder
-- folds universalPlaceholder
instances that appear in the term being folded (useDefaultPlaceholderFolder
to ignore/forbid these altogether)
To apply a folder, use the Fold::fold_with
method, like so
let x = x.fold_with(&mut folder, 0);
Required methods
fn as_dyn(&mut self) -> &mut dyn Folder<'i, I, TI>
Creates a dyn
value from this folder. Unfortunately, this
must be added manually to each impl of Folder; it permits the
default implements below to create a &mut dyn Folder
from
Self
without knowing what Self
is (by invoking this
method). Effectively, this limits impls of Folder
to types
for which we are able to create a dyn value (i.e., not [T]
types).
fn interner(&self) -> &'i I
Gets the interner that is being folded from.
fn target_interner(&self) -> &'i TI
Gets the interner that is being folded to.
Provided methods
fn fold_ty(
&mut self,
ty: &Ty<I>,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
&mut self,
ty: &Ty<I>,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
Top-level callback: invoked for each Ty<I>
that is
encountered when folding. By default, invokes
super_fold_with
, which will in turn invoke the more
specialized folding methods below, like fold_free_var_ty
.
fn fold_lifetime(
&mut self,
lifetime: &Lifetime<I>,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
&mut self,
lifetime: &Lifetime<I>,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
Top-level callback: invoked for each Lifetime<I>
that is
encountered when folding. By default, invokes
super_fold_with
, which will in turn invoke the more
specialized folding methods below, like fold_free_var_lifetime
.
fn fold_const(
&mut self,
constant: &Const<I>,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
&mut self,
constant: &Const<I>,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
Top-level callback: invoked for each Const<I>
that is
encountered when folding. By default, invokes
super_fold_with
, which will in turn invoke the more
specialized folding methods below, like fold_free_var_const
.
fn fold_program_clause(
&mut self,
clause: &ProgramClause<I>,
outer_binder: DebruijnIndex
) -> Fallible<ProgramClause<TI>>
&mut self,
clause: &ProgramClause<I>,
outer_binder: DebruijnIndex
) -> Fallible<ProgramClause<TI>>
Invoked for every program clause. By default, recursively folds the goals contents.
fn fold_goal(
&mut self,
goal: &Goal<I>,
outer_binder: DebruijnIndex
) -> Fallible<Goal<TI>>
&mut self,
goal: &Goal<I>,
outer_binder: DebruijnIndex
) -> Fallible<Goal<TI>>
Invoked for every goal. By default, recursively folds the goals contents.
fn forbid_free_vars(&self) -> bool
If overridden to return true, then folding will panic if a free variable is encountered. This should be done if free type/lifetime variables are not expected.
fn fold_free_var_ty(
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
Invoked for TyData::BoundVar
instances that are not bound
within the type being folded over:
depth
is the depth of theTyData::BoundVar
; this has been adjusted to account for binders in scope.binders
is the number of binders in scope.
This should return a type suitable for a context with
binders
in scope.
fn fold_free_var_lifetime(
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
As fold_free_var_ty
, but for lifetimes.
fn fold_free_var_const(
&mut self,
ty: &Ty<I>,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
&mut self,
ty: &Ty<I>,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
As fold_free_var_ty
, but for constants.
fn forbid_free_placeholders(&self) -> bool
If overridden to return true, we will panic when a free placeholder type/lifetime/const is encountered.
fn fold_free_placeholder_ty(
&mut self,
universe: PlaceholderIndex,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
&mut self,
universe: PlaceholderIndex,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
Invoked for each occurrence of a placeholder type; these are
used when we instantiate binders universally. Returns a type
to use instead, which should be suitably shifted to account
for binders
.
universe
is the universe of theTypeName::ForAll
that was foundbinders
is the number of binders in scope
fn fold_free_placeholder_lifetime(
&mut self,
universe: PlaceholderIndex,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
&mut self,
universe: PlaceholderIndex,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
As with fold_free_placeholder_ty
, but for lifetimes.
fn fold_free_placeholder_const(
&mut self,
ty: &Ty<I>,
universe: PlaceholderIndex,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
&mut self,
ty: &Ty<I>,
universe: PlaceholderIndex,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
As with fold_free_placeholder_ty
, but for constants.
fn forbid_inference_vars(&self) -> bool
If overridden to return true, inference variables will trigger panics when folded. Used when inference variables are unexpected.
fn fold_inference_ty(
&mut self,
var: InferenceVar,
kind: TyKind,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
&mut self,
var: InferenceVar,
kind: TyKind,
outer_binder: DebruijnIndex
) -> Fallible<Ty<TI>>
Invoked for each occurrence of a inference type; these are
used when we instantiate binders universally. Returns a type
to use instead, which should be suitably shifted to account
for binders
.
universe
is the universe of theTypeName::ForAll
that was foundbinders
is the number of binders in scope
fn fold_inference_lifetime(
&mut self,
var: InferenceVar,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
&mut self,
var: InferenceVar,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<TI>>
As with fold_inference_ty
, but for lifetimes.
fn fold_inference_const(
&mut self,
ty: &Ty<I>,
var: InferenceVar,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
&mut self,
ty: &Ty<I>,
var: InferenceVar,
outer_binder: DebruijnIndex
) -> Fallible<Const<TI>>
As with fold_inference_ty
, but for constants.
Implementors
impl<'i, I: Interner, '_> Folder<'i, I, I> for Subst<'_, 'i, I>
[src]
fn as_dyn(&mut self) -> &mut dyn Folder<'i, I>
[src]
fn fold_free_var_ty(
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Ty<I>>
[src]
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Ty<I>>
We are eliminating one binder, but binders outside of that get preserved.
So e.g. consider this:
for<A, B> { for<C> { [A, C] } }
// ^ the binder we are substituing with `[u32]`
Here, A
would be ^1.0
and C
would be ^0.0
. We will replace ^0.0
with the
0th index from the list (u32
). We will convert ^1.0
(A) to ^0.0
-- i.e., shift
it out of one level of binder (the for<C>
binder we are eliminating).
This gives us as a result:
for<A, B> { [A, u32] }
^ represented as `^0.0`
fn fold_free_var_lifetime(
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<I>>
[src]
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Lifetime<I>>
see fold_free_var_ty
fn fold_free_var_const(
&mut self,
ty: &Ty<I>,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Const<I>>
[src]
&mut self,
ty: &Ty<I>,
bound_var: BoundVar,
outer_binder: DebruijnIndex
) -> Fallible<Const<I>>
see fold_free_var_ty