(index<- )        ./libsyntax/ext/deriving/generic.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
    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  /*!
   12  
   13  Some code that abstracts away much of the boilerplate of writing
   14  `deriving` instances for traits. Among other things it manages getting
   15  access to the fields of the 4 different sorts of structs and enum
   16  variants, as well as creating the method and impl ast instances.
   17  
   18  Supported features (fairly exhaustive):
   19  
   20  - Methods taking any number of parameters of any type, and returning
   21    any type, other than vectors, bottom and closures.
   22  - Generating `impl`s for types with type parameters and lifetimes
   23    (e.g. `Option<T>`), the parameters are automatically given the
   24    current trait as a bound. (This includes separate type parameters
   25    and lifetimes for methods.)
   26  - Additional bounds on the type parameters, e.g. the `Ord` instance
   27    requires an explicit `Eq` bound at the
   28    moment. (`TraitDef.additional_bounds`)
   29  
   30  Unsupported: FIXME #6257: calling methods on reference fields,
   31  e.g. deriving TotalEq/TotalOrd/Clone don't work on `struct A(&int)`,
   32  because of how the auto-dereferencing happens.
   33  
   34  The most important thing for implementers is the `Substructure` and
   35  `SubstructureFields` objects. The latter groups 5 possibilities of the
   36  arguments:
   37  
   38  - `Struct`, when `Self` is a struct (including tuple structs, e.g
   39    `struct T(int, char)`).
   40  - `EnumMatching`, when `Self` is an enum and all the arguments are the
   41    same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`)
   42  - `EnumNonMatching` when `Self` is an enum and the arguments are not
   43    the same variant (e.g. `None`, `Some(1)` and `None`). If
   44    `const_nonmatching` is true, this will contain an empty list.
   45  - `StaticEnum` and `StaticStruct` for static methods, where the type
   46    being derived upon is either an enum or struct respectively. (Any
   47    argument with type Self is just grouped among the non-self
   48    arguments.)
   49  
   50  In the first two cases, the values from the corresponding fields in
   51  all the arguments are grouped together. In the `EnumNonMatching` case
   52  this isn't possible (different variants have different fields), so the
   53  fields are grouped by which argument they come from. There are no
   54  fields with values in the static cases, so these are treated entirely
   55  differently.
   56  
   57  The non-static cases have `Option<ident>` in several places associated
   58  with field `expr`s. This represents the name of the field it is
   59  associated with. It is only not `None` when the associated field has
   60  an identifier in the source code. For example, the `x`s in the
   61  following snippet
   62  
   63  ```rust
   64  struct A { x : int }
   65  
   66  struct B(int);
   67  
   68  enum C {
   69      C0(int),
   70      C1 { x: int }
   71  }
   72  ```
   73  
   74  The `int`s in `B` and `C0` don't have an identifier, so the
   75  `Option<ident>`s would be `None` for them.
   76  
   77  In the static cases, the structure is summarised, either into the just
   78  spans of the fields or a list of spans and the field idents (for tuple
   79  structs and record structs, respectively), or a list of these, for
   80  enums (one for each variant). For empty struct and empty enum
   81  variants, it is represented as a count of 0.
   82  
   83  # Examples
   84  
   85  The following simplified `Eq` is used for in-code examples:
   86  
   87  ```rust
   88  trait Eq {
   89      fn eq(&self, other: &Self);
   90  }
   91  impl Eq for int {
   92      fn eq(&self, other: &int) -> bool {
   93          *self == *other
   94      }
   95  }
   96  ```
   97  
   98  Some examples of the values of `SubstructureFields` follow, using the
   99  above `Eq`, `A`, `B` and `C`.
  100  
  101  ## Structs
  102  
  103  When generating the `expr` for the `A` impl, the `SubstructureFields` is
  104  
  105  ~~~notrust
  106  Struct(~[FieldInfo {
  107             span: <span of x>
  108             name: Some(<ident of x>),
  109             self_: <expr for &self.x>,
  110             other: ~[<expr for &other.x]
  111           }])
  112  ~~~
  113  
  114  For the `B` impl, called with `B(a)` and `B(b)`,
  115  
  116  ~~~notrust
  117  Struct(~[FieldInfo {
  118            span: <span of `int`>,
  119            name: None,
  120            <expr for &a>
  121            ~[<expr for &b>]
  122           }])
  123  ~~~
  124  
  125  ## Enums
  126  
  127  When generating the `expr` for a call with `self == C0(a)` and `other
  128  == C0(b)`, the SubstructureFields is
  129  
  130  ~~~notrust
  131  EnumMatching(0, <ast::Variant for C0>,
  132               ~[FieldInfo {
  133                  span: <span of int>
  134                  name: None,
  135                  self_: <expr for &a>,
  136                  other: ~[<expr for &b>]
  137                }])
  138  ~~~
  139  
  140  For `C1 {x}` and `C1 {x}`,
  141  
  142  ~~~notrust
  143  EnumMatching(1, <ast::Variant for C1>,
  144               ~[FieldInfo {
  145                  span: <span of x>
  146                  name: Some(<ident of x>),
  147                  self_: <expr for &self.x>,
  148                  other: ~[<expr for &other.x>]
  149                 }])
  150  ~~~
  151  
  152  For `C0(a)` and `C1 {x}` ,
  153  
  154  ~~~notrust
  155  EnumNonMatching(~[(0, <ast::Variant for B0>,
  156                     ~[(<span of int>, None, <expr for &a>)]),
  157                    (1, <ast::Variant for B1>,
  158                     ~[(<span of x>, Some(<ident of x>),
  159                        <expr for &other.x>)])])
  160  ~~~
  161  
  162  (and vice versa, but with the order of the outermost list flipped.)
  163  
  164  ## Static
  165  
  166  A static method on the above would result in,
  167  
  168  ~~~~notrust
  169  StaticStruct(<ast::StructDef of A>, Named(~[(<ident of x>, <span of x>)]))
  170  
  171  StaticStruct(<ast::StructDef of B>, Unnamed(~[<span of x>]))
  172  
  173  StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span of int>])),
  174                                    (<ident of C1>, <span of C1>,
  175                                     Named(~[(<ident of x>, <span of x>)]))])
  176  ~~~
  177  
  178  */
  179  
  180  use std::cell::RefCell;
  181  
  182  use ast;
  183  use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
  184  use ast_util;
  185  use ext::base::ExtCtxt;
  186  use ext::build::AstBuilder;
  187  use codemap;
  188  use codemap::Span;
  189  use owned_slice::OwnedSlice;
  190  use parse::token::InternedString;
  191  
  192  pub use self::ty::*;
  193  mod ty;
  194  
  195  pub struct TraitDef<'a> {
  196      /// The span for the current #[deriving(Foo)] header.
  197      pub span: Span,
  198  
  199      pub attributes: Vec<ast::Attribute>,
  200  
  201      /// Path of the trait, including any type parameters
  202      pub path: Path<'a>,
  203  
  204      /// Additional bounds required of any type parameters of the type,
  205      /// other than the current trait
  206      pub additional_bounds: Vec<Ty<'a>>,
  207  
  208      /// Any extra lifetimes and/or bounds, e.g. `D: serialize::Decoder`
  209      pub generics: LifetimeBounds<'a>,
  210  
  211      pub methods: Vec<MethodDef<'a>>,
  212  }
  213  
  214  
  215  pub struct MethodDef<'a> {
  216      /// name of the method
  217      pub name: &'a str,
  218      /// List of generics, e.g. `R: rand::Rng`
  219      pub generics: LifetimeBounds<'a>,
  220  
  221      /// Whether there is a self argument (outer Option) i.e. whether
  222      /// this is a static function, and whether it is a pointer (inner
  223      /// Option)
  224      pub explicit_self: Option<Option<PtrTy<'a>>>,
  225  
  226      /// Arguments other than the self argument
  227      pub args: Vec<Ty<'a>>,
  228  
  229      /// Return type
  230      pub ret_ty: Ty<'a>,
  231  
  232      pub attributes: Vec<ast::Attribute>,
  233  
  234      /// if the value of the nonmatching enums is independent of the
  235      /// actual enum variants, i.e. can use _ => .. match.
  236      pub const_nonmatching: bool,
  237  
  238      pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
  239  }
  240  
  241  /// All the data about the data structure/method being derived upon.
  242  pub struct Substructure<'a> {
  243      /// ident of self
  244      pub type_ident: Ident,
  245      /// ident of the method
  246      pub method_ident: Ident,
  247      /// dereferenced access to any Self or Ptr(Self, _) arguments
  248      pub self_args: &'a [@Expr],
  249      /// verbatim access to any other arguments
  250      pub nonself_args: &'a [@Expr],
  251      pub fields: &'a SubstructureFields<'a>
  252  }
  253  
  254  /// Summary of the relevant parts of a struct/enum field.
  255  pub struct FieldInfo {
  256      pub span: Span,
  257      /// None for tuple structs/normal enum variants, Some for normal
  258      /// structs/struct enum variants.
  259      pub name: Option<Ident>,
  260      /// The expression corresponding to this field of `self`
  261      /// (specifically, a reference to it).
  262      pub self_: @Expr,
  263      /// The expressions corresponding to references to this field in
  264      /// the other Self arguments.
  265      pub other: Vec<@Expr>,
  266  }
  267  
  268  /// Fields for a static method
  269  pub enum StaticFields {
  270      /// Tuple structs/enum variants like this
  271      Unnamed(Vec<Span> ),
  272      /// Normal structs/struct variants.
  273      Named(Vec<(Ident, Span)> )
  274  }
  275  
  276  /// A summary of the possible sets of fields. See above for details
  277  /// and examples
  278  pub enum SubstructureFields<'a> {
  279      Struct(Vec<FieldInfo> ),
  280      /**
  281      Matching variants of the enum: variant index, ast::Variant,
  282      fields: the field name is only non-`None` in the case of a struct
  283      variant.
  284      */
  285      EnumMatching(uint, &'a ast::Variant, Vec<FieldInfo> ),
  286  
  287      /**
  288      non-matching variants of the enum, [(variant index, ast::Variant,
  289      [field span, field ident, fields])] (i.e. all fields for self are in the
  290      first tuple, for other1 are in the second tuple, etc.)
  291      */
  292      EnumNonMatching(&'a [(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, @Expr)> )]),
  293  
  294      /// A static method where Self is a struct.
  295      StaticStruct(&'a ast::StructDef, StaticFields),
  296      /// A static method where Self is an enum.
  297      StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)> )
  298  }
  299  
  300  
  301  
  302  /**
  303  Combine the values of all the fields together. The last argument is
  304  all the fields of all the structures, see above for details.
  305  */
  306  pub type CombineSubstructureFunc<'a> =
  307      |&mut ExtCtxt, Span, &Substructure|: 'a -> @Expr;
  308  
  309  /**
  310  Deal with non-matching enum variants, the arguments are a list
  311  representing each variant: (variant index, ast::Variant instance,
  312  [variant fields]), and a list of the nonself args of the type
  313  */
  314  pub type EnumNonMatchFunc<'a> =
  315      |&mut ExtCtxt,
  316             Span,
  317             &[(uint, P<ast::Variant>, Vec<(Span, Option<Ident>, @Expr)> )],
  318             &[@Expr]|: 'a
  319             -> @Expr;
  320  
  321  pub fn combine_substructure<'a>(fCombineSubstructureFunc<'a>)
  322      -> RefCell<CombineSubstructureFunc<'a>> {
  323      RefCell::new(f)
  324  }
  325  
  326  
  327  impl<'a> TraitDef<'a> {
  328      pub fn expand(&self,
  329                    cx&mut ExtCtxt,
  330                    _mitem@ast::MetaItem,
  331                    item@ast::Item,
  332                    push|@ast::Item|) {
  333          match item.node {
  334              ast::ItemStruct(struct_def, ref generics) => {
  335                  push(self.expand_struct_def(cx,
  336                                              struct_def,
  337                                              item.ident,
  338                                              generics));
  339              }
  340              ast::ItemEnum(ref enum_def, ref generics) => {
  341                  push(self.expand_enum_def(cx,
  342                                            enum_def,
  343                                            item.ident,
  344                                            generics));
  345              }
  346              _ => ()
  347          }
  348      }
  349  
  350      /**
  351       *
  352       * Given that we are deriving a trait `Tr` for a type `T<'a, ...,
  353       * 'z, A, ..., Z>`, creates an impl like:
  354       *
  355       * ```ignore
  356       *      impl<'a, ..., 'z, A:Tr B1 B2, ..., Z: Tr B1 B2> Tr for T<A, ..., Z> { ... }
  357       * ```
  358       *
  359       * where B1, B2, ... are the bounds given by `bounds_paths`.'
  360       *
  361       */
  362      fn create_derived_impl(&self,
  363                             cx&mut ExtCtxt,
  364                             type_identIdent,
  365                             generics&Generics,
  366                             methodsVec<@ast::Method> ) -> @ast::Item {
  367          let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
  368  
  369          let Generics { mut lifetimes, ty_params } =
  370              self.generics.to_generics(cx, self.span, type_ident, generics);
  371          let mut ty_params = ty_params.into_vec();
  372  
  373          // Copy the lifetimes
  374          lifetimes.extend(generics.lifetimes.iter().map(|l| *l));
  375  
  376          // Create the type parameters.
  377          ty_params.extend(generics.ty_params.iter().map(|ty_param| {
  378              // I don't think this can be moved out of the loop, since
  379              // a TyParamBound requires an ast id
  380              let mut boundsVec<_> =
  381                  // extra restrictions on the generics parameters to the type being derived upon
  382                  self.additional_bounds.iter().map(|p| {
  383                      cx.typarambound(p.to_path(cx, self.span,
  384                                                    type_ident, generics))
  385                  }).collect();
  386              // require the current trait
  387              bounds.push(cx.typarambound(trait_path.clone()));
  388  
  389              cx.typaram(self.span,
  390                         ty_param.ident,
  391                         ty_param.sized,
  392                         OwnedSlice::from_vec(bounds),
  393                         None)
  394          }));
  395          let trait_generics = Generics {
  396              lifetimes: lifetimes,
  397              ty_params: OwnedSlice::from_vec(ty_params)
  398          };
  399  
  400          // Create the reference to the trait.
  401          let trait_ref = cx.trait_ref(trait_path);
  402  
  403          // Create the type parameters on the `self` path.
  404          let self_ty_params = generics.ty_params.map(|ty_param| {
  405              cx.ty_ident(self.span, ty_param.ident)
  406          });
  407  
  408          let self_lifetimes = generics.lifetimes.clone();
  409  
  410          // Create the type of `self`.
  411          let self_type = cx.ty_path(
  412              cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
  413                          self_ty_params.into_vec()), None);
  414  
  415          let attr = cx.attribute(
  416              self.span,
  417              cx.meta_word(self.span,
  418                           InternedString::new("automatically_derived")));
  419          let opt_trait_ref = Some(trait_ref);
  420          let ident = ast_util::impl_pretty_name(&opt_trait_ref, self_type);
  421          cx.item(
  422              self.span,
  423              ident,
  424              (vec!(attr)).append(self.attributes.as_slice()),
  425              ast::ItemImpl(trait_generics, opt_trait_ref,
  426                            self_type, methods))
  427      }
  428  
  429      fn expand_struct_def(&self,
  430                           cx&mut ExtCtxt,
  431                           struct_def&StructDef,
  432                           type_identIdent,
  433                           generics&Generics) -> @ast::Item {
  434          let methods = self.methods.iter().map(|method_def| {
  435              let (explicit_self, self_args, nonself_args, tys) =
  436                  method_def.split_self_nonself_args(
  437                      cx, self, type_ident, generics);
  438  
  439              let body = if method_def.is_static() {
  440                  method_def.expand_static_struct_method_body(
  441                      cx,
  442                      self,
  443                      struct_def,
  444                      type_ident,
  445                      self_args.as_slice(),
  446                      nonself_args.as_slice())
  447              } else {
  448                  method_def.expand_struct_method_body(cx,
  449                                                       self,
  450                                                       struct_def,
  451                                                       type_ident,
  452                                                       self_args.as_slice(),
  453                                                       nonself_args.as_slice())
  454              };
  455  
  456              method_def.create_method(cx, self,
  457                                       type_ident, generics,
  458                                       explicit_self, tys,
  459                                       body)
  460          }).collect();
  461  
  462          self.create_derived_impl(cx, type_ident, generics, methods)
  463      }
  464  
  465      fn expand_enum_def(&self,
  466                         cx&mut ExtCtxt,
  467                         enum_def&EnumDef,
  468                         type_identIdent,
  469                         generics&Generics) -> @ast::Item {
  470          let methods = self.methods.iter().map(|method_def| {
  471              let (explicit_self, self_args, nonself_args, tys) =
  472                  method_def.split_self_nonself_args(cx, self,
  473                                                     type_ident, generics);
  474  
  475              let body = if method_def.is_static() {
  476                  method_def.expand_static_enum_method_body(
  477                      cx,
  478                      self,
  479                      enum_def,
  480                      type_ident,
  481                      self_args.as_slice(),
  482                      nonself_args.as_slice())
  483              } else {
  484                  method_def.expand_enum_method_body(cx,
  485                                                     self,
  486                                                     enum_def,
  487                                                     type_ident,
  488                                                     self_args.as_slice(),
  489                                                     nonself_args.as_slice())
  490              };
  491  
  492              method_def.create_method(cx, self,
  493                                       type_ident, generics,
  494                                       explicit_self, tys,
  495                                       body)
  496          }).collect();
  497  
  498          self.create_derived_impl(cx, type_ident, generics, methods)
  499      }
  500  }
  501  
  502  impl<'a> MethodDef<'a> {
  503      fn call_substructure_method(&self,
  504                                  cx&mut ExtCtxt,
  505                                  trait_&TraitDef,
  506                                  type_identIdent,
  507                                  self_args&[@Expr],
  508                                  nonself_args&[@Expr],
  509                                  fields&SubstructureFields)
  510          -> @Expr {
  511          let substructure = Substructure {
  512              type_ident: type_ident,
  513              method_ident: cx.ident_of(self.name),
  514              self_args: self_args,
  515              nonself_args: nonself_args,
  516              fields: fields
  517          };
  518          let mut f = self.combine_substructure.borrow_mut();
  519          let f&mut CombineSubstructureFunc = &mut *f;
  520          (*f)(cx, trait_.span, &substructure)
  521      }
  522  
  523      fn get_ret_ty(&self,
  524                    cx&mut ExtCtxt,
  525                    trait_&TraitDef,
  526                    generics&Generics,
  527                    type_identIdent)
  528                    -> P<ast::Ty> {
  529          self.ret_ty.to_ty(cx, trait_.span, type_ident, generics)
  530      }
  531  
  532      fn is_static(&self) -> bool {
  533          self.explicit_self.is_none()
  534      }
  535  
  536      fn split_self_nonself_args(&self,
  537                                 cx&mut ExtCtxt,
  538                                 trait_&TraitDef,
  539                                 type_identIdent,
  540                                 generics&Generics)
  541          -> (ast::ExplicitSelf, Vec<@Expr> , Vec<@Expr> , Vec<(Ident, P<ast::Ty>)> ) {
  542  
  543          let mut self_args = Vec::new();
  544          let mut nonself_args = Vec::new();
  545          let mut arg_tys = Vec::new();
  546          let mut nonstatic = false;
  547  
  548          let ast_explicit_self = match self.explicit_self {
  549              Some(ref self_ptr) => {
  550                  let (self_expr, explicit_self) =
  551                      ty::get_explicit_self(cx, trait_.span, self_ptr);
  552  
  553                  self_args.push(self_expr);
  554                  nonstatic = true;
  555  
  556                  explicit_self
  557              }
  558              None => codemap::respan(trait_.span, ast::SelfStatic),
  559          };
  560  
  561          for (i, ty) in self.args.iter().enumerate() {
  562              let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
  563              let ident = cx.ident_of(format!("__arg_{}", i));
  564              arg_tys.push((ident, ast_ty));
  565  
  566              let arg_expr = cx.expr_ident(trait_.span, ident);
  567  
  568              match *ty {
  569                  // for static methods, just treat any Self
  570                  // arguments as a normal arg
  571                  Self if nonstatic  => {
  572                      self_args.push(arg_expr);
  573                  }
  574                  Ptr(box Self, _) if nonstatic => {
  575                      self_args.push(cx.expr_deref(trait_.span, arg_expr))
  576                  }
  577                  _ => {
  578                      nonself_args.push(arg_expr);
  579                  }
  580              }
  581          }
  582  
  583          (ast_explicit_self, self_args, nonself_args, arg_tys)
  584      }
  585  
  586      fn create_method(&self,
  587                       cx&mut ExtCtxt,
  588                       trait_&TraitDef,
  589                       type_identIdent,
  590                       generics&Generics,
  591                       explicit_selfast::ExplicitSelf,
  592                       arg_typesVec<(Ident, P<ast::Ty>)> ,
  593                       body@Expr) -> @ast::Method {
  594          // create the generics that aren't for Self
  595          let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
  596  
  597          let self_arg = match explicit_self.node {
  598              ast::SelfStatic => None,
  599              _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable))
  600          };
  601          let args = {
  602              let args = arg_types.move_iter().map(|(name, ty)| {
  603                      cx.arg(trait_.span, name, ty)
  604                  });
  605              self_arg.move_iter().chain(args).collect()
  606          };
  607  
  608          let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
  609  
  610          let method_ident = cx.ident_of(self.name);
  611          let fn_decl = cx.fn_decl(args, ret_type);
  612          let body_block = cx.block_expr(body);
  613  
  614          // Create the method.
  615          @ast::Method {
  616              ident: method_ident,
  617              attrs: self.attributes.clone(),
  618              generics: fn_generics,
  619              explicit_self: explicit_self,
  620              fn_style: ast::NormalFn,
  621              decl: fn_decl,
  622              body: body_block,
  623              id: ast::DUMMY_NODE_ID,
  624              span: trait_.span,
  625              vis: ast::Inherited,
  626          }
  627      }
  628  
  629      /**
  630     ~~~
  631      #[deriving(Eq)]
  632      struct A { x: int, y: int }
  633  
  634      // equivalent to:
  635      impl Eq for A {
  636          fn eq(&self, __arg_1: &A) -> bool {
  637              match *self {
  638                  A {x: ref __self_0_0, y: ref __self_0_1} => {
  639                      match *__arg_1 {
  640                          A {x: ref __self_1_0, y: ref __self_1_1} => {
  641                              __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1)
  642                          }
  643                      }
  644                  }
  645              }
  646          }
  647      }
  648     ~~~
  649      */
  650      fn expand_struct_method_body(&self,
  651                                   cx&mut ExtCtxt,
  652                                   trait_&TraitDef,
  653                                   struct_def&StructDef,
  654                                   type_identIdent,
  655                                   self_args&[@Expr],
  656                                   nonself_args&[@Expr])
  657          -> @Expr {
  658  
  659          let mut raw_fields = Vec::new(); // ~[[fields of self],
  660                                   // [fields of next Self arg], [etc]]
  661          let mut patterns = Vec::new();
  662          for i in range(0u, self_args.len()) {
  663              let (pat, ident_expr) = trait_.create_struct_pattern(cx, type_ident, struct_def,
  664                                                                   format!("__self_{}", i),
  665                                                                   ast::MutImmutable);
  666              patterns.push(pat);
  667              raw_fields.push(ident_expr);
  668          }
  669  
  670          // transpose raw_fields
  671          let fields = if raw_fields.len() > 0 {
  672              raw_fields.get(0)
  673                        .iter()
  674                        .enumerate()
  675                        .map(|(i, &(span, opt_id, field))| {
  676                  let other_fields = raw_fields.tail().iter().map(|l| {
  677                      match l.get(i) {
  678                          &(_, _, ex) => ex
  679                      }
  680                  }).collect();
  681                  FieldInfo {
  682                      span: span,
  683                      name: opt_id,
  684                      self_: field,
  685                      other: other_fields
  686                  }
  687              }).collect()
  688          } else {
  689              cx.span_bug(trait_.span,
  690                          "no self arguments to non-static method in generic \
  691                           `deriving`")
  692          };
  693  
  694          // body of the inner most destructuring match
  695          let mut body = self.call_substructure_method(
  696              cx,
  697              trait_,
  698              type_ident,
  699              self_args,
  700              nonself_args,
  701              &Struct(fields));
  702  
  703          // make a series of nested matches, to destructure the
  704          // structs. This is actually right-to-left, but it shoudn't
  705          // matter.
  706          for (&arg_expr, &pat) in self_args.iter().zip(patterns.iter()) {
  707              body = cx.expr_match(trait_.span, arg_expr,
  708                                       vec!( cx.arm(trait_.span, vec!(pat), body) ))
  709          }
  710          body
  711      }
  712  
  713      fn expand_static_struct_method_body(&self,
  714                                          cx&mut ExtCtxt,
  715                                          trait_&TraitDef,
  716                                          struct_def&StructDef,
  717                                          type_identIdent,
  718                                          self_args&[@Expr],
  719                                          nonself_args&[@Expr])
  720          -> @Expr {
  721          let summary = trait_.summarise_struct(cx, struct_def);
  722  
  723          self.call_substructure_method(cx,
  724                                        trait_,
  725                                        type_ident,
  726                                        self_args, nonself_args,
  727                                        &StaticStruct(struct_def, summary))
  728      }
  729  
  730      /**
  731     ~~~
  732      #[deriving(Eq)]
  733      enum A {
  734          A1
  735          A2(int)
  736      }
  737  
  738      // is equivalent to (with const_nonmatching == false)
  739  
  740      impl Eq for A {
  741          fn eq(&self, __arg_1: &A) {
  742              match *self {
  743                  A1 => match *__arg_1 {
  744                      A1 => true
  745                      A2(ref __arg_1_1) => false
  746                  },
  747                  A2(self_1) => match *__arg_1 {
  748                      A1 => false,
  749                      A2(ref __arg_1_1) => self_1.eq(__arg_1_1)
  750                  }
  751              }
  752          }
  753      }
  754     ~~~
  755      */
  756      fn expand_enum_method_body(&self,
  757                                 cx&mut ExtCtxt,
  758                                 trait_&TraitDef,
  759                                 enum_def&EnumDef,
  760                                 type_identIdent,
  761                                 self_args&[@Expr],
  762                                 nonself_args&[@Expr])
  763                                 -> @Expr {
  764          let mut matches = Vec::new();
  765          self.build_enum_match(cx, trait_, enum_def, type_ident,
  766                                self_args, nonself_args,
  767                                None, &mut matches, 0)
  768      }
  769  
  770  
  771      /**
  772      Creates the nested matches for an enum definition recursively, i.e.
  773  
  774     ~~~notrust
  775      match self {
  776         Variant1 => match other { Variant1 => matching, Variant2 => nonmatching, ... },
  777         Variant2 => match other { Variant1 => nonmatching, Variant2 => matching, ... },
  778         ...
  779      }
  780     ~~~
  781  
  782      It acts in the most naive way, so every branch (and subbranch,
  783      subsubbranch, etc) exists, not just the ones where all the variants in
  784      the tree are the same. Hopefully the optimisers get rid of any
  785      repetition, otherwise derived methods with many Self arguments will be
  786      exponentially large.
  787  
  788      `matching` is Some(n) if all branches in the tree above the
  789      current position are variant `n`, `None` otherwise (including on
  790      the first call).
  791      */
  792      fn build_enum_match(&self,
  793                          cx&mut ExtCtxt,
  794                          trait_&TraitDef,
  795                          enum_def&EnumDef,
  796                          type_identIdent,
  797                          self_args&[@Expr],
  798                          nonself_args&[@Expr],
  799                          matchingOption<uint>,
  800                          matches_so_far&mut Vec<(uint, P<ast::Variant>,
  801                                                Vec<(Span, Option<Ident>, @Expr))> ,
  802                          match_countuint) -> @Expr {
  803          if match_count == self_args.len() {
  804              // we've matched against all arguments, so make the final
  805              // expression at the bottom of the match tree
  806              if matches_so_far.len() == 0 {
  807                  cx.span_bug(trait_.span,
  808                                  "no self match on an enum in \
  809                                  generic `deriving`");
  810              }
  811  
  812              // `ref` inside let matches is buggy. Causes havoc wih rusc.
  813              // let (variant_index, ref self_vec) = matches_so_far[0];
  814              let (variant, self_vec) = match matches_so_far.get(0) {
  815                  &(_, v, ref s) => (v, s)
  816              };
  817  
  818              // we currently have a vec of vecs, where each
  819              // subvec is the fields of one of the arguments,
  820              // but if the variants all match, we want this as
  821              // vec of tuples, where each tuple represents a
  822              // field.
  823  
  824              // most arms don't have matching variants, so do a
  825              // quick check to see if they match (even though
  826              // this means iterating twice) instead of being
  827              // optimistic and doing a pile of allocations etc.
  828              let substructure = match matching {
  829                  Some(variant_index) => {
  830                      let mut enum_matching_fields = Vec::from_elem(self_vec.len(), Vec::new());
  831  
  832                      for triple in matches_so_far.tail().iter() {
  833                          match triple {
  834                              &(_, _, ref other_fields) => {
  835                                  for (i, &(_, _, e)) in other_fields.iter().enumerate() {
  836                                      enum_matching_fields.get_mut(i).push(e);
  837                                  }
  838                              }
  839                          }
  840                      }
  841                      let field_tuples =
  842                          self_vec.iter()
  843                                  .zip(enum_matching_fields.iter())
  844                                  .map(|(&(span, id, self_f), other)| {
  845                          FieldInfo {
  846                              span: span,
  847                              name: id,
  848                              self_: self_f,
  849                              other: (*other).clone()
  850                          }
  851                      }).collect();
  852                      EnumMatching(variant_index, variant, field_tuples)
  853                  }
  854                  None => {
  855                      EnumNonMatching(matches_so_far.as_slice())
  856                  }
  857              };
  858              self.call_substructure_method(cx, trait_, type_ident,
  859                                            self_args, nonself_args,
  860                                            &substructure)
  861  
  862          } else {  // there are still matches to create
  863              let current_match_str = if match_count == 0 {
  864                  "__self".to_owned()
  865              } else {
  866                  format!("__arg_{}", match_count)
  867              };
  868  
  869              let mut arms = Vec::new();
  870  
  871              // the code for nonmatching variants only matters when
  872              // we've seen at least one other variant already
  873              if self.const_nonmatching && match_count > 0 {
  874                  // make a matching-variant match, and a _ match.
  875                  let index = match matching {
  876                      Some(i) => i,
  877                      None => cx.span_bug(trait_.span,
  878                                          "non-matching variants when required to \
  879                                          be matching in generic `deriving`")
  880                  };
  881  
  882                  // matching-variant match
  883                  let variant = *enum_def.variants.get(index);
  884                  let (pattern, idents) = trait_.create_enum_variant_pattern(cx,
  885                                                                             variant,
  886                                                                             current_match_str,
  887                                                                             ast::MutImmutable);
  888  
  889                  matches_so_far.push((index, variant, idents));
  890                  let arm_expr = self.build_enum_match(cx,
  891                                                       trait_,
  892                                                       enum_def,
  893                                                       type_ident,
  894                                                       self_args, nonself_args,
  895                                                       matching,
  896                                                       matches_so_far,
  897                                                       match_count + 1);
  898                  matches_so_far.pop().unwrap();
  899                  arms.push(cx.arm(trait_.span, vec!( pattern ), arm_expr));
  900  
  901                  if enum_def.variants.len() > 1 {
  902                      let e = &EnumNonMatching(&[]);
  903                      let wild_expr = self.call_substructure_method(cx, trait_, type_ident,
  904                                                                    self_args, nonself_args,
  905                                                                    e);
  906                      let wild_arm = cx.arm(
  907                          trait_.span,
  908                          vec!( cx.pat_wild(trait_.span) ),
  909                          wild_expr);
  910                      arms.push(wild_arm);
  911                  }
  912              } else {
  913                  // create an arm matching on each variant
  914                  for (index, &variant) in enum_def.variants.iter().enumerate() {
  915                      let (pattern, idents) = trait_.create_enum_variant_pattern(cx,
  916                                                                                 variant,
  917                                                                                 current_match_str,
  918                                                                                 ast::MutImmutable);
  919  
  920                      matches_so_far.push((index, variant, idents));
  921                      let new_matching =
  922                          match matching {
  923                              _ if match_count == 0 => Some(index),
  924                              Some(i) if index == i => Some(i),
  925                              _ => None
  926                          };
  927                      let arm_expr = self.build_enum_match(cx,
  928                                                           trait_,
  929                                                           enum_def,
  930                                                           type_ident,
  931                                                           self_args, nonself_args,
  932                                                           new_matching,
  933                                                           matches_so_far,
  934                                                           match_count + 1);
  935                      matches_so_far.pop().unwrap();
  936  
  937                      let arm = cx.arm(trait_.span, vec!( pattern ), arm_expr);
  938                      arms.push(arm);
  939                  }
  940              }
  941  
  942              // match foo { arm, arm, arm, ... }
  943              cx.expr_match(trait_.span, self_args[match_count], arms)
  944          }
  945      }
  946  
  947      fn expand_static_enum_method_body(&self,
  948                                        cx&mut ExtCtxt,
  949                                        trait_&TraitDef,
  950                                        enum_def&EnumDef,
  951                                        type_identIdent,
  952                                        self_args&[@Expr],
  953                                        nonself_args&[@Expr])
  954          -> @Expr {
  955          let summary = enum_def.variants.iter().map(|v| {
  956              let ident = v.node.name;
  957              let summary = match v.node.kind {
  958                  ast::TupleVariantKind(ref args) => {
  959                      Unnamed(args.iter().map(|va| trait_.set_expn_info(cx, va.ty.span)).collect())
  960                  }
  961                  ast::StructVariantKind(struct_def) => {
  962                      trait_.summarise_struct(cx, struct_def)
  963                  }
  964              };
  965              (ident, v.span, summary)
  966          }).collect();
  967          self.call_substructure_method(cx, trait_, type_ident,
  968                                        self_args, nonself_args,
  969                                        &StaticEnum(enum_def, summary))
  970      }
  971  }
  972  
  973  #[deriving(Eq)] // dogfooding!
  974  enum StructType {
  975      Unknown, Record, Tuple
  976  }
  977  
  978  // general helper methods.
  979  impl<'a> TraitDef<'a> {
  980      fn set_expn_info(&self,
  981                       cx&mut ExtCtxt,
  982                       mut to_setSpan) -> Span {
  983          let trait_name = match self.path.path.last() {
  984              None => cx.span_bug(self.span, "trait with empty path in generic `deriving`"),
  985              Some(name) => *name
  986          };
  987          to_set.expn_info = Some(@codemap::ExpnInfo {
  988              call_site: to_set,
  989              callee: codemap::NameAndSpan {
  990                  name: format!("deriving({})", trait_name).to_strbuf(),
  991                  format: codemap::MacroAttribute,
  992                  span: Some(self.span)
  993              }
  994          });
  995          to_set
  996      }
  997  
  998      fn summarise_struct(&self,
  999                          cx&mut ExtCtxt,
 1000                          struct_def&StructDef) -> StaticFields {
 1001          let mut named_idents = Vec::new();
 1002          let mut just_spans = Vec::new();
 1003          for field in struct_def.fields.iter(){
 1004              let sp = self.set_expn_info(cx, field.span);
 1005              match field.node.kind {
 1006                  ast::NamedField(ident, _) => named_idents.push((ident, sp)),
 1007                  ast::UnnamedField(..) => just_spans.push(sp),
 1008              }
 1009          }
 1010  
 1011          match (just_spans.is_empty(), named_idents.is_empty()) {
 1012              (false, false) => cx.span_bug(self.span,
 1013                                            "a struct with named and unnamed \
 1014                                            fields in generic `deriving`"),
 1015              // named fields
 1016              (_, false) => Named(named_idents),
 1017              // tuple structs (includes empty structs)
 1018              (_, _)     => Unnamed(just_spans)
 1019          }
 1020      }
 1021  
 1022      fn create_subpatterns(&self,
 1023                            cx&mut ExtCtxt,
 1024                            field_pathsVec<ast::Path> ,
 1025                            mutblast::Mutability)
 1026                            -> Vec<@ast::Pat> {
 1027          field_paths.iter().map(|path| {
 1028              cx.pat(path.span,
 1029                          ast::PatIdent(ast::BindByRef(mutbl), (*path).clone(), None))
 1030              }).collect()
 1031      }
 1032  
 1033      fn create_struct_pattern(&self,
 1034                               cx&mut ExtCtxt,
 1035                               struct_identIdent,
 1036                               struct_def&StructDef,
 1037                               prefix&str,
 1038                               mutblast::Mutability)
 1039                               -> (@ast::Pat, Vec<(Span, Option<Ident>, @Expr)> ) {
 1040          if struct_def.fields.is_empty() {
 1041              return (
 1042                  cx.pat_ident_binding_mode(
 1043                      self.span, struct_ident, ast::BindByValue(ast::MutImmutable)),
 1044                  Vec::new());
 1045          }
 1046  
 1047          let matching_path = cx.path(self.span, vec!( struct_ident ));
 1048  
 1049          let mut paths = Vec::new();
 1050          let mut ident_expr = Vec::new();
 1051          let mut struct_type = Unknown;
 1052  
 1053          for (i, struct_field) in struct_def.fields.iter().enumerate() {
 1054              let sp = self.set_expn_info(cx, struct_field.span);
 1055              let opt_id = match struct_field.node.kind {
 1056                  ast::NamedField(ident, _) if (struct_type == Unknown ||
 1057                                                struct_type == Record) => {
 1058                      struct_type = Record;
 1059                      Some(ident)
 1060                  }
 1061                  ast::UnnamedField(..) if (struct_type == Unknown ||
 1062                                            struct_type == Tuple) => {
 1063                      struct_type = Tuple;
 1064                      None
 1065                  }
 1066                  _ => {
 1067                      cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`");
 1068                  }
 1069              };
 1070              let path = cx.path_ident(sp, cx.ident_of(format!("{}_{}", prefix, i)));
 1071              paths.push(path.clone());
 1072              let val = cx.expr(
 1073                  sp, ast::ExprParen(
 1074                      cx.expr_deref(sp, cx.expr_path(path))));
 1075              ident_expr.push((sp, opt_id, val));
 1076          }
 1077  
 1078          let subpats = self.create_subpatterns(cx, paths, mutbl);
 1079  
 1080          // struct_type is definitely not Unknown, since struct_def.fields
 1081          // must be nonempty to reach here
 1082          let pattern = if struct_type == Record {
 1083              let field_pats = subpats.iter().zip(ident_expr.iter()).map(|(&pat, &(_, id, _))| {
 1084                  // id is guaranteed to be Some
 1085                  ast::FieldPat { ident: id.unwrap(), pat: pat }
 1086              }).collect();
 1087              cx.pat_struct(self.span, matching_path, field_pats)
 1088          } else {
 1089              cx.pat_enum(self.span, matching_path, subpats)
 1090          };
 1091  
 1092          (pattern, ident_expr)
 1093      }
 1094  
 1095      fn create_enum_variant_pattern(&self,
 1096                                     cx&mut ExtCtxt,
 1097                                     variant&ast::Variant,
 1098                                     prefix&str,
 1099                                     mutblast::Mutability)
 1100          -> (@ast::Pat, Vec<(Span, Option<Ident>, @Expr)> ) {
 1101          let variant_ident = variant.node.name;
 1102          match variant.node.kind {
 1103              ast::TupleVariantKind(ref variant_args) => {
 1104                  if variant_args.is_empty() {
 1105                      return (cx.pat_ident_binding_mode(variant.span, variant_ident,
 1106                                                            ast::BindByValue(ast::MutImmutable)),
 1107                              Vec::new());
 1108                  }
 1109  
 1110                  let matching_path = cx.path_ident(variant.span, variant_ident);
 1111  
 1112                  let mut paths = Vec::new();
 1113                  let mut ident_expr = Vec::new();
 1114                  for (i, va) in variant_args.iter().enumerate() {
 1115                      let sp = self.set_expn_info(cx, va.ty.span);
 1116                      let path = cx.path_ident(sp, cx.ident_of(format!("{}_{}", prefix, i)));
 1117  
 1118                      paths.push(path.clone());
 1119                      let val = cx.expr(
 1120                          sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(path))));
 1121                      ident_expr.push((sp, None, val));
 1122                  }
 1123  
 1124                  let subpats = self.create_subpatterns(cx, paths, mutbl);
 1125  
 1126                  (cx.pat_enum(variant.span, matching_path, subpats),
 1127                   ident_expr)
 1128              }
 1129              ast::StructVariantKind(struct_def) => {
 1130                  self.create_struct_pattern(cx, variant_ident, struct_def,
 1131                                             prefix, mutbl)
 1132              }
 1133          }
 1134      }
 1135  }
 1136  
 1137  /* helpful premade recipes */
 1138  
 1139  /**
 1140  Fold the fields. `use_foldl` controls whether this is done
 1141  left-to-right (`true`) or right-to-left (`false`).
 1142  */
 1143  pub fn cs_fold(use_foldl: bool,
 1144                 f: |&mut ExtCtxt, Span, @Expr, @Expr, &[@Expr]-> @Expr,
 1145                 base: @Expr,
 1146                 enum_nonmatch_fEnumNonMatchFunc,
 1147                 cx: &mut ExtCtxt,
 1148                 trait_spanSpan,
 1149                 substructure: &Substructure)
 1150                 -> @Expr {
 1151      match *substructure.fields {
 1152          EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
 1153              if use_foldl {
 1154                  all_fields.iter().fold(base, |old, field| {
 1155                      f(cx,
 1156                        field.span,
 1157                        old,
 1158                        field.self_,
 1159                        field.other.as_slice())
 1160                  })
 1161              } else {
 1162                  all_fields.iter().rev().fold(base, |old, field| {
 1163                      f(cx,
 1164                        field.span,
 1165                        old,
 1166                        field.self_,
 1167                        field.other.as_slice())
 1168                  })
 1169              }
 1170          },
 1171          EnumNonMatching(ref all_enums) => enum_nonmatch_f(cx, trait_span,
 1172                                                            *all_enums,
 1173                                                            substructure.nonself_args),
 1174          StaticEnum(..) | StaticStruct(..) => {
 1175              cx.span_bug(trait_span, "static function in `deriving`")
 1176          }
 1177      }
 1178  }
 1179  
 1180  
 1181  /**
 1182  Call the method that is being derived on all the fields, and then
 1183  process the collected results. i.e.
 1184  
 1185  ~~~
 1186  f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1),
 1187                self_2.method(__arg_1_2, __arg_2_2)])
 1188  ~~~
 1189  */
 1190  #[inline]
 1191  pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<@Expr> | -> @Expr,
 1192                        enum_nonmatch_fEnumNonMatchFunc,
 1193                        cx: &mut ExtCtxt,
 1194                        trait_spanSpan,
 1195                        substructure: &Substructure)
 1196                        -> @Expr {
 1197      match *substructure.fields {
 1198          EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
 1199              // call self_n.method(other_1_n, other_2_n, ...)
 1200              let called = all_fields.iter().map(|field| {
 1201                  cx.expr_method_call(field.span,
 1202                                      field.self_,
 1203                                      substructure.method_ident,
 1204                                      field.other.iter()
 1205                                                 .map(|e| cx.expr_addr_of(field.span, *e))
 1206                                                 .collect())
 1207              }).collect();
 1208  
 1209              f(cx, trait_span, called)
 1210          },
 1211          EnumNonMatching(ref all_enums) => enum_nonmatch_f(cx, trait_span,
 1212                                                            *all_enums,
 1213                                                            substructure.nonself_args),
 1214          StaticEnum(..) | StaticStruct(..) => {
 1215              cx.span_bug(trait_span, "static function in `deriving`")
 1216          }
 1217      }
 1218  }
 1219  
 1220  /**
 1221  Fold together the results of calling the derived method on all the
 1222  fields. `use_foldl` controls whether this is done left-to-right
 1223  (`true`) or right-to-left (`false`).
 1224  */
 1225  #[inline]
 1226  pub fn cs_same_method_fold(use_foldl: bool,
 1227                             f: |&mut ExtCtxt, Span, @Expr, @Expr-> @Expr,
 1228                             base: @Expr,
 1229                             enum_nonmatch_fEnumNonMatchFunc,
 1230                             cx: &mut ExtCtxt,
 1231                             trait_spanSpan,
 1232                             substructure: &Substructure)
 1233                             -> @Expr {
 1234      cs_same_method(
 1235          |cx, span, vals| {
 1236              if use_foldl {
 1237                  vals.iter().fold(base, |old, &new| {
 1238                      f(cx, span, old, new)
 1239                  })
 1240              } else {
 1241                  vals.iter().rev().fold(base, |old, &new| {
 1242                      f(cx, span, old, new)
 1243                  })
 1244              }
 1245          },
 1246          enum_nonmatch_f,
 1247          cx, trait_span, substructure)
 1248  }
 1249  
 1250  /**
 1251  Use a given binop to combine the result of calling the derived method
 1252  on all the fields.
 1253  */
 1254  #[inline]
 1255  pub fn cs_binop(binopast::BinOp, base: @Expr,
 1256                  enum_nonmatch_fEnumNonMatchFunc,
 1257                  cx: &mut ExtCtxt, trait_spanSpan,
 1258                  substructure: &Substructure) -> @Expr {
 1259      cs_same_method_fold(
 1260          true, // foldl is good enough
 1261          |cx, span, old, new| {
 1262              cx.expr_binary(span,
 1263                             binop,
 1264                             old, new)
 1265  
 1266          },
 1267          base,
 1268          enum_nonmatch_f,
 1269          cx, trait_span, substructure)
 1270  }
 1271  
 1272  /// cs_binop with binop == or
 1273  #[inline]
 1274  pub fn cs_or(enum_nonmatch_fEnumNonMatchFunc,
 1275               cx: &mut ExtCtxt, spanSpan,
 1276               substructure: &Substructure) -> @Expr {
 1277      cs_binop(ast::BiOr, cx.expr_bool(span, false),
 1278               enum_nonmatch_f,
 1279               cx, span, substructure)
 1280  }
 1281  
 1282  /// cs_binop with binop == and
 1283  #[inline]
 1284  pub fn cs_and(enum_nonmatch_fEnumNonMatchFunc,
 1285                cx: &mut ExtCtxt, spanSpan,
 1286                substructure: &Substructure) -> @Expr {
 1287      cs_binop(ast::BiAnd, cx.expr_bool(span, true),
 1288               enum_nonmatch_f,
 1289               cx, span, substructure)
 1290  }


libsyntax/ext/deriving/generic.rs:313:3-313:3 -NK_AS_STR_TODO- definition:
*/
pub type EnumNonMatchFunc<'a> =
    |&mut ExtCtxt,
references:- 6
1145:                base: @Expr,
1146:                enum_nonmatch_f: EnumNonMatchFunc,
1147:                cx: &mut ExtCtxt,
--
1191: pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<@Expr> | -> @Expr,
1192:                       enum_nonmatch_f: EnumNonMatchFunc,
1193:                       cx: &mut ExtCtxt,
--
1284: pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc,
1285:               cx: &mut ExtCtxt, span: Span,


libsyntax/ext/deriving/generic.rs:305:3-305:3 -NK_AS_STR_TODO- definition:
*/
pub type CombineSubstructureFunc<'a> =
    |&mut ExtCtxt, Span, &Substructure|: 'a -> @Expr;
references:- 4
518:         let mut f = self.combine_substructure.borrow_mut();
519:         let f: &mut CombineSubstructureFunc = &mut *f;
520:         (*f)(cx, trait_.span, &substructure)


libsyntax/ext/deriving/generic.rs:1190:10-1190:10 -fn- definition:
pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<@Expr> | -> @Expr,
                      enum_nonmatch_f: EnumNonMatchFunc,
                      cx: &mut ExtCtxt,
references:- 2
libsyntax/ext/deriving/cmp/totaleq.rs:
23:     fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
24:         cs_same_method(|cx, span, exprs| {
25:             // create `a.<method>(); b.<method>(); c.<method>(); ...`
libsyntax/ext/deriving/generic.rs:
1233:                            -> @Expr {
1234:     cs_same_method(
1235:         |cx, span, vals| {


libsyntax/ext/deriving/generic.rs:194:1-194:1 -struct- definition:
pub struct TraitDef<'a> {
    /// The span for the current #[deriving(Foo)] header.
    pub span: Span,
references:- 25
libsyntax/ext/deriving/bounds.rs:
36:     let trait_def = TraitDef {
37:         span: span,
libsyntax/ext/deriving/clone.rs:
24:     let attrs = vec!(cx.attribute(span, inline));
25:     let trait_def = TraitDef {
26:         span: span,
libsyntax/ext/deriving/encodable.rs:
97:                                  push: |@Item|) {
98:     let trait_def = TraitDef {
99:         span: span,
libsyntax/ext/deriving/decodable.rs:
29:                                  push: |@Item|) {
30:     let trait_def = TraitDef {
31:         span: span,
libsyntax/ext/deriving/hash.rs:
39:     let attrs = vec!(cx.attribute(span, inline));
40:     let hash_trait_def = TraitDef {
41:         span: span,
libsyntax/ext/deriving/rand.rs:
22:                             push: |@Item|) {
23:     let trait_def = TraitDef {
24:         span: span,
libsyntax/ext/deriving/show.rs:
32:     let trait_def = TraitDef {
33:         span: span,
libsyntax/ext/deriving/zero.rs:
24:     let attrs = vec!(cx.attribute(span, inline));
25:     let trait_def = TraitDef {
26:         span: span,
libsyntax/ext/deriving/default.rs:
24:     let attrs = vec!(cx.attribute(span, inline));
25:     let trait_def = TraitDef {
26:         span: span,
libsyntax/ext/deriving/primitive.rs:
25:     let attrs = vec!(cx.attribute(span, inline));
26:     let trait_def = TraitDef {
27:         span: span,
libsyntax/ext/deriving/generic.rs:
978: // general helper methods.
979: impl<'a> TraitDef<'a> {
980:     fn set_expn_info(&self,
libsyntax/ext/deriving/cmp/totaleq.rs:
41:                      cx.attribute(span, doc));
42:     let trait_def = TraitDef {
43:         span: span,
libsyntax/ext/deriving/cmp/ord.rs:
43:     let trait_def = TraitDef {
44:         span: span,
libsyntax/ext/deriving/cmp/totalord.rs:
27:     let attrs = vec!(cx.attribute(span, inline));
28:     let trait_def = TraitDef {
29:         span: span,
libsyntax/ext/deriving/cmp/eq.rs:
53:     let trait_def = TraitDef {
54:         span: span,


libsyntax/ext/deriving/generic.rs:320:1-320:1 -fn- definition:
pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
    -> RefCell<CombineSubstructureFunc<'a>> {
    RefCell::new(f)
references:- 19
libsyntax/ext/deriving/clone.rs:
39:                 const_nonmatching: false,
40:                 combine_substructure: combine_substructure(|c, s, sub| {
41:                     cs_clone("Clone", c, s, sub)
libsyntax/ext/deriving/encodable.rs:
125:                 const_nonmatching: true,
126:                 combine_substructure: combine_substructure(|a, b, c| {
127:                     encodable_substructure(a, b, c)
libsyntax/ext/deriving/decodable.rs:
55:                 const_nonmatching: true,
56:                 combine_substructure: combine_substructure(|a, b, c| {
57:                     decodable_substructure(a, b, c)
libsyntax/ext/deriving/hash.rs:
54:                 const_nonmatching: false,
55:                 combine_substructure: combine_substructure(|a, b, c| {
56:                     hash_substructure(a, b, c)
libsyntax/ext/deriving/rand.rs:
45:                 const_nonmatching: false,
46:                 combine_substructure: combine_substructure(|a, b, c| {
47:                     rand_substructure(a, b, c)
libsyntax/ext/deriving/show.rs:
46:                 const_nonmatching: false,
47:                 combine_substructure: combine_substructure(|a, b, c| {
48:                     show_substructure(a, b, c)
libsyntax/ext/deriving/zero.rs:
39:                 const_nonmatching: false,
40:                 combine_substructure: combine_substructure(|a, b, c| {
41:                     zero_substructure(a, b, c)
--
51:                 const_nonmatching: false,
52:                 combine_substructure: combine_substructure(|cx, span, substr| {
53:                     cs_and(|cx, span, _, _| cx.span_bug(span,
libsyntax/ext/deriving/default.rs:
39:                 const_nonmatching: false,
40:                 combine_substructure: combine_substructure(|a, b, c| {
41:                     default_substructure(a, b, c)
libsyntax/ext/deriving/primitive.rs:
45:                 const_nonmatching: false,
46:                 combine_substructure: combine_substructure(|c, s, sub| {
47:                     cs_from("i64", c, s, sub)
--
62:                 const_nonmatching: false,
63:                 combine_substructure: combine_substructure(|c, s, sub| {
64:                     cs_from("u64", c, s, sub)
libsyntax/ext/deriving/cmp/eq.rs:
45:                 const_nonmatching: true,
46:                 combine_substructure: combine_substructure(|a, b, c| {
47:                     $f(a, b, c)
libsyntax/ext/deriving/cmp/totaleq.rs:
56:                 const_nonmatching: true,
57:                 combine_substructure: combine_substructure(|a, b, c| {
58:                     cs_total_eq_assert(a, b, c)
libsyntax/ext/deriving/cmp/ord.rs:
35:                 const_nonmatching: false,
36:                 combine_substructure: combine_substructure(|cx, span, substr| {
37:                     cs_op($op, $equal, cx, span, substr)
libsyntax/ext/deriving/cmp/totalord.rs:
42:                 const_nonmatching: false,
43:                 combine_substructure: combine_substructure(|a, b, c| {
44:                     cs_cmp(a, b, c)


libsyntax/ext/deriving/generic.rs:277:17-277:17 -enum- definition:
/// and examples
pub enum SubstructureFields<'a> {
    Struct(Vec<FieldInfo> ),
references:- 2
250:     pub nonself_args: &'a [@Expr],
251:     pub fields: &'a SubstructureFields<'a>
252: }
--
508:                                 nonself_args: &[@Expr],
509:                                 fields: &SubstructureFields)
510:         -> @Expr {


libsyntax/ext/deriving/generic.rs:214:1-214:1 -struct- definition:
pub struct MethodDef<'a> {
    /// name of the method
    pub name: &'a str,
references:- 21
libsyntax/ext/deriving/clone.rs:
31:         methods: vec!(
32:             MethodDef {
33:                 name: "clone",
libsyntax/ext/deriving/encodable.rs:
112:         methods: vec!(
113:             MethodDef {
114:                 name: "encode",
libsyntax/ext/deriving/decodable.rs:
44:         methods: vec!(
45:             MethodDef {
46:                 name: "decode",
libsyntax/ext/deriving/hash.rs:
46:         methods: vec!(
47:             MethodDef {
48:                 name: "hash",
libsyntax/ext/deriving/rand.rs:
29:         methods: vec!(
30:             MethodDef {
31:                 name: "rand",
libsyntax/ext/deriving/show.rs:
38:         methods: vec!(
39:             MethodDef {
40:                 name: "fmt",
libsyntax/ext/deriving/zero.rs:
43:             },
44:             MethodDef {
45:                 name: "is_zero",
libsyntax/ext/deriving/default.rs:
31:         methods: vec!(
32:             MethodDef {
33:                 name: "default",
libsyntax/ext/deriving/primitive.rs:
49:             },
50:             MethodDef {
51:                 name: "from_u64",
libsyntax/ext/deriving/cmp/eq.rs:
37:             let attrs = vec!(cx.attribute(span, inline));
38:             MethodDef {
39:                 name: $name,
libsyntax/ext/deriving/cmp/totaleq.rs:
48:         methods: vec!(
49:             MethodDef {
50:                 name: "assert_receiver_is_total_eq",
libsyntax/ext/deriving/generic.rs:
211:     pub methods: Vec<MethodDef<'a>>,
212: }
--
502: impl<'a> MethodDef<'a> {
503:     fn call_substructure_method(&self,
libsyntax/ext/deriving/cmp/ord.rs:
27:             let attrs = vec!(cx.attribute(span, inline));
28:             MethodDef {
29:                 name: $name,
libsyntax/ext/deriving/cmp/totalord.rs:
34:         methods: vec!(
35:             MethodDef {
36:                 name: "cmp",
libsyntax/ext/deriving/cmp/ord.rs:
27:             let attrs = vec!(cx.attribute(span, inline));
28:             MethodDef {
29:                 name: $name,


libsyntax/ext/deriving/generic.rs:973:31-973:31 -enum- definition:
enum StructType {
    Unknown, Record, Tuple
}
references:- 3
974: enum StructType {


libsyntax/ext/deriving/generic.rs:254:58-254:58 -struct- definition:
/// Summary of the relevant parts of a struct/enum field.
pub struct FieldInfo {
    pub span: Span,
references:- 8
680:                 }).collect();
681:                 FieldInfo {
682:                     span: span,
--
844:                                 .map(|(&(span, id, self_f), other)| {
845:                         FieldInfo {
846:                             span: span,
libsyntax/ext/deriving/clone.rs:
56:     let all_fields;
57:     let subcall = |field: &FieldInfo|
58:         cx.expr_method_call(field.span, field.self_, clone_ident, Vec::new());
libsyntax/ext/deriving/encodable.rs:
147:             let last = fields.len() - 1;
148:             for (i, &FieldInfo {
149:                     name,
--
197:             let last = fields.len() - 1;
198:             for (i, &FieldInfo { self_, span, .. }) in fields.iter().enumerate() {
199:                 let enc = cx.expr_method_call(span, self_, encode, vec!(blkencoder));
libsyntax/ext/deriving/hash.rs:
94:     for &FieldInfo { self_, span, .. } in fields.iter() {
95:         stmts.push(call_hash(span, self_));


libsyntax/ext/deriving/generic.rs:1254:10-1254:10 -fn- definition:
pub fn cs_binop(binop: ast::BinOp, base: @Expr,
                enum_nonmatch_f: EnumNonMatchFunc,
                cx: &mut ExtCtxt, trait_span: Span,
references:- 2
1276:              substructure: &Substructure) -> @Expr {
1277:     cs_binop(ast::BiOr, cx.expr_bool(span, false),
1278:              enum_nonmatch_f,
--
1286:               substructure: &Substructure) -> @Expr {
1287:     cs_binop(ast::BiAnd, cx.expr_bool(span, true),
1288:              enum_nonmatch_f,


libsyntax/ext/deriving/generic.rs:1283:10-1283:10 -fn- definition:
pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc,
              cx: &mut ExtCtxt, span: Span,
              substructure: &Substructure) -> @Expr {
references:- 2
libsyntax/ext/deriving/cmp/eq.rs:
25:     fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
26:         cs_and(|cx, span, _, _| cx.expr_bool(span, false),
27:                                  cx, span, substr)
libsyntax/ext/deriving/zero.rs:
52:                 combine_substructure: combine_substructure(|cx, span, substr| {
53:                     cs_and(|cx, span, _, _| cx.span_bug(span,
54:                                                         "Non-matching enum \


libsyntax/ext/deriving/generic.rs:1225:10-1225:10 -fn- definition:
pub fn cs_same_method_fold(use_foldl: bool,
                           f: |&mut ExtCtxt, Span, @Expr, @Expr| -> @Expr,
                           base: @Expr,
references:- 2
1258:                 substructure: &Substructure) -> @Expr {
1259:     cs_same_method_fold(
1260:         true, // foldl is good enough
libsyntax/ext/deriving/cmp/totalord.rs:
87:     */
88:     cs_same_method_fold(
89:         // foldr nests the if-elses correctly, leaving the first field


libsyntax/ext/deriving/generic.rs:268:31-268:31 -enum- definition:
/// Fields for a static method
pub enum StaticFields {
    /// Tuple structs/enum variants like this
references:- 5
999:                         cx: &mut ExtCtxt,
1000:                         struct_def: &StructDef) -> StaticFields {
1001:         let mut named_idents = Vec::new();
libsyntax/ext/deriving/decodable.rs:
159:                         outer_pat_ident: Ident,
160:                         fields: &StaticFields,
161:                         getarg: |&mut ExtCtxt, Span, InternedString, uint| -> @Expr)
libsyntax/ext/deriving/rand.rs:
133:                   ctor_ident: Ident,
134:                   summary: &StaticFields,
135:                   rand_call: |&mut ExtCtxt, Span| -> @Expr)
libsyntax/ext/deriving/generic.rs:
296:     /// A static method where Self is an enum.
297:     StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)> )
298: }


libsyntax/ext/deriving/generic.rs:241:69-241:69 -struct- definition:
/// All the data about the data structure/method being derived upon.
pub struct Substructure<'a> {
    /// ident of self
references:- 22
510:         -> @Expr {
511:         let substructure = Substructure {
512:             type_ident: type_ident,
--
1148:                trait_span: Span,
1149:                substructure: &Substructure)
1150:                -> @Expr {
--
1194:                       trait_span: Span,
1195:                       substructure: &Substructure)
1196:                       -> @Expr {
--
1275:              cx: &mut ExtCtxt, span: Span,
1276:              substructure: &Substructure) -> @Expr {
1277:     cs_binop(ast::BiOr, cx.expr_bool(span, false),
--
1285:               cx: &mut ExtCtxt, span: Span,
1286:               substructure: &Substructure) -> @Expr {
1287:     cs_binop(ast::BiAnd, cx.expr_bool(span, true),
libsyntax/ext/deriving/clone.rs:
52:     cx: &mut ExtCtxt, trait_span: Span,
53:     substr: &Substructure) -> @Expr {
54:     let clone_ident = substr.method_ident;
libsyntax/ext/deriving/encodable.rs:
135: fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
136:                           substr: &Substructure) -> @Expr {
137:     let encoder = substr.nonself_args[0];
libsyntax/ext/deriving/decodable.rs:
65: fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
66:                           substr: &Substructure) -> @Expr {
67:     let decoder = substr.nonself_args[0];
libsyntax/ext/deriving/hash.rs:
65: fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
66:     let state_expr = match substr.nonself_args {
libsyntax/ext/deriving/rand.rs:
55: fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
56:     let rng = match substr.nonself_args {
libsyntax/ext/deriving/show.rs:
58: fn show_substructure(cx: &mut ExtCtxt, span: Span,
59:                      substr: &Substructure) -> @Expr {
60:     // build `<name>`, `<name>({}, {}, ...)` or `<name> { <field>: {},
libsyntax/ext/deriving/zero.rs:
65: fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
66:     let zero_ident = vec!(
libsyntax/ext/deriving/default.rs:
48: fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
49:     let default_ident = vec!(
libsyntax/ext/deriving/primitive.rs:
72: fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
73:     let n = match substr.nonself_args {
libsyntax/ext/deriving/cmp/eq.rs:
28:     }
29:     fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
30:         cs_or(|cx, span, _, _| cx.expr_bool(span, true),
libsyntax/ext/deriving/cmp/totaleq.rs:
22:                                push: |@Item|) {
23:     fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
24:         cs_same_method(|cx, span, exprs| {
libsyntax/ext/deriving/cmp/ord.rs:
59: /// Strict inequality.
60: fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
61:     let op = if less {ast::BiLt} else {ast::BiGt};
libsyntax/ext/deriving/cmp/totalord.rs:
66: pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
67:               substr: &Substructure) -> @Expr {
68:     let test_id = cx.ident_of("__test");
libsyntax/ext/deriving/generic.rs:
306: pub type CombineSubstructureFunc<'a> =
307:     |&mut ExtCtxt, Span, &Substructure|: 'a -> @Expr;