mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-18 09:53:26 +00:00
Respect attributes on proc macro definitions
This commit is contained in:
parent
32e5acb3eb
commit
52c62eaae4
@ -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),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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(
|
||||
|
12
src/test/ui/proc-macro/attributes-on-definitions.rs
Normal file
12
src/test/ui/proc-macro/attributes-on-definitions.rs
Normal file
@ -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() {}
|
8
src/test/ui/proc-macro/attributes-on-definitions.stderr
Normal file
8
src/test/ui/proc-macro/attributes-on-definitions.stderr
Normal file
@ -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
|
||||
|
@ -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()
|
||||
}
|
Loading…
Reference in New Issue
Block a user