]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 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 | ||
54a0048b | 11 | use deriving; |
9cc50fc6 SL |
12 | use deriving::generic::*; |
13 | use deriving::generic::ty::*; | |
14 | ||
5bcae85e SL |
15 | use syntax::ast::{Expr, MetaItem, Mutability}; |
16 | use syntax::ext::base::{Annotatable, ExtCtxt}; | |
9cc50fc6 SL |
17 | use syntax::ext::build::AstBuilder; |
18 | use syntax::ptr::P; | |
3157f602 | 19 | use syntax_pos::Span; |
1a4d82fc | 20 | |
d9579d0f AL |
21 | pub fn expand_deriving_hash(cx: &mut ExtCtxt, |
22 | span: Span, | |
23 | mitem: &MetaItem, | |
62682a34 | 24 | item: &Annotatable, |
5bcae85e | 25 | push: &mut FnMut(Annotatable)) { |
1a4d82fc | 26 | |
5bcae85e | 27 | let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, vec![], true); |
54a0048b SL |
28 | |
29 | let typaram = &*deriving::hygienic_type_parameter(item, "__H"); | |
30 | ||
31 | let arg = Path::new_local(typaram); | |
1a4d82fc JJ |
32 | let hash_trait_def = TraitDef { |
33 | span: span, | |
34 | attributes: Vec::new(), | |
35 | path: path, | |
36 | additional_bounds: Vec::new(), | |
85aaf69f | 37 | generics: LifetimeBounds::empty(), |
e9174d1e | 38 | is_unsafe: false, |
5bcae85e SL |
39 | methods: vec![MethodDef { |
40 | name: "hash", | |
41 | generics: LifetimeBounds { | |
42 | lifetimes: Vec::new(), | |
43 | bounds: vec![(typaram, vec![path_std!(cx, core::hash::Hasher)])], | |
44 | }, | |
45 | explicit_self: borrowed_explicit_self(), | |
46 | args: vec![Ptr(Box::new(Literal(arg)), | |
47 | Borrowed(None, Mutability::Mutable))], | |
48 | ret_ty: nil_ty(), | |
49 | attributes: vec![], | |
50 | is_unsafe: false, | |
51 | unify_fieldless_variants: true, | |
52 | combine_substructure: combine_substructure(Box::new(|a, b, c| { | |
53 | hash_substructure(a, b, c) | |
54 | })), | |
55 | }], | |
85aaf69f | 56 | associated_types: Vec::new(), |
1a4d82fc JJ |
57 | }; |
58 | ||
62682a34 | 59 | hash_trait_def.expand(cx, mitem, item, push); |
1a4d82fc JJ |
60 | } |
61 | ||
62 | fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> { | |
d9579d0f AL |
63 | let state_expr = match (substr.nonself_args.len(), substr.nonself_args.get(0)) { |
64 | (1, Some(o_f)) => o_f, | |
5bcae85e SL |
65 | _ => { |
66 | cx.span_bug(trait_span, | |
67 | "incorrect number of arguments in `derive(Hash)`") | |
68 | } | |
1a4d82fc | 69 | }; |
85aaf69f SL |
70 | let call_hash = |span, thing_expr| { |
71 | let hash_path = { | |
e9174d1e | 72 | let strs = cx.std_path(&["hash", "Hash", "hash"]); |
85aaf69f SL |
73 | |
74 | cx.expr_path(cx.path_global(span, strs)) | |
75 | }; | |
76 | let ref_thing = cx.expr_addr_of(span, thing_expr); | |
5bcae85e | 77 | let expr = cx.expr_call(span, hash_path, vec![ref_thing, state_expr.clone()]); |
1a4d82fc JJ |
78 | cx.stmt_expr(expr) |
79 | }; | |
80 | let mut stmts = Vec::new(); | |
81 | ||
82 | let fields = match *substr.fields { | |
7453a54e | 83 | Struct(_, ref fs) => fs, |
54a0048b SL |
84 | EnumMatching(_, _, ref fs) => { |
85 | let variant_value = deriving::call_intrinsic(cx, | |
86 | trait_span, | |
87 | "discriminant_value", | |
88 | vec![cx.expr_self(trait_span)]); | |
1a4d82fc | 89 | |
54a0048b | 90 | stmts.push(call_hash(trait_span, variant_value)); |
1a4d82fc JJ |
91 | |
92 | fs | |
93 | } | |
5bcae85e | 94 | _ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`"), |
1a4d82fc JJ |
95 | }; |
96 | ||
85aaf69f | 97 | for &FieldInfo { ref self_, span, .. } in fields { |
1a4d82fc JJ |
98 | stmts.push(call_hash(span, self_.clone())); |
99 | } | |
100 | ||
3157f602 | 101 | cx.expr_block(cx.block(trait_span, stmts)) |
1a4d82fc | 102 | } |