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