Module syntex_syntax::ext::deriving::generic
[−]
[src]
Some code that abstracts away much of the boilerplate of writing
derive
instances for traits. Among other things it manages getting
access to the fields of the 4 different sorts of structs and enum
variants, as well as creating the method and impl ast instances.
Supported features (fairly exhaustive):
- Methods taking any number of parameters of any type, and returning any type, other than vectors, bottom and closures.
- Generating
impl
s for types with type parameters and lifetimes (e.g.Option<T>
), the parameters are automatically given the current trait as a bound. (This includes separate type parameters and lifetimes for methods.) - Additional bounds on the type parameters (
TraitDef.additional_bounds
)
The most important thing for implementers is the Substructure
and
SubstructureFields
objects. The latter groups 5 possibilities of the
arguments:
Struct
, whenSelf
is a struct (including tuple structs, e.gstruct T(i32, char)
).EnumMatching
, whenSelf
is an enum and all the arguments are the same variant of the enum (e.g.Some(1)
,Some(3)
andSome(4)
)EnumNonMatchingCollapsed
whenSelf
is an enum and the arguments are not the same variant (e.g.None
,Some(1)
andNone
).StaticEnum
andStaticStruct
for static methods, where the type being derived upon is either an enum or struct respectively. (Any argument with type Self is just grouped among the non-self arguments.)
In the first two cases, the values from the corresponding fields in
all the arguments are grouped together. For EnumNonMatchingCollapsed
this isn't possible (different variants have different fields), so the
fields are inaccessible. (Previous versions of the deriving infrastructure
had a way to expand into code that could access them, at the cost of
generating exponential amounts of code; see issue #15375). There are no
fields with values in the static cases, so these are treated entirely
differently.
The non-static cases have Option<ident>
in several places associated
with field expr
s. This represents the name of the field it is
associated with. It is only not None
when the associated field has
an identifier in the source code. For example, the x
s in the
following snippet
struct A { x : i32 } struct B(i32); enum C { C0(i32), C1 { x: i32 } }
The i32
s in B
and C0
don't have an identifier, so the
Option<ident>
s would be None
for them.
In the static cases, the structure is summarised, either into the just spans of the fields or a list of spans and the field idents (for tuple structs and record structs, respectively), or a list of these, for enums (one for each variant). For empty struct and empty enum variants, it is represented as a count of 0.
"cs
" functions
The cs_...
functions ("combine substructure) are designed to
make life easier by providing some pre-made recipes for common
threads; mostly calling the function being derived on all the
arguments and then combining them back together in some way (or
letting the user chose that). They are not meant to be the only
way to handle the structures that this code creates.
Examples
The following simplified PartialEq
is used for in-code examples:
trait PartialEq { fn eq(&self, other: &Self) -> bool; } impl PartialEq for i32 { fn eq(&self, other: &i32) -> bool { *self == *other } }
Some examples of the values of SubstructureFields
follow, using the
above PartialEq
, A
, B
and C
.
Structs
When generating the expr
for the A
impl, the SubstructureFields
is
Struct(vec![FieldInfo {
span: <span of x>
name: Some(<ident of x>),
self_: <expr for &self.x>,
other: vec![<expr for &other.x]
}])
For the B
impl, called with B(a)
and B(b)
,
Struct(vec![FieldInfo {
span: <span of `i32`>,
name: None,
self_: <expr for &a>
other: vec![<expr for &b>]
}])
Enums
When generating the expr
for a call with self == C0(a)
and other == C0(b)
, the SubstructureFields is
EnumMatching(0, <ast::Variant for C0>,
vec![FieldInfo {
span: <span of i32>
name: None,
self_: <expr for &a>,
other: vec![<expr for &b>]
}])
For C1 {x}
and C1 {x}
,
EnumMatching(1, <ast::Variant for C1>,
vec![FieldInfo {
span: <span of x>
name: Some(<ident of x>),
self_: <expr for &self.x>,
other: vec![<expr for &other.x>]
}])
For C0(a)
and C1 {x}
,
EnumNonMatchingCollapsed(
vec![<ident of self>, <ident of __arg_1>],
&[<ast::Variant for C0>, <ast::Variant for C1>],
&[<ident for self index value>, <ident of __arg_1 index value>])
It is the same for when the arguments are flipped to C1 {x}
and
C0(a)
; the only difference is what the values of the identifiers
EnumNonMatchingCollapsed
deliberately provides far less information
than is generally available for a given pair of variants; see #15375
for discussion.
Static
A static method on the types above would result in,
StaticStruct(<ast::VariantData of A>, Named(vec![(<ident of x>, <span of x>)]))
StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
StaticEnum(<ast::EnumDef of C>,
vec![(<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
(<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)]))])
Reexports
pub use self::StaticFields::*; |
pub use self::SubstructureFields::*; |
Modules
ty |
A mini version of ast::Ty, which is easier to use, and features an explicit |
Structs
FieldInfo |
Summary of the relevant parts of a struct/enum field. |
MethodDef | |
Substructure |
All the data about the data structure/method being derived upon. |
TraitDef |
Enums
StaticFields |
Fields for a static method |
SubstructureFields |
A summary of the possible sets of fields. |
Functions
combine_substructure | |
cs_and |
cs_binop with binop == and |
cs_binop |
Use a given binop to combine the result of calling the derived method on all the fields. |
cs_fold |
Fold the fields. |
cs_or |
cs_binop with binop == or |
cs_same_method |
Call the method that is being derived on all the fields, and then process the collected results. i.e. |
cs_same_method_fold |
Fold together the results of calling the derived method on all the
fields. |
Type Definitions
CombineSubstructureFunc |
Combine the values of all the fields together. The last argument is all the fields of all the structures. |
EnumNonMatchCollapsedFunc |
Deal with non-matching enum variants. The tuple is a list of
identifiers (one for each |