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