1 use crate::deriving
::generic
::ty
::*;
2 use crate::deriving
::generic
::*;
3 use crate::deriving
::{self, path_std, pathvec_std}
;
6 use rustc_ast
::{Expr, MetaItem, Mutability}
;
7 use rustc_expand
::base
::{Annotatable, ExtCtxt}
;
8 use rustc_span
::symbol
::sym
;
11 pub fn expand_deriving_hash(
16 push
: &mut dyn FnMut(Annotatable
),
18 let path
= Path
::new_(pathvec_std
!(hash
::Hash
), None
, vec
![], PathKind
::Std
);
20 let typaram
= sym
::__H
;
22 let arg
= Path
::new_local(typaram
);
23 let hash_trait_def
= TraitDef
{
25 attributes
: Vec
::new(),
27 additional_bounds
: Vec
::new(),
28 generics
: Bounds
::empty(),
30 supports_unions
: false,
31 methods
: vec
![MethodDef
{
33 generics
: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] }
,
34 explicit_self
: borrowed_explicit_self(),
35 args
: vec
![(Ptr(Box
::new(Literal(arg
)), Borrowed(None
, Mutability
::Mut
)), sym
::state
)],
39 unify_fieldless_variants
: true,
40 combine_substructure
: combine_substructure(Box
::new(|a
, b
, c
| {
41 hash_substructure(a
, b
, c
)
44 associated_types
: Vec
::new(),
47 hash_trait_def
.expand(cx
, mitem
, item
, push
);
50 fn hash_substructure(cx
: &mut ExtCtxt
<'_
>, trait_span
: Span
, substr
: &Substructure
<'_
>) -> P
<Expr
> {
51 let state_expr
= match &substr
.nonself_args
{
53 _
=> cx
.span_bug(trait_span
, "incorrect number of arguments in `derive(Hash)`"),
55 let call_hash
= |span
, thing_expr
| {
57 let strs
= cx
.std_path(&[sym
::hash
, sym
::Hash
, sym
::hash
]);
59 cx
.expr_path(cx
.path_global(span
, strs
))
61 let ref_thing
= cx
.expr_addr_of(span
, thing_expr
);
62 let expr
= cx
.expr_call(span
, hash_path
, vec
![ref_thing
, state_expr
.clone()]);
65 let mut stmts
= Vec
::new();
67 let fields
= match *substr
.fields
{
68 Struct(_
, ref fs
) | EnumMatching(_
, 1, .., ref fs
) => fs
,
69 EnumMatching(.., ref fs
) => {
70 let variant_value
= deriving
::call_intrinsic(
73 sym
::discriminant_value
,
74 vec
![cx
.expr_self(trait_span
)],
77 stmts
.push(call_hash(trait_span
, variant_value
));
81 _
=> cx
.span_bug(trait_span
, "impossible substructure in `derive(Hash)`"),
85 fields
.iter().map(|FieldInfo { ref self_, span, .. }
| call_hash(*span
, self_
.clone())),
88 cx
.expr_block(cx
.block(trait_span
, stmts
))