Module rustc_type_ir::fold
source · Expand description
A folding traversal mechanism for complex data structures that contain type information.
This is a modifying traversal. It consumes the data structure, producing a
(possibly) modified version of it. Both fallible and infallible versions are
available. The name is potentially confusing, because this traversal is more
like Iterator::map
than Iterator::fold
.
This traversal has limited flexibility. Only a small number of “types of
interest” within the complex data structures can receive custom
modification. These are the ones containing the most important type-related
information, such as Ty
, Predicate
, Region
, and Const
.
There are three traits involved in each traversal.
TypeFoldable
. This is implemented once for many types, including:- Types of interest, for which the methods delegate to the folder.
- All other types, including generic containers like
Vec
andOption
. It defines a “skeleton” of how they should be folded.
TypeSuperFoldable
. This is implemented only for recursive types of interest, and defines the folding “skeleton” for these types. (This excludesRegion
because it is non-recursive, i.e. it never contains other types of interest.)TypeFolder
/FallibleTypeFolder
. One of these is implemented for each folder. This defines how types of interest are folded.
This means each fold is a mixture of (a) generic folding operations, and (b) custom fold operations that are specific to the folder.
- The
TypeFoldable
impls handle most of the traversal, and call intoTypeFolder
/FallibleTypeFolder
when they encounter a type of interest. - A
TypeFolder
/FallibleTypeFolder
may call into anotherTypeFoldable
impl, because some of the types of interest are recursive and can contain other types of interest. - A
TypeFolder
/FallibleTypeFolder
may also call into aTypeSuperFoldable
impl, because each folder might provide custom handling only for some types of interest, or only for some variants of each type of interest, and then use default traversal for the remaining cases.
For example, if you have struct S(Ty, U)
where S: TypeFoldable
and U: TypeFoldable
, and an instance s = S(ty, u)
, it would be folded like so:
s.fold_with(folder) calls
- ty.fold_with(folder) calls
- folder.fold_ty(ty) may call
- ty.super_fold_with(folder)
- u.fold_with(folder)
Traits
- This trait is implemented for every folding traversal. There is a fold method defined for every type of interest. Each such method has a default that does an “identity” fold.
- This trait is implemented for every type that can be folded, providing the skeleton of the traversal.
- This trait is implemented for every infallible folding traversal. There is a fold method defined for every type of interest. Each such method has a default that does an “identity” fold. Implementations of these methods often fall back to a
super_fold_with
method if the primary argument doesn’t satisfy a particular condition.