Auto merge of #63269 - Aaron1011:feature/proc-macro-data, r=eddyb,petrochenkov

Serialize additional data for procedural macros

Split off from #62855

This PR serializes the declaration `Span` and attributes for all
procedural macros. This allows Rustdoc to properly render doc comments
and source links when performing inlinig procedural macros across crates
This commit is contained in:
bors 2019-08-18 08:15:38 +00:00
commit 71e2882973
17 changed files with 240 additions and 210 deletions

View File

@ -468,6 +468,14 @@ pub enum ProcMacro {
}
impl ProcMacro {
pub fn name(&self) -> &'static str {
match self {
ProcMacro::CustomDerive { trait_name, .. } => trait_name,
ProcMacro::Attr { name, .. } => name,
ProcMacro::Bang { name, ..} => name
}
}
pub const fn custom_derive(
trait_name: &'static str,
attributes: &'static [&'static str],

View File

@ -1,5 +1,4 @@
use crate::ty::{self, TyCtxt};
use crate::hir::map::definitions::FIRST_FREE_DEF_INDEX;
use rustc_data_structures::indexed_vec::Idx;
use std::fmt;
use std::u32;
@ -102,31 +101,6 @@ newtype_index! {
}
}
impl DefIndex {
// Proc macros from a proc-macro crate have a kind of virtual DefIndex. This
// function maps the index of the macro within the crate (which is also the
// index of the macro in the CrateMetadata::proc_macros array) to the
// corresponding DefIndex.
pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
// DefIndex for proc macros start from FIRST_FREE_DEF_INDEX,
// because the first FIRST_FREE_DEF_INDEX indexes are reserved
// for internal use.
let def_index = DefIndex::from(
proc_macro_index.checked_add(FIRST_FREE_DEF_INDEX)
.expect("integer overflow adding `proc_macro_index`"));
assert!(def_index != CRATE_DEF_INDEX);
def_index
}
// This function is the reverse of from_proc_macro_index() above.
pub fn to_proc_macro_index(self: DefIndex) -> usize {
self.index().checked_sub(FIRST_FREE_DEF_INDEX)
.unwrap_or_else(|| {
bug!("using local index {:?} as proc-macro index", self)
})
}
}
impl rustc_serialize::UseSpecializedEncodable for DefIndex {}
impl rustc_serialize::UseSpecializedDecodable for DefIndex {}

View File

@ -411,10 +411,6 @@ impl Definitions {
}
/// Adds a root definition (no parent) and a few other reserved definitions.
///
/// After the initial definitions are created the first `FIRST_FREE_DEF_INDEX` indexes
/// are taken, so the "user" indexes will be allocated starting with `FIRST_FREE_DEF_INDEX`
/// in ascending order.
pub fn create_root_def(&mut self,
crate_name: &str,
crate_disambiguator: CrateDisambiguator)
@ -589,19 +585,6 @@ impl DefPathData {
}
}
/// Evaluates to the number of tokens passed to it.
///
/// Logarithmic counting: every one or two recursive expansions, the number of
/// tokens to count is divided by two, instead of being reduced by one.
/// Therefore, the recursion depth is the binary logarithm of the number of
/// tokens to count, and the expanded tree is likewise very small.
macro_rules! count {
() => (0usize);
($one:tt) => (1usize);
($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize);
($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize);
}
// We define the GlobalMetaDataKind enum with this macro because we want to
// make sure that we exhaustively iterate over all variants when registering
// the corresponding DefIndices in the DefTable.
@ -614,8 +597,6 @@ macro_rules! define_global_metadata_kind {
$($variant),*
}
pub const FIRST_FREE_DEF_INDEX: usize = 1 + count!($($variant)*);
impl GlobalMetaDataKind {
fn allocate_def_indices(definitions: &mut Definitions) {
$({

View File

@ -2,8 +2,7 @@
use crate::cstore::{self, CStore, CrateSource, MetadataBlob};
use crate::locator::{self, CratePaths};
use crate::decoder::proc_macro_def_path_table;
use crate::schema::CrateRoot;
use crate::schema::{CrateRoot};
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use rustc::hir::def_id::CrateNum;
@ -26,11 +25,11 @@ use std::{cmp, fs};
use syntax::ast;
use syntax::attr;
use syntax::ext::allocator::{global_allocator_spans, AllocatorKind};
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
use syntax::symbol::{Symbol, sym};
use syntax::{span_err, span_fatal};
use syntax_pos::{Span, DUMMY_SP};
use log::{debug, info, log_enabled};
use proc_macro::bridge::client::ProcMacro;
pub struct Library {
pub dylib: Option<(PathBuf, PathKind)>,
@ -230,24 +229,13 @@ impl<'a> CrateLoader<'a> {
let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
let proc_macros = crate_root.proc_macro_decls_static.map(|_| {
let raw_proc_macros = crate_root.proc_macro_data.map(|_| {
if self.sess.opts.debugging_opts.dual_proc_macros {
let host_lib = host_lib.unwrap();
self.load_derive_macros(
&host_lib.metadata.get_root(),
host_lib.dylib.map(|p| p.0),
span
)
let host_lib = host_lib.as_ref().unwrap();
self.dlsym_proc_macros(host_lib.dylib.as_ref().map(|p| p.0.clone()),
&host_lib.metadata.get_root(), span)
} else {
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
}
});
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
if let Some(proc_macros) = &proc_macros {
proc_macro_def_path_table(&crate_root, proc_macros)
} else {
crate_root.def_path_table.decode((&metadata, self.sess))
self.dlsym_proc_macros(dylib.clone().map(|p| p.0), &crate_root, span)
}
});
@ -260,13 +248,16 @@ impl<'a> CrateLoader<'a> {
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
.collect();
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
crate_root.def_path_table.decode((&metadata, self.sess))
});
let cmeta = cstore::CrateMetadata {
name: crate_root.name,
imported_name: ident,
extern_crate: Lock::new(None),
def_path_table: Lrc::new(def_path_table),
trait_impls,
proc_macros,
root: crate_root,
blob: metadata,
cnum_map,
@ -280,7 +271,10 @@ impl<'a> CrateLoader<'a> {
rlib,
rmeta,
},
private_dep
private_dep,
span,
host_lib,
raw_proc_macros
};
let cmeta = Lrc::new(cmeta);
@ -389,7 +383,7 @@ impl<'a> CrateLoader<'a> {
match result {
(LoadResult::Previous(cnum), None) => {
let data = self.cstore.get_crate_data(cnum);
if data.root.proc_macro_decls_static.is_some() {
if data.root.proc_macro_data.is_some() {
dep_kind = DepKind::UnexportedMacrosOnly;
}
data.dep_kind.with_lock(|data_dep_kind| {
@ -482,7 +476,7 @@ impl<'a> CrateLoader<'a> {
dep_kind: DepKind)
-> cstore::CrateNumMap {
debug!("resolving deps of external crate");
if crate_root.proc_macro_decls_static.is_some() {
if crate_root.proc_macro_data.is_some() {
return cstore::CrateNumMap::new();
}
@ -574,19 +568,13 @@ impl<'a> CrateLoader<'a> {
}
}
/// Loads custom derive macros.
///
/// Note that this is intentionally similar to how we load plugins today,
/// but also intentionally separate. Plugins are likely always going to be
/// implemented as dynamic libraries, but we have a possible future where
/// custom derive (and other macro-1.1 style features) are implemented via
/// executables and custom IPC.
fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, span: Span)
-> Vec<(ast::Name, Lrc<SyntaxExtension>)> {
use std::{env, mem};
fn dlsym_proc_macros(&self,
dylib: Option<PathBuf>,
root: &CrateRoot<'_>,
span: Span
) -> &'static [ProcMacro] {
use std::env;
use crate::dynamic_lib::DynamicLibrary;
use proc_macro::bridge::client::ProcMacro;
use syntax::ext::proc_macro::{BangProcMacro, AttrProcMacro, ProcMacroDerive};
let path = match dylib {
Some(dylib) => dylib,
@ -608,38 +596,11 @@ impl<'a> CrateLoader<'a> {
*(sym as *const &[ProcMacro])
};
let extensions = decls.iter().map(|&decl| {
let (name, kind, helper_attrs) = match decl {
ProcMacro::CustomDerive { trait_name, attributes, client } => {
let helper_attrs =
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
(
trait_name,
SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
client, attrs: helper_attrs.clone()
})),
helper_attrs,
)
}
ProcMacro::Attr { name, client } => (
name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
),
ProcMacro::Bang { name, client } => (
name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
)
};
(Symbol::intern(name), Lrc::new(SyntaxExtension {
helper_attrs,
..SyntaxExtension::default(kind, root.edition)
}))
}).collect();
// Intentionally leak the dynamic library. We can't ever unload it
// since the library can make things that will live arbitrarily long.
mem::forget(lib);
std::mem::forget(lib);
extensions
decls
}
/// Look for a plugin registrar. Returns library path, crate

View File

@ -28,6 +28,9 @@ pub use crate::cstore_impl::{provide, provide_extern};
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
pub use rustc_data_structures::sync::MetadataRef;
use crate::creader::Library;
use syntax_pos::Span;
use proc_macro::bridge::client::ProcMacro;
pub struct MetadataBlob(pub MetadataRef);
@ -82,11 +85,19 @@ pub struct CrateMetadata {
pub dep_kind: Lock<DepKind>,
pub source: CrateSource,
pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
/// Whether or not this crate should be consider a private dependency
/// for purposes of the 'exported_private_dependencies' lint
pub private_dep: bool
pub private_dep: bool,
pub host_lib: Option<Library>,
pub span: Span,
pub raw_proc_macros: Option<&'static [ProcMacro]>,
}
pub struct FullProcMacro {
pub name: ast::Name,
pub ext: Lrc<SyntaxExtension>
}
pub struct CStore {

View File

@ -426,8 +426,8 @@ impl cstore::CStore {
pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
let data = self.get_crate_data(id.krate);
if let Some(ref proc_macros) = data.proc_macros {
return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
if data.is_proc_macro_crate() {
return LoadedMacro::ProcMacro(data.get_proc_macro(id.index, sess).ext);
} else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote {
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }));
@ -439,7 +439,8 @@ impl cstore::CStore {
}
let def = data.get_macro(id.index);
let macro_full_name = data.def_path(id.index).to_string_friendly(|_| data.imported_name);
let macro_full_name = data.def_path(id.index)
.to_string_friendly(|_| data.imported_name);
let source_name = FileName::Macros(macro_full_name);
let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body);

View File

@ -1,16 +1,15 @@
// Decoding metadata from a single crate's metadata
use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule};
use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro};
use crate::schema::*;
use rustc_data_structures::sync::{Lrc, ReadGuard};
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions};
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc::hir;
use rustc::middle::cstore::LinkagePreference;
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::hir::map::definitions::DefPathTable;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc::middle::lang_items;
use rustc::mir::{self, interpret};
@ -30,10 +29,11 @@ use syntax::attr;
use syntax::ast::{self, Ident};
use syntax::source_map;
use syntax::symbol::{Symbol, sym};
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::hygiene::ExpnId;
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension};
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}};
use log::debug;
use proc_macro::bridge::client::ProcMacro;
use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro};
pub struct DecodeContext<'a, 'tcx> {
opaque: opaque::Decoder<'a>,
@ -138,7 +138,7 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> LazySeq<T> {
pub fn decode<M: Metadata<'a, 'tcx>>(
self,
meta: M,
) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x {
) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x {
let mut dcx = meta.decoder(self.position);
dcx.lazy_state = LazyState::NodeStart(self.position);
(0..self.len).map(move |_| T::decode(&mut dcx).unwrap())
@ -442,46 +442,16 @@ impl<'tcx> EntryKind<'tcx> {
}
}
/// Creates the "fake" DefPathTable for a given proc macro crate.
///
/// The DefPathTable is as follows:
///
/// CRATE_ROOT (DefIndex 0:0)
/// |- GlobalMetaDataKind data (DefIndex 1:0 .. DefIndex 1:N)
/// |- proc macro #0 (DefIndex 1:N)
/// |- proc macro #1 (DefIndex 1:N+1)
/// \- ...
crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>,
proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
-> DefPathTable
{
let mut definitions = Definitions::default();
let name = crate_root.name.as_str();
let disambiguator = crate_root.disambiguator;
debug!("creating proc macro def path table for {:?}/{:?}", name, disambiguator);
let crate_root = definitions.create_root_def(&name, disambiguator);
for (index, (name, _)) in proc_macros.iter().enumerate() {
let def_index = definitions.create_def_with_parent(
crate_root,
ast::DUMMY_NODE_ID,
DefPathData::MacroNs(name.as_interned_str()),
ExpnId::root(),
DUMMY_SP);
debug!("definition for {:?} is {:?}", name, def_index);
assert_eq!(def_index, DefIndex::from_proc_macro_index(index));
}
definitions.def_path_table().clone()
}
impl<'a, 'tcx> CrateMetadata {
pub fn is_proc_macro_crate(&self) -> bool {
self.root.proc_macro_decls_static.is_some()
}
fn is_proc_macro(&self, id: DefIndex) -> bool {
self.proc_macros.is_some() && id != CRATE_DEF_INDEX
self.is_proc_macro_crate() &&
self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some()
}
fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
assert!(!self.is_proc_macro(item_id));
self.root.entries_index.lookup(self.blob.raw_bytes(), item_id)
}
@ -504,13 +474,24 @@ impl<'a, 'tcx> CrateMetadata {
}
}
fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
// DefIndex's in root.proc_macro_data have a one-to-one correspondence
// with items in 'raw_proc_macros'
let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap();
&self.raw_proc_macros.unwrap()[pos]
}
pub fn item_name(&self, item_index: DefIndex) -> Symbol {
self.def_key(item_index)
.disambiguated_data
.data
.get_opt_name()
.expect("no name in item_name")
.as_symbol()
if !self.is_proc_macro(item_index) {
self.def_key(item_index)
.disambiguated_data
.data
.get_opt_name()
.expect("no name in item_name")
.as_symbol()
} else {
Symbol::intern(self.raw_proc_macro(item_index).name())
}
}
pub fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
@ -518,15 +499,64 @@ impl<'a, 'tcx> CrateMetadata {
self.entry(index).kind.def_kind()
} else {
Some(DefKind::Macro(
self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind()
macro_kind(self.raw_proc_macro(index))
))
}
}
pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
match self.is_proc_macro(index) {
true => DUMMY_SP,
false => self.entry(index).span.decode((self, sess)),
self.entry(index).span.decode((self, sess))
}
pub fn get_proc_macro(&self, id: DefIndex, sess: &Session) -> FullProcMacro {
if sess.opts.debugging_opts.dual_proc_macros {
let host_lib = self.host_lib.as_ref().unwrap();
self.load_proc_macro(
&host_lib.metadata.get_root(),
id,
sess
)
} else {
self.load_proc_macro(&self.root, id, sess)
}
}
fn load_proc_macro(&self, root: &CrateRoot<'_>,
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 } => {
let helper_attrs =
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
(
trait_name,
SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
client, attrs: helper_attrs.clone()
})),
helper_attrs,
)
}
ProcMacro::Attr { name, client } => (
name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
),
ProcMacro::Bang { name, client } => (
name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
)
};
let span = self.get_span(id, sess);
FullProcMacro {
name: Symbol::intern(name),
ext: Lrc::new(SyntaxExtension {
span,
helper_attrs,
..SyntaxExtension::default(kind, root.edition)
})
}
}
@ -723,7 +753,7 @@ impl<'a, 'tcx> CrateMetadata {
/// Iterates over the language items in the given crate.
pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
if self.proc_macros.is_some() {
if self.is_proc_macro_crate() {
// Proc macro crates do not export any lang-items to the target.
&[]
} else {
@ -738,18 +768,18 @@ impl<'a, 'tcx> CrateMetadata {
pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
where F: FnMut(def::Export<hir::HirId>)
{
if let Some(ref proc_macros) = self.proc_macros {
if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) {
/* If we are loading as a proc macro, we want to return the view of this crate
* as a proc macro crate, not as a Rust crate. See `proc_macro_def_path_table`
* for the DefPathTable we are corresponding to.
* as a proc macro crate.
*/
if id == CRATE_DEF_INDEX {
for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
for def_index in proc_macros_ids {
let raw_macro = self.raw_proc_macro(def_index);
let res = Res::Def(
DefKind::Macro(ext.macro_kind()),
self.local_def_id(DefIndex::from_proc_macro_index(id)),
DefKind::Macro(macro_kind(raw_macro)),
self.local_def_id(def_index),
);
let ident = Ident::with_dummy_span(name);
let ident = Ident::from_str(raw_macro.name());
callback(def::Export {
ident: ident,
res: res,
@ -960,11 +990,8 @@ impl<'a, 'tcx> CrateMetadata {
}
}
pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
if self.is_proc_macro(node_id) {
return Lrc::new([]);
}
pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> {
// The attributes for a tuple struct/variant are attached to the definition, not the ctor;
// we assume that someone passing in a tuple struct ctor is actually wanting to
// look at the definition
@ -1022,7 +1049,7 @@ impl<'a, 'tcx> CrateMetadata {
tcx: TyCtxt<'tcx>,
filter: Option<DefId>,
) -> &'tcx [DefId] {
if self.proc_macros.is_some() {
if self.is_proc_macro_crate() {
// proc-macro crates export no trait impls.
return &[]
}
@ -1066,7 +1093,7 @@ impl<'a, 'tcx> CrateMetadata {
pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
if self.proc_macros.is_some() {
if self.is_proc_macro_crate() {
// Proc macro crates do not have any *target* native libraries.
vec![]
} else {
@ -1075,7 +1102,7 @@ impl<'a, 'tcx> CrateMetadata {
}
pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
if self.proc_macros.is_some() {
if self.is_proc_macro_crate() {
// Proc macro crates do not have any *target* foreign modules.
&[]
} else {
@ -1098,7 +1125,7 @@ impl<'a, 'tcx> CrateMetadata {
}
pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
if self.proc_macros.is_some() {
if self.is_proc_macro_crate() {
// Proc macro crates do not depend on any target weak lang-items.
&[]
} else {
@ -1122,7 +1149,7 @@ impl<'a, 'tcx> CrateMetadata {
&self,
tcx: TyCtxt<'tcx>,
) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
if self.proc_macros.is_some() {
if self.is_proc_macro_crate() {
// If this crate is a custom derive crate, then we're not even going to
// link those in so we skip those crates.
vec![]
@ -1191,13 +1218,18 @@ impl<'a, 'tcx> CrateMetadata {
#[inline]
pub fn def_key(&self, index: DefIndex) -> DefKey {
self.def_path_table.def_key(index)
let mut key = self.def_path_table.def_key(index);
if self.is_proc_macro(index) {
let name = self.raw_proc_macro(index).name();
key.disambiguated_data.data = DefPathData::MacroNs(InternedString::intern(name));
}
key
}
// Returns the path leading to the thing with this `id`.
pub fn def_path(&self, id: DefIndex) -> DefPath {
debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent))
DefPath::make(self.cnum, id, |parent| self.def_key(parent))
}
#[inline]
@ -1310,3 +1342,13 @@ impl<'a, 'tcx> CrateMetadata {
self.source_map_import_info.borrow()
}
}
// Cannot be implemented on 'ProcMacro', as libproc_macro
// does not depend on libsyntax
fn macro_kind(raw: &ProcMacro) -> MacroKind {
match raw {
ProcMacro::CustomDerive { .. } => MacroKind::Derive,
ProcMacro::Attr { .. } => MacroKind::Attr,
ProcMacro::Bang { .. } => MacroKind::Bang
}
}

View File

@ -30,6 +30,7 @@ use rustc_data_structures::sync::Lrc;
use std::u32;
use syntax::ast;
use syntax::attr;
use syntax::ext::proc_macro::is_proc_macro_attr;
use syntax::source_map::Spanned;
use syntax::symbol::{kw, sym, Ident};
use syntax_pos::{self, FileName, SourceFile, Span};
@ -383,6 +384,8 @@ impl<'tcx> EncodeContext<'tcx> {
}
fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
let mut i = self.position();
let crate_deps = self.encode_crate_deps();
@ -463,16 +466,23 @@ impl<'tcx> EncodeContext<'tcx> {
self.lazy_seq(interpret_alloc_index)
};
i = self.position();
let entries_index = self.entries_index.write_index(&mut self.opaque);
let entries_index_bytes = self.position() - i;
// Encode the proc macro data
i = self.position();
let proc_macro_data = self.encode_proc_macros();
let proc_macro_data_bytes = self.position() - i;
let attrs = tcx.hir().krate_attrs();
let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator);
let has_global_allocator = *tcx.sess.has_global_allocator.get();
let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false);
let root = self.lazy(&CrateRoot {
name: tcx.crate_name(LOCAL_CRATE),
extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
@ -491,6 +501,7 @@ impl<'tcx> EncodeContext<'tcx> {
} else {
None
},
proc_macro_data,
proc_macro_stability: if is_proc_macro {
tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone())
} else {
@ -539,6 +550,7 @@ impl<'tcx> EncodeContext<'tcx> {
println!(" impl bytes: {}", impl_bytes);
println!(" exp. symbols bytes: {}", exported_symbols_bytes);
println!(" def-path table bytes: {}", def_path_table_bytes);
println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
println!(" item bytes: {}", item_bytes);
println!(" entries index bytes: {}", entries_index_bytes);
println!(" zero bytes: {}", zero_bytes);
@ -1470,6 +1482,22 @@ impl EncodeContext<'tcx> {
self.lazy_seq(foreign_modules.iter().cloned())
}
fn encode_proc_macros(&mut self) -> Option<LazySeq<DefIndex>> {
let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
if is_proc_macro {
let proc_macros: Vec<_> = self.tcx.hir().krate().items.values().filter_map(|item| {
if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)) {
Some(item.hir_id.owner)
} else {
None
}
}).collect();
Some(self.lazy_seq(proc_macros))
} else {
None
}
}
fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
let crates = self.tcx.crates();

View File

@ -716,7 +716,9 @@ impl<'a> Context<'a> {
let root = metadata.get_root();
if let Some(is_proc_macro) = self.is_proc_macro {
if root.proc_macro_decls_static.is_some() != is_proc_macro {
if root.proc_macro_data.is_some() != is_proc_macro {
info!("Rejecting via proc macro: expected {} got {}",
is_proc_macro, root.proc_macro_data.is_some());
return None;
}
}

View File

@ -182,6 +182,10 @@ pub struct CrateRoot<'tcx> {
pub entries_index: LazySeq<index::Index<'tcx>>,
/// The DefIndex's of any proc macros delcared by
/// this crate
pub proc_macro_data: Option<LazySeq<DefIndex>>,
pub compiler_builtins: bool,
pub needs_allocator: bool,
pub needs_panic_runtime: bool,

View File

@ -18,7 +18,10 @@ error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fra
--> $DIR/same-sequence-span.rs:20:1
|
LL | proc_macro_sequence::make_foo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| not allowed after `expr` fragments
| in this macro invocation
|
= note: allowed there are: `=>`, `,` or `;`
@ -26,7 +29,10 @@ error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragmen
--> $DIR/same-sequence-span.rs:20:1
|
LL | proc_macro_sequence::make_foo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| not allowed after `expr` fragments
| in this macro invocation
|
= note: allowed there are: `=>`, `,` or `;`

View File

@ -2,13 +2,19 @@ error[E0412]: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:9:1
|
LL | generate_mod::check!();
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
| ^^^^^^^^^^^^^^^^^^^^^^^
| |
| not found in this scope
| in this macro invocation
error[E0412]: cannot find type `Outer` in this scope
--> $DIR/generate-mod.rs:9:1
|
LL | generate_mod::check!();
| ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
| ^^^^^^^^^^^^^^^^^^^^^^^
| |
| not found in this scope
| in this macro invocation
error[E0412]: cannot find type `FromOutside` in this scope
--> $DIR/generate-mod.rs:12:1

View File

@ -2,7 +2,10 @@ error: unexpected close delimiter: `)`
--> $DIR/invalid-punct-ident-4.rs:6:1
|
LL | lexer_failure!();
| ^^^^^^^^^^^^^^^^^ unexpected close delimiter
| ^^^^^^^^^^^^^^^^^
| |
| unexpected close delimiter
| in this macro invocation
error: proc macro panicked
--> $DIR/invalid-punct-ident-4.rs:6:1

View File

@ -2,7 +2,10 @@ error[E0425]: cannot find value `foobar2` in this scope
--> $DIR/lints_in_proc_macros.rs:12:5
|
LL | bang_proc_macro2!();
| ^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar`
| ^^^^^^^^^^^^^^^^^^^^
| |
| help: a local variable with a similar name exists: `foobar`
| in this macro invocation
error: aborting due to previous error

View File

@ -2,7 +2,7 @@ error: hello to you, too!
--> $DIR/multispan.rs:14:5
|
LL | hello!(hi);
| ^^^^^^^^^^^
| ^^^^^^^^^^^ in this macro invocation
|
note: found these 'hi's
--> $DIR/multispan.rs:14:12
@ -14,7 +14,7 @@ error: hello to you, too!
--> $DIR/multispan.rs:17:5
|
LL | hello!(hi hi);
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ in this macro invocation
|
note: found these 'hi's
--> $DIR/multispan.rs:17:12
@ -26,7 +26,7 @@ error: hello to you, too!
--> $DIR/multispan.rs:20:5
|
LL | hello!(hi hi hi);
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: found these 'hi's
--> $DIR/multispan.rs:20:12
@ -38,7 +38,7 @@ error: hello to you, too!
--> $DIR/multispan.rs:23:5
|
LL | hello!(hi hey hi yo hi beep beep hi hi);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: found these 'hi's
--> $DIR/multispan.rs:23:12
@ -50,7 +50,7 @@ error: hello to you, too!
--> $DIR/multispan.rs:24:5
|
LL | hello!(hi there, hi how are you? hi... hi.);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: found these 'hi's
--> $DIR/multispan.rs:24:12
@ -62,7 +62,7 @@ error: hello to you, too!
--> $DIR/multispan.rs:25:5
|
LL | hello!(whoah. hi di hi di ho);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: found these 'hi's
--> $DIR/multispan.rs:25:19
@ -74,7 +74,7 @@ error: hello to you, too!
--> $DIR/multispan.rs:26:5
|
LL | hello!(hi good hi and good bye);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: found these 'hi's
--> $DIR/multispan.rs:26:12

View File

@ -2,7 +2,7 @@ error: found 'hi's
--> $DIR/subspan.rs:11:1
|
LL | subspan!("hi");
| ^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:11:11
@ -14,7 +14,7 @@ error: found 'hi's
--> $DIR/subspan.rs:14:1
|
LL | subspan!("hihi");
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:14:11
@ -26,7 +26,7 @@ error: found 'hi's
--> $DIR/subspan.rs:17:1
|
LL | subspan!("hihihi");
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:17:11
@ -38,7 +38,7 @@ error: found 'hi's
--> $DIR/subspan.rs:20:1
|
LL | subspan!("why I hide? hi!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:20:17
@ -50,7 +50,7 @@ error: found 'hi's
--> $DIR/subspan.rs:21:1
|
LL | subspan!("hey, hi, hidy, hidy, hi hi");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:21:16
@ -62,7 +62,7 @@ error: found 'hi's
--> $DIR/subspan.rs:22:1
|
LL | subspan!("this is a hi, and this is another hi");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:22:12
@ -74,7 +74,7 @@ error: found 'hi's
--> $DIR/subspan.rs:23:1
|
LL | subspan!("how are you this evening");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:23:24
@ -86,7 +86,7 @@ error: found 'hi's
--> $DIR/subspan.rs:24:1
|
LL | subspan!("this is highly eradic");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation
|
note: here
--> $DIR/subspan.rs:24:12

View File

@ -2,7 +2,7 @@ error: found 2 equal signs, need exactly 3
--> $DIR/three-equals.rs:15:5
|
LL | three_equals!(==);
| ^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^ in this macro invocation
|
= help: input must be: `===`