Skip to content

Commit 52c62ea

Browse files
committed
Respect attributes on proc macro definitions
1 parent 32e5acb commit 52c62ea

File tree

6 files changed

+131
-67
lines changed

6 files changed

+131
-67
lines changed

src/librustc_metadata/decoder.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,6 @@ impl<'a, 'tcx> CrateMetadata {
530530
id: DefIndex,
531531
sess: &Session)
532532
-> FullProcMacro {
533-
534533
let raw_macro = self.raw_proc_macro(id);
535534
let (name, kind, helper_attrs) = match *raw_macro {
536535
ProcMacro::CustomDerive { trait_name, attributes, client } => {
@@ -551,16 +550,19 @@ impl<'a, 'tcx> CrateMetadata {
551550
name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
552551
)
553552
};
554-
555-
let span = self.get_span(id, sess);
553+
let name = Symbol::intern(name);
556554

557555
FullProcMacro {
558-
name: Symbol::intern(name),
559-
ext: Lrc::new(SyntaxExtension {
560-
span,
556+
name,
557+
ext: Lrc::new(SyntaxExtension::new(
558+
&sess.parse_sess,
559+
kind,
560+
self.get_span(id, sess),
561561
helper_attrs,
562-
..SyntaxExtension::default(kind, root.edition)
563-
})
562+
root.edition,
563+
name,
564+
&self.get_attributes(&self.entry(id), sess),
565+
)),
564566
}
565567
}
566568

src/libsyntax/ext/base.rs

+65-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use crate::ast::{self, NodeId, Attribute, Name, PatKind};
2-
use crate::attr::{HasAttrs, Stability, Deprecation};
2+
use crate::attr::{self, HasAttrs, Stability, Deprecation};
33
use crate::source_map::SourceMap;
44
use crate::edition::Edition;
55
use crate::ext::expand::{self, AstFragment, Invocation};
66
use crate::ext::hygiene::{ExpnId, Transparency};
77
use crate::mut_visit::{self, MutVisitor};
8-
use crate::parse::{self, parser, DirectoryOwnership};
8+
use crate::parse::{self, parser, ParseSess, DirectoryOwnership};
99
use crate::parse::token;
1010
use crate::ptr::P;
1111
use crate::symbol::{kw, sym, Ident, Symbol};
@@ -601,6 +601,69 @@ impl SyntaxExtension {
601601
}
602602
}
603603

604+
/// Constructs a syntax extension with the given properties
605+
/// and other properties converted from attributes.
606+
pub fn new(
607+
sess: &ParseSess,
608+
kind: SyntaxExtensionKind,
609+
span: Span,
610+
helper_attrs: Vec<Symbol>,
611+
edition: Edition,
612+
name: Name,
613+
attrs: &[ast::Attribute],
614+
) -> SyntaxExtension {
615+
let allow_internal_unstable =
616+
attr::find_by_name(attrs, sym::allow_internal_unstable).map(|attr| {
617+
attr.meta_item_list()
618+
.map(|list| {
619+
list.iter()
620+
.filter_map(|it| {
621+
let name = it.ident().map(|ident| ident.name);
622+
if name.is_none() {
623+
sess.span_diagnostic.span_err(
624+
it.span(), "allow internal unstable expects feature names"
625+
)
626+
}
627+
name
628+
})
629+
.collect::<Vec<Symbol>>()
630+
.into()
631+
})
632+
.unwrap_or_else(|| {
633+
sess.span_diagnostic.span_warn(
634+
attr.span,
635+
"allow_internal_unstable expects list of feature names. In the future \
636+
this will become a hard error. Please use `allow_internal_unstable(\
637+
foo, bar)` to only allow the `foo` and `bar` features",
638+
);
639+
vec![sym::allow_internal_unstable_backcompat_hack].into()
640+
})
641+
});
642+
643+
let mut local_inner_macros = false;
644+
if let Some(macro_export) = attr::find_by_name(attrs, sym::macro_export) {
645+
if let Some(l) = macro_export.meta_item_list() {
646+
local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
647+
}
648+
}
649+
650+
let is_builtin = attr::contains_name(attrs, sym::rustc_builtin_macro);
651+
652+
SyntaxExtension {
653+
kind,
654+
span,
655+
allow_internal_unstable,
656+
allow_internal_unsafe: attr::contains_name(attrs, sym::allow_internal_unsafe),
657+
local_inner_macros,
658+
stability: attr::find_stability(&sess, attrs, span),
659+
deprecation: attr::find_deprecation(&sess, attrs, span),
660+
helper_attrs,
661+
edition,
662+
is_builtin,
663+
is_derive_copy: is_builtin && name == sym::Copy,
664+
}
665+
}
666+
604667
pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
605668
fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree])
606669
-> Box<dyn MacResult + 'cx> {

src/libsyntax/ext/tt/macro_rules.rs

+13-57
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::ast;
2+
use crate::attr::{self, TransparencyError};
13
use crate::edition::Edition;
24
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
35
use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
@@ -15,7 +17,6 @@ use crate::parse::token::{self, NtTT, Token};
1517
use crate::parse::{Directory, ParseSess};
1618
use crate::symbol::{kw, sym, Symbol};
1719
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
18-
use crate::{ast, attr, attr::TransparencyError};
1920

2021
use errors::{DiagnosticBuilder, FatalError};
2122
use log::debug;
@@ -290,6 +291,7 @@ pub fn compile(
290291
def: &ast::Item,
291292
edition: Edition,
292293
) -> SyntaxExtension {
294+
let diag = &sess.span_diagnostic;
293295
let lhs_nm = ast::Ident::new(sym::lhs, def.span);
294296
let rhs_nm = ast::Ident::new(sym::rhs, def.span);
295297
let tt_spec = ast::Ident::new(sym::tt, def.span);
@@ -423,71 +425,25 @@ pub fn compile(
423425
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, body.legacy);
424426
match transparency_error {
425427
Some(TransparencyError::UnknownTransparency(value, span)) =>
426-
sess.span_diagnostic.span_err(
427-
span, &format!("unknown macro transparency: `{}`", value)
428-
),
428+
diag.span_err(span, &format!("unknown macro transparency: `{}`", value)),
429429
Some(TransparencyError::MultipleTransparencyAttrs(old_span, new_span)) =>
430-
sess.span_diagnostic.span_err(
431-
vec![old_span, new_span], "multiple macro transparency attributes"
432-
),
430+
diag.span_err(vec![old_span, new_span], "multiple macro transparency attributes"),
433431
None => {}
434432
}
435433

436434
let expander: Box<_> = Box::new(MacroRulesMacroExpander {
437435
name: def.ident, span: def.span, transparency, lhses, rhses, valid
438436
});
439437

440-
let allow_internal_unstable =
441-
attr::find_by_name(&def.attrs, sym::allow_internal_unstable).map(|attr| {
442-
attr.meta_item_list()
443-
.map(|list| {
444-
list.iter()
445-
.filter_map(|it| {
446-
let name = it.ident().map(|ident| ident.name);
447-
if name.is_none() {
448-
sess.span_diagnostic.span_err(
449-
it.span(),
450-
"allow internal unstable expects feature names",
451-
)
452-
}
453-
name
454-
})
455-
.collect::<Vec<Symbol>>()
456-
.into()
457-
})
458-
.unwrap_or_else(|| {
459-
sess.span_diagnostic.span_warn(
460-
attr.span,
461-
"allow_internal_unstable expects list of feature names. In the \
462-
future this will become a hard error. Please use `allow_internal_unstable(\
463-
foo, bar)` to only allow the `foo` and `bar` features",
464-
);
465-
vec![sym::allow_internal_unstable_backcompat_hack].into()
466-
})
467-
});
468-
469-
let mut local_inner_macros = false;
470-
if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) {
471-
if let Some(l) = macro_export.meta_item_list() {
472-
local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
473-
}
474-
}
475-
476-
let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro);
477-
478-
SyntaxExtension {
479-
kind: SyntaxExtensionKind::LegacyBang(expander),
480-
span: def.span,
481-
allow_internal_unstable,
482-
allow_internal_unsafe: attr::contains_name(&def.attrs, sym::allow_internal_unsafe),
483-
local_inner_macros,
484-
stability: attr::find_stability(&sess, &def.attrs, def.span),
485-
deprecation: attr::find_deprecation(&sess, &def.attrs, def.span),
486-
helper_attrs: Vec::new(),
438+
SyntaxExtension::new(
439+
sess,
440+
SyntaxExtensionKind::LegacyBang(expander),
441+
def.span,
442+
Vec::new(),
487443
edition,
488-
is_builtin,
489-
is_derive_copy: is_builtin && def.ident.name == sym::Copy,
490-
}
444+
def.ident.name,
445+
&def.attrs,
446+
)
491447
}
492448

493449
fn check_lhs_nt_follows(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// check-pass
2+
// aux-build:attributes-on-definitions.rs
3+
4+
#![forbid(unsafe_code)]
5+
6+
extern crate attributes_on_definitions;
7+
8+
attributes_on_definitions::with_attrs!();
9+
//~^ WARN use of deprecated item
10+
// No errors about the use of unstable and unsafe code inside the macro.
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
warning: use of deprecated item 'attributes_on_definitions::with_attrs': test
2+
--> $DIR/attributes-on-definitions.rs:8:1
3+
|
4+
LL | attributes_on_definitions::with_attrs!();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(deprecated)]` on by default
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![feature(allow_internal_unsafe)]
5+
#![feature(allow_internal_unstable)]
6+
7+
#![crate_type = "proc-macro"]
8+
9+
extern crate proc_macro;
10+
use proc_macro::*;
11+
12+
#[proc_macro]
13+
#[allow_internal_unstable(proc_macro_internals)]
14+
#[allow_internal_unsafe]
15+
#[deprecated(since = "1.0.0", note = "test")]
16+
pub fn with_attrs(_: TokenStream) -> TokenStream {
17+
"
18+
extern crate proc_macro;
19+
use ::proc_macro::bridge;
20+
21+
fn contains_unsafe() { unsafe {} }
22+
".parse().unwrap()
23+
}

0 commit comments

Comments
 (0)