about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2018-12-16 04:44:12 +0100
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-03-05 00:36:25 +0100
commit10d2008c510f088186234dbd2e43c2ba77b5e954 (patch)
treed6533a4b216d5e8f15a6dd8c4e8b29adfa29b3ce
parent70156fbb752d5c8726c6c47104922575164a92e3 (diff)
downloadrust-10d2008c510f088186234dbd2e43c2ba77b5e954.tar.gz
rust-10d2008c510f088186234dbd2e43c2ba77b5e954.zip
Add ignore and project attributes
-rw-r--r--src/librustc_macros/src/hash_stable.rs64
-rw-r--r--src/librustc_macros/src/lib.rs2
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<String>,
+}
+
+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);