]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_ext/deriving/generic/mod.rs
Remove unused import.
[rust.git] / src / libsyntax_ext / deriving / generic / mod.rs
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.
4 //
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.
10
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.
15 //!
16 //! Supported features (fairly exhaustive):
17 //!
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`)
25 //!
26 //! The most important thing for implementers is the `Substructure` and
27 //! `SubstructureFields` objects. The latter groups 5 possibilities of the
28 //! arguments:
29 //!
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
39 //!   arguments.)
40 //!
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
48 //! differently.
49 //!
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
54 //! following snippet
55 //!
56 //! ```rust
57 //! # #![allow(dead_code)]
58 //! struct A { x : i32 }
59 //!
60 //! struct B(i32);
61 //!
62 //! enum C {
63 //!     C0(i32),
64 //!     C1 { x: i32 }
65 //! }
66 //! ```
67 //!
68 //! The `i32`s in `B` and `C0` don't have an identifier, so the
69 //! `Option<ident>`s would be `None` for them.
70 //!
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.
76 //!
77 //! # "`cs`" functions
78 //!
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.
85 //!
86 //! # Examples
87 //!
88 //! The following simplified `PartialEq` is used for in-code examples:
89 //!
90 //! ```rust
91 //! trait PartialEq {
92 //!     fn eq(&self, other: &Self) -> bool;
93 //! }
94 //! impl PartialEq for i32 {
95 //!     fn eq(&self, other: &i32) -> bool {
96 //!         *self == *other
97 //!     }
98 //! }
99 //! ```
100 //!
101 //! Some examples of the values of `SubstructureFields` follow, using the
102 //! above `PartialEq`, `A`, `B` and `C`.
103 //!
104 //! ## Structs
105 //!
106 //! When generating the `expr` for the `A` impl, the `SubstructureFields` is
107 //!
108 //! ```{.text}
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]
114 //!          }])
115 //! ```
116 //!
117 //! For the `B` impl, called with `B(a)` and `B(b)`,
118 //!
119 //! ```{.text}
120 //! Struct(vec![FieldInfo {
121 //!           span: <span of `i32`>,
122 //!           name: None,
123 //!           self_: <expr for &a>
124 //!           other: vec![<expr for &b>]
125 //!          }])
126 //! ```
127 //!
128 //! ## Enums
129 //!
130 //! When generating the `expr` for a call with `self == C0(a)` and `other
131 //! == C0(b)`, the SubstructureFields is
132 //!
133 //! ```{.text}
134 //! EnumMatching(0, <ast::Variant for C0>,
135 //!              vec![FieldInfo {
136 //!                 span: <span of i32>
137 //!                 name: None,
138 //!                 self_: <expr for &a>,
139 //!                 other: vec![<expr for &b>]
140 //!               }])
141 //! ```
142 //!
143 //! For `C1 {x}` and `C1 {x}`,
144 //!
145 //! ```{.text}
146 //! EnumMatching(1, <ast::Variant for C1>,
147 //!              vec![FieldInfo {
148 //!                 span: <span of x>
149 //!                 name: Some(<ident of x>),
150 //!                 self_: <expr for &self.x>,
151 //!                 other: vec![<expr for &other.x>]
152 //!                }])
153 //! ```
154 //!
155 //! For `C0(a)` and `C1 {x}` ,
156 //!
157 //! ```{.text}
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>])
162 //! ```
163 //!
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.
168 //!
169 //! `EnumNonMatchingCollapsed` deliberately provides far less information
170 //! than is generally available for a given pair of variants; see #15375
171 //! for discussion.
172 //!
173 //! ## Static
174 //!
175 //! A static method on the types above would result in,
176 //!
177 //! ```{.text}
178 //! StaticStruct(<ast::VariantData of A>, Named(vec![(<ident of x>, <span of x>)]))
179 //!
180 //! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
181 //!
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>)]))])
185 //! ```
186
187 pub use self::StaticFields::*;
188 pub use self::SubstructureFields::*;
189
190 use std::cell::RefCell;
191 use std::collections::HashSet;
192 use std::vec;
193
194 use syntax::abi::Abi;
195 use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind, VariantData};
196 use syntax::attr;
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;
201 use syntax::ptr::P;
202 use syntax::symbol::{Symbol, keywords};
203 use syntax_pos::{DUMMY_SP, Span};
204 use errors::Handler;
205
206 use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
207
208 use deriving;
209
210 pub mod ty;
211
212 pub struct TraitDef<'a> {
213     /// The span for the current #[derive(Foo)] header.
214     pub span: Span,
215
216     pub attributes: Vec<ast::Attribute>,
217
218     /// Path of the trait, including any type parameters
219     pub path: Path<'a>,
220
221     /// Additional bounds required of any type parameters of the type,
222     /// other than the current trait
223     pub additional_bounds: Vec<Ty<'a>>,
224
225     /// Any extra lifetimes and/or bounds, e.g. `D: serialize::Decoder`
226     pub generics: LifetimeBounds<'a>,
227
228     /// Is it an `unsafe` trait?
229     pub is_unsafe: bool,
230
231     /// Can this trait be derived for unions?
232     pub supports_unions: bool,
233
234     pub methods: Vec<MethodDef<'a>>,
235
236     pub associated_types: Vec<(ast::Ident, Ty<'a>)>,
237 }
238
239
240 pub struct MethodDef<'a> {
241     /// name of the method
242     pub name: &'a str,
243     /// List of generics, e.g. `R: rand::Rng`
244     pub generics: LifetimeBounds<'a>,
245
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
248     /// Option)
249     pub explicit_self: Option<Option<PtrTy<'a>>>,
250
251     /// Arguments other than the self argument
252     pub args: Vec<Ty<'a>>,
253
254     /// Return type
255     pub ret_ty: Ty<'a>,
256
257     pub attributes: Vec<ast::Attribute>,
258
259     // Is it an `unsafe fn`?
260     pub is_unsafe: bool,
261
262     /// Can we combine fieldless variants for enums into a single match arm?
263     pub unify_fieldless_variants: bool,
264
265     pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
266 }
267
268 /// All the data about the data structure/method being derived upon.
269 pub struct Substructure<'a> {
270     /// ident of self
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>,
279 }
280
281 /// Summary of the relevant parts of a struct/enum field.
282 pub struct FieldInfo<'a> {
283     pub span: Span,
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).
289     pub self_: P<Expr>,
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],
295 }
296
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)>),
303 }
304
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, ast::Variant,
309     /// fields: the field name is only non-`None` in the case of a struct
310     /// variant.
311     EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
312
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]),
320
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)>),
325 }
326
327
328
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>;
333
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>;
341
342 pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
343                                 -> RefCell<CombineSubstructureFunc<'a>> {
344     RefCell::new(f)
345 }
346
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],
352                         span: Span,
353                         cx: &ExtCtxt)
354                         -> Vec<P<ast::Ty>> {
355     use syntax::visit;
356
357     struct Visitor<'a, 'b: 'a> {
358         cx: &'a ExtCtxt<'b>,
359         span: Span,
360         ty_param_names: &'a [ast::Name],
361         types: Vec<P<ast::Ty>>,
362     }
363
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()));
370                     }
371                 }
372             }
373
374             visit::walk_ty(self, ty)
375         }
376
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");
380         }
381     }
382
383     let mut visitor = Visitor {
384         ty_param_names: ty_param_names,
385         types: Vec::new(),
386         span: span,
387         cx: cx,
388     };
389
390     visit::Visitor::visit_ty(&mut visitor, ty);
391
392     visitor.types
393 }
394
395 impl<'a> TraitDef<'a> {
396     pub fn expand(&self,
397                   cx: &mut ExtCtxt,
398                   mitem: &ast::MetaItem,
399                   item: &'a Annotatable,
400                   push: &mut FnMut(Annotatable)) {
401         self.expand_ext(cx, mitem, item, push, false);
402     }
403
404     pub fn expand_ext(&self,
405                       cx: &mut ExtCtxt,
406                       mitem: &ast::MetaItem,
407                       item: &'a Annotatable,
408                       push: &mut FnMut(Annotatable),
409                       from_scratch: bool) {
410         match *item {
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)
415                     }
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)
419                     }
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)
424                         } else {
425                             cx.span_err(mitem.span,
426                                         "this trait cannot be derived for unions");
427                             return;
428                         }
429                     }
430                     _ => {
431                         cx.span_err(mitem.span,
432                                     "`derive` may only be applied to structs, enums and unions");
433                         return;
434                     }
435                 };
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
440                     .iter()
441                     .filter(|a| {
442                         a.name().is_some() && match &*a.name().unwrap().as_str() {
443                             "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
444                             _ => false,
445                         }
446                     })
447                     .cloned());
448                 push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
449             }
450             _ => {
451                 cx.span_err(mitem.span,
452                             "`derive` may only be applied to structs and enums");
453             }
454         }
455     }
456
457     /// Given that we are deriving a trait `DerivedTrait` for a type like:
458     ///
459     /// ```ignore
460     /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait {
461     ///     a: A,
462     ///     b: B::Item,
463     ///     b1: <B as DeclaredTrait>::Item,
464     ///     c1: <C as WhereTrait>::Item,
465     ///     c2: Option<<C as WhereTrait>::Item>,
466     ///     ...
467     /// }
468     /// ```
469     ///
470     /// create an impl like:
471     ///
472     /// ```ignore
473     /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ...  Z> where
474     ///     C:                       WhereTrait,
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,
480     ///     ...
481     /// {
482     ///     ...
483     /// }
484     /// ```
485     ///
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,
489                            cx: &mut ExtCtxt,
490                            type_ident: Ident,
491                            generics: &Generics,
492                            field_tys: Vec<P<ast::Ty>>,
493                            methods: Vec<ast::ImplItem>)
494                            -> P<ast::Item> {
495         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
496
497         // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem`
498         let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
499             ast::ImplItem {
500                 id: ast::DUMMY_NODE_ID,
501                 span: self.span,
502                 ident: ident,
503                 vis: ast::Visibility::Inherited,
504                 defaultness: ast::Defaultness::Final,
505                 attrs: Vec::new(),
506                 node: ast::ImplItemKind::Type(type_def.to_ty(cx, self.span, type_ident, generics)),
507             }
508         });
509
510         let Generics { mut lifetimes, mut ty_params, mut where_clause, span } = self.generics
511             .to_generics(cx, self.span, type_ident, generics);
512
513         // Copy the lifetimes
514         lifetimes.extend(generics.lifetimes.iter().cloned());
515
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))
525                 }).collect();
526
527             // require the current trait
528             bounds.push(cx.typarambound(trait_path.clone()));
529
530             // also add in any bounds from the declaration
531             for declared_bound in ty_param.bounds.iter() {
532                 bounds.push((*declared_bound).clone());
533             }
534
535             cx.typaram(self.span, ty_param.ident, vec![], bounds, None)
536         }));
537
538         // and similarly for where clauses
539         where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
540             match *clause {
541                 ast::WherePredicate::BoundPredicate(ref wb) => {
542                     ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
543                         span: self.span,
544                         bound_lifetimes: wb.bound_lifetimes.clone(),
545                         bounded_ty: wb.bounded_ty.clone(),
546                         bounds: wb.bounds.iter().cloned().collect(),
547                     })
548                 }
549                 ast::WherePredicate::RegionPredicate(ref rb) => {
550                     ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
551                         span: self.span,
552                         lifetime: rb.lifetime,
553                         bounds: rb.bounds.iter().cloned().collect(),
554                     })
555                 }
556                 ast::WherePredicate::EqPredicate(ref we) => {
557                     ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
558                         id: ast::DUMMY_NODE_ID,
559                         span: self.span,
560                         lhs_ty: we.lhs_ty.clone(),
561                         rhs_ty: we.rhs_ty.clone(),
562                     })
563                 }
564             }
565         }));
566
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)
570                 .collect();
571
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);
575
576                 for ty in tys {
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) {
582                             continue;
583                         };
584                         processed_field_types.insert(p.segments.clone());
585                     }
586                     let mut bounds: Vec<_> = self.additional_bounds
587                         .iter()
588                         .map(|p| cx.typarambound(p.to_path(cx, self.span, type_ident, generics)))
589                         .collect();
590
591                     // require the current trait
592                     bounds.push(cx.typarambound(trait_path.clone()));
593
594                     let predicate = ast::WhereBoundPredicate {
595                         span: self.span,
596                         bound_lifetimes: vec![],
597                         bounded_ty: ty,
598                         bounds: bounds,
599                     };
600
601                     let predicate = ast::WherePredicate::BoundPredicate(predicate);
602                     where_clause.predicates.push(predicate);
603                 }
604             }
605         }
606
607         let trait_generics = Generics {
608             lifetimes: lifetimes,
609             ty_params: ty_params,
610             where_clause: where_clause,
611             span: span,
612         };
613
614         // Create the reference to the trait.
615         let trait_ref = cx.trait_ref(trait_path);
616
617         // Create the type parameters on the `self` path.
618         let self_ty_params = generics.ty_params
619             .iter()
620             .map(|ty_param| cx.ty_ident(self.span, ty_param.ident))
621             .collect();
622
623         let self_lifetimes: Vec<ast::Lifetime> = generics.lifetimes
624             .iter()
625             .map(|ld| ld.lifetime)
626             .collect();
627
628         // Create the type of `self`.
629         let self_type = cx.ty_path(cx.path_all(self.span,
630                                                false,
631                                                vec![type_ident],
632                                                self_lifetimes,
633                                                self_ty_params,
634                                                Vec::new()));
635
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);
642         let unused_qual = {
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]))
645         };
646
647         let mut a = vec![attr, unused_qual];
648         a.extend(self.attributes.iter().cloned());
649
650         let unsafety = if self.is_unsafe {
651             ast::Unsafety::Unsafe
652         } else {
653             ast::Unsafety::Normal
654         };
655
656         cx.item(self.span,
657                 keywords::Invalid.ident(),
658                 a,
659                 ast::ItemKind::Impl(unsafety,
660                                     ast::ImplPolarity::Positive,
661                                     trait_generics,
662                                     opt_trait_ref,
663                                     self_type,
664                                     methods.into_iter().chain(associated_types).collect()))
665     }
666
667     fn expand_struct_def(&self,
668                          cx: &mut ExtCtxt,
669                          struct_def: &'a VariantData,
670                          type_ident: Ident,
671                          generics: &Generics,
672                          from_scratch: bool)
673                          -> P<ast::Item> {
674         let field_tys: Vec<P<ast::Ty>> = struct_def.fields()
675             .iter()
676             .map(|field| field.ty.clone())
677             .collect();
678
679         let methods = self.methods
680             .iter()
681             .map(|method_def| {
682                 let (explicit_self, self_args, nonself_args, tys) =
683                     method_def.split_self_nonself_args(cx, self, type_ident, generics);
684
685                 let body = if from_scratch || method_def.is_static() {
686                     method_def.expand_static_struct_method_body(cx,
687                                                                 self,
688                                                                 struct_def,
689                                                                 type_ident,
690                                                                 &self_args[..],
691                                                                 &nonself_args[..])
692                 } else {
693                     method_def.expand_struct_method_body(cx,
694                                                          self,
695                                                          struct_def,
696                                                          type_ident,
697                                                          &self_args[..],
698                                                          &nonself_args[..])
699                 };
700
701                 method_def.create_method(cx,
702                                          self,
703                                          type_ident,
704                                          generics,
705                                          Abi::Rust,
706                                          explicit_self,
707                                          tys,
708                                          body)
709             })
710             .collect();
711
712         self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
713     }
714
715     fn expand_enum_def(&self,
716                        cx: &mut ExtCtxt,
717                        enum_def: &'a EnumDef,
718                        type_attrs: &[ast::Attribute],
719                        type_ident: Ident,
720                        generics: &Generics,
721                        from_scratch: bool)
722                        -> P<ast::Item> {
723         let mut field_tys = Vec::new();
724
725         for variant in &enum_def.variants {
726             field_tys.extend(variant.node
727                 .data
728                 .fields()
729                 .iter()
730                 .map(|field| field.ty.clone()));
731         }
732
733         let methods = self.methods
734             .iter()
735             .map(|method_def| {
736                 let (explicit_self, self_args, nonself_args, tys) =
737                     method_def.split_self_nonself_args(cx, self, type_ident, generics);
738
739                 let body = if from_scratch || method_def.is_static() {
740                     method_def.expand_static_enum_method_body(cx,
741                                                               self,
742                                                               enum_def,
743                                                               type_ident,
744                                                               &self_args[..],
745                                                               &nonself_args[..])
746                 } else {
747                     method_def.expand_enum_method_body(cx,
748                                                        self,
749                                                        enum_def,
750                                                        type_attrs,
751                                                        type_ident,
752                                                        self_args,
753                                                        &nonself_args[..])
754                 };
755
756                 method_def.create_method(cx,
757                                          self,
758                                          type_ident,
759                                          generics,
760                                          Abi::Rust,
761                                          explicit_self,
762                                          tys,
763                                          body)
764             })
765             .collect();
766
767         self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
768     }
769 }
770
771 fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &'static str {
772     let mut repr_type_name = "isize";
773     for a in type_attrs {
774         for r in &attr::find_repr_attrs(diagnostic, a) {
775             repr_type_name = match *r {
776                 attr::ReprPacked | attr::ReprSimd => continue,
777                 attr::ReprExtern => "i32",
778
779                 attr::ReprInt(attr::SignedInt(ast::IntTy::Is)) => "isize",
780                 attr::ReprInt(attr::SignedInt(ast::IntTy::I8)) => "i8",
781                 attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16",
782                 attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32",
783                 attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64",
784                 attr::ReprInt(attr::SignedInt(ast::IntTy::I128)) => "i128",
785
786                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::Us)) => "usize",
787                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8",
788                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16",
789                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32",
790                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U64)) => "u64",
791                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U128)) => "u128",
792             }
793         }
794     }
795     repr_type_name
796 }
797
798 impl<'a> MethodDef<'a> {
799     fn call_substructure_method(&self,
800                                 cx: &mut ExtCtxt,
801                                 trait_: &TraitDef,
802                                 type_ident: Ident,
803                                 self_args: &[P<Expr>],
804                                 nonself_args: &[P<Expr>],
805                                 fields: &SubstructureFields)
806                                 -> P<Expr> {
807         let substructure = Substructure {
808             type_ident: type_ident,
809             method_ident: cx.ident_of(self.name),
810             self_args: self_args,
811             nonself_args: nonself_args,
812             fields: fields,
813         };
814         let mut f = self.combine_substructure.borrow_mut();
815         let f: &mut CombineSubstructureFunc = &mut *f;
816         f(cx, trait_.span, &substructure)
817     }
818
819     fn get_ret_ty(&self,
820                   cx: &mut ExtCtxt,
821                   trait_: &TraitDef,
822                   generics: &Generics,
823                   type_ident: Ident)
824                   -> P<ast::Ty> {
825         self.ret_ty.to_ty(cx, trait_.span, type_ident, generics)
826     }
827
828     fn is_static(&self) -> bool {
829         self.explicit_self.is_none()
830     }
831
832     fn split_self_nonself_args
833         (&self,
834          cx: &mut ExtCtxt,
835          trait_: &TraitDef,
836          type_ident: Ident,
837          generics: &Generics)
838          -> (Option<ast::ExplicitSelf>, Vec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
839
840         let mut self_args = Vec::new();
841         let mut nonself_args = Vec::new();
842         let mut arg_tys = Vec::new();
843         let mut nonstatic = false;
844
845         let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| {
846             let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_.span, self_ptr);
847
848             self_args.push(self_expr);
849             nonstatic = true;
850
851             explicit_self
852         });
853
854         for (i, ty) in self.args.iter().enumerate() {
855             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
856             let ident = cx.ident_of(&format!("__arg_{}", i));
857             arg_tys.push((ident, ast_ty));
858
859             let arg_expr = cx.expr_ident(trait_.span, ident);
860
861             match *ty {
862                 // for static methods, just treat any Self
863                 // arguments as a normal arg
864                 Self_ if nonstatic => {
865                     self_args.push(arg_expr);
866                 }
867                 Ptr(ref ty, _) if **ty == Self_ && nonstatic => {
868                     self_args.push(cx.expr_deref(trait_.span, arg_expr))
869                 }
870                 _ => {
871                     nonself_args.push(arg_expr);
872                 }
873             }
874         }
875
876         (ast_explicit_self, self_args, nonself_args, arg_tys)
877     }
878
879     fn create_method(&self,
880                      cx: &mut ExtCtxt,
881                      trait_: &TraitDef,
882                      type_ident: Ident,
883                      generics: &Generics,
884                      abi: Abi,
885                      explicit_self: Option<ast::ExplicitSelf>,
886                      arg_types: Vec<(Ident, P<ast::Ty>)>,
887                      body: P<Expr>)
888                      -> ast::ImplItem {
889
890         // create the generics that aren't for Self
891         let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
892
893         let args = {
894             let self_args = explicit_self.map(|explicit_self| {
895                 ast::Arg::from_self(explicit_self,
896                                     respan(trait_.span, keywords::SelfValue.ident()))
897             });
898             let nonself_args = arg_types.into_iter()
899                 .map(|(name, ty)| cx.arg(trait_.span, name, ty));
900             self_args.into_iter().chain(nonself_args).collect()
901         };
902
903         let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
904
905         let method_ident = cx.ident_of(self.name);
906         let fn_decl = cx.fn_decl(args, ret_type);
907         let body_block = cx.block_expr(body);
908
909         let unsafety = if self.is_unsafe {
910             ast::Unsafety::Unsafe
911         } else {
912             ast::Unsafety::Normal
913         };
914
915         // Create the method.
916         ast::ImplItem {
917             id: ast::DUMMY_NODE_ID,
918             attrs: self.attributes.clone(),
919             span: trait_.span,
920             vis: ast::Visibility::Inherited,
921             defaultness: ast::Defaultness::Final,
922             ident: method_ident,
923             node: ast::ImplItemKind::Method(ast::MethodSig {
924                                                 generics: fn_generics,
925                                                 abi: abi,
926                                                 unsafety: unsafety,
927                                                 constness:
928                                                     dummy_spanned(ast::Constness::NotConst),
929                                                 decl: fn_decl,
930                                             },
931                                             body_block),
932         }
933     }
934
935     /// ```ignore
936     /// #[derive(PartialEq)]
937     /// struct A { x: i32, y: i32 }
938     ///
939     /// // equivalent to:
940     /// impl PartialEq for A {
941     ///     fn eq(&self, __arg_1: &A) -> bool {
942     ///         match *self {
943     ///             A {x: ref __self_0_0, y: ref __self_0_1} => {
944     ///                 match *__arg_1 {
945     ///                     A {x: ref __self_1_0, y: ref __self_1_1} => {
946     ///                         __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1)
947     ///                     }
948     ///                 }
949     ///             }
950     ///         }
951     ///     }
952     /// }
953     /// ```
954     fn expand_struct_method_body<'b>(&self,
955                                      cx: &mut ExtCtxt,
956                                      trait_: &TraitDef<'b>,
957                                      struct_def: &'b VariantData,
958                                      type_ident: Ident,
959                                      self_args: &[P<Expr>],
960                                      nonself_args: &[P<Expr>])
961                                      -> P<Expr> {
962
963         let mut raw_fields = Vec::new(); // Vec<[fields of self],
964                                  // [fields of next Self arg], [etc]>
965         let mut patterns = Vec::new();
966         for i in 0..self_args.len() {
967             let struct_path = cx.path(DUMMY_SP, vec![type_ident]);
968             let (pat, ident_expr) = trait_.create_struct_pattern(cx,
969                                                                  struct_path,
970                                                                  struct_def,
971                                                                  &format!("__self_{}", i),
972                                                                  ast::Mutability::Immutable);
973             patterns.push(pat);
974             raw_fields.push(ident_expr);
975         }
976
977         // transpose raw_fields
978         let fields = if !raw_fields.is_empty() {
979             let mut raw_fields = raw_fields.into_iter().map(|v| v.into_iter());
980             let first_field = raw_fields.next().unwrap();
981             let mut other_fields: Vec<vec::IntoIter<_>> = raw_fields.collect();
982             first_field.map(|(span, opt_id, field, attrs)| {
983                     FieldInfo {
984                         span: span,
985                         name: opt_id,
986                         self_: field,
987                         other: other_fields.iter_mut()
988                             .map(|l| {
989                                 match l.next().unwrap() {
990                                     (.., ex, _) => ex,
991                                 }
992                             })
993                             .collect(),
994                         attrs: attrs,
995                     }
996                 })
997                 .collect()
998         } else {
999             cx.span_bug(trait_.span,
1000                         "no self arguments to non-static method in generic \
1001                          `derive`")
1002         };
1003
1004         // body of the inner most destructuring match
1005         let mut body = self.call_substructure_method(cx,
1006                                                      trait_,
1007                                                      type_ident,
1008                                                      self_args,
1009                                                      nonself_args,
1010                                                      &Struct(struct_def, fields));
1011
1012         // make a series of nested matches, to destructure the
1013         // structs. This is actually right-to-left, but it shouldn't
1014         // matter.
1015         for (arg_expr, pat) in self_args.iter().zip(patterns) {
1016             body = cx.expr_match(trait_.span,
1017                                  arg_expr.clone(),
1018                                  vec![cx.arm(trait_.span, vec![pat.clone()], body)])
1019         }
1020
1021         body
1022     }
1023
1024     fn expand_static_struct_method_body(&self,
1025                                         cx: &mut ExtCtxt,
1026                                         trait_: &TraitDef,
1027                                         struct_def: &VariantData,
1028                                         type_ident: Ident,
1029                                         self_args: &[P<Expr>],
1030                                         nonself_args: &[P<Expr>])
1031                                         -> P<Expr> {
1032         let summary = trait_.summarise_struct(cx, struct_def);
1033
1034         self.call_substructure_method(cx,
1035                                       trait_,
1036                                       type_ident,
1037                                       self_args,
1038                                       nonself_args,
1039                                       &StaticStruct(struct_def, summary))
1040     }
1041
1042     /// ```ignore
1043     /// #[derive(PartialEq)]
1044     /// enum A {
1045     ///     A1,
1046     ///     A2(i32)
1047     /// }
1048     ///
1049     /// // is equivalent to
1050     ///
1051     /// impl PartialEq for A {
1052     ///     fn eq(&self, __arg_1: &A) -> ::bool {
1053     ///         match (&*self, &*__arg_1) {
1054     ///             (&A1, &A1) => true,
1055     ///             (&A2(ref self_0),
1056     ///              &A2(ref __arg_1_0)) => (*self_0).eq(&(*__arg_1_0)),
1057     ///             _ => {
1058     ///                 let __self_vi = match *self { A1(..) => 0, A2(..) => 1 };
1059     ///                 let __arg_1_vi = match *__arg_1 { A1(..) => 0, A2(..) => 1 };
1060     ///                 false
1061     ///             }
1062     ///         }
1063     ///     }
1064     /// }
1065     /// ```
1066     ///
1067     /// (Of course `__self_vi` and `__arg_1_vi` are unused for
1068     /// `PartialEq`, and those subcomputations will hopefully be removed
1069     /// as their results are unused.  The point of `__self_vi` and
1070     /// `__arg_1_vi` is for `PartialOrd`; see #15503.)
1071     fn expand_enum_method_body<'b>(&self,
1072                                    cx: &mut ExtCtxt,
1073                                    trait_: &TraitDef<'b>,
1074                                    enum_def: &'b EnumDef,
1075                                    type_attrs: &[ast::Attribute],
1076                                    type_ident: Ident,
1077                                    self_args: Vec<P<Expr>>,
1078                                    nonself_args: &[P<Expr>])
1079                                    -> P<Expr> {
1080         self.build_enum_match_tuple(cx,
1081                                     trait_,
1082                                     enum_def,
1083                                     type_attrs,
1084                                     type_ident,
1085                                     self_args,
1086                                     nonself_args)
1087     }
1088
1089
1090     /// Creates a match for a tuple of all `self_args`, where either all
1091     /// variants match, or it falls into a catch-all for when one variant
1092     /// does not match.
1093
1094     /// There are N + 1 cases because is a case for each of the N
1095     /// variants where all of the variants match, and one catch-all for
1096     /// when one does not match.
1097
1098     /// As an optimization we generate code which checks whether all variants
1099     /// match first which makes llvm see that C-like enums can be compiled into
1100     /// a simple equality check (for PartialEq).
1101
1102     /// The catch-all handler is provided access the variant index values
1103     /// for each of the self-args, carried in precomputed variables.
1104
1105     /// ```{.text}
1106     /// let __self0_vi = unsafe {
1107     ///     std::intrinsics::discriminant_value(&self) } as i32;
1108     /// let __self1_vi = unsafe {
1109     ///     std::intrinsics::discriminant_value(&arg1) } as i32;
1110     /// let __self2_vi = unsafe {
1111     ///     std::intrinsics::discriminant_value(&arg2) } as i32;
1112     ///
1113     /// if __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... {
1114     ///     match (...) {
1115     ///         (Variant1, Variant1, ...) => Body1
1116     ///         (Variant2, Variant2, ...) => Body2,
1117     ///         ...
1118     ///         _ => ::core::intrinsics::unreachable()
1119     ///     }
1120     /// }
1121     /// else {
1122     ///     ... // catch-all remainder can inspect above variant index values.
1123     /// }
1124     /// ```
1125     fn build_enum_match_tuple<'b>(&self,
1126                                   cx: &mut ExtCtxt,
1127                                   trait_: &TraitDef<'b>,
1128                                   enum_def: &'b EnumDef,
1129                                   type_attrs: &[ast::Attribute],
1130                                   type_ident: Ident,
1131                                   self_args: Vec<P<Expr>>,
1132                                   nonself_args: &[P<Expr>])
1133                                   -> P<Expr> {
1134
1135         let sp = trait_.span;
1136         let variants = &enum_def.variants;
1137
1138         let self_arg_names = self_args.iter()
1139             .enumerate()
1140             .map(|(arg_count, _self_arg)| {
1141                 if arg_count == 0 {
1142                     "__self".to_string()
1143                 } else {
1144                     format!("__arg_{}", arg_count)
1145                 }
1146             })
1147             .collect::<Vec<String>>();
1148
1149         let self_arg_idents = self_arg_names.iter()
1150             .map(|name| cx.ident_of(&name[..]))
1151             .collect::<Vec<ast::Ident>>();
1152
1153         // The `vi_idents` will be bound, solely in the catch-all, to
1154         // a series of let statements mapping each self_arg to an int
1155         // value corresponding to its discriminant.
1156         let vi_idents: Vec<ast::Ident> = self_arg_names.iter()
1157             .map(|name| {
1158                 let vi_suffix = format!("{}_vi", &name[..]);
1159                 cx.ident_of(&vi_suffix[..])
1160             })
1161             .collect::<Vec<ast::Ident>>();
1162
1163         // Builds, via callback to call_substructure_method, the
1164         // delegated expression that handles the catch-all case,
1165         // using `__variants_tuple` to drive logic if necessary.
1166         let catch_all_substructure =
1167             EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]);
1168
1169         let first_fieldless = variants.iter().find(|v| v.node.data.fields().is_empty());
1170
1171         // These arms are of the form:
1172         // (Variant1, Variant1, ...) => Body1
1173         // (Variant2, Variant2, ...) => Body2
1174         // ...
1175         // where each tuple has length = self_args.len()
1176         let mut match_arms: Vec<ast::Arm> = variants.iter()
1177             .enumerate()
1178             .filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty()))
1179             .map(|(index, variant)| {
1180                 let mk_self_pat = |cx: &mut ExtCtxt, self_arg_name: &str| {
1181                     let (p, idents) = trait_.create_enum_variant_pattern(cx,
1182                                                      type_ident,
1183                                                      variant,
1184                                                      self_arg_name,
1185                                                      ast::Mutability::Immutable);
1186                     (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Immutable)), idents)
1187                 };
1188
1189                 // A single arm has form (&VariantK, &VariantK, ...) => BodyK
1190                 // (see "Final wrinkle" note below for why.)
1191                 let mut subpats = Vec::with_capacity(self_arg_names.len());
1192                 let mut self_pats_idents = Vec::with_capacity(self_arg_names.len() - 1);
1193                 let first_self_pat_idents = {
1194                     let (p, idents) = mk_self_pat(cx, &self_arg_names[0]);
1195                     subpats.push(p);
1196                     idents
1197                 };
1198                 for self_arg_name in &self_arg_names[1..] {
1199                     let (p, idents) = mk_self_pat(cx, &self_arg_name[..]);
1200                     subpats.push(p);
1201                     self_pats_idents.push(idents);
1202                 }
1203
1204                 // Here is the pat = `(&VariantK, &VariantK, ...)`
1205                 let single_pat = cx.pat_tuple(sp, subpats);
1206
1207                 // For the BodyK, we need to delegate to our caller,
1208                 // passing it an EnumMatching to indicate which case
1209                 // we are in.
1210
1211                 // All of the Self args have the same variant in these
1212                 // cases.  So we transpose the info in self_pats_idents
1213                 // to gather the getter expressions together, in the
1214                 // form that EnumMatching expects.
1215
1216                 // The transposition is driven by walking across the
1217                 // arg fields of the variant for the first self pat.
1218                 let field_tuples = first_self_pat_idents.into_iter().enumerate()
1219                     // For each arg field of self, pull out its getter expr ...
1220                     .map(|(field_index, (sp, opt_ident, self_getter_expr, attrs))| {
1221                         // ... but FieldInfo also wants getter expr
1222                         // for matching other arguments of Self type;
1223                         // so walk across the *other* self_pats_idents
1224                         // and pull out getter for same field in each
1225                         // of them (using `field_index` tracked above).
1226                         // That is the heart of the transposition.
1227                         let others = self_pats_idents.iter().map(|fields| {
1228                             let (_, _opt_ident, ref other_getter_expr, _) =
1229                                 fields[field_index];
1230
1231                             // All Self args have same variant, so
1232                             // opt_idents are the same.  (Assert
1233                             // here to make it self-evident that
1234                             // it is okay to ignore `_opt_ident`.)
1235                             assert!(opt_ident == _opt_ident);
1236
1237                             other_getter_expr.clone()
1238                         }).collect::<Vec<P<Expr>>>();
1239
1240                         FieldInfo { span: sp,
1241                                     name: opt_ident,
1242                                     self_: self_getter_expr,
1243                                     other: others,
1244                                     attrs: attrs,
1245                         }
1246                     }).collect::<Vec<FieldInfo>>();
1247
1248                 // Now, for some given VariantK, we have built up
1249                 // expressions for referencing every field of every
1250                 // Self arg, assuming all are instances of VariantK.
1251                 // Build up code associated with such a case.
1252                 let substructure = EnumMatching(index, variant, field_tuples);
1253                 let arm_expr = self.call_substructure_method(cx,
1254                                                              trait_,
1255                                                              type_ident,
1256                                                              &self_args[..],
1257                                                              nonself_args,
1258                                                              &substructure);
1259
1260                 cx.arm(sp, vec![single_pat], arm_expr)
1261             })
1262             .collect();
1263
1264         let default = match first_fieldless {
1265             Some(v) if self.unify_fieldless_variants => {
1266                 // We need a default case that handles the fieldless variants.
1267                 // The index and actual variant aren't meaningful in this case,
1268                 // so just use whatever
1269                 Some(self.call_substructure_method(cx,
1270                                                    trait_,
1271                                                    type_ident,
1272                                                    &self_args[..],
1273                                                    nonself_args,
1274                                                    &EnumMatching(0, v, Vec::new())))
1275             }
1276             _ if variants.len() > 1 && self_args.len() > 1 => {
1277                 // Since we know that all the arguments will match if we reach
1278                 // the match expression we add the unreachable intrinsics as the
1279                 // result of the catch all which should help llvm in optimizing it
1280                 Some(deriving::call_intrinsic(cx, sp, "unreachable", vec![]))
1281             }
1282             _ => None,
1283         };
1284         if let Some(arm) = default {
1285             match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], arm));
1286         }
1287
1288         // We will usually need the catch-all after matching the
1289         // tuples `(VariantK, VariantK, ...)` for each VariantK of the
1290         // enum.  But:
1291         //
1292         // * when there is only one Self arg, the arms above suffice
1293         // (and the deriving we call back into may not be prepared to
1294         // handle EnumNonMatchCollapsed), and,
1295         //
1296         // * when the enum has only one variant, the single arm that
1297         // is already present always suffices.
1298         //
1299         // * In either of the two cases above, if we *did* add a
1300         //   catch-all `_` match, it would trigger the
1301         //   unreachable-pattern error.
1302         //
1303         if variants.len() > 1 && self_args.len() > 1 {
1304             // Build a series of let statements mapping each self_arg
1305             // to its discriminant value. If this is a C-style enum
1306             // with a specific repr type, then casts the values to
1307             // that type.  Otherwise casts to `i32` (the default repr
1308             // type).
1309             //
1310             // i.e. for `enum E<T> { A, B(1), C(T, T) }`, and a deriving
1311             // with three Self args, builds three statements:
1312             //
1313             // ```
1314             // let __self0_vi = unsafe {
1315             //     std::intrinsics::discriminant_value(&self) } as i32;
1316             // let __self1_vi = unsafe {
1317             //     std::intrinsics::discriminant_value(&arg1) } as i32;
1318             // let __self2_vi = unsafe {
1319             //     std::intrinsics::discriminant_value(&arg2) } as i32;
1320             // ```
1321             let mut index_let_stmts: Vec<ast::Stmt> = Vec::new();
1322
1323             // We also build an expression which checks whether all discriminants are equal
1324             // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
1325             let mut discriminant_test = cx.expr_bool(sp, true);
1326
1327             let target_type_name = find_repr_type_name(&cx.parse_sess.span_diagnostic, type_attrs);
1328
1329             let mut first_ident = None;
1330             for (&ident, self_arg) in vi_idents.iter().zip(&self_args) {
1331                 let self_addr = cx.expr_addr_of(sp, self_arg.clone());
1332                 let variant_value =
1333                     deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]);
1334
1335                 let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name));
1336                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
1337                 let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
1338                 index_let_stmts.push(let_stmt);
1339
1340                 match first_ident {
1341                     Some(first) => {
1342                         let first_expr = cx.expr_ident(sp, first);
1343                         let id = cx.expr_ident(sp, ident);
1344                         let test = cx.expr_binary(sp, BinOpKind::Eq, first_expr, id);
1345                         discriminant_test =
1346                             cx.expr_binary(sp, BinOpKind::And, discriminant_test, test)
1347                     }
1348                     None => {
1349                         first_ident = Some(ident);
1350                     }
1351                 }
1352             }
1353
1354             let arm_expr = self.call_substructure_method(cx,
1355                                                          trait_,
1356                                                          type_ident,
1357                                                          &self_args[..],
1358                                                          nonself_args,
1359                                                          &catch_all_substructure);
1360
1361             // Final wrinkle: the self_args are expressions that deref
1362             // down to desired l-values, but we cannot actually deref
1363             // them when they are fed as r-values into a tuple
1364             // expression; here add a layer of borrowing, turning
1365             // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1366             let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
1367             let match_arg = cx.expr(sp, ast::ExprKind::Tup(borrowed_self_args));
1368
1369             // Lastly we create an expression which branches on all discriminants being equal
1370             //  if discriminant_test {
1371             //      match (...) {
1372             //          (Variant1, Variant1, ...) => Body1
1373             //          (Variant2, Variant2, ...) => Body2,
1374             //          ...
1375             //          _ => ::core::intrinsics::unreachable()
1376             //      }
1377             //  }
1378             //  else {
1379             //      <delegated expression referring to __self0_vi, et al.>
1380             //  }
1381             let all_match = cx.expr_match(sp, match_arg, match_arms);
1382             let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr));
1383             index_let_stmts.push(cx.stmt_expr(arm_expr));
1384             cx.expr_block(cx.block(sp, index_let_stmts))
1385         } else if variants.is_empty() {
1386             // As an additional wrinkle, For a zero-variant enum A,
1387             // currently the compiler
1388             // will accept `fn (a: &Self) { match   *a   { } }`
1389             // but rejects `fn (a: &Self) { match (&*a,) { } }`
1390             // as well as  `fn (a: &Self) { match ( *a,) { } }`
1391             //
1392             // This means that the strategy of building up a tuple of
1393             // all Self arguments fails when Self is a zero variant
1394             // enum: rustc rejects the expanded program, even though
1395             // the actual code tends to be impossible to execute (at
1396             // least safely), according to the type system.
1397             //
1398             // The most expedient fix for this is to just let the
1399             // code fall through to the catch-all.  But even this is
1400             // error-prone, since the catch-all as defined above would
1401             // generate code like this:
1402             //
1403             //     _ => { let __self0 = match *self { };
1404             //            let __self1 = match *__arg_0 { };
1405             //            <catch-all-expr> }
1406             //
1407             // Which is yields bindings for variables which type
1408             // inference cannot resolve to unique types.
1409             //
1410             // One option to the above might be to add explicit type
1411             // annotations.  But the *only* reason to go down that path
1412             // would be to try to make the expanded output consistent
1413             // with the case when the number of enum variants >= 1.
1414             //
1415             // That just isn't worth it.  In fact, trying to generate
1416             // sensible code for *any* deriving on a zero-variant enum
1417             // does not make sense.  But at the same time, for now, we
1418             // do not want to cause a compile failure just because the
1419             // user happened to attach a deriving to their
1420             // zero-variant enum.
1421             //
1422             // Instead, just generate a failing expression for the
1423             // zero variant case, skipping matches and also skipping
1424             // delegating back to the end user code entirely.
1425             //
1426             // (See also #4499 and #12609; note that some of the
1427             // discussions there influence what choice we make here;
1428             // e.g. if we feature-gate `match x { ... }` when x refers
1429             // to an uninhabited type (e.g. a zero-variant enum or a
1430             // type holding such an enum), but do not feature-gate
1431             // zero-variant enums themselves, then attempting to
1432             // derive Debug on such a type could here generate code
1433             // that needs the feature gate enabled.)
1434
1435             deriving::call_intrinsic(cx, sp, "unreachable", vec![])
1436         } else {
1437
1438             // Final wrinkle: the self_args are expressions that deref
1439             // down to desired l-values, but we cannot actually deref
1440             // them when they are fed as r-values into a tuple
1441             // expression; here add a layer of borrowing, turning
1442             // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1443             let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
1444             let match_arg = cx.expr(sp, ast::ExprKind::Tup(borrowed_self_args));
1445             cx.expr_match(sp, match_arg, match_arms)
1446         }
1447     }
1448
1449     fn expand_static_enum_method_body(&self,
1450                                       cx: &mut ExtCtxt,
1451                                       trait_: &TraitDef,
1452                                       enum_def: &EnumDef,
1453                                       type_ident: Ident,
1454                                       self_args: &[P<Expr>],
1455                                       nonself_args: &[P<Expr>])
1456                                       -> P<Expr> {
1457         let summary = enum_def.variants
1458             .iter()
1459             .map(|v| {
1460                 let ident = v.node.name;
1461                 let sp = Span { ctxt: trait_.span.ctxt, ..v.span };
1462                 let summary = trait_.summarise_struct(cx, &v.node.data);
1463                 (ident, sp, summary)
1464             })
1465             .collect();
1466         self.call_substructure_method(cx,
1467                                       trait_,
1468                                       type_ident,
1469                                       self_args,
1470                                       nonself_args,
1471                                       &StaticEnum(enum_def, summary))
1472     }
1473 }
1474
1475 // general helper methods.
1476 impl<'a> TraitDef<'a> {
1477     fn summarise_struct(&self, cx: &mut ExtCtxt, struct_def: &VariantData) -> StaticFields {
1478         let mut named_idents = Vec::new();
1479         let mut just_spans = Vec::new();
1480         for field in struct_def.fields() {
1481             let sp = Span { ctxt: self.span.ctxt, ..field.span };
1482             match field.ident {
1483                 Some(ident) => named_idents.push((ident, sp)),
1484                 _ => just_spans.push(sp),
1485             }
1486         }
1487
1488         match (just_spans.is_empty(), named_idents.is_empty()) {
1489             (false, false) => {
1490                 cx.span_bug(self.span,
1491                             "a struct with named and unnamed \
1492                                           fields in generic `derive`")
1493             }
1494             // named fields
1495             (_, false) => Named(named_idents),
1496             // empty structs
1497             _ if struct_def.is_struct() => Named(named_idents),
1498             _ => Unnamed(just_spans, struct_def.is_tuple()),
1499         }
1500     }
1501
1502     fn create_subpatterns(&self,
1503                           cx: &mut ExtCtxt,
1504                           field_paths: Vec<ast::SpannedIdent>,
1505                           mutbl: ast::Mutability)
1506                           -> Vec<P<ast::Pat>> {
1507         field_paths.iter()
1508             .map(|path| {
1509                 cx.pat(path.span,
1510                        PatKind::Ident(ast::BindingMode::ByRef(mutbl), (*path).clone(), None))
1511             })
1512             .collect()
1513     }
1514
1515     fn create_struct_pattern
1516         (&self,
1517          cx: &mut ExtCtxt,
1518          struct_path: ast::Path,
1519          struct_def: &'a VariantData,
1520          prefix: &str,
1521          mutbl: ast::Mutability)
1522          -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
1523         let mut paths = Vec::new();
1524         let mut ident_exprs = Vec::new();
1525         for (i, struct_field) in struct_def.fields().iter().enumerate() {
1526             let sp = Span { ctxt: self.span.ctxt, ..struct_field.span };
1527             let ident = cx.ident_of(&format!("{}_{}", prefix, i));
1528             paths.push(codemap::Spanned {
1529                 span: sp,
1530                 node: ident,
1531             });
1532             let val = cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp, ident)));
1533             let val = cx.expr(sp, ast::ExprKind::Paren(val));
1534             ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..]));
1535         }
1536
1537         let subpats = self.create_subpatterns(cx, paths, mutbl);
1538         let pattern = match *struct_def {
1539             VariantData::Struct(..) => {
1540                 let field_pats = subpats.into_iter()
1541                     .zip(&ident_exprs)
1542                     .map(|(pat, &(sp, ident, ..))| {
1543                         if ident.is_none() {
1544                             cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
1545                         }
1546                         codemap::Spanned {
1547                             span: Span { ctxt: self.span.ctxt, ..pat.span },
1548                             node: ast::FieldPat {
1549                                 ident: ident.unwrap(),
1550                                 pat: pat,
1551                                 is_shorthand: false,
1552                                 attrs: ast::ThinVec::new(),
1553                             },
1554                         }
1555                     })
1556                     .collect();
1557                 cx.pat_struct(self.span, struct_path, field_pats)
1558             }
1559             VariantData::Tuple(..) => {
1560                 cx.pat_tuple_struct(self.span, struct_path, subpats)
1561             }
1562             VariantData::Unit(..) => {
1563                 cx.pat_path(self.span, struct_path)
1564             }
1565         };
1566
1567         (pattern, ident_exprs)
1568     }
1569
1570     fn create_enum_variant_pattern
1571         (&self,
1572          cx: &mut ExtCtxt,
1573          enum_ident: ast::Ident,
1574          variant: &'a ast::Variant,
1575          prefix: &str,
1576          mutbl: ast::Mutability)
1577          -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
1578         let variant_ident = variant.node.name;
1579         let sp = Span { ctxt: self.span.ctxt, ..variant.span };
1580         let variant_path = cx.path(sp, vec![enum_ident, variant_ident]);
1581         self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl)
1582     }
1583 }
1584
1585 // helpful premade recipes
1586
1587 /// Fold the fields. `use_foldl` controls whether this is done
1588 /// left-to-right (`true`) or right-to-left (`false`).
1589 pub fn cs_fold<F>(use_foldl: bool,
1590                   mut f: F,
1591                   base: P<Expr>,
1592                   mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
1593                   cx: &mut ExtCtxt,
1594                   trait_span: Span,
1595                   substructure: &Substructure)
1596                   -> P<Expr>
1597     where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
1598 {
1599     match *substructure.fields {
1600         EnumMatching(.., ref all_fields) |
1601         Struct(_, ref all_fields) => {
1602             if use_foldl {
1603                 all_fields.iter().fold(base, |old, field| {
1604                     f(cx, field.span, old, field.self_.clone(), &field.other)
1605                 })
1606             } else {
1607                 all_fields.iter().rev().fold(base, |old, field| {
1608                     f(cx, field.span, old, field.self_.clone(), &field.other)
1609                 })
1610             }
1611         }
1612         EnumNonMatchingCollapsed(ref all_args, _, tuple) => {
1613             enum_nonmatch_f(cx,
1614                             trait_span,
1615                             (&all_args[..], tuple),
1616                             substructure.nonself_args)
1617         }
1618         StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
1619     }
1620 }
1621
1622
1623 /// Call the method that is being derived on all the fields, and then
1624 /// process the collected results. i.e.
1625 ///
1626 /// ```ignore
1627 /// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
1628 ///                  self_2.method(__arg_1_2, __arg_2_2)])
1629 /// ```
1630 #[inline]
1631 pub fn cs_same_method<F>(f: F,
1632                          mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
1633                          cx: &mut ExtCtxt,
1634                          trait_span: Span,
1635                          substructure: &Substructure)
1636                          -> P<Expr>
1637     where F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>
1638 {
1639     match *substructure.fields {
1640         EnumMatching(.., ref all_fields) |
1641         Struct(_, ref all_fields) => {
1642             // call self_n.method(other_1_n, other_2_n, ...)
1643             let called = all_fields.iter()
1644                 .map(|field| {
1645                     cx.expr_method_call(field.span,
1646                                         field.self_.clone(),
1647                                         substructure.method_ident,
1648                                         field.other
1649                                             .iter()
1650                                             .map(|e| cx.expr_addr_of(field.span, e.clone()))
1651                                             .collect())
1652                 })
1653                 .collect();
1654
1655             f(cx, trait_span, called)
1656         }
1657         EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => {
1658             enum_nonmatch_f(cx,
1659                             trait_span,
1660                             (&all_self_args[..], tuple),
1661                             substructure.nonself_args)
1662         }
1663         StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
1664     }
1665 }
1666
1667 /// Return true if the type has no value fields
1668 /// (for an enum, no variant has any fields)
1669 pub fn is_type_without_fields(item: &Annotatable) -> bool {
1670     if let Annotatable::Item(ref item) = *item {
1671         match item.node {
1672             ast::ItemKind::Enum(ref enum_def, _) => {
1673                 enum_def.variants.iter().all(|v| v.node.data.fields().is_empty())
1674             }
1675             ast::ItemKind::Struct(ref variant_data, _) => variant_data.fields().is_empty(),
1676             _ => false,
1677         }
1678     } else {
1679         false
1680     }
1681 }