Auto merge of #37292 - jseyfried:import_macros_in_resolve, r=nrc

Process `#[macro_use]` imports in `resolve` and clean up macro loading

Groundwork macro modularization (cc #35896).
r? @nrc
This commit is contained in:
bors 2016-10-24 23:15:59 -07:00 committed by GitHub
commit affc3b7552
15 changed files with 493 additions and 645 deletions

View File

@ -716,8 +716,6 @@ impl<'a> LoweringContext<'a> {
id: m.id, id: m.id,
span: m.span, span: m.span,
imported_from: m.imported_from.map(|x| x.name), imported_from: m.imported_from.map(|x| x.name),
export: m.export,
use_locally: m.use_locally,
allow_internal_unstable: m.allow_internal_unstable, allow_internal_unstable: m.allow_internal_unstable,
body: m.body.clone().into(), body: m.body.clone().into(),
} }

View File

@ -458,8 +458,6 @@ pub struct MacroDef {
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
pub imported_from: Option<Name>, pub imported_from: Option<Name>,
pub export: bool,
pub use_locally: bool,
pub allow_internal_unstable: bool, pub allow_internal_unstable: bool,
pub body: HirVec<TokenTree>, pub body: HirVec<TokenTree>,
} }

View File

@ -37,7 +37,7 @@ use util::nodemap::{NodeSet, DefIdMap};
use std::path::PathBuf; use std::path::PathBuf;
use syntax::ast; use syntax::ast;
use syntax::attr; use syntax::attr;
use syntax::ext::base::MultiItemModifier; use syntax::ext::base::SyntaxExtension;
use syntax::ptr::P; use syntax::ptr::P;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use syntax_pos::Span; use syntax_pos::Span;
@ -417,18 +417,22 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
} }
pub struct LoadedMacro { pub enum LoadedMacros {
pub import_site: Span, MacroRules(Vec<ast::MacroDef>),
pub kind: LoadedMacroKind, ProcMacros(Vec<(ast::Name, SyntaxExtension)>),
} }
pub enum LoadedMacroKind { impl LoadedMacros {
Def(ast::MacroDef), pub fn is_proc_macros(&self) -> bool {
CustomDerive(String, Box<MultiItemModifier>), match *self {
LoadedMacros::ProcMacros(_) => true,
_ => false,
}
}
} }
pub trait CrateLoader { pub trait CrateLoader {
fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro>; fn process_item(&mut self, item: &ast::Item, defs: &Definitions, load_macros: bool)
fn process_item(&mut self, item: &ast::Item, defs: &Definitions); -> Option<LoadedMacros>;
fn postprocess(&mut self, krate: &ast::Crate); fn postprocess(&mut self, krate: &ast::Crate);
} }

View File

@ -675,13 +675,11 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
fn visit_macro_def(&mut self, macro_def: &'tcx MacroDef) { fn visit_macro_def(&mut self, macro_def: &'tcx MacroDef) {
debug!("visit_macro_def: st={:?}", self.st); debug!("visit_macro_def: st={:?}", self.st);
if macro_def.export { SawMacroDef.hash(self.st);
SawMacroDef.hash(self.st); hash_attrs!(self, &macro_def.attrs);
hash_attrs!(self, &macro_def.attrs); visit::walk_macro_def(self, macro_def)
visit::walk_macro_def(self, macro_def) // FIXME(mw): We should hash the body of the macro too but we don't
// FIXME(mw): We should hash the body of the macro too but we don't // have a stable way of doing so yet.
// have a stable way of doing so yet.
}
} }
} }

View File

@ -12,19 +12,18 @@
use cstore::{self, CStore, CrateSource, MetadataBlob}; use cstore::{self, CStore, CrateSource, MetadataBlob};
use locator::{self, CratePaths}; use locator::{self, CratePaths};
use macro_import;
use schema::CrateRoot; use schema::CrateRoot;
use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::def_id::{CrateNum, DefIndex};
use rustc::hir::svh::Svh; use rustc::hir::svh::Svh;
use rustc::middle::cstore::LoadedMacro; use rustc::middle::cstore::LoadedMacros;
use rustc::session::{config, Session}; use rustc::session::{config, Session};
use rustc_back::PanicStrategy; use rustc_back::PanicStrategy;
use rustc::session::search_paths::PathKind; use rustc::session::search_paths::PathKind;
use rustc::middle; use rustc::middle;
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate}; use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
use rustc::hir::map as hir_map; use rustc::hir::map::Definitions;
use std::cell::{RefCell, Cell}; use std::cell::{RefCell, Cell};
use std::ops::Deref; use std::ops::Deref;
@ -36,7 +35,8 @@ use syntax::ast;
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::parse; use syntax::parse;
use syntax::attr; use syntax::attr;
use syntax::parse::token::InternedString; use syntax::ext::base::SyntaxExtension;
use syntax::parse::token::{InternedString, intern};
use syntax_pos::{self, Span, mk_sp}; use syntax_pos::{self, Span, mk_sp};
use log; use log;
@ -120,11 +120,6 @@ struct ExtensionCrate {
metadata: PMDSource, metadata: PMDSource,
dylib: Option<PathBuf>, dylib: Option<PathBuf>,
target_only: bool, target_only: bool,
ident: String,
name: String,
span: Span,
should_link: bool,
} }
enum PMDSource { enum PMDSource {
@ -148,17 +143,6 @@ enum LoadResult {
Loaded(Library), Loaded(Library),
} }
pub struct Macros {
pub macro_rules: Vec<ast::MacroDef>,
/// An array of pairs where the first element is the name of the custom
/// derive (e.g. the trait being derived) and the second element is the
/// index of the definition.
pub custom_derive_registrar: Option<DefIndex>,
pub svh: Svh,
pub dylib: Option<PathBuf>,
}
impl<'a> CrateLoader<'a> { impl<'a> CrateLoader<'a> {
pub fn new(sess: &'a Session, pub fn new(sess: &'a Session,
cstore: &'a CStore, cstore: &'a CStore,
@ -490,7 +474,6 @@ impl<'a> CrateLoader<'a> {
info.id, info.name, info.ident, info.should_link); info.id, info.name, info.ident, info.should_link);
let target_triple = &self.sess.opts.target_triple[..]; let target_triple = &self.sess.opts.target_triple[..];
let is_cross = target_triple != config::host_triple(); let is_cross = target_triple != config::host_triple();
let mut should_link = info.should_link && !is_cross;
let mut target_only = false; let mut target_only = false;
let ident = info.ident.clone(); let ident = info.ident.clone();
let name = info.name.clone(); let name = info.name.clone();
@ -517,7 +500,6 @@ impl<'a> CrateLoader<'a> {
// Try loading from target crates. This will abort later if we // Try loading from target crates. This will abort later if we
// try to load a plugin registrar function, // try to load a plugin registrar function,
target_only = true; target_only = true;
should_link = info.should_link;
locate_ctxt.target = &self.sess.target.target; locate_ctxt.target = &self.sess.target.target;
locate_ctxt.triple = target_triple; locate_ctxt.triple = target_triple;
@ -547,25 +529,14 @@ impl<'a> CrateLoader<'a> {
metadata: metadata, metadata: metadata,
dylib: dylib.map(|p| p.0), dylib: dylib.map(|p| p.0),
target_only: target_only, target_only: target_only,
name: info.name.to_string(),
ident: info.ident.to_string(),
span: span,
should_link: should_link,
} }
} }
pub fn read_macros(&mut self, item: &ast::Item) -> Macros { fn read_macros(&mut self, item: &ast::Item, ekrate: &ExtensionCrate) -> LoadedMacros {
let ci = self.extract_crate_info(item).unwrap();
let ekrate = self.read_extension_crate(item.span, &ci);
let root = ekrate.metadata.get_root(); let root = ekrate.metadata.get_root();
let source_name = format!("<{} macros>", item.ident); let source_name = format!("<{} macros>", item.ident);
let mut ret = Macros { let mut macro_rules = Vec::new();
macro_rules: Vec::new(),
custom_derive_registrar: None,
svh: root.hash,
dylib: None,
};
for def in root.macro_defs.decode(&*ekrate.metadata) { for def in root.macro_defs.decode(&*ekrate.metadata) {
// NB: Don't use parse::parse_tts_from_source_str because it parses with // NB: Don't use parse::parse_tts_from_source_str because it parses with
// quote_depth > 0. // quote_depth > 0.
@ -589,54 +560,90 @@ impl<'a> CrateLoader<'a> {
attr::mark_used(attr); attr::mark_used(attr);
} }
ret.macro_rules.push(ast::MacroDef { macro_rules.push(ast::MacroDef {
ident: ast::Ident::with_empty_ctxt(def.name), ident: ast::Ident::with_empty_ctxt(def.name),
attrs: def.attrs,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: local_span, span: local_span,
imported_from: Some(item.ident), imported_from: Some(item.ident),
// overridden in plugin/load.rs allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"),
export: false, attrs: def.attrs,
use_locally: false,
allow_internal_unstable: false,
body: body, body: body,
}); });
self.sess.imported_macro_spans.borrow_mut() self.sess.imported_macro_spans.borrow_mut()
.insert(local_span, (def.name.as_str().to_string(), def.span)); .insert(local_span, (def.name.as_str().to_string(), def.span));
} }
match root.macro_derive_registrar { if let Some(id) = root.macro_derive_registrar {
Some(id) => ret.custom_derive_registrar = Some(id), let dylib = match ekrate.dylib.clone() {
Some(dylib) => dylib,
None => span_bug!(item.span, "proc-macro crate not dylib"),
};
if ekrate.target_only {
let message = format!("proc-macro crate is not available for \
triple `{}` (only found {})",
config::host_triple(),
self.sess.opts.target_triple);
self.sess.span_fatal(item.span, &message);
}
// If this crate is not a proc-macro crate then we might be able to // custom derive crates currently should not have any macro_rules!
// register it with the local crate store to prevent loading the // exported macros, enforced elsewhere
// metadata twice. assert_eq!(macro_rules.len(), 0);
// LoadedMacros::ProcMacros(self.load_derive_macros(item, id, root.hash, dylib))
// If it's a proc-macro crate, though, then we definitely don't } else {
// want to register it with the local crate store as we're just LoadedMacros::MacroRules(macro_rules)
// going to use it as we would a plugin. }
None => { }
ekrate.register(self);
return ret /// Load 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, item: &ast::Item, index: DefIndex, svh: Svh, path: PathBuf)
-> Vec<(ast::Name, SyntaxExtension)> {
use std::{env, mem};
use proc_macro::TokenStream;
use proc_macro::__internal::Registry;
use rustc_back::dynamic_lib::DynamicLibrary;
use syntax_ext::deriving::custom::CustomDerive;
// Make sure the path contains a / or the linker will search for it.
let path = env::current_dir().unwrap().join(path);
let lib = match DynamicLibrary::open(Some(&path)) {
Ok(lib) => lib,
Err(err) => self.sess.span_fatal(item.span, &err),
};
let sym = self.sess.generate_derive_registrar_symbol(&svh, index);
let registrar = unsafe {
let sym = match lib.symbol(&sym) {
Ok(f) => f,
Err(err) => self.sess.span_fatal(item.span, &err),
};
mem::transmute::<*mut u8, fn(&mut Registry)>(sym)
};
struct MyRegistrar(Vec<(ast::Name, SyntaxExtension)>);
impl Registry for MyRegistrar {
fn register_custom_derive(&mut self,
trait_name: &str,
expand: fn(TokenStream) -> TokenStream) {
let derive = SyntaxExtension::CustomDerive(Box::new(CustomDerive::new(expand)));
self.0.push((intern(trait_name), derive));
} }
} }
self.cstore.add_used_for_derive_macros(item); let mut my_registrar = MyRegistrar(Vec::new());
ret.dylib = ekrate.dylib.clone(); registrar(&mut my_registrar);
if ret.dylib.is_none() {
span_bug!(item.span, "proc-macro crate not dylib");
}
if ekrate.target_only { // Intentionally leak the dynamic library. We can't ever unload it
let message = format!("proc-macro crate is not available for \ // since the library can make things that will live arbitrarily long.
triple `{}` (only found {})", mem::forget(lib);
config::host_triple(), my_registrar.0
self.sess.opts.target_triple);
self.sess.span_fatal(item.span, &message);
}
return ret
} }
/// Look for a plugin registrar. Returns library path, crate /// Look for a plugin registrar. Returns library path, crate
@ -889,22 +896,6 @@ impl<'a> CrateLoader<'a> {
} }
} }
impl ExtensionCrate {
fn register(self, loader: &mut CrateLoader) {
if !self.should_link {
return
}
let library = match self.metadata {
PMDSource::Owned(lib) => lib,
PMDSource::Registered(_) => return,
};
// Register crate now to avoid double-reading metadata
loader.register_crate(&None, &self.ident, &self.name, self.span, library, true);
}
}
impl<'a> CrateLoader<'a> { impl<'a> CrateLoader<'a> {
pub fn preprocess(&mut self, krate: &ast::Crate) { pub fn preprocess(&mut self, krate: &ast::Crate) {
for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") { for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") {
@ -990,47 +981,56 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
self.register_statically_included_foreign_items(); self.register_statically_included_foreign_items();
} }
fn process_item(&mut self, item: &ast::Item, definitions: &hir_map::Definitions) { fn process_item(&mut self, item: &ast::Item, definitions: &Definitions, load_macros: bool)
-> Option<LoadedMacros> {
match item.node { match item.node {
ast::ItemKind::ExternCrate(_) => {} ast::ItemKind::ExternCrate(_) => {}
ast::ItemKind::ForeignMod(ref fm) => return self.process_foreign_mod(item, fm), ast::ItemKind::ForeignMod(ref fm) => {
_ => return, self.process_foreign_mod(item, fm);
} return None;
// If this `extern crate` item has `#[macro_use]` then we can safely skip it.
// These annotations were processed during macro expansion and are already loaded
// (if necessary) into our crate store.
//
// Note that it's important we *don't* fall through below as some `#[macro_use]`
// crates are explicitly not linked (e.g. macro crates) so we want to ensure
// we avoid `resolve_crate` with those.
if attr::contains_name(&item.attrs, "macro_use") {
if self.cstore.was_used_for_derive_macros(item) {
return
} }
_ => return None,
} }
if let Some(info) = self.extract_crate_info(item) { let info = self.extract_crate_info(item).unwrap();
let loaded_macros = if load_macros {
let ekrate = self.read_extension_crate(item.span, &info);
let loaded_macros = self.read_macros(item, &ekrate);
// If this is a proc-macro crate or `#[no_link]` crate, it is only used at compile time,
// so we return here to avoid registering the crate.
if loaded_macros.is_proc_macros() || !info.should_link {
return Some(loaded_macros);
}
// Register crate now to avoid double-reading metadata
if let PMDSource::Owned(lib) = ekrate.metadata {
if ekrate.target_only || config::host_triple() == self.sess.opts.target_triple {
let ExternCrateInfo { ref ident, ref name, .. } = info;
self.register_crate(&None, ident, name, item.span, lib, true);
}
}
Some(loaded_macros)
} else {
if !info.should_link { if !info.should_link {
return; return None;
} }
None
};
let (cnum, ..) = self.resolve_crate( let (cnum, ..) = self.resolve_crate(
&None, &info.ident, &info.name, None, item.span, PathKind::Crate, true, &None, &info.ident, &info.name, None, item.span, PathKind::Crate, true,
); );
let def_id = definitions.opt_local_def_id(item.id).unwrap(); let def_id = definitions.opt_local_def_id(item.id).unwrap();
let len = definitions.def_path(def_id.index).data.len(); let len = definitions.def_path(def_id.index).data.len();
let extern_crate = let extern_crate =
ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len }; ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len };
self.update_extern_crate(cnum, extern_crate, &mut FnvHashSet()); self.update_extern_crate(cnum, extern_crate, &mut FnvHashSet());
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum); loaded_macros
}
}
fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro> {
macro_import::load_macros(self, extern_crate, allows_macros)
} }
} }

View File

@ -21,14 +21,13 @@ use rustc::hir::svh::Svh;
use rustc::middle::cstore::ExternCrate; use rustc::middle::cstore::ExternCrate;
use rustc_back::PanicStrategy; use rustc_back::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap, FnvHashSet}; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
use std::cell::{RefCell, Cell}; use std::cell::{RefCell, Cell};
use std::rc::Rc; use std::rc::Rc;
use std::path::PathBuf; use std::path::PathBuf;
use flate::Bytes; use flate::Bytes;
use syntax::ast::{self, Ident}; use syntax::{ast, attr};
use syntax::attr;
use syntax_pos; use syntax_pos;
pub use rustc::middle::cstore::{NativeLibraryKind, LinkagePreference}; pub use rustc::middle::cstore::{NativeLibraryKind, LinkagePreference};
@ -105,7 +104,6 @@ pub struct CStore {
pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>, pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
pub defid_for_inlined_node: RefCell<NodeMap<DefId>>, pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
pub visible_parent_map: RefCell<DefIdMap<DefId>>, pub visible_parent_map: RefCell<DefIdMap<DefId>>,
pub used_for_derive_macro: RefCell<FnvHashSet<Ident>>,
} }
impl CStore { impl CStore {
@ -121,7 +119,6 @@ impl CStore {
visible_parent_map: RefCell::new(FnvHashMap()), visible_parent_map: RefCell::new(FnvHashMap()),
inlined_item_cache: RefCell::new(FnvHashMap()), inlined_item_cache: RefCell::new(FnvHashMap()),
defid_for_inlined_node: RefCell::new(FnvHashMap()), defid_for_inlined_node: RefCell::new(FnvHashMap()),
used_for_derive_macro: RefCell::new(FnvHashSet()),
} }
} }
@ -279,14 +276,6 @@ impl CStore {
pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> { pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
self.extern_mod_crate_map.borrow().get(&emod_id).cloned() self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
} }
pub fn was_used_for_derive_macros(&self, i: &ast::Item) -> bool {
self.used_for_derive_macro.borrow().contains(&i.ident)
}
pub fn add_used_for_derive_macros(&self, i: &ast::Item) {
self.used_for_derive_macro.borrow_mut().insert(i.ident);
}
} }
impl CrateMetadata { impl CrateMetadata {

View File

@ -91,185 +91,6 @@ You need to link your code to the relevant crate in order to be able to use it
well, and you link to them the same way. well, and you link to them the same way.
"##, "##,
E0466: r##"
Macro import declarations were malformed.
Erroneous code examples:
```compile_fail,E0466
#[macro_use(a_macro(another_macro))] // error: invalid import declaration
extern crate core as some_crate;
#[macro_use(i_want = "some_macros")] // error: invalid import declaration
extern crate core as another_crate;
```
This is a syntax error at the level of attribute declarations. The proper
syntax for macro imports is the following:
```ignore
// In some_crate:
#[macro_export]
macro_rules! get_tacos {
...
}
#[macro_export]
macro_rules! get_pimientos {
...
}
// In your crate:
#[macro_use(get_tacos, get_pimientos)] // It imports `get_tacos` and
extern crate some_crate; // `get_pimientos` macros from some_crate
```
If you would like to import all exported macros, write `macro_use` with no
arguments.
"##,
E0467: r##"
Macro reexport declarations were empty or malformed.
Erroneous code examples:
```compile_fail,E0467
#[macro_reexport] // error: no macros listed for export
extern crate core as macros_for_good;
#[macro_reexport(fun_macro = "foo")] // error: not a macro identifier
extern crate core as other_macros_for_good;
```
This is a syntax error at the level of attribute declarations.
Currently, `macro_reexport` requires at least one macro name to be listed.
Unlike `macro_use`, listing no names does not reexport all macros from the
given crate.
Decide which macros you would like to export and list them properly.
These are proper reexport declarations:
```ignore
#[macro_reexport(some_macro, another_macro)]
extern crate macros_for_good;
```
"##,
E0468: r##"
A non-root module attempts to import macros from another crate.
Example of erroneous code:
```compile_fail,E0468
mod foo {
#[macro_use(helpful_macro)] // error: must be at crate root to import
extern crate core; // macros from another crate
helpful_macro!(...);
}
```
Only `extern crate` imports at the crate root level are allowed to import
macros.
Either move the macro import to crate root or do without the foreign macros.
This will work:
```ignore
#[macro_use(helpful_macro)]
extern crate some_crate;
mod foo {
helpful_macro!(...)
}
```
"##,
E0469: r##"
A macro listed for import was not found.
Erroneous code example:
```compile_fail,E0469
#[macro_use(drink, be_merry)] // error: imported macro not found
extern crate collections;
fn main() {
// ...
}
```
Either the listed macro is not contained in the imported crate, or it is not
exported from the given crate.
This could be caused by a typo. Did you misspell the macro's name?
Double-check the names of the macros listed for import, and that the crate
in question exports them.
A working version would be:
```ignore
// In some_crate crate:
#[macro_export]
macro_rules! eat {
...
}
#[macro_export]
macro_rules! drink {
...
}
// In your crate:
#[macro_use(eat, drink)]
extern crate some_crate; //ok!
```
"##,
E0470: r##"
A macro listed for reexport was not found.
Erroneous code example:
```compile_fail,E0470
#[macro_reexport(drink, be_merry)]
extern crate collections;
fn main() {
// ...
}
```
Either the listed macro is not contained in the imported crate, or it is not
exported from the given crate.
This could be caused by a typo. Did you misspell the macro's name?
Double-check the names of the macros listed for reexport, and that the crate
in question exports them.
A working version:
```ignore
// In some_crate crate:
#[macro_export]
macro_rules! eat {
...
}
#[macro_export]
macro_rules! drink {
...
}
// In your_crate:
#[macro_reexport(eat, drink)]
extern crate some_crate;
```
"##,
} }
register_diagnostics! { register_diagnostics! {

View File

@ -59,6 +59,5 @@ mod schema;
pub mod creader; pub mod creader;
pub mod cstore; pub mod cstore;
pub mod locator; pub mod locator;
pub mod macro_import;
__build_diagnostic_array! { librustc_metadata, DIAGNOSTICS } __build_diagnostic_array! { librustc_metadata, DIAGNOSTICS }

View File

@ -1,235 +0,0 @@
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Used by `rustc` when loading a crate with exported macros.
use std::collections::HashSet;
use std::env;
use std::mem;
use creader::{CrateLoader, Macros};
use proc_macro::TokenStream;
use proc_macro::__internal::Registry;
use rustc::hir::def_id::DefIndex;
use rustc::middle::cstore::{LoadedMacro, LoadedMacroKind};
use rustc::session::Session;
use rustc::util::nodemap::FnvHashMap;
use rustc_back::dynamic_lib::DynamicLibrary;
use syntax::ast;
use syntax::attr;
use syntax::parse::token;
use syntax_ext::deriving::custom::CustomDerive;
use syntax_pos::{Span, DUMMY_SP};
pub fn call_bad_macro_reexport(a: &Session, b: Span) {
span_err!(a, b, E0467, "bad macro reexport");
}
pub type MacroSelection = FnvHashMap<token::InternedString, Span>;
enum ImportSelection {
All(Span),
Some(MacroSelection),
}
pub fn load_macros(loader: &mut CrateLoader, extern_crate: &ast::Item, allows_macros: bool)
-> Vec<LoadedMacro> {
loader.load_crate(extern_crate, allows_macros)
}
impl<'a> CrateLoader<'a> {
fn load_crate(&mut self,
extern_crate: &ast::Item,
allows_macros: bool) -> Vec<LoadedMacro> {
// Parse the attributes relating to macros.
let mut import = ImportSelection::Some(FnvHashMap());
let mut reexport = FnvHashMap();
let mut no_link = false;
for attr in &extern_crate.attrs {
let mut used = true;
match &attr.name()[..] {
"macro_use" => {
let names = attr.meta_item_list();
if names.is_none() {
import = ImportSelection::All(attr.span);
} else if let ImportSelection::Some(ref mut sel) = import {
for attr in names.unwrap() {
if let Some(word) = attr.word() {
sel.insert(word.name().clone(), attr.span());
} else {
span_err!(self.sess, attr.span(), E0466, "bad macro import");
}
}
}
}
"macro_reexport" => {
let names = match attr.meta_item_list() {
Some(names) => names,
None => {
call_bad_macro_reexport(self.sess, attr.span);
continue;
}
};
for attr in names {
if let Some(word) = attr.word() {
reexport.insert(word.name().clone(), attr.span());
} else {
call_bad_macro_reexport(self.sess, attr.span());
}
}
}
"no_link" => no_link = true,
_ => used = false,
}
if used {
attr::mark_used(attr);
}
}
self.load_macros(extern_crate, allows_macros, import, reexport, no_link)
}
fn load_macros<'b>(&mut self,
vi: &ast::Item,
allows_macros: bool,
import: ImportSelection,
reexport: MacroSelection,
no_link: bool)
-> Vec<LoadedMacro> {
if let ImportSelection::Some(ref sel) = import {
if sel.is_empty() && reexport.is_empty() {
// Make sure we can read macros from `#[no_link]` crates.
if no_link {
self.read_macros(vi);
}
return Vec::new();
}
}
if !allows_macros {
span_err!(self.sess, vi.span, E0468,
"an `extern crate` loading macros must be at the crate root");
return Vec::new();
}
let mut macros = self.read_macros(vi);
let mut ret = Vec::new();
let mut seen = HashSet::new();
for mut def in macros.macro_rules.drain(..) {
let name = def.ident.name.as_str();
let import_site = match import {
ImportSelection::All(span) => Some(span),
ImportSelection::Some(ref sel) => sel.get(&name).cloned()
};
def.use_locally = import_site.is_some();
def.export = reexport.contains_key(&name);
def.allow_internal_unstable = attr::contains_name(&def.attrs,
"allow_internal_unstable");
debug!("load_macros: loaded: {:?}", def);
ret.push(LoadedMacro {
kind: LoadedMacroKind::Def(def),
import_site: import_site.unwrap_or(DUMMY_SP),
});
seen.insert(name);
}
if let Some(index) = macros.custom_derive_registrar {
// custom derive crates currently should not have any macro_rules!
// exported macros, enforced elsewhere
assert_eq!(ret.len(), 0);
if let ImportSelection::Some(..) = import {
self.sess.span_err(vi.span, "`proc-macro` crates cannot be \
selectively imported from, must \
use `#[macro_use]`");
}
if reexport.len() > 0 {
self.sess.span_err(vi.span, "`proc-macro` crates cannot be \
reexported from");
}
self.load_derive_macros(vi.span, &macros, index, &mut ret);
}
if let ImportSelection::Some(sel) = import {
for (name, span) in sel {
if !seen.contains(&name) {
span_err!(self.sess, span, E0469,
"imported macro not found");
}
}
}
for (name, span) in &reexport {
if !seen.contains(&name) {
span_err!(self.sess, *span, E0470,
"reexported macro not found");
}
}
return ret
}
/// Load the custom derive macros into the list of macros we're loading.
///
/// 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,
span: Span,
macros: &Macros,
index: DefIndex,
ret: &mut Vec<LoadedMacro>) {
// Make sure the path contains a / or the linker will search for it.
let path = macros.dylib.as_ref().unwrap();
let path = env::current_dir().unwrap().join(path);
let lib = match DynamicLibrary::open(Some(&path)) {
Ok(lib) => lib,
Err(err) => self.sess.span_fatal(span, &err),
};
let sym = self.sess.generate_derive_registrar_symbol(&macros.svh, index);
let registrar = unsafe {
let sym = match lib.symbol(&sym) {
Ok(f) => f,
Err(err) => self.sess.span_fatal(span, &err),
};
mem::transmute::<*mut u8, fn(&mut Registry)>(sym)
};
struct MyRegistrar<'a>(&'a mut Vec<LoadedMacro>, Span);
impl<'a> Registry for MyRegistrar<'a> {
fn register_custom_derive(&mut self,
trait_name: &str,
expand: fn(TokenStream) -> TokenStream) {
let derive = Box::new(CustomDerive::new(expand));
self.0.push(LoadedMacro {
kind: LoadedMacroKind::CustomDerive(trait_name.to_string(), derive),
import_site: self.1,
});
}
}
registrar(&mut MyRegistrar(ret, span));
// 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);
}
}

View File

@ -21,10 +21,11 @@ use {NameBinding, NameBindingKind, ToNameBinding};
use Resolver; use Resolver;
use {resolve_error, resolve_struct_error, ResolutionError}; use {resolve_error, resolve_struct_error, ResolutionError};
use rustc::middle::cstore::LoadedMacroKind; use rustc::middle::cstore::LoadedMacros;
use rustc::hir::def::*; use rustc::hir::def::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty; use rustc::ty;
use rustc::util::nodemap::FnvHashMap;
use std::cell::Cell; use std::cell::Cell;
use std::rc::Rc; use std::rc::Rc;
@ -58,6 +59,14 @@ impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
} }
} }
#[derive(Default, PartialEq, Eq)]
struct LegacyMacroImports {
import_all: Option<Span>,
imports: Vec<(Name, Span)>,
reexports: Vec<(Name, Span)>,
no_link: bool,
}
impl<'b> Resolver<'b> { impl<'b> Resolver<'b> {
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
/// otherwise, reports an error. /// otherwise, reports an error.
@ -193,57 +202,27 @@ impl<'b> Resolver<'b> {
} }
ItemKind::ExternCrate(_) => { ItemKind::ExternCrate(_) => {
// We need to error on `#[macro_use] extern crate` when it isn't at the let legacy_imports = self.legacy_macro_imports(&item.attrs);
// crate root, because `$crate` won't work properly. // `#[macro_use]` and `#[macro_reexport]` are only allowed at the crate root.
let is_crate_root = self.current_module.parent.is_none(); if self.current_module.parent.is_some() && {
let import_macro = |this: &mut Self, name, ext, span| { legacy_imports.import_all.is_some() || !legacy_imports.imports.is_empty() ||
let shadowing = this.builtin_macros.insert(name, Rc::new(ext)).is_some(); !legacy_imports.reexports.is_empty()
if shadowing && expansion != Mark::root() { } {
let msg = format!("`{}` is already in scope", name); if self.current_module.parent.is_some() {
this.session.struct_span_err(span, &msg) span_err!(self.session, item.span, E0468,
.note("macro-expanded `#[macro_use]`s may not shadow \ "an `extern crate` loading macros must be at the crate root");
existing macros (see RFC 1560)")
.emit();
} }
}
let loaded_macros = if legacy_imports != LegacyMacroImports::default() {
self.crate_loader.process_item(item, &self.definitions, true)
} else {
self.crate_loader.process_item(item, &self.definitions, false)
}; };
let mut custom_derive_crate = false;
// The mark of the expansion that generates the loaded macros.
let mut opt_mark = None;
for loaded_macro in self.crate_loader.load_macros(item, is_crate_root) {
let mark = opt_mark.unwrap_or_else(Mark::fresh);
opt_mark = Some(mark);
match loaded_macro.kind {
LoadedMacroKind::Def(mut def) => {
if def.use_locally {
self.macro_names.insert(def.ident.name);
def.body = mark_tts(&def.body, mark);
let ext = macro_rules::compile(&self.session.parse_sess, &def);
import_macro(self, def.ident.name, ext, loaded_macro.import_site);
}
if def.export {
def.id = self.next_node_id();
self.exported_macros.push(def);
}
}
LoadedMacroKind::CustomDerive(name, ext) => {
custom_derive_crate = true;
let ext = SyntaxExtension::CustomDerive(ext);
import_macro(self, token::intern(&name), ext, loaded_macro.import_site);
}
}
}
if custom_derive_crate && !self.session.features.borrow().proc_macro {
let issue = feature_gate::GateIssue::Language;
let msg = "loading custom derive macro crates is experimentally supported";
emit_feature_err(&self.session.parse_sess, "proc_macro", item.span, issue, msg);
}
self.crate_loader.process_item(item, &self.definitions);
// n.b. we don't need to look at the path option here, because cstore already did // n.b. we don't need to look at the path option here, because cstore already did
if let Some(crate_id) = self.session.cstore.extern_mod_stmt_cnum(item.id) { let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id);
let module = if let Some(crate_id) = crate_id {
let def_id = DefId { let def_id = DefId {
krate: crate_id, krate: crate_id,
index: CRATE_DEF_INDEX, index: CRATE_DEF_INDEX,
@ -254,25 +233,21 @@ impl<'b> Resolver<'b> {
..ModuleS::new(Some(parent), ModuleKind::Def(Def::Mod(def_id), name)) ..ModuleS::new(Some(parent), ModuleKind::Def(Def::Mod(def_id), name))
}); });
self.define(parent, name, TypeNS, (module, sp, vis)); self.define(parent, name, TypeNS, (module, sp, vis));
if let Some(mark) = opt_mark {
let invocation = self.arenas.alloc_invocation_data(InvocationData {
module: Cell::new(module),
def_index: CRATE_DEF_INDEX,
const_integer: false,
legacy_scope: Cell::new(LegacyScope::Empty),
expansion: Cell::new(LegacyScope::Empty),
});
self.invocations.insert(mark, invocation);
}
self.populate_module_if_necessary(module); self.populate_module_if_necessary(module);
module
} else { } else {
// Define an empty module // Define an empty module
let def = Def::Mod(self.definitions.local_def_id(item.id)); let def = Def::Mod(self.definitions.local_def_id(item.id));
let module = ModuleS::new(Some(parent), ModuleKind::Def(def, name)); let module = ModuleS::new(Some(parent), ModuleKind::Def(def, name));
let module = self.arenas.alloc_module(module); let module = self.arenas.alloc_module(module);
self.define(parent, name, TypeNS, (module, sp, vis)); self.define(parent, name, TypeNS, (module, sp, vis));
module
};
if let Some(loaded_macros) = loaded_macros {
self.import_extern_crate_macros(
item, module, loaded_macros, legacy_imports, expansion == Mark::root(),
);
} }
} }
@ -294,7 +269,9 @@ impl<'b> Resolver<'b> {
self.current_module = module; self.current_module = module;
} }
ItemKind::ForeignMod(..) => self.crate_loader.process_item(item, &self.definitions), ItemKind::ForeignMod(..) => {
self.crate_loader.process_item(item, &self.definitions, false);
}
// These items live in the value namespace. // These items live in the value namespace.
ItemKind::Static(_, m, _) => { ItemKind::Static(_, m, _) => {
@ -516,6 +493,93 @@ impl<'b> Resolver<'b> {
module.populated.set(true) module.populated.set(true)
} }
fn import_extern_crate_macros(&mut self,
extern_crate: &Item,
module: Module<'b>,
loaded_macros: LoadedMacros,
legacy_imports: LegacyMacroImports,
allow_shadowing: bool) {
let import_macro = |this: &mut Self, name, ext: Rc<_>, span| {
if let SyntaxExtension::NormalTT(..) = *ext {
this.macro_names.insert(name);
}
if this.builtin_macros.insert(name, ext).is_some() && !allow_shadowing {
let msg = format!("`{}` is already in scope", name);
let note =
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
this.session.struct_span_err(span, &msg).note(note).emit();
}
};
match loaded_macros {
LoadedMacros::MacroRules(macros) => {
let mark = Mark::fresh();
if !macros.is_empty() {
let invocation = self.arenas.alloc_invocation_data(InvocationData {
module: Cell::new(module),
def_index: CRATE_DEF_INDEX,
const_integer: false,
legacy_scope: Cell::new(LegacyScope::Empty),
expansion: Cell::new(LegacyScope::Empty),
});
self.invocations.insert(mark, invocation);
}
let mut macros: FnvHashMap<_, _> = macros.into_iter().map(|mut def| {
def.body = mark_tts(&def.body, mark);
let ext = macro_rules::compile(&self.session.parse_sess, &def);
(def.ident.name, (def, Rc::new(ext)))
}).collect();
if let Some(span) = legacy_imports.import_all {
for (&name, &(_, ref ext)) in macros.iter() {
import_macro(self, name, ext.clone(), span);
}
} else {
for (name, span) in legacy_imports.imports {
if let Some(&(_, ref ext)) = macros.get(&name) {
import_macro(self, name, ext.clone(), span);
} else {
span_err!(self.session, span, E0469, "imported macro not found");
}
}
}
for (name, span) in legacy_imports.reexports {
if let Some((mut def, _)) = macros.remove(&name) {
def.id = self.next_node_id();
self.exported_macros.push(def);
} else {
span_err!(self.session, span, E0470, "reexported macro not found");
}
}
}
LoadedMacros::ProcMacros(macros) => {
if !self.session.features.borrow().proc_macro {
let sess = &self.session.parse_sess;
let issue = feature_gate::GateIssue::Language;
let msg =
"loading custom derive macro crates is experimentally supported";
emit_feature_err(sess, "proc_macro", extern_crate.span, issue, msg);
}
if !legacy_imports.imports.is_empty() {
let msg = "`proc-macro` crates cannot be selectively imported from, \
must use `#[macro_use]`";
self.session.span_err(extern_crate.span, msg);
}
if !legacy_imports.reexports.is_empty() {
let msg = "`proc-macro` crates cannot be reexported from";
self.session.span_err(extern_crate.span, msg);
}
if let Some(span) = legacy_imports.import_all {
for (name, ext) in macros {
import_macro(self, name, Rc::new(ext), span);
}
}
}
}
}
// does this attribute list contain "macro_use"? // does this attribute list contain "macro_use"?
fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool { fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
for attr in attrs { for attr in attrs {
@ -539,6 +603,42 @@ impl<'b> Resolver<'b> {
false false
} }
fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImports {
let mut imports = LegacyMacroImports::default();
for attr in attrs {
if attr.check_name("macro_use") {
match attr.meta_item_list() {
Some(names) => for attr in names {
if let Some(word) = attr.word() {
imports.imports.push((token::intern(&word.name()), attr.span()));
} else {
span_err!(self.session, attr.span(), E0466, "bad macro import");
}
},
None => imports.import_all = Some(attr.span),
}
} else if attr.check_name("macro_reexport") {
let bad_macro_reexport = |this: &mut Self, span| {
span_err!(this.session, span, E0467, "bad macro reexport");
};
if let Some(names) = attr.meta_item_list() {
for attr in names {
if let Some(word) = attr.word() {
imports.reexports.push((token::intern(&word.name()), attr.span()));
} else {
bad_macro_reexport(self, attr.span());
}
}
} else {
bad_macro_reexport(self, attr.span());
}
} else if attr.check_name("no_link") {
imports.no_link = true;
}
}
imports
}
} }
pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { pub struct BuildReducedGraphVisitor<'a, 'b: 'a> {

View File

@ -1272,6 +1272,185 @@ impl Foo for i32 {}
``` ```
"##, "##,
E0466: r##"
Macro import declarations were malformed.
Erroneous code examples:
```compile_fail,E0466
#[macro_use(a_macro(another_macro))] // error: invalid import declaration
extern crate core as some_crate;
#[macro_use(i_want = "some_macros")] // error: invalid import declaration
extern crate core as another_crate;
```
This is a syntax error at the level of attribute declarations. The proper
syntax for macro imports is the following:
```ignore
// In some_crate:
#[macro_export]
macro_rules! get_tacos {
...
}
#[macro_export]
macro_rules! get_pimientos {
...
}
// In your crate:
#[macro_use(get_tacos, get_pimientos)] // It imports `get_tacos` and
extern crate some_crate; // `get_pimientos` macros from some_crate
```
If you would like to import all exported macros, write `macro_use` with no
arguments.
"##,
E0467: r##"
Macro reexport declarations were empty or malformed.
Erroneous code examples:
```compile_fail,E0467
#[macro_reexport] // error: no macros listed for export
extern crate core as macros_for_good;
#[macro_reexport(fun_macro = "foo")] // error: not a macro identifier
extern crate core as other_macros_for_good;
```
This is a syntax error at the level of attribute declarations.
Currently, `macro_reexport` requires at least one macro name to be listed.
Unlike `macro_use`, listing no names does not reexport all macros from the
given crate.
Decide which macros you would like to export and list them properly.
These are proper reexport declarations:
```ignore
#[macro_reexport(some_macro, another_macro)]
extern crate macros_for_good;
```
"##,
E0468: r##"
A non-root module attempts to import macros from another crate.
Example of erroneous code:
```compile_fail,E0468
mod foo {
#[macro_use(helpful_macro)] // error: must be at crate root to import
extern crate core; // macros from another crate
helpful_macro!(...);
}
```
Only `extern crate` imports at the crate root level are allowed to import
macros.
Either move the macro import to crate root or do without the foreign macros.
This will work:
```ignore
#[macro_use(helpful_macro)]
extern crate some_crate;
mod foo {
helpful_macro!(...)
}
```
"##,
E0469: r##"
A macro listed for import was not found.
Erroneous code example:
```compile_fail,E0469
#[macro_use(drink, be_merry)] // error: imported macro not found
extern crate collections;
fn main() {
// ...
}
```
Either the listed macro is not contained in the imported crate, or it is not
exported from the given crate.
This could be caused by a typo. Did you misspell the macro's name?
Double-check the names of the macros listed for import, and that the crate
in question exports them.
A working version would be:
```ignore
// In some_crate crate:
#[macro_export]
macro_rules! eat {
...
}
#[macro_export]
macro_rules! drink {
...
}
// In your crate:
#[macro_use(eat, drink)]
extern crate some_crate; //ok!
```
"##,
E0470: r##"
A macro listed for reexport was not found.
Erroneous code example:
```compile_fail,E0470
#[macro_reexport(drink, be_merry)]
extern crate collections;
fn main() {
// ...
}
```
Either the listed macro is not contained in the imported crate, or it is not
exported from the given crate.
This could be caused by a typo. Did you misspell the macro's name?
Double-check the names of the macros listed for reexport, and that the crate
in question exports them.
A working version:
```ignore
// In some_crate crate:
#[macro_export]
macro_rules! eat {
...
}
#[macro_export]
macro_rules! drink {
...
}
// In your_crate:
#[macro_reexport(eat, drink)]
extern crate some_crate;
```
"##,
E0530: r##" E0530: r##"
A binding shadowed something it shouldn't. A binding shadowed something it shouldn't.

View File

@ -114,22 +114,22 @@ impl<'a> base::Resolver for Resolver<'a> {
invocation.expansion.set(visitor.legacy_scope); invocation.expansion.set(visitor.legacy_scope);
} }
fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) { fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef, export: bool) {
if &def.ident.name.as_str() == "macro_rules" { if &def.ident.name.as_str() == "macro_rules" {
self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`"); self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`");
} }
if def.use_locally {
let invocation = self.invocations[&scope]; let invocation = self.invocations[&scope];
let binding = self.arenas.alloc_legacy_binding(LegacyBinding { let binding = self.arenas.alloc_legacy_binding(LegacyBinding {
parent: invocation.legacy_scope.get(), parent: invocation.legacy_scope.get(),
name: def.ident.name, name: def.ident.name,
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)), ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
span: def.span, span: def.span,
}); });
invocation.legacy_scope.set(LegacyScope::Binding(binding)); invocation.legacy_scope.set(LegacyScope::Binding(binding));
self.macro_names.insert(def.ident.name); self.macro_names.insert(def.ident.name);
}
if def.export { if export {
def.id = self.next_node_id(); def.id = self.next_node_id();
self.exported_macros.push(def); self.exported_macros.push(def);
} }

View File

@ -2012,8 +2012,6 @@ pub struct MacroDef {
pub id: NodeId, pub id: NodeId,
pub span: Span, pub span: Span,
pub imported_from: Option<Ident>, pub imported_from: Option<Ident>,
pub export: bool,
pub use_locally: bool,
pub allow_internal_unstable: bool, pub allow_internal_unstable: bool,
pub body: Vec<TokenTree>, pub body: Vec<TokenTree>,
} }

View File

@ -519,7 +519,7 @@ pub trait Resolver {
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion); fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
fn add_macro(&mut self, scope: Mark, def: ast::MacroDef); fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool);
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>); fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>); fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
@ -541,7 +541,7 @@ impl Resolver for DummyResolver {
fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {} fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef) {} fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {}
fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {} fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {} fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

View File

@ -157,14 +157,13 @@ impl IdentMacroExpander for MacroRulesExpander {
tts: Vec<tokenstream::TokenTree>, tts: Vec<tokenstream::TokenTree>,
attrs: Vec<ast::Attribute>) attrs: Vec<ast::Attribute>)
-> Box<MacResult> { -> Box<MacResult> {
let export = attr::contains_name(&attrs, "macro_export");
let def = ast::MacroDef { let def = ast::MacroDef {
ident: ident, ident: ident,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: span, span: span,
imported_from: None, imported_from: None,
use_locally: true,
body: tts, body: tts,
export: attr::contains_name(&attrs, "macro_export"),
allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"), allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
attrs: attrs, attrs: attrs,
}; };
@ -176,7 +175,7 @@ impl IdentMacroExpander for MacroRulesExpander {
MacEager::items(placeholders::macro_scope_placeholder().make_items()) MacEager::items(placeholders::macro_scope_placeholder().make_items())
}; };
cx.resolver.add_macro(cx.current_expansion.mark, def); cx.resolver.add_macro(cx.current_expansion.mark, def, export);
result result
} }
} }