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