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