From 10d2008c510f088186234dbd2e43c2ba77b5e954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 16 Dec 2018 04:44:12 +0100 Subject: [PATCH] Add ignore and project attributes --- src/librustc_macros/src/hash_stable.rs | 64 ++++++++++++++++++++++++-- src/librustc_macros/src/lib.rs | 2 +- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/librustc_macros/src/hash_stable.rs b/src/librustc_macros/src/hash_stable.rs index 86ac0b353e5..585f5505f1f 100644 --- a/src/librustc_macros/src/hash_stable.rs +++ b/src/librustc_macros/src/hash_stable.rs @@ -1,13 +1,69 @@ use synstructure; -use syn; -use proc_macro2; +use syn::{self, Meta, NestedMeta}; +use proc_macro2::{self, Ident, Span}; + +struct Attributes { + ignore: bool, + project: Option, +} + +fn parse_attributes(field: &syn::Field) -> Attributes { + let mut attrs = Attributes { + ignore: false, + project: None, + }; + for attr in &field.attrs { + if let Ok(meta) = attr.parse_meta() { + if &meta.name().to_string() != "stable_hasher" { + continue; + } + let mut any_attr = false; + if let Meta::List(list) = meta { + for nested in list.nested.iter() { + if let NestedMeta::Meta(meta) = nested { + if &meta.name().to_string() == "ignore" { + attrs.ignore = true; + any_attr = true; + } + if &meta.name().to_string() == "project" { + if let Meta::List(list) = meta { + if let Some(nested) = list.nested.iter().next() { + if let NestedMeta::Meta(meta) = nested { + attrs.project = Some(meta.name().to_string()); + any_attr = true; + } + } + } + } + } + } + } + if !any_attr { + panic!("error parsing stable_hasher"); + } + } + } + attrs +} pub fn hash_stable_derive(mut s: synstructure::Structure) -> proc_macro2::TokenStream { let generic: syn::GenericParam = parse_quote!('__ctx); s.add_bounds(synstructure::AddBounds::Generics); s.add_impl_generic(generic); - let body = s.each(|bi| quote!{ - ::rustc_data_structures::stable_hasher::HashStable::hash_stable(#bi, __hcx, __hasher); + let body = s.each(|bi| { + let attrs = parse_attributes(bi.ast()); + if attrs.ignore { + quote!{} + } else if let Some(project) = attrs.project { + let project = Ident::new(&project, Span::call_site()); + quote!{ + &#bi.#project.hash_stable(__hcx, __hasher); + } + } else { + quote!{ + #bi.hash_stable(__hcx, __hasher); + } + } }); let discriminant = match s.ast().data { diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs index 8dcf2b76fad..460b415c537 100644 --- a/src/librustc_macros/src/lib.rs +++ b/src/librustc_macros/src/lib.rs @@ -11,4 +11,4 @@ extern crate proc_macro2; mod hash_stable; -decl_derive!([HashStable] => hash_stable::hash_stable_derive); +decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);