1 // Copyright 2013 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 use deriving
::generic
::*;
12 use deriving
::generic
::ty
::*;
14 use syntax
::ast
::{BinOpKind, Expr, MetaItem}
;
15 use syntax
::ext
::base
::{Annotatable, ExtCtxt}
;
16 use syntax
::ext
::build
::AstBuilder
;
17 use syntax
::parse
::token
::InternedString
;
21 pub fn expand_deriving_partial_eq(cx
: &mut ExtCtxt
,
25 push
: &mut FnMut(Annotatable
)) {
26 // structures are equal if all fields are equal, and non equal, if
27 // any fields are not equal or if the enum variants are different
28 fn cs_eq(cx
: &mut ExtCtxt
, span
: Span
, substr
: &Substructure
) -> P
<Expr
> {
29 cs_fold(true, // use foldl
30 |cx
, span
, subexpr
, self_f
, other_fs
| {
31 let other_f
= match (other_fs
.len(), other_fs
.get(0)) {
32 (1, Some(o_f
)) => o_f
,
33 _
=> cx
.span_bug(span
, "not exactly 2 arguments in `derive(PartialEq)`"),
36 let eq
= cx
.expr_binary(span
, BinOpKind
::Eq
, self_f
, other_f
.clone());
38 cx
.expr_binary(span
, BinOpKind
::And
, subexpr
, eq
)
40 cx
.expr_bool(span
, true),
41 Box
::new(|cx
, span
, _
, _
| cx
.expr_bool(span
, false)),
46 fn cs_ne(cx
: &mut ExtCtxt
, span
: Span
, substr
: &Substructure
) -> P
<Expr
> {
47 cs_fold(true, // use foldl
48 |cx
, span
, subexpr
, self_f
, other_fs
| {
49 let other_f
= match (other_fs
.len(), other_fs
.get(0)) {
50 (1, Some(o_f
)) => o_f
,
51 _
=> cx
.span_bug(span
, "not exactly 2 arguments in `derive(PartialEq)`"),
54 let eq
= cx
.expr_binary(span
, BinOpKind
::Ne
, self_f
, other_f
.clone());
56 cx
.expr_binary(span
, BinOpKind
::Or
, subexpr
, eq
)
58 cx
.expr_bool(span
, false),
59 Box
::new(|cx
, span
, _
, _
| cx
.expr_bool(span
, true)),
66 ($name
:expr
, $f
:ident
) => { {
67 let inline
= cx
.meta_word(span
, InternedString
::new("inline"));
68 let attrs
= vec
!(cx
.attribute(span
, inline
));
71 generics
: LifetimeBounds
::empty(),
72 explicit_self
: borrowed_explicit_self(),
73 args
: vec
!(borrowed_self()),
74 ret_ty
: Literal(path_local
!(bool
)),
77 unify_fieldless_variants
: true,
78 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| {
85 // avoid defining `ne` if we can
86 // c-like enums, enums without any fields and structs without fields
87 // can safely define only `eq`.
88 let mut methods
= vec
![md
!("eq", cs_eq
)];
89 if !is_type_without_fields(item
) {
90 methods
.push(md
!("ne", cs_ne
));
93 let trait_def
= TraitDef
{
95 attributes
: Vec
::new(),
96 path
: path_std
!(cx
, core
::cmp
::PartialEq
),
97 additional_bounds
: Vec
::new(),
98 generics
: LifetimeBounds
::empty(),
100 supports_unions
: false,
102 associated_types
: Vec
::new(),
104 trait_def
.expand(cx
, mitem
, item
, push
)