diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2016-11-09 20:51:18 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-09 20:51:18 +0200 |
| commit | 5ebd7c50a0b9236af4389b00c97b00a59d9fa747 (patch) | |
| tree | 7ae11942986307fad0aa452b5ee4a9db0cb89e9f /src/libsyntax | |
| parent | 3d2ffa06ea4e04dbda99d7038e9afd04c040b472 (diff) | |
| parent | 134ef4f7933b87efdc04eac3e8d9a530d56d9cfe (diff) | |
| download | rust-5ebd7c50a0b9236af4389b00c97b00a59d9fa747.tar.gz rust-5ebd7c50a0b9236af4389b00c97b00a59d9fa747.zip | |
Rollup merge of #37614 - keeperofdakeys:proc_macro, r=jseyfried
macros 1.1: Allow proc_macro functions to declare attributes to be mark as used This PR allows proc macro functions to declare attribute names that should be marked as used when attached to the deriving item. There are a few questions for this PR. - Currently this uses a separate attribute named `#[proc_macro_attributes(..)]`, is this the best choice? - In order to make this work, the `check_attribute` function had to be modified to not error on attributes marked as used. This is a pretty large change in semantics, is there a better way to do this? - I've got a few clones where I don't know if I need them (like turning `item` into a `TokenStream`), can these be avoided? - Is switching to `MultiItemDecorator` the right thing here? Also fixes https://github.com/rust-lang/rust/issues/37563.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/attr.rs | 26 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 10 |
2 files changed, 31 insertions, 5 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 0335f210347..57a936bf9b0 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -32,7 +32,8 @@ use std::cell::{RefCell, Cell}; use std::collections::HashSet; thread_local! { - static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new()) + static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new()); + static KNOWN_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new()); } enum AttrError { @@ -81,6 +82,29 @@ pub fn is_used(attr: &Attribute) -> bool { }) } +pub fn mark_known(attr: &Attribute) { + debug!("Marking {:?} as known.", attr); + let AttrId(id) = attr.node.id; + KNOWN_ATTRS.with(|slot| { + let idx = (id / 64) as usize; + let shift = id % 64; + if slot.borrow().len() <= idx { + slot.borrow_mut().resize(idx + 1, 0); + } + slot.borrow_mut()[idx] |= 1 << shift; + }); +} + +pub fn is_known(attr: &Attribute) -> bool { + let AttrId(id) = attr.node.id; + KNOWN_ATTRS.with(|slot| { + let idx = (id / 64) as usize; + let shift = id % 64; + slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0) + .unwrap_or(false) + }) +} + impl NestedMetaItem { /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem. pub fn meta_item(&self) -> Option<&P<MetaItem>> { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 8ac3f9e5e54..a6493872338 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -421,11 +421,11 @@ macro_rules! cfg_fn { } pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, AttributeGate)> { - KNOWN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect() + BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect() } // Attributes that have a special meaning to rustc or rustdoc -pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[ +pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGate)] = &[ // Normal attributes ("warn", Normal, Ungated), @@ -800,12 +800,12 @@ impl<'a> Context<'a> { fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) { debug!("check_attribute(attr = {:?})", attr); let name = &*attr.name(); - for &(n, ty, ref gateage) in KNOWN_ATTRIBUTES { + for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES { if n == name { if let &Gated(_, ref name, ref desc, ref has_feature) = gateage { gate_feature_fn!(self, has_feature, attr.span, name, desc); } - debug!("check_attribute: {:?} is known, {:?}, {:?}", name, ty, gateage); + debug!("check_attribute: {:?} is builtin, {:?}, {:?}", name, ty, gateage); return; } } @@ -825,6 +825,8 @@ impl<'a> Context<'a> { are reserved for internal compiler diagnostics"); } else if name.starts_with("derive_") { gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE); + } else if attr::is_known(attr) { + debug!("check_attribute: {:?} is known", name); } else { // Only run the custom attribute lint during regular // feature gate checking. Macro gating runs |
