Skip to content

Commit 64f867a

Browse files
committed
Serialize additional data for procedural macros
Split off from #62855 This PR deerializes the declaration `Span` and attributes for all procedural macros from their underlying function definitions. This allows Rustdoc to properly render doc comments and source links when inlining procedural macros across crates
1 parent ac60ca0 commit 64f867a

17 files changed

+240
-210
lines changed

src/libproc_macro/bridge/client.rs

+8
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,14 @@ pub enum ProcMacro {
468468
}
469469

470470
impl ProcMacro {
471+
pub fn name(&self) -> &'static str {
472+
match self {
473+
ProcMacro::CustomDerive { trait_name, .. } => trait_name,
474+
ProcMacro::Attr { name, .. } => name,
475+
ProcMacro::Bang { name, ..} => name
476+
}
477+
}
478+
471479
pub const fn custom_derive(
472480
trait_name: &'static str,
473481
attributes: &'static [&'static str],

src/librustc/hir/def_id.rs

-26
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::ty::{self, TyCtxt};
2-
use crate::hir::map::definitions::FIRST_FREE_DEF_INDEX;
32
use rustc_data_structures::indexed_vec::Idx;
43
use std::fmt;
54
use std::u32;
@@ -102,31 +101,6 @@ newtype_index! {
102101
}
103102
}
104103

105-
impl DefIndex {
106-
// Proc macros from a proc-macro crate have a kind of virtual DefIndex. This
107-
// function maps the index of the macro within the crate (which is also the
108-
// index of the macro in the CrateMetadata::proc_macros array) to the
109-
// corresponding DefIndex.
110-
pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
111-
// DefIndex for proc macros start from FIRST_FREE_DEF_INDEX,
112-
// because the first FIRST_FREE_DEF_INDEX indexes are reserved
113-
// for internal use.
114-
let def_index = DefIndex::from(
115-
proc_macro_index.checked_add(FIRST_FREE_DEF_INDEX)
116-
.expect("integer overflow adding `proc_macro_index`"));
117-
assert!(def_index != CRATE_DEF_INDEX);
118-
def_index
119-
}
120-
121-
// This function is the reverse of from_proc_macro_index() above.
122-
pub fn to_proc_macro_index(self: DefIndex) -> usize {
123-
self.index().checked_sub(FIRST_FREE_DEF_INDEX)
124-
.unwrap_or_else(|| {
125-
bug!("using local index {:?} as proc-macro index", self)
126-
})
127-
}
128-
}
129-
130104
impl rustc_serialize::UseSpecializedEncodable for DefIndex {}
131105
impl rustc_serialize::UseSpecializedDecodable for DefIndex {}
132106

src/librustc/hir/map/definitions.rs

-19
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,6 @@ impl Definitions {
411411
}
412412

413413
/// Adds a root definition (no parent) and a few other reserved definitions.
414-
///
415-
/// After the initial definitions are created the first `FIRST_FREE_DEF_INDEX` indexes
416-
/// are taken, so the "user" indexes will be allocated starting with `FIRST_FREE_DEF_INDEX`
417-
/// in ascending order.
418414
pub fn create_root_def(&mut self,
419415
crate_name: &str,
420416
crate_disambiguator: CrateDisambiguator)
@@ -589,19 +585,6 @@ impl DefPathData {
589585
}
590586
}
591587

592-
/// Evaluates to the number of tokens passed to it.
593-
///
594-
/// Logarithmic counting: every one or two recursive expansions, the number of
595-
/// tokens to count is divided by two, instead of being reduced by one.
596-
/// Therefore, the recursion depth is the binary logarithm of the number of
597-
/// tokens to count, and the expanded tree is likewise very small.
598-
macro_rules! count {
599-
() => (0usize);
600-
($one:tt) => (1usize);
601-
($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize);
602-
($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize);
603-
}
604-
605588
// We define the GlobalMetaDataKind enum with this macro because we want to
606589
// make sure that we exhaustively iterate over all variants when registering
607590
// the corresponding DefIndices in the DefTable.
@@ -614,8 +597,6 @@ macro_rules! define_global_metadata_kind {
614597
$($variant),*
615598
}
616599

617-
pub const FIRST_FREE_DEF_INDEX: usize = 1 + count!($($variant)*);
618-
619600
impl GlobalMetaDataKind {
620601
fn allocate_def_indices(definitions: &mut Definitions) {
621602
$({

src/librustc_metadata/creader.rs

+25-64
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
33
use crate::cstore::{self, CStore, CrateSource, MetadataBlob};
44
use crate::locator::{self, CratePaths};
5-
use crate::decoder::proc_macro_def_path_table;
6-
use crate::schema::CrateRoot;
5+
use crate::schema::{CrateRoot};
76
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
87

98
use rustc::hir::def_id::CrateNum;
@@ -26,11 +25,11 @@ use std::{cmp, fs};
2625
use syntax::ast;
2726
use syntax::attr;
2827
use syntax::ext::allocator::{global_allocator_spans, AllocatorKind};
29-
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
3028
use syntax::symbol::{Symbol, sym};
3129
use syntax::{span_err, span_fatal};
3230
use syntax_pos::{Span, DUMMY_SP};
3331
use log::{debug, info, log_enabled};
32+
use proc_macro::bridge::client::ProcMacro;
3433

3534
pub struct Library {
3635
pub dylib: Option<(PathBuf, PathKind)>,
@@ -230,24 +229,13 @@ impl<'a> CrateLoader<'a> {
230229

231230
let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
232231

233-
let proc_macros = crate_root.proc_macro_decls_static.map(|_| {
232+
let raw_proc_macros = crate_root.proc_macro_data.map(|_| {
234233
if self.sess.opts.debugging_opts.dual_proc_macros {
235-
let host_lib = host_lib.unwrap();
236-
self.load_derive_macros(
237-
&host_lib.metadata.get_root(),
238-
host_lib.dylib.map(|p| p.0),
239-
span
240-
)
234+
let host_lib = host_lib.as_ref().unwrap();
235+
self.dlsym_proc_macros(host_lib.dylib.as_ref().map(|p| p.0.clone()),
236+
&host_lib.metadata.get_root(), span)
241237
} else {
242-
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
243-
}
244-
});
245-
246-
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
247-
if let Some(proc_macros) = &proc_macros {
248-
proc_macro_def_path_table(&crate_root, proc_macros)
249-
} else {
250-
crate_root.def_path_table.decode((&metadata, self.sess))
238+
self.dlsym_proc_macros(dylib.clone().map(|p| p.0), &crate_root, span)
251239
}
252240
});
253241

@@ -260,13 +248,16 @@ impl<'a> CrateLoader<'a> {
260248
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
261249
.collect();
262250

251+
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
252+
crate_root.def_path_table.decode((&metadata, self.sess))
253+
});
254+
263255
let cmeta = cstore::CrateMetadata {
264256
name: crate_root.name,
265257
imported_name: ident,
266258
extern_crate: Lock::new(None),
267259
def_path_table: Lrc::new(def_path_table),
268260
trait_impls,
269-
proc_macros,
270261
root: crate_root,
271262
blob: metadata,
272263
cnum_map,
@@ -280,7 +271,10 @@ impl<'a> CrateLoader<'a> {
280271
rlib,
281272
rmeta,
282273
},
283-
private_dep
274+
private_dep,
275+
span,
276+
host_lib,
277+
raw_proc_macros
284278
};
285279

286280
let cmeta = Lrc::new(cmeta);
@@ -389,7 +383,7 @@ impl<'a> CrateLoader<'a> {
389383
match result {
390384
(LoadResult::Previous(cnum), None) => {
391385
let data = self.cstore.get_crate_data(cnum);
392-
if data.root.proc_macro_decls_static.is_some() {
386+
if data.root.proc_macro_data.is_some() {
393387
dep_kind = DepKind::UnexportedMacrosOnly;
394388
}
395389
data.dep_kind.with_lock(|data_dep_kind| {
@@ -482,7 +476,7 @@ impl<'a> CrateLoader<'a> {
482476
dep_kind: DepKind)
483477
-> cstore::CrateNumMap {
484478
debug!("resolving deps of external crate");
485-
if crate_root.proc_macro_decls_static.is_some() {
479+
if crate_root.proc_macro_data.is_some() {
486480
return cstore::CrateNumMap::new();
487481
}
488482

@@ -574,19 +568,13 @@ impl<'a> CrateLoader<'a> {
574568
}
575569
}
576570

577-
/// Loads custom derive macros.
578-
///
579-
/// Note that this is intentionally similar to how we load plugins today,
580-
/// but also intentionally separate. Plugins are likely always going to be
581-
/// implemented as dynamic libraries, but we have a possible future where
582-
/// custom derive (and other macro-1.1 style features) are implemented via
583-
/// executables and custom IPC.
584-
fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, span: Span)
585-
-> Vec<(ast::Name, Lrc<SyntaxExtension>)> {
586-
use std::{env, mem};
571+
fn dlsym_proc_macros(&self,
572+
dylib: Option<PathBuf>,
573+
root: &CrateRoot<'_>,
574+
span: Span
575+
) -> &'static [ProcMacro] {
576+
use std::env;
587577
use crate::dynamic_lib::DynamicLibrary;
588-
use proc_macro::bridge::client::ProcMacro;
589-
use syntax::ext::proc_macro::{BangProcMacro, AttrProcMacro, ProcMacroDerive};
590578

591579
let path = match dylib {
592580
Some(dylib) => dylib,
@@ -608,38 +596,11 @@ impl<'a> CrateLoader<'a> {
608596
*(sym as *const &[ProcMacro])
609597
};
610598

611-
let extensions = decls.iter().map(|&decl| {
612-
let (name, kind, helper_attrs) = match decl {
613-
ProcMacro::CustomDerive { trait_name, attributes, client } => {
614-
let helper_attrs =
615-
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
616-
(
617-
trait_name,
618-
SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
619-
client, attrs: helper_attrs.clone()
620-
})),
621-
helper_attrs,
622-
)
623-
}
624-
ProcMacro::Attr { name, client } => (
625-
name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
626-
),
627-
ProcMacro::Bang { name, client } => (
628-
name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
629-
)
630-
};
631-
632-
(Symbol::intern(name), Lrc::new(SyntaxExtension {
633-
helper_attrs,
634-
..SyntaxExtension::default(kind, root.edition)
635-
}))
636-
}).collect();
637-
638599
// Intentionally leak the dynamic library. We can't ever unload it
639600
// since the library can make things that will live arbitrarily long.
640-
mem::forget(lib);
601+
std::mem::forget(lib);
641602

642-
extensions
603+
decls
643604
}
644605

645606
/// Look for a plugin registrar. Returns library path, crate

src/librustc_metadata/cstore.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub use crate::cstore_impl::{provide, provide_extern};
2828
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
2929

3030
pub use rustc_data_structures::sync::MetadataRef;
31+
use crate::creader::Library;
32+
use syntax_pos::Span;
33+
use proc_macro::bridge::client::ProcMacro;
3134

3235
pub struct MetadataBlob(pub MetadataRef);
3336

@@ -82,11 +85,19 @@ pub struct CrateMetadata {
8285
pub dep_kind: Lock<DepKind>,
8386
pub source: CrateSource,
8487

85-
pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
86-
8788
/// Whether or not this crate should be consider a private dependency
8889
/// for purposes of the 'exported_private_dependencies' lint
89-
pub private_dep: bool
90+
pub private_dep: bool,
91+
92+
pub host_lib: Option<Library>,
93+
pub span: Span,
94+
95+
pub raw_proc_macros: Option<&'static [ProcMacro]>,
96+
}
97+
98+
pub struct FullProcMacro {
99+
pub name: ast::Name,
100+
pub ext: Lrc<SyntaxExtension>
90101
}
91102

92103
pub struct CStore {

src/librustc_metadata/cstore_impl.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,8 @@ impl cstore::CStore {
426426

427427
pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
428428
let data = self.get_crate_data(id.krate);
429-
if let Some(ref proc_macros) = data.proc_macros {
430-
return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
429+
if data.is_proc_macro_crate() {
430+
return LoadedMacro::ProcMacro(data.get_proc_macro(id.index, sess).ext);
431431
} else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote {
432432
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
433433
let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }));
@@ -439,7 +439,8 @@ impl cstore::CStore {
439439
}
440440

441441
let def = data.get_macro(id.index);
442-
let macro_full_name = data.def_path(id.index).to_string_friendly(|_| data.imported_name);
442+
let macro_full_name = data.def_path(id.index)
443+
.to_string_friendly(|_| data.imported_name);
443444
let source_name = FileName::Macros(macro_full_name);
444445

445446
let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);

0 commit comments

Comments
 (0)