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
::{MetaItem, Expr, BinOpKind}
;
15 use syntax
::codemap
::Span
;
16 use syntax
::ext
::base
::{ExtCtxt, Annotatable}
;
17 use syntax
::ext
::build
::AstBuilder
;
18 use syntax
::parse
::token
::InternedString
;
21 pub fn expand_deriving_partial_eq(cx
: &mut ExtCtxt
,
25 push
: &mut FnMut(Annotatable
))
27 // structures are equal if all fields are equal, and non equal, if
28 // any fields are not equal or if the enum variants are different
29 fn cs_eq(cx
: &mut ExtCtxt
, span
: Span
, substr
: &Substructure
) -> P
<Expr
> {
32 |cx
, span
, subexpr
, self_f
, other_fs
| {
33 let other_f
= match (other_fs
.len(), other_fs
.get(0)) {
34 (1, Some(o_f
)) => o_f
,
35 _
=> cx
.span_bug(span
, "not exactly 2 arguments in `derive(PartialEq)`")
38 let eq
= cx
.expr_binary(span
, BinOpKind
::Eq
, self_f
, other_f
.clone());
40 cx
.expr_binary(span
, BinOpKind
::And
, subexpr
, eq
)
42 cx
.expr_bool(span
, true),
43 Box
::new(|cx
, span
, _
, _
| cx
.expr_bool(span
, false)),
46 fn cs_ne(cx
: &mut ExtCtxt
, span
: Span
, substr
: &Substructure
) -> P
<Expr
> {
49 |cx
, span
, subexpr
, self_f
, other_fs
| {
50 let other_f
= match (other_fs
.len(), other_fs
.get(0)) {
51 (1, Some(o_f
)) => o_f
,
52 _
=> cx
.span_bug(span
, "not exactly 2 arguments in `derive(PartialEq)`")
55 let eq
= cx
.expr_binary(span
, BinOpKind
::Ne
, self_f
, other_f
.clone());
57 cx
.expr_binary(span
, BinOpKind
::Or
, subexpr
, eq
)
59 cx
.expr_bool(span
, false),
60 Box
::new(|cx
, span
, _
, _
| cx
.expr_bool(span
, true)),
65 ($name
:expr
, $f
:ident
) => { {
66 let inline
= cx
.meta_word(span
, InternedString
::new("inline"));
67 let attrs
= vec
!(cx
.attribute(span
, inline
));
70 generics
: LifetimeBounds
::empty(),
71 explicit_self
: borrowed_explicit_self(),
72 args
: vec
!(borrowed_self()),
73 ret_ty
: Literal(path_local
!(bool
)),
76 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| {
83 // avoid defining `ne` if we can
84 // c-like enums, enums without any fields and structs without fields
85 // can safely define only `eq`.
86 let mut methods
= vec
![md
!("eq", cs_eq
)];
87 if !is_type_without_fields(item
) {
88 methods
.push(md
!("ne", cs_ne
));
91 let trait_def
= TraitDef
{
93 attributes
: Vec
::new(),
94 path
: path_std
!(cx
, core
::cmp
::PartialEq
),
95 additional_bounds
: Vec
::new(),
96 generics
: LifetimeBounds
::empty(),
99 associated_types
: Vec
::new(),
101 trait_def
.expand(cx
, mitem
, item
, push
)