Skip to content

Commit 0da7098

Browse files
authored
Rollup merge of rust-lang#63761 - petrochenkov:procattrs, r=eddyb
Propagate spans and attributes from proc macro definitions Thanks to rust-lang#63269 we now have spans and attributes from proc macro definitions available in metadata. However, that PR didn't actually put them into use! This PR finishes that work. Attributes `rustc_macro_transparency`, `allow_internal_unstable`, `allow_internal_unsafe`, `local_inner_macros`, `rustc_builtin_macro`, `stable`, `unstable`, `rustc_deprecated`, `deprecated` now have effect when applied to proc macro definition functions. From those attributes only `deprecated` is both stable and supposed to be used in new code. (`#![staged_api]` still cannot be used in proc macro crates for unrelated reasons though.) `Span::def_site` from the proc macro API now returns the correct location of the proc macro definition. Also, I made a mistake in rust-lang#63269 (comment), loaded proc macros didn't actually use the resolver cache. This PR fixes the caching issue, now proc macros go through the `Resolver::macro_map` cache as well. (Also, the first commit turns `proc_macro::quote` into a regular built-in macro to reduce the number of places where `SyntaxExtension`s need to be manually created.)
2 parents 68597c7 + c476b55 commit 0da7098

21 files changed

+318
-172
lines changed

src/libproc_macro/lib.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919

2020
#![feature(nll)]
2121
#![feature(staged_api)]
22+
#![feature(allow_internal_unstable)]
2223
#![feature(const_fn)]
24+
#![feature(decl_macro)]
2325
#![feature(extern_types)]
2426
#![feature(in_band_lifetimes)]
2527
#![feature(optin_builtin_traits)]
2628
#![feature(mem_take)]
2729
#![feature(non_exhaustive)]
30+
#![feature(rustc_attrs)]
2831
#![feature(specialization)]
2932

3033
#![recursion_limit="256"]
@@ -222,11 +225,10 @@ pub mod token_stream {
222225
///
223226
/// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
224227
/// To quote `$` itself, use `$$`.
225-
///
226-
/// This is a dummy macro, the actual implementation is in `quote::quote`.`
227228
#[unstable(feature = "proc_macro_quote", issue = "54722")]
228-
#[macro_export]
229-
macro_rules! quote { () => {} }
229+
#[allow_internal_unstable(proc_macro_def_site)]
230+
#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
231+
pub macro quote ($($t:tt)*) { /* compiler built-in */ }
230232

231233
#[unstable(feature = "proc_macro_internals", issue = "27812")]
232234
#[doc(hidden)]

src/libproc_macro/quote.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ macro_rules! quote {
5757
}
5858

5959
/// Quote a `TokenStream` into a `TokenStream`.
60-
/// This is the actual `quote!()` proc macro.
60+
/// This is the actual implementation of the `quote!()` proc macro.
6161
///
62-
/// It is manually loaded in `CStore::load_macro_untracked`.
62+
/// It is loaded by the compiler in `register_builtin_macros`.
6363
#[unstable(feature = "proc_macro_quote", issue = "54722")]
6464
pub fn quote(stream: TokenStream) -> TokenStream {
6565
if stream.is_empty() {

src/librustc_metadata/cstore.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,6 @@ pub struct CrateMetadata {
9595
pub raw_proc_macros: Option<&'static [ProcMacro]>,
9696
}
9797

98-
pub struct FullProcMacro {
99-
pub name: ast::Name,
100-
pub ext: Lrc<SyntaxExtension>
101-
}
102-
10398
pub struct CStore {
10499
metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
105100
/// Map from NodeId's of local extern crate statements to crate numbers
@@ -109,7 +104,7 @@ pub struct CStore {
109104

110105
pub enum LoadedMacro {
111106
MacroDef(ast::Item),
112-
ProcMacro(Lrc<SyntaxExtension>),
107+
ProcMacro(SyntaxExtension),
113108
}
114109

115110
impl CStore {

src/librustc_metadata/cstore_impl.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ use syntax::ast;
3030
use syntax::attr;
3131
use syntax::source_map;
3232
use syntax::edition::Edition;
33-
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
34-
use syntax::ext::proc_macro::BangProcMacro;
3533
use syntax::parse::source_file_to_stream;
3634
use syntax::parse::parser::emit_unclosed_delims;
37-
use syntax::symbol::{Symbol, sym};
35+
use syntax::symbol::Symbol;
3836
use syntax_pos::{Span, FileName};
3937
use rustc_data_structures::bit_set::BitSet;
4038

@@ -436,15 +434,7 @@ impl cstore::CStore {
436434
pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
437435
let data = self.get_crate_data(id.krate);
438436
if data.is_proc_macro_crate() {
439-
return LoadedMacro::ProcMacro(data.get_proc_macro(id.index, sess).ext);
440-
} else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote {
441-
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
442-
let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }));
443-
let ext = SyntaxExtension {
444-
allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()),
445-
..SyntaxExtension::default(kind, data.root.edition)
446-
};
447-
return LoadedMacro::ProcMacro(Lrc::new(ext));
437+
return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess));
448438
}
449439

450440
let def = data.get_macro(id.index);

src/librustc_metadata/decoder.rs

+17-32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Decoding metadata from a single crate's metadata
22

3-
use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro};
3+
use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
44
use crate::schema::*;
55

66
use rustc_data_structures::indexed_vec::IndexVec;
@@ -512,27 +512,8 @@ impl<'a, 'tcx> CrateMetadata {
512512
self.entry(index).span.decode((self, sess))
513513
}
514514

515-
516-
pub fn get_proc_macro(&self, id: DefIndex, sess: &Session) -> FullProcMacro {
517-
if sess.opts.debugging_opts.dual_proc_macros {
518-
let host_lib = self.host_lib.as_ref().unwrap();
519-
self.load_proc_macro(
520-
&host_lib.metadata.get_root(),
521-
id,
522-
sess
523-
)
524-
} else {
525-
self.load_proc_macro(&self.root, id, sess)
526-
}
527-
}
528-
529-
fn load_proc_macro(&self, root: &CrateRoot<'_>,
530-
id: DefIndex,
531-
sess: &Session)
532-
-> FullProcMacro {
533-
534-
let raw_macro = self.raw_proc_macro(id);
535-
let (name, kind, helper_attrs) = match *raw_macro {
515+
crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
516+
let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) {
536517
ProcMacro::CustomDerive { trait_name, attributes, client } => {
537518
let helper_attrs =
538519
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
@@ -551,17 +532,21 @@ impl<'a, 'tcx> CrateMetadata {
551532
name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
552533
)
553534
};
535+
let edition = if sess.opts.debugging_opts.dual_proc_macros {
536+
self.host_lib.as_ref().unwrap().metadata.get_root().edition
537+
} else {
538+
self.root.edition
539+
};
554540

555-
let span = self.get_span(id, sess);
556-
557-
FullProcMacro {
558-
name: Symbol::intern(name),
559-
ext: Lrc::new(SyntaxExtension {
560-
span,
561-
helper_attrs,
562-
..SyntaxExtension::default(kind, root.edition)
563-
})
564-
}
541+
SyntaxExtension::new(
542+
&sess.parse_sess,
543+
kind,
544+
self.get_span(id, sess),
545+
helper_attrs,
546+
edition,
547+
Symbol::intern(name),
548+
&self.get_attributes(&self.entry(id), sess),
549+
)
565550
}
566551

567552
pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {

src/librustc_resolve/build_reduced_graph.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,12 @@ impl<'a> Resolver<'a> {
150150
return Some(ext.clone());
151151
}
152152

153-
let macro_def = match self.cstore.load_macro_untracked(def_id, &self.session) {
154-
LoadedMacro::MacroDef(macro_def) => macro_def,
155-
LoadedMacro::ProcMacro(ext) => return Some(ext),
156-
};
153+
let ext = Lrc::new(match self.cstore.load_macro_untracked(def_id, &self.session) {
154+
LoadedMacro::MacroDef(item) =>
155+
self.compile_macro(&item, self.cstore.crate_edition_untracked(def_id.krate)),
156+
LoadedMacro::ProcMacro(ext) => ext,
157+
});
157158

158-
let ext = self.compile_macro(&macro_def, self.cstore.crate_edition_untracked(def_id.krate));
159159
self.macro_map.insert(def_id, ext.clone());
160160
Some(ext)
161161
}
@@ -1104,7 +1104,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
11041104
let expansion = parent_scope.expansion;
11051105
let (ext, ident, span, is_legacy) = match &item.node {
11061106
ItemKind::MacroDef(def) => {
1107-
let ext = self.r.compile_macro(item, self.r.session.edition());
1107+
let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition()));
11081108
(ext, item.ident, item.span, def.legacy)
11091109
}
11101110
ItemKind::Fn(..) => match Self::proc_macro_stub(item) {

src/librustc_resolve/macros.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ impl<'a> Resolver<'a> {
800800

801801
/// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined
802802
/// extension partially or entirely for built-in macros and legacy plugin macros.
803-
crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> Lrc<SyntaxExtension> {
803+
crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension {
804804
let mut result = macro_rules::compile(
805805
&self.session.parse_sess, self.session.features_untracked(), item, edition
806806
);
@@ -822,6 +822,6 @@ impl<'a> Resolver<'a> {
822822
}
823823
}
824824

825-
Lrc::new(result)
825+
result
826826
}
827827
}

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/proc_macro_server.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,11 @@ pub(crate) struct Rustc<'a> {
360360

361361
impl<'a> Rustc<'a> {
362362
pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
363-
// No way to determine def location for a proc macro right now, so use call location.
364-
let location = cx.current_expansion.id.expn_data().call_site;
363+
let expn_data = cx.current_expansion.id.expn_data();
365364
Rustc {
366365
sess: cx.parse_sess,
367-
def_site: cx.with_def_site_ctxt(location),
368-
call_site: cx.with_call_site_ctxt(location),
366+
def_site: cx.with_def_site_ctxt(expn_data.def_site),
367+
call_site: cx.with_call_site_ctxt(expn_data.call_site),
369368
}
370369
}
371370

0 commit comments

Comments
 (0)