1 use crate::deriving
::{self, pathvec_std, path_std}
;
2 use crate::deriving
::generic
::*;
3 use crate::deriving
::generic
::ty
::*;
5 use syntax
::ast
::{Expr, MetaItem, Mutability}
;
6 use syntax_expand
::base
::{Annotatable, ExtCtxt}
;
8 use syntax
::symbol
::sym
;
11 pub fn expand_deriving_hash(cx
: &mut ExtCtxt
<'_
>,
15 push
: &mut dyn FnMut(Annotatable
)) {
17 let path
= Path
::new_(pathvec_std
!(cx
, hash
::Hash
), None
, vec
![], PathKind
::Std
);
21 let arg
= Path
::new_local(typaram
);
22 let hash_trait_def
= TraitDef
{
24 attributes
: Vec
::new(),
26 additional_bounds
: Vec
::new(),
27 generics
: LifetimeBounds
::empty(),
29 supports_unions
: false,
30 methods
: vec
![MethodDef
{
32 generics
: LifetimeBounds
{
33 lifetimes
: Vec
::new(),
34 bounds
: vec
![(typaram
, vec
![path_std
!(cx
, hash
::Hasher
)])],
36 explicit_self
: borrowed_explicit_self(),
37 args
: vec
![(Ptr(Box
::new(Literal(arg
)),
38 Borrowed(None
, Mutability
::Mutable
)), "state")],
42 unify_fieldless_variants
: true,
43 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| {
44 hash_substructure(a
, b
, c
)
47 associated_types
: Vec
::new(),
50 hash_trait_def
.expand(cx
, mitem
, item
, push
);
53 fn hash_substructure(cx
: &mut ExtCtxt
<'_
>, trait_span
: Span
, substr
: &Substructure
<'_
>) -> P
<Expr
> {
54 let state_expr
= match &substr
.nonself_args
{
57 cx
.span_bug(trait_span
,
58 "incorrect number of arguments in `derive(Hash)`")
61 let call_hash
= |span
, thing_expr
| {
63 let strs
= cx
.std_path(&[sym
::hash
, sym
::Hash
, sym
::hash
]);
65 cx
.expr_path(cx
.path_global(span
, strs
))
67 let ref_thing
= cx
.expr_addr_of(span
, thing_expr
);
68 let expr
= cx
.expr_call(span
, hash_path
, vec
![ref_thing
, state_expr
.clone()]);
71 let mut stmts
= Vec
::new();
73 let fields
= match *substr
.fields
{
74 Struct(_
, ref fs
) | EnumMatching(_
, 1, .., ref fs
) => fs
,
75 EnumMatching(.., ref fs
) => {
76 let variant_value
= deriving
::call_intrinsic(cx
,
79 vec
![cx
.expr_self(trait_span
)]);
81 stmts
.push(call_hash(trait_span
, variant_value
));
85 _
=> cx
.span_bug(trait_span
, "impossible substructure in `derive(Hash)`"),
88 stmts
.extend(fields
.iter().map(|FieldInfo { ref self_, span, .. }
|
89 call_hash(*span
, self_
.clone())));
91 cx
.expr_block(cx
.block(trait_span
, stmts
))