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