1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Some code that abstracts away much of the boilerplate of writing
12 //! `derive` instances for traits. Among other things it manages getting
13 //! access to the fields of the 4 different sorts of structs and enum
14 //! variants, as well as creating the method and impl ast instances.
16 //! Supported features (fairly exhaustive):
18 //! - Methods taking any number of parameters of any type, and returning
19 //! any type, other than vectors, bottom and closures.
20 //! - Generating `impl`s for types with type parameters and lifetimes
21 //! (e.g. `Option<T>`), the parameters are automatically given the
22 //! current trait as a bound. (This includes separate type parameters
23 //! and lifetimes for methods.)
24 //! - Additional bounds on the type parameters (`TraitDef.additional_bounds`)
26 //! The most important thing for implementers is the `Substructure` and
27 //! `SubstructureFields` objects. The latter groups 5 possibilities of the
30 //! - `Struct`, when `Self` is a struct (including tuple structs, e.g
31 //! `struct T(i32, char)`).
32 //! - `EnumMatching`, when `Self` is an enum and all the arguments are the
33 //! same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`)
34 //! - `EnumNonMatchingCollapsed` when `Self` is an enum and the arguments
35 //! are not the same variant (e.g. `None`, `Some(1)` and `None`).
36 //! - `StaticEnum` and `StaticStruct` for static methods, where the type
37 //! being derived upon is either an enum or struct respectively. (Any
38 //! argument with type Self is just grouped among the non-self
41 //! In the first two cases, the values from the corresponding fields in
42 //! all the arguments are grouped together. For `EnumNonMatchingCollapsed`
43 //! this isn't possible (different variants have different fields), so the
44 //! fields are inaccessible. (Previous versions of the deriving infrastructure
45 //! had a way to expand into code that could access them, at the cost of
46 //! generating exponential amounts of code; see issue #15375). There are no
47 //! fields with values in the static cases, so these are treated entirely
50 //! The non-static cases have `Option<ident>` in several places associated
51 //! with field `expr`s. This represents the name of the field it is
52 //! associated with. It is only not `None` when the associated field has
53 //! an identifier in the source code. For example, the `x`s in the
57 //! # #![allow(dead_code)]
58 //! struct A { x : i32 }
68 //! The `i32`s in `B` and `C0` don't have an identifier, so the
69 //! `Option<ident>`s would be `None` for them.
71 //! In the static cases, the structure is summarised, either into the just
72 //! spans of the fields or a list of spans and the field idents (for tuple
73 //! structs and record structs, respectively), or a list of these, for
74 //! enums (one for each variant). For empty struct and empty enum
75 //! variants, it is represented as a count of 0.
77 //! # "`cs`" functions
79 //! The `cs_...` functions ("combine substructure) are designed to
80 //! make life easier by providing some pre-made recipes for common
81 //! threads; mostly calling the function being derived on all the
82 //! arguments and then combining them back together in some way (or
83 //! letting the user chose that). They are not meant to be the only
84 //! way to handle the structures that this code creates.
88 //! The following simplified `PartialEq` is used for in-code examples:
92 //! fn eq(&self, other: &Self) -> bool;
94 //! impl PartialEq for i32 {
95 //! fn eq(&self, other: &i32) -> bool {
101 //! Some examples of the values of `SubstructureFields` follow, using the
102 //! above `PartialEq`, `A`, `B` and `C`.
106 //! When generating the `expr` for the `A` impl, the `SubstructureFields` is
109 //! Struct(vec![FieldInfo {
110 //! span: <span of x>
111 //! name: Some(<ident of x>),
112 //! self_: <expr for &self.x>,
113 //! other: vec![<expr for &other.x]
117 //! For the `B` impl, called with `B(a)` and `B(b)`,
120 //! Struct(vec![FieldInfo {
121 //! span: <span of `i32`>,
123 //! self_: <expr for &a>
124 //! other: vec![<expr for &b>]
130 //! When generating the `expr` for a call with `self == C0(a)` and `other
131 //! == C0(b)`, the SubstructureFields is
134 //! EnumMatching(0, <ast::Variant for C0>,
136 //! span: <span of i32>
138 //! self_: <expr for &a>,
139 //! other: vec![<expr for &b>]
143 //! For `C1 {x}` and `C1 {x}`,
146 //! EnumMatching(1, <ast::Variant for C1>,
148 //! span: <span of x>
149 //! name: Some(<ident of x>),
150 //! self_: <expr for &self.x>,
151 //! other: vec![<expr for &other.x>]
155 //! For `C0(a)` and `C1 {x}` ,
158 //! EnumNonMatchingCollapsed(
159 //! vec![<ident of self>, <ident of __arg_1>],
160 //! &[<ast::Variant for C0>, <ast::Variant for C1>],
161 //! &[<ident for self index value>, <ident of __arg_1 index value>])
164 //! It is the same for when the arguments are flipped to `C1 {x}` and
165 //! `C0(a)`; the only difference is what the values of the identifiers
166 //! <ident for self index value> and <ident of __arg_1 index value> will
167 //! be in the generated code.
169 //! `EnumNonMatchingCollapsed` deliberately provides far less information
170 //! than is generally available for a given pair of variants; see #15375
175 //! A static method on the types above would result in,
178 //! StaticStruct(<ast::VariantData of A>, Named(vec![(<ident of x>, <span of x>)]))
180 //! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
182 //! StaticEnum(<ast::EnumDef of C>,
183 //! vec![(<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
184 //! (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)]))])
187 pub use self::StaticFields
::*;
188 pub use self::SubstructureFields
::*;
190 use std
::cell
::RefCell
;
191 use std
::collections
::HashSet
;
194 use syntax
::abi
::Abi
;
195 use syntax
::ast
::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind, VariantData}
;
197 use syntax
::ext
::base
::{Annotatable, ExtCtxt}
;
198 use syntax
::ext
::build
::AstBuilder
;
199 use syntax
::codemap
::{self, dummy_spanned, respan}
;
200 use syntax
::util
::move_map
::MoveMap
;
202 use syntax
::symbol
::{Symbol, keywords}
;
203 use syntax_pos
::{DUMMY_SP, Span}
;
206 use self::ty
::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}
;
212 pub struct TraitDef
<'a
> {
213 /// The span for the current #[derive(Foo)] header.
216 pub attributes
: Vec
<ast
::Attribute
>,
218 /// Path of the trait, including any type parameters
221 /// Additional bounds required of any type parameters of the type,
222 /// other than the current trait
223 pub additional_bounds
: Vec
<Ty
<'a
>>,
225 /// Any extra lifetimes and/or bounds, e.g. `D: serialize::Decoder`
226 pub generics
: LifetimeBounds
<'a
>,
228 /// Is it an `unsafe` trait?
231 /// Can this trait be derived for unions?
232 pub supports_unions
: bool
,
234 pub methods
: Vec
<MethodDef
<'a
>>,
236 pub associated_types
: Vec
<(ast
::Ident
, Ty
<'a
>)>,
240 pub struct MethodDef
<'a
> {
241 /// name of the method
243 /// List of generics, e.g. `R: rand::Rng`
244 pub generics
: LifetimeBounds
<'a
>,
246 /// Whether there is a self argument (outer Option) i.e. whether
247 /// this is a static function, and whether it is a pointer (inner
249 pub explicit_self
: Option
<Option
<PtrTy
<'a
>>>,
251 /// Arguments other than the self argument
252 pub args
: Vec
<Ty
<'a
>>,
257 pub attributes
: Vec
<ast
::Attribute
>,
259 // Is it an `unsafe fn`?
262 /// Can we combine fieldless variants for enums into a single match arm?
263 pub unify_fieldless_variants
: bool
,
265 pub combine_substructure
: RefCell
<CombineSubstructureFunc
<'a
>>,
268 /// All the data about the data structure/method being derived upon.
269 pub struct Substructure
<'a
> {
271 pub type_ident
: Ident
,
272 /// ident of the method
273 pub method_ident
: Ident
,
274 /// dereferenced access to any `Self_` or `Ptr(Self_, _)` arguments
275 pub self_args
: &'a
[P
<Expr
>],
276 /// verbatim access to any other arguments
277 pub nonself_args
: &'a
[P
<Expr
>],
278 pub fields
: &'a SubstructureFields
<'a
>,
281 /// Summary of the relevant parts of a struct/enum field.
282 pub struct FieldInfo
<'a
> {
284 /// None for tuple structs/normal enum variants, Some for normal
285 /// structs/struct enum variants.
286 pub name
: Option
<Ident
>,
287 /// The expression corresponding to this field of `self`
288 /// (specifically, a reference to it).
290 /// The expressions corresponding to references to this field in
291 /// the other `Self` arguments.
292 pub other
: Vec
<P
<Expr
>>,
293 /// The attributes on the field
294 pub attrs
: &'a
[ast
::Attribute
],
297 /// Fields for a static method
298 pub enum StaticFields
{
299 /// Tuple and unit structs/enum variants like this.
300 Unnamed(Vec
<Span
>, bool
/*is tuple*/),
301 /// Normal structs/struct variants.
302 Named(Vec
<(Ident
, Span
)>),
305 /// A summary of the possible sets of fields.
306 pub enum SubstructureFields
<'a
> {
307 Struct(&'a ast
::VariantData
, Vec
<FieldInfo
<'a
>>),
308 /// Matching variants of the enum: variant index, variant count, ast::Variant,
309 /// fields: the field name is only non-`None` in the case of a struct
311 EnumMatching(usize, usize, &'a ast
::Variant
, Vec
<FieldInfo
<'a
>>),
313 /// Non-matching variants of the enum, but with all state hidden from
314 /// the consequent code. The first component holds `Ident`s for all of
315 /// the `Self` arguments; the second component is a slice of all of the
316 /// variants for the enum itself, and the third component is a list of
317 /// `Ident`s bound to the variant index values for each of the actual
318 /// input `Self` arguments.
319 EnumNonMatchingCollapsed(Vec
<Ident
>, &'a
[ast
::Variant
], &'a
[Ident
]),
321 /// A static method where `Self` is a struct.
322 StaticStruct(&'a ast
::VariantData
, StaticFields
),
323 /// A static method where `Self` is an enum.
324 StaticEnum(&'a ast
::EnumDef
, Vec
<(Ident
, Span
, StaticFields
)>),
329 /// Combine the values of all the fields together. The last argument is
330 /// all the fields of all the structures.
331 pub type CombineSubstructureFunc
<'a
> =
332 Box
<FnMut(&mut ExtCtxt
, Span
, &Substructure
) -> P
<Expr
> + 'a
>;
334 /// Deal with non-matching enum variants. The tuple is a list of
335 /// identifiers (one for each `Self` argument, which could be any of the
336 /// variants since they have been collapsed together) and the identifiers
337 /// holding the variant index value for each of the `Self` arguments. The
338 /// last argument is all the non-`Self` args of the method being derived.
339 pub type EnumNonMatchCollapsedFunc
<'a
> =
340 Box
<FnMut(&mut ExtCtxt
, Span
, (&[Ident
], &[Ident
]), &[P
<Expr
>]) -> P
<Expr
> + 'a
>;
342 pub fn combine_substructure
<'a
>(f
: CombineSubstructureFunc
<'a
>)
343 -> RefCell
<CombineSubstructureFunc
<'a
>> {
347 /// This method helps to extract all the type parameters referenced from a
348 /// type. For a type parameter `<T>`, it looks for either a `TyPath` that
349 /// is not global and starts with `T`, or a `TyQPath`.
350 fn find_type_parameters(ty
: &ast
::Ty
,
351 ty_param_names
: &[ast
::Name
],
357 struct Visitor
<'a
, 'b
: 'a
> {
360 ty_param_names
: &'a
[ast
::Name
],
361 types
: Vec
<P
<ast
::Ty
>>,
364 impl<'a
, 'b
> visit
::Visitor
<'a
> for Visitor
<'a
, 'b
> {
365 fn visit_ty(&mut self, ty
: &'a ast
::Ty
) {
366 if let ast
::TyKind
::Path(_
, ref path
) = ty
.node
{
367 if let Some(segment
) = path
.segments
.first() {
368 if self.ty_param_names
.contains(&segment
.identifier
.name
) {
369 self.types
.push(P(ty
.clone()));
374 visit
::walk_ty(self, ty
)
377 fn visit_mac(&mut self, mac
: &ast
::Mac
) {
378 let span
= Span { ctxt: self.span.ctxt, ..mac.span }
;
379 self.cx
.span_err(span
, "`derive` cannot be used on items with type macros");
383 let mut visitor
= Visitor
{
384 ty_param_names
: ty_param_names
,
390 visit
::Visitor
::visit_ty(&mut visitor
, ty
);
395 impl<'a
> TraitDef
<'a
> {
398 mitem
: &ast
::MetaItem
,
399 item
: &'a Annotatable
,
400 push
: &mut FnMut(Annotatable
)) {
401 self.expand_ext(cx
, mitem
, item
, push
, false);
404 pub fn expand_ext(&self,
406 mitem
: &ast
::MetaItem
,
407 item
: &'a Annotatable
,
408 push
: &mut FnMut(Annotatable
),
409 from_scratch
: bool
) {
411 Annotatable
::Item(ref item
) => {
412 let newitem
= match item
.node
{
413 ast
::ItemKind
::Struct(ref struct_def
, ref generics
) => {
414 self.expand_struct_def(cx
, &struct_def
, item
.ident
, generics
, from_scratch
)
416 ast
::ItemKind
::Enum(ref enum_def
, ref generics
) => {
417 self.expand_enum_def(cx
, enum_def
, &item
.attrs
,
418 item
.ident
, generics
, from_scratch
)
420 ast
::ItemKind
::Union(ref struct_def
, ref generics
) => {
421 if self.supports_unions
{
422 self.expand_struct_def(cx
, &struct_def
, item
.ident
,
423 generics
, from_scratch
)
425 cx
.span_err(mitem
.span
,
426 "this trait cannot be derived for unions");
431 cx
.span_err(mitem
.span
,
432 "`derive` may only be applied to structs, enums and unions");
436 // Keep the lint attributes of the previous item to control how the
437 // generated implementations are linted
438 let mut attrs
= newitem
.attrs
.clone();
439 attrs
.extend(item
.attrs
442 a
.name().is_some() && match &*a
.name().unwrap().as_str() {
443 "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
448 push(Annotatable
::Item(P(ast
::Item { attrs: attrs, ..(*newitem).clone() }
)))
451 cx
.span_err(mitem
.span
,
452 "`derive` may only be applied to structs and enums");
457 /// Given that we are deriving a trait `DerivedTrait` for a type like:
459 /// ```ignore (only-for-syntax-highlight)
460 /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait {
463 /// b1: <B as DeclaredTrait>::Item,
464 /// c1: <C as WhereTrait>::Item,
465 /// c2: Option<<C as WhereTrait>::Item>,
470 /// create an impl like:
472 /// ```ignore (only-for-syntax-highlight)
473 /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where
475 /// A: DerivedTrait + B1 + ... + BN,
476 /// B: DerivedTrait + B1 + ... + BN,
477 /// C: DerivedTrait + B1 + ... + BN,
478 /// B::Item: DerivedTrait + B1 + ... + BN,
479 /// <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN,
486 /// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and
487 /// therefore does not get bound by the derived trait.
488 fn create_derived_impl(&self,
492 field_tys
: Vec
<P
<ast
::Ty
>>,
493 methods
: Vec
<ast
::ImplItem
>)
495 let trait_path
= self.path
.to_path(cx
, self.span
, type_ident
, generics
);
497 // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem`
498 let associated_types
= self.associated_types
.iter().map(|&(ident
, ref type_def
)| {
500 id
: ast
::DUMMY_NODE_ID
,
503 vis
: ast
::Visibility
::Inherited
,
504 defaultness
: ast
::Defaultness
::Final
,
506 node
: ast
::ImplItemKind
::Type(type_def
.to_ty(cx
, self.span
, type_ident
, generics
)),
510 let Generics { mut lifetimes, mut ty_params, mut where_clause, span }
= self.generics
511 .to_generics(cx
, self.span
, type_ident
, generics
);
513 // Copy the lifetimes
514 lifetimes
.extend(generics
.lifetimes
.iter().cloned());
516 // Create the type parameters.
517 ty_params
.extend(generics
.ty_params
.iter().map(|ty_param
| {
518 // I don't think this can be moved out of the loop, since
519 // a TyParamBound requires an ast id
520 let mut bounds
: Vec
<_
> =
521 // extra restrictions on the generics parameters to the type being derived upon
522 self.additional_bounds
.iter().map(|p
| {
523 cx
.typarambound(p
.to_path(cx
, self.span
,
524 type_ident
, generics
))
527 // require the current trait
528 bounds
.push(cx
.typarambound(trait_path
.clone()));
530 // also add in any bounds from the declaration
531 for declared_bound
in ty_param
.bounds
.iter() {
532 bounds
.push((*declared_bound
).clone());
535 cx
.typaram(self.span
, ty_param
.ident
, vec
![], bounds
, None
)
538 // and similarly for where clauses
539 where_clause
.predicates
.extend(generics
.where_clause
.predicates
.iter().map(|clause
| {
541 ast
::WherePredicate
::BoundPredicate(ref wb
) => {
542 ast
::WherePredicate
::BoundPredicate(ast
::WhereBoundPredicate
{
544 bound_lifetimes
: wb
.bound_lifetimes
.clone(),
545 bounded_ty
: wb
.bounded_ty
.clone(),
546 bounds
: wb
.bounds
.iter().cloned().collect(),
549 ast
::WherePredicate
::RegionPredicate(ref rb
) => {
550 ast
::WherePredicate
::RegionPredicate(ast
::WhereRegionPredicate
{
552 lifetime
: rb
.lifetime
,
553 bounds
: rb
.bounds
.iter().cloned().collect(),
556 ast
::WherePredicate
::EqPredicate(ref we
) => {
557 ast
::WherePredicate
::EqPredicate(ast
::WhereEqPredicate
{
558 id
: ast
::DUMMY_NODE_ID
,
560 lhs_ty
: we
.lhs_ty
.clone(),
561 rhs_ty
: we
.rhs_ty
.clone(),
567 if !ty_params
.is_empty() {
568 let ty_param_names
: Vec
<ast
::Name
> = ty_params
.iter()
569 .map(|ty_param
| ty_param
.ident
.name
)
572 let mut processed_field_types
= HashSet
::new();
573 for field_ty
in field_tys
{
574 let tys
= find_type_parameters(&field_ty
, &ty_param_names
, self.span
, cx
);
577 // if we have already handled this type, skip it
578 if let ast
::TyKind
::Path(_
, ref p
) = ty
.node
{
579 if p
.segments
.len() == 1 &&
580 ty_param_names
.contains(&p
.segments
[0].identifier
.name
) ||
581 processed_field_types
.contains(&p
.segments
) {
584 processed_field_types
.insert(p
.segments
.clone());
586 let mut bounds
: Vec
<_
> = self.additional_bounds
588 .map(|p
| cx
.typarambound(p
.to_path(cx
, self.span
, type_ident
, generics
)))
591 // require the current trait
592 bounds
.push(cx
.typarambound(trait_path
.clone()));
594 let predicate
= ast
::WhereBoundPredicate
{
596 bound_lifetimes
: vec
![],
601 let predicate
= ast
::WherePredicate
::BoundPredicate(predicate
);
602 where_clause
.predicates
.push(predicate
);
607 let trait_generics
= Generics
{
608 lifetimes
: lifetimes
,
609 ty_params
: ty_params
,
610 where_clause
: where_clause
,
614 // Create the reference to the trait.
615 let trait_ref
= cx
.trait_ref(trait_path
);
617 // Create the type parameters on the `self` path.
618 let self_ty_params
= generics
.ty_params
620 .map(|ty_param
| cx
.ty_ident(self.span
, ty_param
.ident
))
623 let self_lifetimes
: Vec
<ast
::Lifetime
> = generics
.lifetimes
625 .map(|ld
| ld
.lifetime
)
628 // Create the type of `self`.
629 let self_type
= cx
.ty_path(cx
.path_all(self.span
,
636 let attr
= cx
.attribute(self.span
,
637 cx
.meta_word(self.span
,
638 Symbol
::intern("automatically_derived")));
639 // Just mark it now since we know that it'll end up used downstream
640 attr
::mark_used(&attr
);
641 let opt_trait_ref
= Some(trait_ref
);
643 let word
= cx
.meta_list_item_word(self.span
, Symbol
::intern("unused_qualifications"));
644 cx
.attribute(self.span
, cx
.meta_list(self.span
, Symbol
::intern("allow"), vec
![word
]))
647 let mut a
= vec
![attr
, unused_qual
];
648 a
.extend(self.attributes
.iter().cloned());
650 let unsafety
= if self.is_unsafe
{
651 ast
::Unsafety
::Unsafe
653 ast
::Unsafety
::Normal
657 keywords
::Invalid
.ident(),
659 ast
::ItemKind
::Impl(unsafety
,
660 ast
::ImplPolarity
::Positive
,
661 ast
::Defaultness
::Final
,
665 methods
.into_iter().chain(associated_types
).collect()))
668 fn expand_struct_def(&self,
670 struct_def
: &'a VariantData
,
675 let field_tys
: Vec
<P
<ast
::Ty
>> = struct_def
.fields()
677 .map(|field
| field
.ty
.clone())
680 let methods
= self.methods
683 let (explicit_self
, self_args
, nonself_args
, tys
) =
684 method_def
.split_self_nonself_args(cx
, self, type_ident
, generics
);
686 let body
= if from_scratch
|| method_def
.is_static() {
687 method_def
.expand_static_struct_method_body(cx
,
694 method_def
.expand_struct_method_body(cx
,
702 method_def
.create_method(cx
,
713 self.create_derived_impl(cx
, type_ident
, generics
, field_tys
, methods
)
716 fn expand_enum_def(&self,
718 enum_def
: &'a EnumDef
,
719 type_attrs
: &[ast
::Attribute
],
724 let mut field_tys
= Vec
::new();
726 for variant
in &enum_def
.variants
{
727 field_tys
.extend(variant
.node
731 .map(|field
| field
.ty
.clone()));
734 let methods
= self.methods
737 let (explicit_self
, self_args
, nonself_args
, tys
) =
738 method_def
.split_self_nonself_args(cx
, self, type_ident
, generics
);
740 let body
= if from_scratch
|| method_def
.is_static() {
741 method_def
.expand_static_enum_method_body(cx
,
748 method_def
.expand_enum_method_body(cx
,
757 method_def
.create_method(cx
,
768 self.create_derived_impl(cx
, type_ident
, generics
, field_tys
, methods
)
772 fn find_repr_type_name(diagnostic
: &Handler
, type_attrs
: &[ast
::Attribute
]) -> &'
static str {
773 let mut repr_type_name
= "isize";
774 for a
in type_attrs
{
775 for r
in &attr
::find_repr_attrs(diagnostic
, a
) {
776 repr_type_name
= match *r
{
777 attr
::ReprPacked
| attr
::ReprSimd
| attr
::ReprAlign(_
) => continue,
778 attr
::ReprExtern
=> "i32",
780 attr
::ReprInt(attr
::SignedInt(ast
::IntTy
::Is
)) => "isize",
781 attr
::ReprInt(attr
::SignedInt(ast
::IntTy
::I8
)) => "i8",
782 attr
::ReprInt(attr
::SignedInt(ast
::IntTy
::I16
)) => "i16",
783 attr
::ReprInt(attr
::SignedInt(ast
::IntTy
::I32
)) => "i32",
784 attr
::ReprInt(attr
::SignedInt(ast
::IntTy
::I64
)) => "i64",
785 attr
::ReprInt(attr
::SignedInt(ast
::IntTy
::I128
)) => "i128",
787 attr
::ReprInt(attr
::UnsignedInt(ast
::UintTy
::Us
)) => "usize",
788 attr
::ReprInt(attr
::UnsignedInt(ast
::UintTy
::U8
)) => "u8",
789 attr
::ReprInt(attr
::UnsignedInt(ast
::UintTy
::U16
)) => "u16",
790 attr
::ReprInt(attr
::UnsignedInt(ast
::UintTy
::U32
)) => "u32",
791 attr
::ReprInt(attr
::UnsignedInt(ast
::UintTy
::U64
)) => "u64",
792 attr
::ReprInt(attr
::UnsignedInt(ast
::UintTy
::U128
)) => "u128",
799 impl<'a
> MethodDef
<'a
> {
800 fn call_substructure_method(&self,
804 self_args
: &[P
<Expr
>],
805 nonself_args
: &[P
<Expr
>],
806 fields
: &SubstructureFields
)
808 let substructure
= Substructure
{
809 type_ident
: type_ident
,
810 method_ident
: cx
.ident_of(self.name
),
811 self_args
: self_args
,
812 nonself_args
: nonself_args
,
815 let mut f
= self.combine_substructure
.borrow_mut();
816 let f
: &mut CombineSubstructureFunc
= &mut *f
;
817 f(cx
, trait_
.span
, &substructure
)
826 self.ret_ty
.to_ty(cx
, trait_
.span
, type_ident
, generics
)
829 fn is_static(&self) -> bool
{
830 self.explicit_self
.is_none()
833 fn split_self_nonself_args
839 -> (Option
<ast
::ExplicitSelf
>, Vec
<P
<Expr
>>, Vec
<P
<Expr
>>, Vec
<(Ident
, P
<ast
::Ty
>)>) {
841 let mut self_args
= Vec
::new();
842 let mut nonself_args
= Vec
::new();
843 let mut arg_tys
= Vec
::new();
844 let mut nonstatic
= false;
846 let ast_explicit_self
= self.explicit_self
.as_ref().map(|self_ptr
| {
847 let (self_expr
, explicit_self
) = ty
::get_explicit_self(cx
, trait_
.span
, self_ptr
);
849 self_args
.push(self_expr
);
855 for (i
, ty
) in self.args
.iter().enumerate() {
856 let ast_ty
= ty
.to_ty(cx
, trait_
.span
, type_ident
, generics
);
857 let ident
= cx
.ident_of(&format
!("__arg_{}", i
));
858 arg_tys
.push((ident
, ast_ty
));
860 let arg_expr
= cx
.expr_ident(trait_
.span
, ident
);
863 // for static methods, just treat any Self
864 // arguments as a normal arg
865 Self_
if nonstatic
=> {
866 self_args
.push(arg_expr
);
868 Ptr(ref ty
, _
) if **ty
== Self_
&& nonstatic
=> {
869 self_args
.push(cx
.expr_deref(trait_
.span
, arg_expr
))
872 nonself_args
.push(arg_expr
);
877 (ast_explicit_self
, self_args
, nonself_args
, arg_tys
)
880 fn create_method(&self,
886 explicit_self
: Option
<ast
::ExplicitSelf
>,
887 arg_types
: Vec
<(Ident
, P
<ast
::Ty
>)>,
891 // create the generics that aren't for Self
892 let fn_generics
= self.generics
.to_generics(cx
, trait_
.span
, type_ident
, generics
);
895 let self_args
= explicit_self
.map(|explicit_self
| {
896 ast
::Arg
::from_self(explicit_self
,
897 respan(trait_
.span
, keywords
::SelfValue
.ident()))
899 let nonself_args
= arg_types
.into_iter()
900 .map(|(name
, ty
)| cx
.arg(trait_
.span
, name
, ty
));
901 self_args
.into_iter().chain(nonself_args
).collect()
904 let ret_type
= self.get_ret_ty(cx
, trait_
, generics
, type_ident
);
906 let method_ident
= cx
.ident_of(self.name
);
907 let fn_decl
= cx
.fn_decl(args
, ret_type
);
908 let body_block
= cx
.block_expr(body
);
910 let unsafety
= if self.is_unsafe
{
911 ast
::Unsafety
::Unsafe
913 ast
::Unsafety
::Normal
916 // Create the method.
918 id
: ast
::DUMMY_NODE_ID
,
919 attrs
: self.attributes
.clone(),
921 vis
: ast
::Visibility
::Inherited
,
922 defaultness
: ast
::Defaultness
::Final
,
924 node
: ast
::ImplItemKind
::Method(ast
::MethodSig
{
925 generics
: fn_generics
,
929 dummy_spanned(ast
::Constness
::NotConst
),
937 /// #[derive(PartialEq)]
939 /// struct A { x: i32, y: i32 }
941 /// // equivalent to:
942 /// impl PartialEq for A {
943 /// fn eq(&self, __arg_1: &A) -> bool {
945 /// A {x: ref __self_0_0, y: ref __self_0_1} => {
947 /// A {x: ref __self_1_0, y: ref __self_1_1} => {
948 /// __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1)
956 fn expand_struct_method_body
<'b
>(&self,
958 trait_
: &TraitDef
<'b
>,
959 struct_def
: &'b VariantData
,
961 self_args
: &[P
<Expr
>],
962 nonself_args
: &[P
<Expr
>])
965 let mut raw_fields
= Vec
::new(); // Vec<[fields of self],
966 // [fields of next Self arg], [etc]>
967 let mut patterns
= Vec
::new();
968 for i
in 0..self_args
.len() {
969 let struct_path
= cx
.path(DUMMY_SP
, vec
![type_ident
]);
970 let (pat
, ident_expr
) = trait_
.create_struct_pattern(cx
,
973 &format
!("__self_{}", i
),
974 ast
::Mutability
::Immutable
);
976 raw_fields
.push(ident_expr
);
979 // transpose raw_fields
980 let fields
= if !raw_fields
.is_empty() {
981 let mut raw_fields
= raw_fields
.into_iter().map(|v
| v
.into_iter());
982 let first_field
= raw_fields
.next().unwrap();
983 let mut other_fields
: Vec
<vec
::IntoIter
<_
>> = raw_fields
.collect();
984 first_field
.map(|(span
, opt_id
, field
, attrs
)| {
989 other
: other_fields
.iter_mut()
991 match l
.next().unwrap() {
1001 cx
.span_bug(trait_
.span
,
1002 "no self arguments to non-static method in generic \
1006 // body of the inner most destructuring match
1007 let mut body
= self.call_substructure_method(cx
,
1012 &Struct(struct_def
, fields
));
1014 // make a series of nested matches, to destructure the
1015 // structs. This is actually right-to-left, but it shouldn't
1017 for (arg_expr
, pat
) in self_args
.iter().zip(patterns
) {
1018 body
= cx
.expr_match(trait_
.span
,
1020 vec
![cx
.arm(trait_
.span
, vec
![pat
.clone()], body
)])
1026 fn expand_static_struct_method_body(&self,
1029 struct_def
: &VariantData
,
1031 self_args
: &[P
<Expr
>],
1032 nonself_args
: &[P
<Expr
>])
1034 let summary
= trait_
.summarise_struct(cx
, struct_def
);
1036 self.call_substructure_method(cx
,
1041 &StaticStruct(struct_def
, summary
))
1045 /// #[derive(PartialEq)]
1052 /// // is equivalent to
1054 /// impl PartialEq for A {
1055 /// fn eq(&self, __arg_1: &A) -> ::bool {
1056 /// match (&*self, &*__arg_1) {
1057 /// (&A1, &A1) => true,
1058 /// (&A2(ref self_0),
1059 /// &A2(ref __arg_1_0)) => (*self_0).eq(&(*__arg_1_0)),
1061 /// let __self_vi = match *self { A1(..) => 0, A2(..) => 1 };
1062 /// let __arg_1_vi = match *__arg_1 { A1(..) => 0, A2(..) => 1 };
1070 /// (Of course `__self_vi` and `__arg_1_vi` are unused for
1071 /// `PartialEq`, and those subcomputations will hopefully be removed
1072 /// as their results are unused. The point of `__self_vi` and
1073 /// `__arg_1_vi` is for `PartialOrd`; see #15503.)
1074 fn expand_enum_method_body
<'b
>(&self,
1076 trait_
: &TraitDef
<'b
>,
1077 enum_def
: &'b EnumDef
,
1078 type_attrs
: &[ast
::Attribute
],
1080 self_args
: Vec
<P
<Expr
>>,
1081 nonself_args
: &[P
<Expr
>])
1083 self.build_enum_match_tuple(cx
,
1093 /// Creates a match for a tuple of all `self_args`, where either all
1094 /// variants match, or it falls into a catch-all for when one variant
1097 /// There are N + 1 cases because is a case for each of the N
1098 /// variants where all of the variants match, and one catch-all for
1099 /// when one does not match.
1101 /// As an optimization we generate code which checks whether all variants
1102 /// match first which makes llvm see that C-like enums can be compiled into
1103 /// a simple equality check (for PartialEq).
1105 /// The catch-all handler is provided access the variant index values
1106 /// for each of the self-args, carried in precomputed variables.
1109 /// let __self0_vi = unsafe {
1110 /// std::intrinsics::discriminant_value(&self) } as i32;
1111 /// let __self1_vi = unsafe {
1112 /// std::intrinsics::discriminant_value(&arg1) } as i32;
1113 /// let __self2_vi = unsafe {
1114 /// std::intrinsics::discriminant_value(&arg2) } as i32;
1116 /// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... {
1118 /// (Variant1, Variant1, ...) => Body1
1119 /// (Variant2, Variant2, ...) => Body2,
1121 /// _ => ::core::intrinsics::unreachable()
1125 /// ... // catch-all remainder can inspect above variant index values.
1128 fn build_enum_match_tuple
<'b
>(&self,
1130 trait_
: &TraitDef
<'b
>,
1131 enum_def
: &'b EnumDef
,
1132 type_attrs
: &[ast
::Attribute
],
1134 self_args
: Vec
<P
<Expr
>>,
1135 nonself_args
: &[P
<Expr
>])
1138 let sp
= trait_
.span
;
1139 let variants
= &enum_def
.variants
;
1141 let self_arg_names
= self_args
.iter()
1143 .map(|(arg_count
, _self_arg
)| {
1145 "__self".to_string()
1147 format
!("__arg_{}", arg_count
)
1150 .collect
::<Vec
<String
>>();
1152 let self_arg_idents
= self_arg_names
.iter()
1153 .map(|name
| cx
.ident_of(&name
[..]))
1154 .collect
::<Vec
<ast
::Ident
>>();
1156 // The `vi_idents` will be bound, solely in the catch-all, to
1157 // a series of let statements mapping each self_arg to an int
1158 // value corresponding to its discriminant.
1159 let vi_idents
: Vec
<ast
::Ident
> = self_arg_names
.iter()
1161 let vi_suffix
= format
!("{}_vi", &name
[..]);
1162 cx
.ident_of(&vi_suffix
[..])
1164 .collect
::<Vec
<ast
::Ident
>>();
1166 // Builds, via callback to call_substructure_method, the
1167 // delegated expression that handles the catch-all case,
1168 // using `__variants_tuple` to drive logic if necessary.
1169 let catch_all_substructure
=
1170 EnumNonMatchingCollapsed(self_arg_idents
, &variants
[..], &vi_idents
[..]);
1172 let first_fieldless
= variants
.iter().find(|v
| v
.node
.data
.fields().is_empty());
1174 // These arms are of the form:
1175 // (Variant1, Variant1, ...) => Body1
1176 // (Variant2, Variant2, ...) => Body2
1178 // where each tuple has length = self_args.len()
1179 let mut match_arms
: Vec
<ast
::Arm
> = variants
.iter()
1181 .filter(|&(_
, v
)| !(self.unify_fieldless_variants
&& v
.node
.data
.fields().is_empty()))
1182 .map(|(index
, variant
)| {
1183 let mk_self_pat
= |cx
: &mut ExtCtxt
, self_arg_name
: &str| {
1184 let (p
, idents
) = trait_
.create_enum_variant_pattern(cx
,
1188 ast
::Mutability
::Immutable
);
1189 (cx
.pat(sp
, PatKind
::Ref(p
, ast
::Mutability
::Immutable
)), idents
)
1192 // A single arm has form (&VariantK, &VariantK, ...) => BodyK
1193 // (see "Final wrinkle" note below for why.)
1194 let mut subpats
= Vec
::with_capacity(self_arg_names
.len());
1195 let mut self_pats_idents
= Vec
::with_capacity(self_arg_names
.len() - 1);
1196 let first_self_pat_idents
= {
1197 let (p
, idents
) = mk_self_pat(cx
, &self_arg_names
[0]);
1201 for self_arg_name
in &self_arg_names
[1..] {
1202 let (p
, idents
) = mk_self_pat(cx
, &self_arg_name
[..]);
1204 self_pats_idents
.push(idents
);
1207 // Here is the pat = `(&VariantK, &VariantK, ...)`
1208 let single_pat
= cx
.pat_tuple(sp
, subpats
);
1210 // For the BodyK, we need to delegate to our caller,
1211 // passing it an EnumMatching to indicate which case
1214 // All of the Self args have the same variant in these
1215 // cases. So we transpose the info in self_pats_idents
1216 // to gather the getter expressions together, in the
1217 // form that EnumMatching expects.
1219 // The transposition is driven by walking across the
1220 // arg fields of the variant for the first self pat.
1221 let field_tuples
= first_self_pat_idents
.into_iter().enumerate()
1222 // For each arg field of self, pull out its getter expr ...
1223 .map(|(field_index
, (sp
, opt_ident
, self_getter_expr
, attrs
))| {
1224 // ... but FieldInfo also wants getter expr
1225 // for matching other arguments of Self type;
1226 // so walk across the *other* self_pats_idents
1227 // and pull out getter for same field in each
1228 // of them (using `field_index` tracked above).
1229 // That is the heart of the transposition.
1230 let others
= self_pats_idents
.iter().map(|fields
| {
1231 let (_
, _opt_ident
, ref other_getter_expr
, _
) =
1232 fields
[field_index
];
1234 // All Self args have same variant, so
1235 // opt_idents are the same. (Assert
1236 // here to make it self-evident that
1237 // it is okay to ignore `_opt_ident`.)
1238 assert
!(opt_ident
== _opt_ident
);
1240 other_getter_expr
.clone()
1241 }).collect
::<Vec
<P
<Expr
>>>();
1243 FieldInfo
{ span
: sp
,
1245 self_
: self_getter_expr
,
1249 }).collect
::<Vec
<FieldInfo
>>();
1251 // Now, for some given VariantK, we have built up
1252 // expressions for referencing every field of every
1253 // Self arg, assuming all are instances of VariantK.
1254 // Build up code associated with such a case.
1255 let substructure
= EnumMatching(index
, variants
.len(), variant
, field_tuples
);
1256 let arm_expr
= self.call_substructure_method(cx
,
1263 cx
.arm(sp
, vec
![single_pat
], arm_expr
)
1267 let default = match first_fieldless
{
1268 Some(v
) if self.unify_fieldless_variants
=> {
1269 // We need a default case that handles the fieldless variants.
1270 // The index and actual variant aren't meaningful in this case,
1271 // so just use whatever
1272 let substructure
= EnumMatching(0, variants
.len(), v
, Vec
::new());
1273 Some(self.call_substructure_method(cx
,
1280 _
if variants
.len() > 1 && self_args
.len() > 1 => {
1281 // Since we know that all the arguments will match if we reach
1282 // the match expression we add the unreachable intrinsics as the
1283 // result of the catch all which should help llvm in optimizing it
1284 Some(deriving
::call_intrinsic(cx
, sp
, "unreachable", vec
![]))
1288 if let Some(arm
) = default {
1289 match_arms
.push(cx
.arm(sp
, vec
![cx
.pat_wild(sp
)], arm
));
1292 // We will usually need the catch-all after matching the
1293 // tuples `(VariantK, VariantK, ...)` for each VariantK of the
1296 // * when there is only one Self arg, the arms above suffice
1297 // (and the deriving we call back into may not be prepared to
1298 // handle EnumNonMatchCollapsed), and,
1300 // * when the enum has only one variant, the single arm that
1301 // is already present always suffices.
1303 // * In either of the two cases above, if we *did* add a
1304 // catch-all `_` match, it would trigger the
1305 // unreachable-pattern error.
1307 if variants
.len() > 1 && self_args
.len() > 1 {
1308 // Build a series of let statements mapping each self_arg
1309 // to its discriminant value. If this is a C-style enum
1310 // with a specific repr type, then casts the values to
1311 // that type. Otherwise casts to `i32` (the default repr
1314 // i.e. for `enum E<T> { A, B(1), C(T, T) }`, and a deriving
1315 // with three Self args, builds three statements:
1318 // let __self0_vi = unsafe {
1319 // std::intrinsics::discriminant_value(&self) } as i32;
1320 // let __self1_vi = unsafe {
1321 // std::intrinsics::discriminant_value(&arg1) } as i32;
1322 // let __self2_vi = unsafe {
1323 // std::intrinsics::discriminant_value(&arg2) } as i32;
1325 let mut index_let_stmts
: Vec
<ast
::Stmt
> = Vec
::new();
1327 // We also build an expression which checks whether all discriminants are equal
1328 // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
1329 let mut discriminant_test
= cx
.expr_bool(sp
, true);
1331 let target_type_name
= find_repr_type_name(&cx
.parse_sess
.span_diagnostic
, type_attrs
);
1333 let mut first_ident
= None
;
1334 for (&ident
, self_arg
) in vi_idents
.iter().zip(&self_args
) {
1335 let self_addr
= cx
.expr_addr_of(sp
, self_arg
.clone());
1337 deriving
::call_intrinsic(cx
, sp
, "discriminant_value", vec
![self_addr
]);
1339 let target_ty
= cx
.ty_ident(sp
, cx
.ident_of(target_type_name
));
1340 let variant_disr
= cx
.expr_cast(sp
, variant_value
, target_ty
);
1341 let let_stmt
= cx
.stmt_let(sp
, false, ident
, variant_disr
);
1342 index_let_stmts
.push(let_stmt
);
1346 let first_expr
= cx
.expr_ident(sp
, first
);
1347 let id
= cx
.expr_ident(sp
, ident
);
1348 let test
= cx
.expr_binary(sp
, BinOpKind
::Eq
, first_expr
, id
);
1350 cx
.expr_binary(sp
, BinOpKind
::And
, discriminant_test
, test
)
1353 first_ident
= Some(ident
);
1358 let arm_expr
= self.call_substructure_method(cx
,
1363 &catch_all_substructure
);
1365 // Final wrinkle: the self_args are expressions that deref
1366 // down to desired l-values, but we cannot actually deref
1367 // them when they are fed as r-values into a tuple
1368 // expression; here add a layer of borrowing, turning
1369 // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1370 let borrowed_self_args
= self_args
.move_map(|self_arg
| cx
.expr_addr_of(sp
, self_arg
));
1371 let match_arg
= cx
.expr(sp
, ast
::ExprKind
::Tup(borrowed_self_args
));
1373 // Lastly we create an expression which branches on all discriminants being equal
1374 // if discriminant_test {
1376 // (Variant1, Variant1, ...) => Body1
1377 // (Variant2, Variant2, ...) => Body2,
1379 // _ => ::core::intrinsics::unreachable()
1383 // <delegated expression referring to __self0_vi, et al.>
1385 let all_match
= cx
.expr_match(sp
, match_arg
, match_arms
);
1386 let arm_expr
= cx
.expr_if(sp
, discriminant_test
, all_match
, Some(arm_expr
));
1387 index_let_stmts
.push(cx
.stmt_expr(arm_expr
));
1388 cx
.expr_block(cx
.block(sp
, index_let_stmts
))
1389 } else if variants
.is_empty() {
1390 // As an additional wrinkle, For a zero-variant enum A,
1391 // currently the compiler
1392 // will accept `fn (a: &Self) { match *a { } }`
1393 // but rejects `fn (a: &Self) { match (&*a,) { } }`
1394 // as well as `fn (a: &Self) { match ( *a,) { } }`
1396 // This means that the strategy of building up a tuple of
1397 // all Self arguments fails when Self is a zero variant
1398 // enum: rustc rejects the expanded program, even though
1399 // the actual code tends to be impossible to execute (at
1400 // least safely), according to the type system.
1402 // The most expedient fix for this is to just let the
1403 // code fall through to the catch-all. But even this is
1404 // error-prone, since the catch-all as defined above would
1405 // generate code like this:
1407 // _ => { let __self0 = match *self { };
1408 // let __self1 = match *__arg_0 { };
1409 // <catch-all-expr> }
1411 // Which is yields bindings for variables which type
1412 // inference cannot resolve to unique types.
1414 // One option to the above might be to add explicit type
1415 // annotations. But the *only* reason to go down that path
1416 // would be to try to make the expanded output consistent
1417 // with the case when the number of enum variants >= 1.
1419 // That just isn't worth it. In fact, trying to generate
1420 // sensible code for *any* deriving on a zero-variant enum
1421 // does not make sense. But at the same time, for now, we
1422 // do not want to cause a compile failure just because the
1423 // user happened to attach a deriving to their
1424 // zero-variant enum.
1426 // Instead, just generate a failing expression for the
1427 // zero variant case, skipping matches and also skipping
1428 // delegating back to the end user code entirely.
1430 // (See also #4499 and #12609; note that some of the
1431 // discussions there influence what choice we make here;
1432 // e.g. if we feature-gate `match x { ... }` when x refers
1433 // to an uninhabited type (e.g. a zero-variant enum or a
1434 // type holding such an enum), but do not feature-gate
1435 // zero-variant enums themselves, then attempting to
1436 // derive Debug on such a type could here generate code
1437 // that needs the feature gate enabled.)
1439 deriving
::call_intrinsic(cx
, sp
, "unreachable", vec
![])
1442 // Final wrinkle: the self_args are expressions that deref
1443 // down to desired l-values, but we cannot actually deref
1444 // them when they are fed as r-values into a tuple
1445 // expression; here add a layer of borrowing, turning
1446 // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1447 let borrowed_self_args
= self_args
.move_map(|self_arg
| cx
.expr_addr_of(sp
, self_arg
));
1448 let match_arg
= cx
.expr(sp
, ast
::ExprKind
::Tup(borrowed_self_args
));
1449 cx
.expr_match(sp
, match_arg
, match_arms
)
1453 fn expand_static_enum_method_body(&self,
1458 self_args
: &[P
<Expr
>],
1459 nonself_args
: &[P
<Expr
>])
1461 let summary
= enum_def
.variants
1464 let ident
= v
.node
.name
;
1465 let sp
= Span { ctxt: trait_.span.ctxt, ..v.span }
;
1466 let summary
= trait_
.summarise_struct(cx
, &v
.node
.data
);
1467 (ident
, sp
, summary
)
1470 self.call_substructure_method(cx
,
1475 &StaticEnum(enum_def
, summary
))
1479 // general helper methods.
1480 impl<'a
> TraitDef
<'a
> {
1481 fn summarise_struct(&self, cx
: &mut ExtCtxt
, struct_def
: &VariantData
) -> StaticFields
{
1482 let mut named_idents
= Vec
::new();
1483 let mut just_spans
= Vec
::new();
1484 for field
in struct_def
.fields() {
1485 let sp
= Span { ctxt: self.span.ctxt, ..field.span }
;
1487 Some(ident
) => named_idents
.push((ident
, sp
)),
1488 _
=> just_spans
.push(sp
),
1492 match (just_spans
.is_empty(), named_idents
.is_empty()) {
1494 cx
.span_bug(self.span
,
1495 "a struct with named and unnamed \
1496 fields in generic `derive`")
1499 (_
, false) => Named(named_idents
),
1501 _
if struct_def
.is_struct() => Named(named_idents
),
1502 _
=> Unnamed(just_spans
, struct_def
.is_tuple()),
1506 fn create_subpatterns(&self,
1508 field_paths
: Vec
<ast
::SpannedIdent
>,
1509 mutbl
: ast
::Mutability
)
1510 -> Vec
<P
<ast
::Pat
>> {
1514 PatKind
::Ident(ast
::BindingMode
::ByRef(mutbl
), (*path
).clone(), None
))
1519 fn create_struct_pattern
1522 struct_path
: ast
::Path
,
1523 struct_def
: &'a VariantData
,
1525 mutbl
: ast
::Mutability
)
1526 -> (P
<ast
::Pat
>, Vec
<(Span
, Option
<Ident
>, P
<Expr
>, &'a
[ast
::Attribute
])>) {
1527 let mut paths
= Vec
::new();
1528 let mut ident_exprs
= Vec
::new();
1529 for (i
, struct_field
) in struct_def
.fields().iter().enumerate() {
1530 let sp
= Span { ctxt: self.span.ctxt, ..struct_field.span }
;
1531 let ident
= cx
.ident_of(&format
!("{}_{}", prefix
, i
));
1532 paths
.push(codemap
::Spanned
{
1536 let val
= cx
.expr_deref(sp
, cx
.expr_path(cx
.path_ident(sp
, ident
)));
1537 let val
= cx
.expr(sp
, ast
::ExprKind
::Paren(val
));
1538 ident_exprs
.push((sp
, struct_field
.ident
, val
, &struct_field
.attrs
[..]));
1541 let subpats
= self.create_subpatterns(cx
, paths
, mutbl
);
1542 let pattern
= match *struct_def
{
1543 VariantData
::Struct(..) => {
1544 let field_pats
= subpats
.into_iter()
1546 .map(|(pat
, &(sp
, ident
, ..))| {
1547 if ident
.is_none() {
1548 cx
.span_bug(sp
, "a braced struct with unnamed fields in `derive`");
1551 span
: Span { ctxt: self.span.ctxt, ..pat.span }
,
1552 node
: ast
::FieldPat
{
1553 ident
: ident
.unwrap(),
1555 is_shorthand
: false,
1556 attrs
: ast
::ThinVec
::new(),
1561 cx
.pat_struct(self.span
, struct_path
, field_pats
)
1563 VariantData
::Tuple(..) => {
1564 cx
.pat_tuple_struct(self.span
, struct_path
, subpats
)
1566 VariantData
::Unit(..) => {
1567 cx
.pat_path(self.span
, struct_path
)
1571 (pattern
, ident_exprs
)
1574 fn create_enum_variant_pattern
1577 enum_ident
: ast
::Ident
,
1578 variant
: &'a ast
::Variant
,
1580 mutbl
: ast
::Mutability
)
1581 -> (P
<ast
::Pat
>, Vec
<(Span
, Option
<Ident
>, P
<Expr
>, &'a
[ast
::Attribute
])>) {
1582 let variant_ident
= variant
.node
.name
;
1583 let sp
= Span { ctxt: self.span.ctxt, ..variant.span }
;
1584 let variant_path
= cx
.path(sp
, vec
![enum_ident
, variant_ident
]);
1585 self.create_struct_pattern(cx
, variant_path
, &variant
.node
.data
, prefix
, mutbl
)
1589 // helpful premade recipes
1591 /// Fold the fields. `use_foldl` controls whether this is done
1592 /// left-to-right (`true`) or right-to-left (`false`).
1593 pub fn cs_fold
<F
>(use_foldl
: bool
,
1596 mut enum_nonmatch_f
: EnumNonMatchCollapsedFunc
,
1599 substructure
: &Substructure
)
1601 where F
: FnMut(&mut ExtCtxt
, Span
, P
<Expr
>, P
<Expr
>, &[P
<Expr
>]) -> P
<Expr
>
1603 match *substructure
.fields
{
1604 EnumMatching(.., ref all_fields
) |
1605 Struct(_
, ref all_fields
) => {
1607 all_fields
.iter().fold(base
, |old
, field
| {
1608 f(cx
, field
.span
, old
, field
.self_
.clone(), &field
.other
)
1611 all_fields
.iter().rev().fold(base
, |old
, field
| {
1612 f(cx
, field
.span
, old
, field
.self_
.clone(), &field
.other
)
1616 EnumNonMatchingCollapsed(ref all_args
, _
, tuple
) => {
1619 (&all_args
[..], tuple
),
1620 substructure
.nonself_args
)
1622 StaticEnum(..) | StaticStruct(..) => cx
.span_bug(trait_span
, "static function in `derive`"),
1627 /// Call the method that is being derived on all the fields, and then
1628 /// process the collected results. i.e.
1630 /// ```ignore (only-for-syntax-highlight)
1631 /// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
1632 /// self_2.method(__arg_1_2, __arg_2_2)])
1635 pub fn cs_same_method
<F
>(f
: F
,
1636 mut enum_nonmatch_f
: EnumNonMatchCollapsedFunc
,
1639 substructure
: &Substructure
)
1641 where F
: FnOnce(&mut ExtCtxt
, Span
, Vec
<P
<Expr
>>) -> P
<Expr
>
1643 match *substructure
.fields
{
1644 EnumMatching(.., ref all_fields
) |
1645 Struct(_
, ref all_fields
) => {
1646 // call self_n.method(other_1_n, other_2_n, ...)
1647 let called
= all_fields
.iter()
1649 cx
.expr_method_call(field
.span
,
1650 field
.self_
.clone(),
1651 substructure
.method_ident
,
1654 .map(|e
| cx
.expr_addr_of(field
.span
, e
.clone()))
1659 f(cx
, trait_span
, called
)
1661 EnumNonMatchingCollapsed(ref all_self_args
, _
, tuple
) => {
1664 (&all_self_args
[..], tuple
),
1665 substructure
.nonself_args
)
1667 StaticEnum(..) | StaticStruct(..) => cx
.span_bug(trait_span
, "static function in `derive`"),
1671 /// Return true if the type has no value fields
1672 /// (for an enum, no variant has any fields)
1673 pub fn is_type_without_fields(item
: &Annotatable
) -> bool
{
1674 if let Annotatable
::Item(ref item
) = *item
{
1676 ast
::ItemKind
::Enum(ref enum_def
, _
) => {
1677 enum_def
.variants
.iter().all(|v
| v
.node
.data
.fields().is_empty())
1679 ast
::ItemKind
::Struct(ref variant_data
, _
) => variant_data
.fields().is_empty(),