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