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