|
1 | 1 | use synstructure;
|
2 |
| -use syn; |
3 |
| -use proc_macro2; |
| 2 | +use syn::{self, Meta, NestedMeta}; |
| 3 | +use proc_macro2::{self, Ident, Span}; |
| 4 | + |
| 5 | +struct Attributes { |
| 6 | + ignore: bool, |
| 7 | + project: Option<String>, |
| 8 | +} |
| 9 | + |
| 10 | +fn parse_attributes(field: &syn::Field) -> Attributes { |
| 11 | + let mut attrs = Attributes { |
| 12 | + ignore: false, |
| 13 | + project: None, |
| 14 | + }; |
| 15 | + for attr in &field.attrs { |
| 16 | + if let Ok(meta) = attr.parse_meta() { |
| 17 | + if &meta.name().to_string() != "stable_hasher" { |
| 18 | + continue; |
| 19 | + } |
| 20 | + let mut any_attr = false; |
| 21 | + if let Meta::List(list) = meta { |
| 22 | + for nested in list.nested.iter() { |
| 23 | + if let NestedMeta::Meta(meta) = nested { |
| 24 | + if &meta.name().to_string() == "ignore" { |
| 25 | + attrs.ignore = true; |
| 26 | + any_attr = true; |
| 27 | + } |
| 28 | + if &meta.name().to_string() == "project" { |
| 29 | + if let Meta::List(list) = meta { |
| 30 | + if let Some(nested) = list.nested.iter().next() { |
| 31 | + if let NestedMeta::Meta(meta) = nested { |
| 32 | + attrs.project = Some(meta.name().to_string()); |
| 33 | + any_attr = true; |
| 34 | + } |
| 35 | + } |
| 36 | + } |
| 37 | + } |
| 38 | + } |
| 39 | + } |
| 40 | + } |
| 41 | + if !any_attr { |
| 42 | + panic!("error parsing stable_hasher"); |
| 43 | + } |
| 44 | + } |
| 45 | + } |
| 46 | + attrs |
| 47 | +} |
4 | 48 |
|
5 | 49 | pub fn hash_stable_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream {
|
6 | 50 | let generic: syn::GenericParam = parse_quote!('__ctx);
|
7 | 51 | s.add_bounds(synstructure::AddBounds::Generics);
|
8 | 52 | s.add_impl_generic(generic);
|
9 |
| - let body = s.each(|bi| quote!{ |
10 |
| - ::rustc_data_structures::stable_hasher::HashStable::hash_stable(#bi, __hcx, __hasher); |
| 53 | + let body = s.each(|bi| { |
| 54 | + let attrs = parse_attributes(bi.ast()); |
| 55 | + if attrs.ignore { |
| 56 | + quote!{} |
| 57 | + } else if let Some(project) = attrs.project { |
| 58 | + let project = Ident::new(&project, Span::call_site()); |
| 59 | + quote!{ |
| 60 | + &#bi.#project.hash_stable(__hcx, __hasher); |
| 61 | + } |
| 62 | + } else { |
| 63 | + quote!{ |
| 64 | + #bi.hash_stable(__hcx, __hasher); |
| 65 | + } |
| 66 | + } |
11 | 67 | });
|
12 | 68 |
|
13 | 69 | let discriminant = match s.ast().data {
|
|
0 commit comments