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.
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.
11 //! Some code that abstracts away much of the boilerplate of writing
12 //! `deriving` 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.
16 //! Supported features (fairly exhaustive):
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, e.g. the `Ord` instance
25 //! requires an explicit `PartialEq` bound at the
26 //! moment. (`TraitDef.additional_bounds`)
28 //! Unsupported: FIXME #6257: calling methods on reference fields,
29 //! e.g. deriving Eq/Ord/Clone don't work on `struct A(&int)`,
30 //! because of how the auto-dereferencing happens.
32 //! The most important thing for implementers is the `Substructure` and
33 //! `SubstructureFields` objects. The latter groups 5 possibilities of the
36 //! - `Struct`, when `Self` is a struct (including tuple structs, e.g
37 //! `struct T(int, char)`).
38 //! - `EnumMatching`, when `Self` is an enum and all the arguments are the
39 //! same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`)
40 //! - `EnumNonMatching` when `Self` is an enum and the arguments are not
41 //! the same variant (e.g. `None`, `Some(1)` and `None`). If
42 //! `on_nonmatching == NonMatchesCollapse`, this will contain an empty list.
43 //! - `StaticEnum` and `StaticStruct` for static methods, where the type
44 //! being derived upon is either an enum or struct respectively. (Any
45 //! argument with type Self is just grouped among the non-self
48 //! In the first two cases, the values from the corresponding fields in
49 //! all the arguments are grouped together. In the `EnumNonMatching` case
50 //! this isn't possible (different variants have different fields), so the
51 //! fields are grouped by which argument they come from. There are no
52 //! fields with values in the static cases, so these are treated entirely
55 //! The non-static cases have `Option<ident>` in several places associated
56 //! with field `expr`s. This represents the name of the field it is
57 //! associated with. It is only not `None` when the associated field has
58 //! an identifier in the source code. For example, the `x`s in the
62 //! struct A { x : int }
72 //! The `int`s in `B` and `C0` don't have an identifier, so the
73 //! `Option<ident>`s would be `None` for them.
75 //! In the static cases, the structure is summarised, either into the just
76 //! spans of the fields or a list of spans and the field idents (for tuple
77 //! structs and record structs, respectively), or a list of these, for
78 //! enums (one for each variant). For empty struct and empty enum
79 //! variants, it is represented as a count of 0.
83 //! The following simplified `PartialEq` is used for in-code examples:
87 //! fn eq(&self, other: &Self);
89 //! impl PartialEq for int {
90 //! fn eq(&self, other: &int) -> bool {
96 //! Some examples of the values of `SubstructureFields` follow, using the
97 //! above `PartialEq`, `A`, `B` and `C`.
101 //! When generating the `expr` for the `A` impl, the `SubstructureFields` is
104 //! Struct(~[FieldInfo {
105 //! span: <span of x>
106 //! name: Some(<ident of x>),
107 //! self_: <expr for &self.x>,
108 //! other: ~[<expr for &other.x]
112 //! For the `B` impl, called with `B(a)` and `B(b)`,
115 //! Struct(~[FieldInfo {
116 //! span: <span of `int`>,
125 //! When generating the `expr` for a call with `self == C0(a)` and `other
126 //! == C0(b)`, the SubstructureFields is
129 //! EnumMatching(0, <ast::Variant for C0>,
131 //! span: <span of int>
133 //! self_: <expr for &a>,
134 //! other: ~[<expr for &b>]
138 //! For `C1 {x}` and `C1 {x}`,
141 //! EnumMatching(1, <ast::Variant for C1>,
143 //! span: <span of x>
144 //! name: Some(<ident of x>),
145 //! self_: <expr for &self.x>,
146 //! other: ~[<expr for &other.x>]
150 //! For `C0(a)` and `C1 {x}` ,
153 //! EnumNonMatchingCollapsed(
154 //! ~[<ident of self>, <ident of __arg_1>],
155 //! &[<ast::Variant for C0>, <ast::Variant for C1>],
156 //! &[<ident for self index value>, <ident of __arg_1 index value>])
159 //! It is the same for when the arguments are flipped to `C1 {x}` and
160 //! `C0(a)`; the only difference is what the values of the identifiers
161 //! <ident for self index value> and <ident of __arg_1 index value> will
162 //! be in the generated code.
164 //! `EnumNonMatchingCollapsed` deliberately provides far less information
165 //! than is generally available for a given pair of variants; see #15375
170 //! A static method on the above would result in,
173 //! StaticStruct(<ast::StructDef of A>, Named(~[(<ident of x>, <span of x>)]))
175 //! StaticStruct(<ast::StructDef of B>, Unnamed(~[<span of x>]))
177 //! StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span of int>])),
178 //! (<ident of C1>, <span of C1>,
179 //! Named(~[(<ident of x>, <span of x>)]))])
182 use std::cell::RefCell;
183 use std::gc::{Gc, GC};
186 use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
189 use attr::AttrMetaMethods;
190 use ext::base::ExtCtxt;
191 use ext::build::AstBuilder;
194 use owned_slice::OwnedSlice;
195 use parse::token::InternedString;
196 use parse::token::special_idents;
202 pub struct TraitDef<'a> {
203 /// The span for the current #[deriving(Foo)] header.
206 pub attributes: Vec<ast::Attribute>,
208 /// Path of the trait, including any type parameters
211 /// Additional bounds required of any type parameters of the type,
212 /// other than the current trait
213 pub additional_bounds: Vec<Ty<'a>>,
215 /// Any extra lifetimes and/or bounds, e.g. `D: serialize::Decoder`
216 pub generics: LifetimeBounds<'a>,
218 pub methods: Vec<MethodDef<'a>>,
221 #[deriving(PartialEq, Eq)]
222 pub enum HandleNonMatchingEnums {
223 /// handle all non-matches via one `_ => ..` clause
226 /// handle all non-matches via one `_ => ..` clause that has
227 /// access to a tuple of tags indicating each variant index.
228 NonMatchesCollapseWithTags,
230 /// handle via n^k cases for n variants and k self-args
233 /// cannot encounter two enums of Self type
234 NonMatchHandlingIrrelevant,
237 pub struct MethodDef<'a> {
238 /// name of the method
240 /// List of generics, e.g. `R: rand::Rng`
241 pub generics: LifetimeBounds<'a>,
243 /// Whether there is a self argument (outer Option) i.e. whether
244 /// this is a static function, and whether it is a pointer (inner
246 pub explicit_self: Option<Option<PtrTy<'a>>>,
248 /// Arguments other than the self argument
249 pub args: Vec<Ty<'a>>,
254 pub attributes: Vec<ast::Attribute>,
256 /// How to handle nonmatching enums; `NonMatchesCollapse`
257 /// indicates value is independent of the actual enum variants,
258 /// i.e. can use _ => .. match.
260 /// Note that if this is `NonMatchesExplode`, then deriving will
261 /// generate `Omega(n^k)` code, where `n` is the number of
262 /// variants and `k` is the number of arguments of `Self` type for
263 /// the method (including the `self` argument, if any). Strive to
264 /// avoid use of `NonMatchesExplode`, to avoid generating
265 /// quadratic amounts of code (#15375) or worse.
266 pub on_nonmatching: HandleNonMatchingEnums,
268 pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
271 /// All the data about the data structure/method being derived upon.
272 pub struct Substructure<'a> {
274 pub type_ident: Ident,
275 /// ident of the method
276 pub method_ident: Ident,
277 /// dereferenced access to any Self or Ptr(Self, _) arguments
278 pub self_args: &'a [Gc<Expr>],
279 /// verbatim access to any other arguments
280 pub nonself_args: &'a [Gc<Expr>],
281 pub fields: &'a SubstructureFields<'a>
284 /// Summary of the relevant parts of a struct/enum field.
285 pub struct FieldInfo {
287 /// None for tuple structs/normal enum variants, Some for normal
288 /// structs/struct enum variants.
289 pub name: Option<Ident>,
290 /// The expression corresponding to this field of `self`
291 /// (specifically, a reference to it).
293 /// The expressions corresponding to references to this field in
294 /// the other Self arguments.
295 pub other: Vec<Gc<Expr>>,
298 /// Fields for a static method
299 pub enum StaticFields {
300 /// Tuple structs/enum variants like this
302 /// Normal structs/struct variants.
303 Named(Vec<(Ident, Span)>),
306 /// A summary of the possible sets of fields. See above for details
308 pub enum SubstructureFields<'a> {
309 Struct(Vec<FieldInfo>),
311 Matching variants of the enum: variant index, ast::Variant,
312 fields: the field name is only non-`None` in the case of a struct
315 EnumMatching(uint, &'a ast::Variant, Vec<FieldInfo>),
318 non-matching variants of the enum, [(variant index, ast::Variant,
319 [field span, field ident, fields])] \(i.e. all fields for self are in the
320 first tuple, for other1 are in the second tuple, etc.)
322 EnumNonMatching(&'a [(uint, P<ast::Variant>,
323 Vec<(Span, Option<Ident>, Gc<Expr>)>)]),
326 non-matching variants of the enum, but with all state hidden from
327 the consequent code. The first component holds Idents for all of
328 the Self arguments; the second component is a slice of all of the
329 variants for the enum itself, and the third component is a list of
330 Idents bound to the variant index values for each of the actual
331 input Self arguments.
333 EnumNonMatchingCollapsed(Vec<Ident>, &'a [Gc<ast::Variant>], &'a [Ident]),
335 /// A static method where Self is a struct.
336 StaticStruct(&'a ast::StructDef, StaticFields),
337 /// A static method where Self is an enum.
338 StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)>),
344 Combine the values of all the fields together. The last argument is
345 all the fields of all the structures, see above for details.
347 pub type CombineSubstructureFunc<'a> =
348 |&mut ExtCtxt, Span, &Substructure|: 'a -> Gc<Expr>;
351 Deal with non-matching enum variants. The tuple is a list of
352 identifiers (one for each Self argument, which could be any of the
353 variants since they have been collapsed together) and the identifiers
354 holding the variant index value for each of the Self arguments. The
355 last argument is all the non-Self args of the method being derived.
357 pub type EnumNonMatchCollapsedFunc<'a> =
360 (&[Ident], &[Ident]),
364 pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
365 -> RefCell<CombineSubstructureFunc<'a>> {
370 impl<'a> TraitDef<'a> {
373 _mitem: Gc<ast::MetaItem>,
375 push: |Gc<ast::Item>|) {
376 let newitem = match item.node {
377 ast::ItemStruct(ref struct_def, ref generics) => {
378 self.expand_struct_def(cx,
383 ast::ItemEnum(ref enum_def, ref generics) => {
384 self.expand_enum_def(cx,
391 // Keep the lint attributes of the previous item to control how the
392 // generated implementations are linted
393 let mut attrs = newitem.attrs.clone();
394 attrs.extend(item.attrs.iter().filter(|a| {
395 match a.name().get() {
396 "allow" | "warn" | "deny" | "forbid" => true,
399 }).map(|a| a.clone()));
400 push(box(GC) ast::Item {
408 * Given that we are deriving a trait `Tr` for a type `T<'a, ...,
409 * 'z, A, ..., Z>`, creates an impl like:
412 * impl<'a, ..., 'z, A:Tr B1 B2, ..., Z: Tr B1 B2> Tr for T<A, ..., Z> { ... }
415 * where B1, B2, ... are the bounds given by `bounds_paths`.'
418 fn create_derived_impl(&self,
422 methods: Vec<Gc<ast::Method>> ) -> Gc<ast::Item> {
423 let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
425 let Generics { mut lifetimes, ty_params } =
426 self.generics.to_generics(cx, self.span, type_ident, generics);
427 let mut ty_params = ty_params.into_vec();
429 // Copy the lifetimes
430 lifetimes.extend(generics.lifetimes.iter().map(|l| *l));
432 // Create the type parameters.
433 ty_params.extend(generics.ty_params.iter().map(|ty_param| {
434 // I don't think this can be moved out of the loop, since
435 // a TyParamBound requires an ast id
436 let mut bounds: Vec<_> =
437 // extra restrictions on the generics parameters to the type being derived upon
438 self.additional_bounds.iter().map(|p| {
439 cx.typarambound(p.to_path(cx, self.span,
440 type_ident, generics))
442 // require the current trait
443 bounds.push(cx.typarambound(trait_path.clone()));
445 cx.typaram(self.span,
447 OwnedSlice::from_vec(bounds),
448 ty_param.unbound.clone(),
451 let trait_generics = Generics {
452 lifetimes: lifetimes,
453 ty_params: OwnedSlice::from_vec(ty_params)
456 // Create the reference to the trait.
457 let trait_ref = cx.trait_ref(trait_path);
459 // Create the type parameters on the `self` path.
460 let self_ty_params = generics.ty_params.map(|ty_param| {
461 cx.ty_ident(self.span, ty_param.ident)
464 let self_lifetimes = generics.lifetimes.clone();
466 // Create the type of `self`.
467 let self_type = cx.ty_path(
468 cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
469 self_ty_params.into_vec()), None);
471 let attr = cx.attribute(
473 cx.meta_word(self.span,
474 InternedString::new("automatically_derived")));
475 // Just mark it now since we know that it'll end up used downstream
476 attr::mark_used(&attr);
477 let opt_trait_ref = Some(trait_ref);
478 let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type);
482 (vec!(attr)).append(self.attributes.as_slice()),
483 ast::ItemImpl(trait_generics, opt_trait_ref,
487 fn expand_struct_def(&self,
489 struct_def: &StructDef,
491 generics: &Generics) -> Gc<ast::Item> {
492 let methods = self.methods.iter().map(|method_def| {
493 let (explicit_self, self_args, nonself_args, tys) =
494 method_def.split_self_nonself_args(
495 cx, self, type_ident, generics);
497 let body = if method_def.is_static() {
498 method_def.expand_static_struct_method_body(
503 self_args.as_slice(),
504 nonself_args.as_slice())
506 method_def.expand_struct_method_body(cx,
510 self_args.as_slice(),
511 nonself_args.as_slice())
514 method_def.create_method(cx, self,
515 type_ident, generics,
520 self.create_derived_impl(cx, type_ident, generics, methods)
523 fn expand_enum_def(&self,
527 generics: &Generics) -> Gc<ast::Item> {
528 let methods = self.methods.iter().map(|method_def| {
529 let (explicit_self, self_args, nonself_args, tys) =
530 method_def.split_self_nonself_args(cx, self,
531 type_ident, generics);
533 let body = if method_def.is_static() {
534 method_def.expand_static_enum_method_body(
539 self_args.as_slice(),
540 nonself_args.as_slice())
542 method_def.expand_enum_method_body(cx,
546 self_args.as_slice(),
547 nonself_args.as_slice())
550 method_def.create_method(cx, self,
551 type_ident, generics,
556 self.create_derived_impl(cx, type_ident, generics, methods)
560 fn variant_to_pat(cx: &mut ExtCtxt, sp: Span, variant: &ast::Variant)
562 let ident = cx.path_ident(sp, variant.node.name);
563 cx.pat(sp, match variant.node.kind {
564 ast::TupleVariantKind(..) => ast::PatEnum(ident, None),
565 ast::StructVariantKind(..) => ast::PatStruct(ident, Vec::new(), true),
569 impl<'a> MethodDef<'a> {
570 fn call_substructure_method(&self,
574 self_args: &[Gc<Expr>],
575 nonself_args: &[Gc<Expr>],
576 fields: &SubstructureFields)
578 let substructure = Substructure {
579 type_ident: type_ident,
580 method_ident: cx.ident_of(self.name),
581 self_args: self_args,
582 nonself_args: nonself_args,
585 let mut f = self.combine_substructure.borrow_mut();
586 let f: &mut CombineSubstructureFunc = &mut *f;
587 (*f)(cx, trait_.span, &substructure)
596 self.ret_ty.to_ty(cx, trait_.span, type_ident, generics)
599 fn is_static(&self) -> bool {
600 self.explicit_self.is_none()
603 fn split_self_nonself_args(&self,
608 -> (ast::ExplicitSelf, Vec<Gc<Expr>>, Vec<Gc<Expr>>,
609 Vec<(Ident, P<ast::Ty>)>) {
611 let mut self_args = Vec::new();
612 let mut nonself_args = Vec::new();
613 let mut arg_tys = Vec::new();
614 let mut nonstatic = false;
616 let ast_explicit_self = match self.explicit_self {
617 Some(ref self_ptr) => {
618 let (self_expr, explicit_self) =
619 ty::get_explicit_self(cx, trait_.span, self_ptr);
621 self_args.push(self_expr);
626 None => codemap::respan(trait_.span, ast::SelfStatic),
629 for (i, ty) in self.args.iter().enumerate() {
630 let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
631 let ident = cx.ident_of(format!("__arg_{}", i).as_slice());
632 arg_tys.push((ident, ast_ty));
634 let arg_expr = cx.expr_ident(trait_.span, ident);
637 // for static methods, just treat any Self
638 // arguments as a normal arg
639 Self if nonstatic => {
640 self_args.push(arg_expr);
642 Ptr(box Self, _) if nonstatic => {
643 self_args.push(cx.expr_deref(trait_.span, arg_expr))
646 nonself_args.push(arg_expr);
651 (ast_explicit_self, self_args, nonself_args, arg_tys)
654 fn create_method(&self,
659 explicit_self: ast::ExplicitSelf,
660 arg_types: Vec<(Ident, P<ast::Ty>)> ,
661 body: Gc<Expr>) -> Gc<ast::Method> {
662 // create the generics that aren't for Self
663 let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
665 let self_arg = match explicit_self.node {
666 ast::SelfStatic => None,
667 // creating fresh self id
668 _ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable, special_idents::self_))
671 let args = arg_types.move_iter().map(|(name, ty)| {
672 cx.arg(trait_.span, name, ty)
674 self_arg.move_iter().chain(args).collect()
677 let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident);
679 let method_ident = cx.ident_of(self.name);
680 let fn_decl = cx.fn_decl(args, ret_type);
681 let body_block = cx.block_expr(body);
683 // Create the method.
684 box(GC) ast::Method {
686 attrs: self.attributes.clone(),
687 generics: fn_generics,
688 explicit_self: explicit_self,
689 fn_style: ast::NormalFn,
692 id: ast::DUMMY_NODE_ID,
700 #[deriving(PartialEq)]
701 struct A { x: int, y: int }
704 impl PartialEq for A {
705 fn eq(&self, __arg_1: &A) -> bool {
707 A {x: ref __self_0_0, y: ref __self_0_1} => {
709 A {x: ref __self_1_0, y: ref __self_1_1} => {
710 __self_0_0.eq(__self_1_0) && __self_0_1.eq(__self_1_1)
719 fn expand_struct_method_body(&self,
722 struct_def: &StructDef,
724 self_args: &[Gc<Expr>],
725 nonself_args: &[Gc<Expr>])
728 let mut raw_fields = Vec::new(); // ~[[fields of self],
729 // [fields of next Self arg], [etc]]
730 let mut patterns = Vec::new();
731 for i in range(0u, self_args.len()) {
732 let (pat, ident_expr) =
733 trait_.create_struct_pattern(cx,
740 raw_fields.push(ident_expr);
743 // transpose raw_fields
744 let fields = if raw_fields.len() > 0 {
748 .map(|(i, &(span, opt_id, field))| {
749 let other_fields = raw_fields.tail().iter().map(|l| {
762 cx.span_bug(trait_.span,
763 "no self arguments to non-static method in generic \
767 // body of the inner most destructuring match
768 let mut body = self.call_substructure_method(
776 // make a series of nested matches, to destructure the
777 // structs. This is actually right-to-left, but it shouldn't
779 for (&arg_expr, &pat) in self_args.iter().zip(patterns.iter()) {
780 body = cx.expr_match(trait_.span, arg_expr,
781 vec!( cx.arm(trait_.span, vec!(pat), body) ))
786 fn expand_static_struct_method_body(&self,
789 struct_def: &StructDef,
791 self_args: &[Gc<Expr>],
792 nonself_args: &[Gc<Expr>])
794 let summary = trait_.summarise_struct(cx, struct_def);
796 self.call_substructure_method(cx,
799 self_args, nonself_args,
800 &StaticStruct(struct_def, summary))
805 #[deriving(PartialEq)]
813 impl PartialEq for A {
814 fn eq(&self, __arg_1: &A) -> ::bool {
815 match (&*self, &*__arg_1) {
818 &A2(ref __arg_1_0)) => (*__self_0).eq(&(*__arg_1_0)),
820 let __self_vi = match *self { A1(..) => 0u, A2(..) => 1u };
821 let __arg_1_vi = match *__arg_1 { A1(..) => 0u, A2(..) => 1u };
829 (Of course `__self_vi` and `__arg_1_vi` are unused for
830 `PartialEq`, and those subcomputations will hopefully be removed
831 as their results are unused. The point of `__self_vi` and
832 `__arg_1_vi` is for `PartialOrd`; see #15503.)
834 fn expand_enum_method_body(&self,
839 self_args: &[Gc<Expr>],
840 nonself_args: &[Gc<Expr>])
842 let mut matches = Vec::new();
843 match self.on_nonmatching {
844 NonMatchesCollapseWithTags =>
845 self.build_enum_match_tuple(
846 cx, trait_, enum_def, type_ident, self_args, nonself_args),
847 NonMatchesCollapse | NonMatchesExplode | NonMatchHandlingIrrelevant =>
848 self.build_enum_match(
849 cx, trait_, enum_def, type_ident, self_args, nonself_args,
850 None, &mut matches, 0),
856 Creates the nested matches for an enum definition recursively, i.e.
860 Variant1 => match other { Variant1 => matching, Variant2 => nonmatching, ... },
861 Variant2 => match other { Variant1 => nonmatching, Variant2 => matching, ... },
866 It acts in the most naive way, so every branch (and subbranch,
867 subsubbranch, etc) exists, not just the ones where all the variants in
868 the tree are the same. Hopefully the optimisers get rid of any
869 repetition, otherwise derived methods with many Self arguments will be
872 `matching` is Some(n) if all branches in the tree above the
873 current position are variant `n`, `None` otherwise (including on
876 fn build_enum_match(&self,
881 self_args: &[Gc<Expr>],
882 nonself_args: &[Gc<Expr>],
883 matching: Option<uint>,
884 matches_so_far: &mut Vec<(uint, P<ast::Variant>,
885 Vec<(Span, Option<Ident>, Gc<Expr>)>)> ,
886 match_count: uint) -> Gc<Expr> {
887 if match_count == self_args.len() {
888 // we've matched against all arguments, so make the final
889 // expression at the bottom of the match tree
890 if matches_so_far.len() == 0 {
891 cx.span_bug(trait_.span,
892 "no self match on an enum in \
893 generic `deriving`");
896 // `ref` inside let matches is buggy. Causes havoc with rusc.
897 // let (variant_index, ref self_vec) = matches_so_far[0];
898 let (variant, self_vec) = match matches_so_far.get(0) {
899 &(_, v, ref s) => (v, s)
902 // we currently have a vec of vecs, where each
903 // subvec is the fields of one of the arguments,
904 // but if the variants all match, we want this as
905 // vec of tuples, where each tuple represents a
908 // most arms don't have matching variants, so do a
909 // quick check to see if they match (even though
910 // this means iterating twice) instead of being
911 // optimistic and doing a pile of allocations etc.
912 let substructure = match matching {
913 Some(variant_index) => {
914 let mut enum_matching_fields = Vec::from_elem(self_vec.len(), Vec::new());
916 for triple in matches_so_far.tail().iter() {
918 &(_, _, ref other_fields) => {
919 for (i, &(_, _, e)) in other_fields.iter().enumerate() {
920 enum_matching_fields.get_mut(i).push(e);
927 .zip(enum_matching_fields.iter())
928 .map(|(&(span, id, self_f), other)| {
933 other: (*other).clone()
936 EnumMatching(variant_index, &*variant, field_tuples)
939 EnumNonMatching(matches_so_far.as_slice())
942 self.call_substructure_method(cx, trait_, type_ident,
943 self_args, nonself_args,
946 } else { // there are still matches to create
947 let current_match_str = if match_count == 0 {
950 format!("__arg_{}", match_count)
953 let mut arms = Vec::new();
955 assert!(self.on_nonmatching == NonMatchesCollapse ||
956 self.on_nonmatching == NonMatchesExplode ||
957 self.on_nonmatching == NonMatchHandlingIrrelevant);
959 // the code for nonmatching variants only matters when
960 // we've seen at least one other variant already
961 assert!(match_count == 0 ||
962 self.on_nonmatching != NonMatchHandlingIrrelevant);
963 if self.on_nonmatching == NonMatchesCollapse && match_count > 0 {
964 // make a matching-variant match, and a _ match.
965 let index = match matching {
967 None => cx.span_bug(trait_.span,
968 "non-matching variants when required to \
969 be matching in generic `deriving`")
972 // matching-variant match
973 let variant = *enum_def.variants.get(index);
974 let (pattern, idents) = trait_.create_enum_variant_pattern(
977 current_match_str.as_slice(),
980 matches_so_far.push((index, variant, idents));
981 let arm_expr = self.build_enum_match(cx,
985 self_args, nonself_args,
989 matches_so_far.pop().unwrap();
990 arms.push(cx.arm(trait_.span, vec!( pattern ), arm_expr));
992 if enum_def.variants.len() > 1 {
993 let e = &EnumNonMatching(&[]);
994 let wild_expr = self.call_substructure_method(cx, trait_, type_ident,
995 self_args, nonself_args,
997 let wild_arm = cx.arm(
999 vec!( cx.pat_wild(trait_.span) ),
1001 arms.push(wild_arm);
1004 // create an arm matching on each variant
1005 for (index, &variant) in enum_def.variants.iter().enumerate() {
1006 let (pattern, idents) =
1007 trait_.create_enum_variant_pattern(
1010 current_match_str.as_slice(),
1013 matches_so_far.push((index, variant, idents));
1016 _ if match_count == 0 => Some(index),
1017 Some(i) if index == i => Some(i),
1020 let arm_expr = self.build_enum_match(cx,
1024 self_args, nonself_args,
1028 matches_so_far.pop().unwrap();
1030 let arm = cx.arm(trait_.span, vec!( pattern ), arm_expr);
1035 // match foo { arm, arm, arm, ... }
1036 cx.expr_match(trait_.span, self_args[match_count], arms)
1041 Creates a match for a tuple of all `self_args`, where either all
1042 variants match, or it falls into a catch-all for when one variant
1045 There are N + 1 cases because is a case for each of the N
1046 variants where all of the variants match, and one catch-all for
1047 when one does not match.
1049 The catch-all handler is provided access the variant index values
1050 for each of the self-args, carried in precomputed variables. (Nota
1051 bene: the variant index values are not necessarily the
1052 discriminant values. See issue #15523.)
1055 match (this, that, ...) {
1056 (Variant1, Variant1, Variant1) => ... // delegate Matching on Variant1
1057 (Variant2, Variant2, Variant2) => ... // delegate Matching on Variant2
1060 let __this_vi = match this { Variant1 => 0u, Variant2 => 1u, ... };
1061 let __that_vi = match that { Variant1 => 0u, Variant2 => 1u, ... };
1062 ... // catch-all remainder can inspect above variant index values.
1067 fn build_enum_match_tuple(
1073 self_args: &[Gc<Expr>],
1074 nonself_args: &[Gc<Expr>]) -> Gc<Expr> {
1076 let sp = trait_.span;
1077 let variants = &enum_def.variants;
1079 let self_arg_names = self_args.iter().enumerate()
1080 .map(|(arg_count, _self_arg)| {
1082 "__self".to_string()
1084 format!("__arg_{}", arg_count)
1087 .collect::<Vec<String>>();
1089 let self_arg_idents = self_arg_names.iter()
1090 .map(|name|cx.ident_of(name.as_slice()))
1091 .collect::<Vec<ast::Ident>>();
1093 // The `vi_idents` will be bound, solely in the catch-all, to
1094 // a series of let statements mapping each self_arg to a uint
1095 // corresponding to its variant index.
1096 let vi_idents : Vec<ast::Ident> = self_arg_names.iter()
1097 .map(|name| { let vi_suffix = format!("{:s}_vi", name.as_slice());
1098 cx.ident_of(vi_suffix.as_slice()) })
1099 .collect::<Vec<ast::Ident>>();
1101 // Builds, via callback to call_substructure_method, the
1102 // delegated expression that handles the catch-all case,
1103 // using `__variants_tuple` to drive logic if necessary.
1104 let catch_all_substructure = EnumNonMatchingCollapsed(
1105 self_arg_idents, variants.as_slice(), vi_idents.as_slice());
1107 // These arms are of the form:
1108 // (Variant1, Variant1, ...) => Body1
1109 // (Variant2, Variant2, ...) => Body2
1111 // where each tuple has length = self_args.len()
1112 let mut match_arms : Vec<ast::Arm> = variants.iter().enumerate()
1113 .map(|(index, &variant)| {
1115 // These self_pats have form Variant1, Variant2, ...
1116 let self_pats : Vec<(Gc<ast::Pat>,
1117 Vec<(Span, Option<Ident>, Gc<Expr>)>)>;
1118 self_pats = self_arg_names.iter()
1119 .map(|self_arg_name|
1120 trait_.create_enum_variant_pattern(
1121 cx, &*variant, self_arg_name.as_slice(),
1125 // A single arm has form (&VariantK, &VariantK, ...) => BodyK
1126 // (see "Final wrinkle" note below for why.)
1127 let subpats = self_pats.iter()
1128 .map(|&(p, ref _idents)| cx.pat(sp, ast::PatRegion(p)))
1129 .collect::<Vec<Gc<ast::Pat>>>();
1131 // Here is the pat = `(&VariantK, &VariantK, ...)`
1132 let single_pat = cx.pat(sp, ast::PatTup(subpats));
1134 // For the BodyK, we need to delegate to our caller,
1135 // passing it an EnumMatching to indicate which case
1138 // All of the Self args have the same variant in these
1139 // cases. So we transpose the info in self_pats to
1140 // gather the getter expressions together, in the form
1141 // that EnumMatching expects.
1143 // The transposition is driven by walking across the
1144 // arg fields of the variant for the first self pat.
1145 let &(_, ref self_arg_fields) = self_pats.get(0);
1147 let field_tuples : Vec<FieldInfo>;
1149 field_tuples = self_arg_fields.iter().enumerate()
1150 // For each arg field of self, pull out its getter expr ...
1151 .map(|(field_index, &(sp, opt_ident, self_getter_expr))| {
1152 // ... but FieldInfo also wants getter expr
1153 // for matching other arguments of Self type;
1154 // so walk across the *other* self_pats and
1155 // pull out getter for same field in each of
1156 // them (using `field_index` tracked above).
1157 // That is the heart of the transposition.
1158 let others = self_pats.tail().iter()
1159 .map(|&(_pat, ref fields)| {
1161 let &(_, _opt_ident, other_getter_expr) =
1162 fields.get(field_index);
1164 // All Self args have same variant, so
1165 // opt_idents are the same. (Assert
1166 // here to make it self-evident that
1167 // it is okay to ignore `_opt_ident`.)
1168 assert!(opt_ident == _opt_ident);
1171 }).collect::<Vec<Gc<Expr>>>();
1173 FieldInfo { span: sp,
1175 self_: self_getter_expr,
1178 }).collect::<Vec<FieldInfo>>();
1180 // Now, for some given VariantK, we have built up
1181 // expressions for referencing every field of every
1182 // Self arg, assuming all are instances of VariantK.
1183 // Build up code associated with such a case.
1184 let substructure = EnumMatching(index, variant, field_tuples);
1185 let arm_expr = self.call_substructure_method(
1186 cx, trait_, type_ident, self_args, nonself_args,
1189 cx.arm(sp, vec![single_pat], arm_expr)
1192 // We will usually need the catch-all after matching the
1193 // tuples `(VariantK, VariantK, ...)` for each VariantK of the
1196 // * when there is only one Self arg, the arms above suffice
1197 // (and the deriving we call back into may not be prepared to
1198 // handle EnumNonMatchCollapsed), and,
1200 // * when the enum has only one variant, the single arm that
1201 // is already present always suffices.
1203 // * In either of the two cases above, if we *did* add a
1204 // catch-all `_` match, it would trigger the
1205 // unreachable-pattern error.
1207 if variants.len() > 1 && self_args.len() > 1 {
1208 let arms : Vec<ast::Arm> = variants.iter().enumerate()
1209 .map(|(index, &variant)| {
1210 let pat = variant_to_pat(cx, sp, &*variant);
1211 let lit = ast::LitUint(index as u64, ast::TyU);
1212 cx.arm(sp, vec![pat], cx.expr_lit(sp, lit))
1215 // Build a series of let statements mapping each self_arg
1216 // to a uint corresponding to its variant index.
1217 // i.e. for `enum E<T> { A, B(1), C(T, T) }`, and a deriving
1218 // with three Self args, builds three statements:
1221 // let __self0_vi = match self {
1222 // A => 0u, B(..) => 1u, C(..) => 2u
1224 // let __self1_vi = match __arg1 {
1225 // A => 0u, B(..) => 1u, C(..) => 2u
1227 // let __self2_vi = match __arg2 {
1228 // A => 0u, B(..) => 1u, C(..) => 2u
1231 let mut index_let_stmts : Vec<Gc<ast::Stmt>> = Vec::new();
1232 for (&ident, &self_arg) in vi_idents.iter().zip(self_args.iter()) {
1233 let variant_idx = cx.expr_match(sp, self_arg, arms.clone());
1234 let let_stmt = cx.stmt_let(sp, false, ident, variant_idx);
1235 index_let_stmts.push(let_stmt);
1238 let arm_expr = self.call_substructure_method(
1239 cx, trait_, type_ident, self_args, nonself_args,
1240 &catch_all_substructure);
1242 // Builds the expression:
1244 // let __self0_vi = ...;
1245 // let __self1_vi = ...;
1247 // <delegated expression referring to __self0_vi, et al.>
1249 let arm_expr = cx.expr_block(
1250 cx.block_all(sp, Vec::new(), index_let_stmts, Some(arm_expr)));
1253 // _ => { let __self0_vi = ...;
1254 // let __self1_vi = ...;
1256 // <delegated expression as above> }
1257 let catch_all_match_arm =
1258 cx.arm(sp, vec![cx.pat_wild(sp)], arm_expr);
1260 match_arms.push(catch_all_match_arm);
1262 } else if variants.len() == 0 {
1263 // As an additional wrinkle, For a zero-variant enum A,
1264 // currently the compiler
1265 // will accept `fn (a: &Self) { match *a { } }`
1266 // but rejects `fn (a: &Self) { match (&*a,) { } }`
1267 // as well as `fn (a: &Self) { match ( *a,) { } }`
1269 // This means that the strategy of building up a tuple of
1270 // all Self arguments fails when Self is a zero variant
1271 // enum: rustc rejects the expanded program, even though
1272 // the actual code tends to be impossible to execute (at
1273 // least safely), according to the type system.
1275 // The most expedient fix for this is to just let the
1276 // code fall through to the catch-all. But even this is
1277 // error-prone, since the catch-all as defined above would
1278 // generate code like this:
1280 // _ => { let __self0 = match *self { };
1281 // let __self1 = match *__arg_0 { };
1282 // <catch-all-expr> }
1284 // Which is yields bindings for variables which type
1285 // inference cannot resolve to unique types.
1287 // One option to the above might be to add explicit type
1288 // annotations. But the *only* reason to go down that path
1289 // would be to try to make the expanded output consistent
1290 // with the case when the number of enum variants >= 1.
1292 // That just isn't worth it. In fact, trying to generate
1293 // sensible code for *any* deriving on a zero-variant enum
1294 // does not make sense. But at the same time, for now, we
1295 // do not want to cause a compile failure just because the
1296 // user happened to attach a deriving to their
1297 // zero-variant enum.
1299 // Instead, just generate a failing expression for the
1300 // zero variant case, skipping matches and also skipping
1301 // delegating back to the end user code entirely.
1303 // (See also #4499 and #12609; note that some of the
1304 // discussions there influence what choice we make here;
1305 // e.g. if we feature-gate `match x { ... }` when x refers
1306 // to an uninhabited type (e.g. a zero-variant enum or a
1307 // type holding such an enum), but do not feature-gate
1308 // zero-variant enums themselves, then attempting to
1309 // derive Show on such a type could here generate code
1310 // that needs the feature gate enabled.)
1312 return cx.expr_unreachable(sp);
1315 // Final wrinkle: the self_args are expressions that deref
1316 // down to desired l-values, but we cannot actually deref
1317 // them when they are fed as r-values into a tuple
1318 // expression; here add a layer of borrowing, turning
1319 // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
1320 let borrowed_self_args = self_args.iter()
1321 .map(|&self_arg| cx.expr_addr_of(sp, self_arg))
1322 .collect::<Vec<Gc<ast::Expr>>>();
1323 let match_arg = cx.expr(sp, ast::ExprTup(borrowed_self_args));
1324 cx.expr_match(sp, match_arg, match_arms)
1327 fn expand_static_enum_method_body(&self,
1332 self_args: &[Gc<Expr>],
1333 nonself_args: &[Gc<Expr>])
1335 let summary = enum_def.variants.iter().map(|v| {
1336 let ident = v.node.name;
1337 let summary = match v.node.kind {
1338 ast::TupleVariantKind(ref args) => {
1339 Unnamed(args.iter().map(|va| trait_.set_expn_info(cx, va.ty.span)).collect())
1341 ast::StructVariantKind(ref struct_def) => {
1342 trait_.summarise_struct(cx, &**struct_def)
1345 (ident, v.span, summary)
1347 self.call_substructure_method(cx, trait_, type_ident,
1348 self_args, nonself_args,
1349 &StaticEnum(enum_def, summary))
1353 #[deriving(PartialEq)] // dogfooding!
1355 Unknown, Record, Tuple
1358 // general helper methods.
1359 impl<'a> TraitDef<'a> {
1360 fn set_expn_info(&self,
1362 mut to_set: Span) -> Span {
1363 let trait_name = match self.path.path.last() {
1364 None => cx.span_bug(self.span, "trait with empty path in generic `deriving`"),
1367 to_set.expn_info = Some(box(GC) codemap::ExpnInfo {
1369 callee: codemap::NameAndSpan {
1370 name: format!("deriving({})", trait_name),
1371 format: codemap::MacroAttribute,
1372 span: Some(self.span)
1378 fn summarise_struct(&self,
1380 struct_def: &StructDef) -> StaticFields {
1381 let mut named_idents = Vec::new();
1382 let mut just_spans = Vec::new();
1383 for field in struct_def.fields.iter(){
1384 let sp = self.set_expn_info(cx, field.span);
1385 match field.node.kind {
1386 ast::NamedField(ident, _) => named_idents.push((ident, sp)),
1387 ast::UnnamedField(..) => just_spans.push(sp),
1391 match (just_spans.is_empty(), named_idents.is_empty()) {
1392 (false, false) => cx.span_bug(self.span,
1393 "a struct with named and unnamed \
1394 fields in generic `deriving`"),
1396 (_, false) => Named(named_idents),
1397 // tuple structs (includes empty structs)
1398 (_, _) => Unnamed(just_spans)
1402 fn create_subpatterns(&self,
1404 field_paths: Vec<ast::SpannedIdent> ,
1405 mutbl: ast::Mutability)
1406 -> Vec<Gc<ast::Pat>> {
1407 field_paths.iter().map(|path| {
1409 ast::PatIdent(ast::BindByRef(mutbl), (*path).clone(), None))
1413 fn create_struct_pattern(&self,
1415 struct_ident: Ident,
1416 struct_def: &StructDef,
1418 mutbl: ast::Mutability)
1419 -> (Gc<ast::Pat>, Vec<(Span, Option<Ident>, Gc<Expr>)>) {
1420 if struct_def.fields.is_empty() {
1422 cx.pat_ident_binding_mode(
1423 self.span, struct_ident, ast::BindByValue(ast::MutImmutable)),
1427 let matching_path = cx.path(self.span, vec!( struct_ident ));
1429 let mut paths = Vec::new();
1430 let mut ident_expr = Vec::new();
1431 let mut struct_type = Unknown;
1433 for (i, struct_field) in struct_def.fields.iter().enumerate() {
1434 let sp = self.set_expn_info(cx, struct_field.span);
1435 let opt_id = match struct_field.node.kind {
1436 ast::NamedField(ident, _) if (struct_type == Unknown ||
1437 struct_type == Record) => {
1438 struct_type = Record;
1441 ast::UnnamedField(..) if (struct_type == Unknown ||
1442 struct_type == Tuple) => {
1443 struct_type = Tuple;
1447 cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`");
1450 let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
1451 paths.push(codemap::Spanned{span: sp, node: ident});
1453 sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)))));
1454 ident_expr.push((sp, opt_id, val));
1457 let subpats = self.create_subpatterns(cx, paths, mutbl);
1459 // struct_type is definitely not Unknown, since struct_def.fields
1460 // must be nonempty to reach here
1461 let pattern = if struct_type == Record {
1462 let field_pats = subpats.iter().zip(ident_expr.iter()).map(|(&pat, &(_, id, _))| {
1463 // id is guaranteed to be Some
1464 ast::FieldPat { ident: id.unwrap(), pat: pat }
1466 cx.pat_struct(self.span, matching_path, field_pats)
1468 cx.pat_enum(self.span, matching_path, subpats)
1471 (pattern, ident_expr)
1474 fn create_enum_variant_pattern(&self,
1476 variant: &ast::Variant,
1478 mutbl: ast::Mutability)
1479 -> (Gc<ast::Pat>, Vec<(Span, Option<Ident>, Gc<Expr>)> ) {
1480 let variant_ident = variant.node.name;
1481 match variant.node.kind {
1482 ast::TupleVariantKind(ref variant_args) => {
1483 if variant_args.is_empty() {
1484 return (cx.pat_ident_binding_mode(variant.span, variant_ident,
1485 ast::BindByValue(ast::MutImmutable)),
1489 let matching_path = cx.path_ident(variant.span, variant_ident);
1491 let mut paths = Vec::new();
1492 let mut ident_expr = Vec::new();
1493 for (i, va) in variant_args.iter().enumerate() {
1494 let sp = self.set_expn_info(cx, va.ty.span);
1495 let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
1496 let path1 = codemap::Spanned{span: sp, node: ident};
1498 let expr_path = cx.expr_path(cx.path_ident(sp, ident));
1499 let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path)));
1500 ident_expr.push((sp, None, val));
1503 let subpats = self.create_subpatterns(cx, paths, mutbl);
1505 (cx.pat_enum(variant.span, matching_path, subpats),
1508 ast::StructVariantKind(ref struct_def) => {
1509 self.create_struct_pattern(cx, variant_ident, &**struct_def,
1516 /* helpful premade recipes */
1519 Fold the fields. `use_foldl` controls whether this is done
1520 left-to-right (`true`) or right-to-left (`false`).
1522 pub fn cs_fold(use_foldl: bool,
1523 f: |&mut ExtCtxt, Span, Gc<Expr>, Gc<Expr>, &[Gc<Expr>]| -> Gc<Expr>,
1525 enum_nonmatch_f: EnumNonMatchFunc,
1526 enum_nonmatch_g: EnumNonMatchCollapsedFunc,
1529 substructure: &Substructure)
1531 match *substructure.fields {
1532 EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
1534 all_fields.iter().fold(base, |old, field| {
1539 field.other.as_slice())
1542 all_fields.iter().rev().fold(base, |old, field| {
1547 field.other.as_slice())
1551 EnumNonMatching(ref all_enums) =>
1552 enum_nonmatch_f(cx, trait_span, *all_enums,
1553 substructure.nonself_args),
1554 EnumNonMatchingCollapsed(ref all_args, _, tuple) =>
1555 enum_nonmatch_g(cx, trait_span, (all_args.as_slice(), tuple),
1556 substructure.nonself_args),
1557 StaticEnum(..) | StaticStruct(..) => {
1558 cx.span_bug(trait_span, "static function in `deriving`")
1565 Call the method that is being derived on all the fields, and then
1566 process the collected results. i.e.
1569 f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1),
1570 self_2.method(__arg_1_2, __arg_2_2)])
1574 pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<Gc<Expr>>| -> Gc<Expr>,
1575 enum_nonmatch_f: EnumNonMatchFunc,
1576 enum_nonmatch_g: EnumNonMatchCollapsedFunc,
1579 substructure: &Substructure)
1581 match *substructure.fields {
1582 EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
1583 // call self_n.method(other_1_n, other_2_n, ...)
1584 let called = all_fields.iter().map(|field| {
1585 cx.expr_method_call(field.span,
1587 substructure.method_ident,
1589 .map(|e| cx.expr_addr_of(field.span, *e))
1593 f(cx, trait_span, called)
1595 EnumNonMatching(ref all_enums) =>
1596 enum_nonmatch_f(cx, trait_span, *all_enums,
1597 substructure.nonself_args),
1598 EnumNonMatchingCollapsed(ref all_self_args, _, tuple) =>
1599 enum_nonmatch_g(cx, trait_span, (all_self_args.as_slice(), tuple),
1600 substructure.nonself_args),
1601 StaticEnum(..) | StaticStruct(..) => {
1602 cx.span_bug(trait_span, "static function in `deriving`")
1608 Fold together the results of calling the derived method on all the
1609 fields. `use_foldl` controls whether this is done left-to-right
1610 (`true`) or right-to-left (`false`).
1613 pub fn cs_same_method_fold(use_foldl: bool,
1614 f: |&mut ExtCtxt, Span, Gc<Expr>, Gc<Expr>| -> Gc<Expr>,
1616 enum_nonmatch_f: EnumNonMatchFunc,
1617 enum_nonmatch_g: EnumNonMatchCollapsedFunc,
1620 substructure: &Substructure)
1625 vals.iter().fold(base, |old, &new| {
1626 f(cx, span, old, new)
1629 vals.iter().rev().fold(base, |old, &new| {
1630 f(cx, span, old, new)
1636 cx, trait_span, substructure)
1640 Use a given binop to combine the result of calling the derived method
1644 pub fn cs_binop(binop: ast::BinOp, base: Gc<Expr>,
1645 enum_nonmatch_f: EnumNonMatchFunc,
1646 enum_nonmatch_g: EnumNonMatchCollapsedFunc,
1647 cx: &mut ExtCtxt, trait_span: Span,
1648 substructure: &Substructure) -> Gc<Expr> {
1649 cs_same_method_fold(
1650 true, // foldl is good enough
1651 |cx, span, old, new| {
1652 cx.expr_binary(span,
1660 cx, trait_span, substructure)
1663 /// cs_binop with binop == or
1665 pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc,
1666 enum_nonmatch_g: EnumNonMatchCollapsedFunc,
1667 cx: &mut ExtCtxt, span: Span,
1668 substructure: &Substructure) -> Gc<Expr> {
1669 cs_binop(ast::BiOr, cx.expr_bool(span, false),
1672 cx, span, substructure)
1675 /// cs_binop with binop == and
1677 pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc,
1678 enum_nonmatch_g: EnumNonMatchCollapsedFunc,
1679 cx: &mut ExtCtxt, span: Span,
1680 substructure: &Substructure) -> Gc<Expr> {
1681 cs_binop(ast::BiAnd, cx.expr_bool(span, true),
1684 cx, span, substructure)