diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-08-20 21:22:32 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-08-27 01:33:13 +0300 |
| commit | 52c62eaae42ebc0efe370848a142c2858ac7fffc (patch) | |
| tree | bcbe3ea27cda012be261e4355ef0b3bff40b2050 | |
| parent | 32e5acb3eba7a92029488b9684d7bb27bc716294 (diff) | |
| download | rust-52c62eaae42ebc0efe370848a142c2858ac7fffc.tar.gz rust-52c62eaae42ebc0efe370848a142c2858ac7fffc.zip | |
Respect attributes on proc macro definitions
| -rw-r--r-- | src/librustc_metadata/decoder.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax/ext/base.rs | 67 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 70 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/attributes-on-definitions.rs | 12 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/attributes-on-definitions.stderr | 8 | ||||
| -rw-r--r-- | src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs | 23 |
6 files changed, 131 insertions, 67 deletions
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5b9cb966af2..fffeee82d8d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -530,7 +530,6 @@ impl<'a, 'tcx> CrateMetadata { id: DefIndex, sess: &Session) -> FullProcMacro { - let raw_macro = self.raw_proc_macro(id); let (name, kind, helper_attrs) = match *raw_macro { ProcMacro::CustomDerive { trait_name, attributes, client } => { @@ -551,16 +550,19 @@ impl<'a, 'tcx> CrateMetadata { name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() ) }; - - let span = self.get_span(id, sess); + let name = Symbol::intern(name); FullProcMacro { - name: Symbol::intern(name), - ext: Lrc::new(SyntaxExtension { - span, + name, + ext: Lrc::new(SyntaxExtension::new( + &sess.parse_sess, + kind, + self.get_span(id, sess), helper_attrs, - ..SyntaxExtension::default(kind, root.edition) - }) + root.edition, + name, + &self.get_attributes(&self.entry(id), sess), + )), } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a63c4181d5e..10ff1b17285 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,11 +1,11 @@ use crate::ast::{self, NodeId, Attribute, Name, PatKind}; -use crate::attr::{HasAttrs, Stability, Deprecation}; +use crate::attr::{self, HasAttrs, Stability, Deprecation}; use crate::source_map::SourceMap; use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; use crate::ext::hygiene::{ExpnId, Transparency}; use crate::mut_visit::{self, MutVisitor}; -use crate::parse::{self, parser, DirectoryOwnership}; +use crate::parse::{self, parser, ParseSess, DirectoryOwnership}; use crate::parse::token; use crate::ptr::P; use crate::symbol::{kw, sym, Ident, Symbol}; @@ -601,6 +601,69 @@ impl SyntaxExtension { } } + /// Constructs a syntax extension with the given properties + /// and other properties converted from attributes. + pub fn new( + sess: &ParseSess, + kind: SyntaxExtensionKind, + span: Span, + helper_attrs: Vec<Symbol>, + edition: Edition, + name: Name, + attrs: &[ast::Attribute], + ) -> SyntaxExtension { + let allow_internal_unstable = + attr::find_by_name(attrs, sym::allow_internal_unstable).map(|attr| { + attr.meta_item_list() + .map(|list| { + list.iter() + .filter_map(|it| { + let name = it.ident().map(|ident| ident.name); + if name.is_none() { + sess.span_diagnostic.span_err( + it.span(), "allow internal unstable expects feature names" + ) + } + name + }) + .collect::<Vec<Symbol>>() + .into() + }) + .unwrap_or_else(|| { + sess.span_diagnostic.span_warn( + attr.span, + "allow_internal_unstable expects list of feature names. In the future \ + this will become a hard error. Please use `allow_internal_unstable(\ + foo, bar)` to only allow the `foo` and `bar` features", + ); + vec![sym::allow_internal_unstable_backcompat_hack].into() + }) + }); + + let mut local_inner_macros = false; + if let Some(macro_export) = attr::find_by_name(attrs, sym::macro_export) { + if let Some(l) = macro_export.meta_item_list() { + local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); + } + } + + let is_builtin = attr::contains_name(attrs, sym::rustc_builtin_macro); + + SyntaxExtension { + kind, + span, + allow_internal_unstable, + allow_internal_unsafe: attr::contains_name(attrs, sym::allow_internal_unsafe), + local_inner_macros, + stability: attr::find_stability(&sess, attrs, span), + deprecation: attr::find_deprecation(&sess, attrs, span), + helper_attrs, + edition, + is_builtin, + is_derive_copy: is_builtin && name == sym::Copy, + } + } + pub fn dummy_bang(edition: Edition) -> SyntaxExtension { fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree]) -> Box<dyn MacResult + 'cx> { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 37cb8467ff5..46ffa52f7f5 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1,3 +1,5 @@ +use crate::ast; +use crate::attr::{self, TransparencyError}; use crate::edition::Edition; use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; @@ -15,7 +17,6 @@ use crate::parse::token::{self, NtTT, Token}; use crate::parse::{Directory, ParseSess}; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; -use crate::{ast, attr, attr::TransparencyError}; use errors::{DiagnosticBuilder, FatalError}; use log::debug; @@ -290,6 +291,7 @@ pub fn compile( def: &ast::Item, edition: Edition, ) -> SyntaxExtension { + let diag = &sess.span_diagnostic; let lhs_nm = ast::Ident::new(sym::lhs, def.span); let rhs_nm = ast::Ident::new(sym::rhs, def.span); let tt_spec = ast::Ident::new(sym::tt, def.span); @@ -423,13 +425,9 @@ pub fn compile( let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => - sess.span_diagnostic.span_err( - span, &format!("unknown macro transparency: `{}`", value) - ), + diag.span_err(span, &format!("unknown macro transparency: `{}`", value)), Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) => - sess.span_diagnostic.span_err( - vec![old_span, new_span], "multiple macro transparency attributes" - ), + diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"), None => {} } @@ -437,57 +435,15 @@ pub fn compile( name: def.ident, span: def.span, transparency, lhses, rhses, valid }); - let allow_internal_unstable = - attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| { - attr.meta_item_list() - .map(|list| { - list.iter() - .filter_map(|it| { - let name = it.ident().map(|ident| ident.name); - if name.is_none() { - sess.span_diagnostic.span_err( - it.span(), - "allow internal unstable expects feature names", - ) - } - name - }) - .collect::<Vec<Symbol>>() - .into() - }) - .unwrap_or_else(|| { - sess.span_diagnostic.span_warn( - attr.span, - "allow_internal_unstable expects list of feature names. In the \ - future this will become a hard error. Please use `allow_internal_unstable(\ - foo, bar)` to only allow the `foo` and `bar` features", - ); - vec![sym::allow_internal_unstable_backcompat_hack].into() - }) - }); - - let mut local_inner_macros = false; - if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) { - if let Some(l) = macro_export.meta_item_list() { - local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros); - } - } - - let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro); - - SyntaxExtension { - kind: SyntaxExtensionKind::LegacyBang(expander), - span: def.span, - allow_internal_unstable, - allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe), - local_inner_macros, - stability: attr::find_stability(&sess, &def.attrs, def.span), - deprecation: attr::find_deprecation(&sess, &def.attrs, def.span), - helper_attrs: Vec::new(), + SyntaxExtension::new( + sess, + SyntaxExtensionKind::LegacyBang(expander), + def.span, + Vec::new(), edition, - is_builtin, - is_derive_copy: is_builtin && def.ident.name == sym::Copy, - } + def.ident.name, + &def.attrs, + ) } fn check_lhs_nt_follows( diff --git a/src/test/ui/proc-macro/attributes-on-definitions.rs b/src/test/ui/proc-macro/attributes-on-definitions.rs new file mode 100644 index 00000000000..055781d2c60 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.rs @@ -0,0 +1,12 @@ +// check-pass +// aux-build:attributes-on-definitions.rs + +#![forbid(unsafe_code)] + +extern crate attributes_on_definitions; + +attributes_on_definitions::with_attrs!(); +//~^ WARN use of deprecated item +// No errors about the use of unstable and unsafe code inside the macro. + +fn main() {} diff --git a/src/test/ui/proc-macro/attributes-on-definitions.stderr b/src/test/ui/proc-macro/attributes-on-definitions.stderr new file mode 100644 index 00000000000..c61e043b229 --- /dev/null +++ b/src/test/ui/proc-macro/attributes-on-definitions.stderr @@ -0,0 +1,8 @@ +warning: use of deprecated item 'attributes_on_definitions::with_attrs': test + --> $DIR/attributes-on-definitions.rs:8:1 + | +LL | attributes_on_definitions::with_attrs!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + diff --git a/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs new file mode 100644 index 00000000000..93a339840d6 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/attributes-on-definitions.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![feature(allow_internal_unsafe)] +#![feature(allow_internal_unstable)] + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +#[allow_internal_unstable(proc_macro_internals)] +#[allow_internal_unsafe] +#[deprecated(since = "1.0.0", note = "test")] +pub fn with_attrs(_: TokenStream) -> TokenStream { + " + extern crate proc_macro; + use ::proc_macro::bridge; + + fn contains_unsafe() { unsafe {} } + ".parse().unwrap() +} |
