diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-10-28 06:52:45 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-11-10 10:04:24 +0000 |
| commit | 872943c3172619afa275987c4ad3e2041ede9fa3 (patch) | |
| tree | 834c54f834381a238cfddc793461650a267ed31f | |
| parent | 85f74c0eea3667e85720d6f427709873eb576b49 (diff) | |
| download | rust-872943c3172619afa275987c4ad3e2041ede9fa3.tar.gz rust-872943c3172619afa275987c4ad3e2041ede9fa3.zip | |
Improve macro reexports.
| -rw-r--r-- | src/librustc/hir/def_id.rs | 4 | ||||
| -rw-r--r-- | src/librustc/hir/map/collector.rs | 4 | ||||
| -rw-r--r-- | src/librustc/middle/cstore.rs | 18 | ||||
| -rw-r--r-- | src/librustc_metadata/creader.rs | 117 | ||||
| -rw-r--r-- | src/librustc_metadata/cstore_impl.rs | 41 | ||||
| -rw-r--r-- | src/librustc_metadata/decoder.rs | 9 | ||||
| -rw-r--r-- | src/librustc_metadata/encoder.rs | 55 | ||||
| -rw-r--r-- | src/librustc_metadata/index_builder.rs | 1 | ||||
| -rw-r--r-- | src/librustc_metadata/schema.rs | 2 | ||||
| -rw-r--r-- | src/librustc_resolve/build_reduced_graph.rs | 178 | ||||
| -rw-r--r-- | src/librustc_resolve/lib.rs | 13 | ||||
| -rw-r--r-- | src/librustc_resolve/macros.rs | 22 | ||||
| -rw-r--r-- | src/librustc_resolve/resolve_imports.rs | 5 |
13 files changed, 241 insertions, 228 deletions
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 399243551d6..d3771b1755b 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -34,6 +34,10 @@ impl Idx for CrateNum { /// LOCAL_CRATE in their DefId. pub const LOCAL_CRATE: CrateNum = CrateNum(0); +/// Virtual crate for builtin macros +// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s. +pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(!0); + impl CrateNum { pub fn new(x: usize) -> CrateNum { assert!(x < (u32::MAX as usize)); diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index e23a721da08..04fcf7e8450 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -226,4 +226,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) { self.insert(lifetime.id, NodeLifetime(lifetime)); } + + fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) { + self.insert_entry(macro_def.id, NotPresent); + } } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index bdef44bf5c1..db3c7d0450b 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -211,6 +211,7 @@ pub trait CrateStore<'tcx> { fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath>; fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>; fn item_children(&self, did: DefId) -> Vec<def::Export>; + fn load_macro(&self, did: DefId, sess: &Session) -> ast::MacroDef; // misc. metadata fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -382,6 +383,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { } fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") } fn item_children(&self, did: DefId) -> Vec<def::Export> { bug!("item_children") } + fn load_macro(&self, did: DefId, sess: &Session) -> ast::MacroDef { bug!("load_macro") } // misc. metadata fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) @@ -421,22 +423,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } } -pub enum LoadedMacros { - MacroRules(Vec<ast::MacroDef>), - ProcMacros(Vec<(ast::Name, SyntaxExtension)>), -} - -impl LoadedMacros { - pub fn is_proc_macros(&self) -> bool { - match *self { - LoadedMacros::ProcMacros(_) => true, - _ => false, - } - } -} - pub trait CrateLoader { fn process_item(&mut self, item: &ast::Item, defs: &Definitions, load_macros: bool) - -> Option<LoadedMacros>; + -> Vec<(ast::Name, SyntaxExtension)>; fn postprocess(&mut self, krate: &ast::Crate); } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 9101f95c882..e53f1a0633b 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -16,7 +16,7 @@ use schema::CrateRoot; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; -use rustc::middle::cstore::{DepKind, LoadedMacros}; +use rustc::middle::cstore::DepKind; use rustc::session::{config, Session}; use rustc_back::PanicStrategy; use rustc::session::search_paths::PathKind; @@ -33,11 +33,11 @@ use std::{cmp, fs}; use syntax::ast; use syntax::abi::Abi; -use syntax::parse; use syntax::attr; use syntax::ext::base::SyntaxExtension; +use syntax::feature_gate::{self, emit_feature_err}; use syntax::parse::token::{InternedString, intern}; -use syntax_pos::{Span, DUMMY_SP, mk_sp}; +use syntax_pos::{Span, DUMMY_SP}; use log; pub struct Library { @@ -518,68 +518,6 @@ impl<'a> CrateLoader<'a> { } } - fn read_macros(&mut self, item: &ast::Item, ekrate: &ExtensionCrate) -> LoadedMacros { - let root = ekrate.metadata.get_root(); - let source_name = format!("<{} macros>", item.ident); - let mut macro_rules = Vec::new(); - - for def in root.macro_defs.decode(&*ekrate.metadata) { - // NB: Don't use parse::parse_tts_from_source_str because it parses with - // quote_depth > 0. - let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess, - source_name.clone(), - def.body); - let lo = p.span.lo; - let body = match p.parse_all_token_trees() { - Ok(body) => body, - Err(mut err) => { - err.emit(); - self.sess.abort_if_errors(); - unreachable!(); - } - }; - let local_span = mk_sp(lo, p.prev_span.hi); - - // Mark the attrs as used - for attr in &def.attrs { - attr::mark_used(attr); - } - - macro_rules.push(ast::MacroDef { - ident: ast::Ident::with_empty_ctxt(def.name), - id: ast::DUMMY_NODE_ID, - span: local_span, - imported_from: Some(item.ident), - allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"), - attrs: def.attrs, - body: body, - }); - self.sess.imported_macro_spans.borrow_mut() - .insert(local_span, (def.name.as_str().to_string(), def.span)); - } - - if let Some(id) = root.macro_derive_registrar { - 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); - } - - // custom derive crates currently should not have any macro_rules! - // exported macros, enforced elsewhere - assert_eq!(macro_rules.len(), 0); - LoadedMacros::ProcMacros(self.load_derive_macros(item, id, root.hash, dylib)) - } else { - LoadedMacros::MacroRules(macro_rules) - } - } - /// Load custom derive macros. /// /// Note that this is intentionally similar to how we load plugins today, @@ -587,14 +525,34 @@ impl<'a> CrateLoader<'a> { /// 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)> { + fn load_derive_macros(&mut self, item: &ast::Item, ekrate: &ExtensionCrate) + -> Option<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; + let root = ekrate.metadata.get_root(); + let index = match root.macro_derive_registrar { + Some(index) => index, + None => return None, + }; + if !self.sess.features.borrow().proc_macro { + let issue = feature_gate::GateIssue::Language; + let msg = "loading custom derive macro crates is experimentally supported"; + emit_feature_err(&self.sess.parse_sess, "proc_macro", item.span, issue, msg); + } + + if ekrate.target_only { + let msg = 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, &msg); + } + let path = match ekrate.dylib.clone() { + Some(dylib) => dylib, + None => span_bug!(item.span, "proc-macro crate not dylib"), + }; // 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)) { @@ -602,7 +560,7 @@ impl<'a> CrateLoader<'a> { Err(err) => self.sess.span_fatal(item.span, &err), }; - let sym = self.sess.generate_derive_registrar_symbol(&svh, index); + let sym = self.sess.generate_derive_registrar_symbol(&root.hash, index); let registrar = unsafe { let sym = match lib.symbol(&sym) { Ok(f) => f, @@ -632,7 +590,7 @@ impl<'a> CrateLoader<'a> { // 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); - my_registrar.0 + Some(my_registrar.0) } /// Look for a plugin registrar. Returns library path, crate @@ -971,24 +929,23 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } fn process_item(&mut self, item: &ast::Item, definitions: &Definitions, load_macros: bool) - -> Option<LoadedMacros> { + -> Vec<(ast::Name, SyntaxExtension)> { match item.node { ast::ItemKind::ExternCrate(_) => {} ast::ItemKind::ForeignMod(ref fm) => { self.process_foreign_mod(item, fm); - return None; + return Vec::new(); } - _ => return None, + _ => return Vec::new(), } let info = self.extract_crate_info(item).unwrap(); - let loaded_macros = if load_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, return here to avoid registering. - if loaded_macros.is_proc_macros() { - return Some(loaded_macros); + if let Some(custom_derives) = self.load_derive_macros(item, &ekrate) { + return custom_derives; } // Register crate now to avoid double-reading metadata @@ -998,11 +955,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { self.register_crate(&None, ident, name, item.span, lib, dep_kind); } } - - Some(loaded_macros) - } else { - None - }; + } let (cnum, ..) = self.resolve_crate( &None, &info.ident, &info.name, None, item.span, PathKind::Crate, info.dep_kind, @@ -1016,6 +969,6 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { self.update_extern_crate(cnum, extern_crate, &mut FxHashSet()); self.cstore.add_extern_mod_stmt_cnum(info.id, cnum); - loaded_macros + Vec::new() } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 59f65c7f7c7..3113bfcb5b4 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -17,6 +17,7 @@ use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, DepKind, Exter use rustc::middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference}; use rustc::hir::def::{self, Def}; use rustc::middle::lang_items; +use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; @@ -30,7 +31,8 @@ use rustc_back::PanicStrategy; use std::path::PathBuf; use syntax::ast; use syntax::attr; -use syntax::parse::token; +use syntax::parse::{token, new_parser_from_source_str}; +use syntax_pos::mk_sp; use rustc::hir::svh::Svh; use rustc_back::target::Target; use rustc::hir; @@ -351,6 +353,43 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } + fn load_macro(&self, id: DefId, sess: &Session) -> ast::MacroDef { + let (name, def) = self.get_crate_data(id.krate).get_macro(id.index); + let source_name = format!("<{} macros>", name); + + // NB: Don't use parse_tts_from_source_str because it parses with quote_depth > 0. + let mut parser = new_parser_from_source_str(&sess.parse_sess, source_name, def.body); + + let lo = parser.span.lo; + let body = match parser.parse_all_token_trees() { + Ok(body) => body, + Err(mut err) => { + err.emit(); + sess.abort_if_errors(); + unreachable!(); + } + }; + let local_span = mk_sp(lo, parser.prev_span.hi); + + // Mark the attrs as used + for attr in &def.attrs { + attr::mark_used(attr); + } + + sess.imported_macro_spans.borrow_mut() + .insert(local_span, (def.name.as_str().to_string(), def.span)); + + ast::MacroDef { + ident: ast::Ident::with_empty_ctxt(def.name), + id: ast::DUMMY_NODE_ID, + span: local_span, + imported_from: None, // FIXME + allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"), + attrs: def.attrs, + body: body, + } + } + fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 8eae4658983..64a90d56d55 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -468,6 +468,7 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Variant(_) => Def::Variant(did), EntryKind::Trait(_) => Def::Trait(did), EntryKind::Enum => Def::Enum(did), + EntryKind::MacroDef(_) => Def::Macro(did), EntryKind::ForeignMod | EntryKind::Impl(_) | @@ -1004,6 +1005,14 @@ impl<'a, 'tcx> CrateMetadata { self.root.reachable_ids.decode(self).map(|index| self.local_def_id(index)).collect() } + pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) { + let entry = self.entry(id); + match entry.kind { + EntryKind::MacroDef(macro_def) => (self.item_name(&entry), macro_def.decode(self)), + _ => bug!(), + } + } + pub fn is_const_fn(&self, id: DefIndex) -> bool { let constness = match self.entry(id).kind { EntryKind::Method(data) => data.decode(self).fn_data.constness, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 931ddb3cf8d..ac1f2afcb2a 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -830,6 +830,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }, } } + + /// Serialize the text of exported macros + fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { + let def_id = self.tcx.map.local_def_id(macro_def.id); + let macro_def = MacroDef { + name: macro_def.name, + attrs: macro_def.attrs.to_vec(), + span: macro_def.span, + body: ::syntax::print::pprust::tts_to_string(¯o_def.body) + }; + Entry { + kind: EntryKind::MacroDef(self.lazy(¯o_def)), + visibility: ty::Visibility::Public, + def_key: self.encode_def_key(def_id), + + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: None, + deprecation: None, + ty: None, + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: None, + predicates: None, + ast: None, + mir: None, + } + } } impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { @@ -964,6 +992,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { intravisit::walk_ty(self, ty); self.index.encode_info_for_ty(ty); } + fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { + let def_id = self.index.tcx.map.local_def_id(macro_def.id); + self.index.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); + } } impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { @@ -1043,6 +1075,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); let mut visitor = EncodeVisitor { index: index }; krate.visit_all_items(&mut visitor); + for macro_def in &krate.exported_macros { + visitor.visit_macro_def(macro_def); + } visitor.index.into_items() } @@ -1122,19 +1157,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) .map(|filemap| &**filemap)) } - - /// Serialize the text of the exported macros - fn encode_macro_defs(&mut self) -> LazySeq<MacroDef> { - let tcx = self.tcx; - self.lazy_seq(tcx.map.krate().exported_macros.iter().map(|def| { - MacroDef { - name: def.name, - attrs: def.attrs.to_vec(), - span: def.span, - body: ::syntax::print::pprust::tts_to_string(&def.body), - } - })) - } } struct ImplVisitor<'a, 'tcx: 'a> { @@ -1228,11 +1250,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let codemap = self.encode_codemap(); let codemap_bytes = self.position() - i; - // Encode macro definitions - i = self.position(); - let macro_defs = self.encode_macro_defs(); - let macro_defs_bytes = self.position() - i; - // Encode the def IDs of impls, for coherence checking. i = self.position(); let impls = self.encode_impls(); @@ -1279,7 +1296,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { lang_items_missing: lang_items_missing, native_libraries: native_libraries, codemap: codemap, - macro_defs: macro_defs, impls: impls, reachable_ids: reachable_ids, index: index, @@ -1300,7 +1316,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" lang item bytes: {}", lang_item_bytes); println!(" native bytes: {}", native_lib_bytes); println!(" codemap bytes: {}", codemap_bytes); - println!(" macro def bytes: {}", macro_defs_bytes); println!(" impl bytes: {}", impl_bytes); println!(" reachable bytes: {}", reachable_bytes); println!(" item bytes: {}", item_bytes); diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 9938e20d186..1a74a925454 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -195,6 +195,7 @@ read_hir!(hir::Item); read_hir!(hir::ImplItem); read_hir!(hir::TraitItem); read_hir!(hir::ForeignItem); +read_hir!(hir::MacroDef); /// Leaks access to a value of type T without any tracking. This is /// suitable for ambiguous types like `usize`, which *could* represent diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 5b1774a1984..d7a5f7ad715 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -177,7 +177,6 @@ pub struct CrateRoot { pub lang_items_missing: LazySeq<lang_items::LangItem>, pub native_libraries: LazySeq<(NativeLibraryKind, String)>, pub codemap: LazySeq<syntax_pos::FileMap>, - pub macro_defs: LazySeq<MacroDef>, pub impls: LazySeq<TraitImpls>, pub reachable_ids: LazySeq<DefIndex>, pub index: LazySeq<index::Index>, @@ -241,6 +240,7 @@ pub enum EntryKind<'tcx> { Fn(Lazy<FnData>), ForeignFn(Lazy<FnData>), Mod(Lazy<ModData>), + MacroDef(Lazy<MacroDef>), Closure(Lazy<ClosureData<'tcx>>), Trait(Lazy<TraitData<'tcx>>), Impl(Lazy<ImplData<'tcx>>), diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 5fb9809104f..0833f85c1f6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -16,17 +16,15 @@ use macros::{InvocationData, LegacyScope}; use resolve_imports::ImportDirective; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport}; -use {Module, ModuleS, ModuleKind}; +use {Resolver, Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; -use {NameBinding, NameBindingKind, ToNameBinding}; -use Resolver; +use ResolveResult::Success; use {resolve_error, resolve_struct_error, ResolutionError}; -use rustc::middle::cstore::{DepKind, LoadedMacros}; +use rustc::middle::cstore::DepKind; use rustc::hir::def::*; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, BUILTIN_MACROS_CRATE}; use rustc::ty; -use rustc::util::nodemap::FxHashMap; use std::cell::Cell; use std::rc::Rc; @@ -38,10 +36,9 @@ use syntax::parse::token; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple}; -use syntax::ext::base::{SyntaxExtension, Resolver as SyntaxResolver}; +use syntax::ext::base::SyntaxExtension; use syntax::ext::expand::mark_tts; use syntax::ext::hygiene::Mark; -use syntax::feature_gate::{self, emit_feature_err}; use syntax::ext::tt::macro_rules; use syntax::parse::token::keywords; use syntax::visit::{self, Visitor}; @@ -227,7 +224,7 @@ impl<'b> Resolver<'b> { } let load_macros = legacy_imports != LegacyMacroImports::default(); - let loaded_macros = + let proc_macros = self.crate_loader.process_item(item, &self.definitions, load_macros); // n.b. we don't need to look at the path option here, because cstore already did @@ -250,19 +247,25 @@ impl<'b> Resolver<'b> { self.populate_module_if_necessary(module); module } else { - // Define an empty module - let def = Def::Mod(self.definitions.local_def_id(item.id)); - let module = ModuleS::new(Some(parent), ModuleKind::Def(def, name)); - let module = self.arenas.alloc_module(module); + // Define a module and populate it with proc macros. + let module_kind = + ModuleKind::Def(Def::Mod(self.definitions.local_def_id(item.id)), name); + let module = self.arenas.alloc_module(ModuleS::new(None, module_kind)); self.define(parent, name, TypeNS, (module, sp, vis)); + for (name, ext) in proc_macros { + let def_id = DefId { + krate: BUILTIN_MACROS_CRATE, + index: DefIndex::new(self.macro_map.len()), + }; + self.macro_map.insert(def_id, Rc::new(ext)); + let vis = ty::Visibility::Public; + self.define(module, name, MacroNS, (Def::Macro(def_id), DUMMY_SP, vis)); + } module }; - if let Some(loaded_macros) = loaded_macros { - self.import_extern_crate_macros( - item, module, loaded_macros, legacy_imports, expansion == Mark::root(), - ); - } + let allow_shadowing = expansion == Mark::root(); + self.process_legacy_macro_imports(module, legacy_imports, allow_shadowing); } ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root @@ -512,6 +515,31 @@ impl<'b> Resolver<'b> { }) } + pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> { + let def_id = match def { + Def::Macro(def_id) => def_id, + _ => panic!("Expected Def::Macro(..)"), + }; + if let Some(ext) = self.macro_map.get(&def_id) { + return ext.clone(); + } + + let mut macro_rules = self.session.cstore.load_macro(def_id, &self.session); + let mark = Mark::fresh(); + let invocation = self.arenas.alloc_invocation_data(InvocationData { + module: Cell::new(self.get_extern_crate_root(def_id.krate)), + def_index: CRATE_DEF_INDEX, + const_integer: false, + legacy_scope: Cell::new(LegacyScope::Empty), + expansion: Cell::new(LegacyScope::Empty), + }); + self.invocations.insert(mark, invocation); + macro_rules.body = mark_tts(¯o_rules.body, mark); + let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, ¯o_rules)); + self.macro_map.insert(def_id, ext.clone()); + ext + } + /// Ensures that the reduced graph rooted at the given external module /// is built, building it if it is not. pub fn populate_module_if_necessary(&mut self, module: Module<'b>) { @@ -522,90 +550,46 @@ impl<'b> Resolver<'b> { 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| { - this.used_crates.insert(module.def_id().unwrap().krate); - 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: FxHashMap<_, _> = 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(); + fn legacy_import_macro(&mut self, name: Name, def: Def, span: Span, allow_shadowing: bool) { + self.used_crates.insert(def.def_id().krate); + self.macro_names.insert(name); + if self.builtin_macros.insert(name, def.def_id()).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)"; + self.session.struct_span_err(span, &msg).note(note).emit(); + } + } - if let Some(span) = legacy_imports.import_all { - for (&name, &(_, ref ext)) in macros.iter() { - import_macro(self, name, ext.clone(), span); - } + fn process_legacy_macro_imports(&mut self, + module: Module<'b>, + legacy_imports: LegacyMacroImports, + allow_shadowing: bool) { + if let Some(span) = legacy_imports.import_all { + module.for_each_child(|name, ns, binding| if ns == MacroNS { + self.legacy_import_macro(name, binding.def(), span, allow_shadowing); + }); + } else { + for (name, span) in legacy_imports.imports { + let result = self.resolve_name_in_module(module, name, MacroNS, false, None); + if let Success(binding) = result { + self.legacy_import_macro(name, binding.def(), span, allow_shadowing); } 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"); - } + span_err!(self.session, span, E0469, "imported 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); - } + } + for (name, span) in legacy_imports.reexports { + self.used_crates.insert(module.def_id().unwrap().krate); + let result = self.resolve_name_in_module(module, name, MacroNS, false, None); + if let Success(binding) = result { + let def = binding.def(); + if let Def::Macro(DefId { krate: BUILTIN_MACROS_CRATE, .. }) = def { + self.session.span_err(span, "`proc-macro` crates cannot be reexported from"); } + self.macro_exports.push(Export { name: name, def: def }); + } else { + span_err!(self.session, span, E0470, "reexported macro not found"); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 31711c0526d..fe90cd34687 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1111,8 +1111,10 @@ pub struct Resolver<'a> { pub exported_macros: Vec<ast::MacroDef>, crate_loader: &'a mut CrateLoader, macro_names: FxHashSet<Name>, - builtin_macros: FxHashMap<Name, Rc<SyntaxExtension>>, + builtin_macros: FxHashMap<Name, DefId>, lexical_macro_resolutions: Vec<(Name, LegacyScope<'a>)>, + macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>, + macro_exports: Vec<Export>, // Maps the `Mark` of an expansion to its containing module or block. invocations: FxHashMap<Mark, &'a InvocationData<'a>>, @@ -1305,6 +1307,8 @@ impl<'a> Resolver<'a> { macro_names: FxHashSet(), builtin_macros: FxHashMap(), lexical_macro_resolutions: Vec::new(), + macro_map: FxHashMap(), + macro_exports: Vec::new(), invocations: invocations, } } @@ -1323,13 +1327,6 @@ impl<'a> Resolver<'a> { /// Entry point to crate resolution. pub fn resolve_crate(&mut self, krate: &Crate) { - // Collect `DefId`s for exported macro defs. - for def in &krate.exported_macros { - DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| { - collector.visit_macro_def(def) - }) - } - self.current_module = self.graph_root; visit::walk_crate(self, krate); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index e3078a42f65..f9d91e3aa63 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -10,7 +10,8 @@ use {Module, Resolver}; use build_reduced_graph::BuildReducedGraphVisitor; -use rustc::hir::def_id::{CRATE_DEF_INDEX, DefIndex}; +use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}; +use rustc::hir::def::{Def, Export}; use rustc::hir::map::{self, DefCollector}; use std::cell::Cell; use std::rc::Rc; @@ -23,6 +24,7 @@ use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::parse::token::intern; use syntax::util::lev_distance::find_best_match_for_name; +use syntax::visit::Visitor; use syntax_pos::Span; #[derive(Clone)] @@ -128,6 +130,13 @@ impl<'a> base::Resolver for Resolver<'a> { if export { def.id = self.next_node_id(); + DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| { + collector.visit_macro_def(&def) + }); + self.macro_exports.push(Export { + name: def.ident.name, + def: Def::Macro(self.definitions.local_def_id(def.id)), + }); self.exported_macros.push(def); } } @@ -136,7 +145,12 @@ impl<'a> base::Resolver for Resolver<'a> { if let NormalTT(..) = *ext { self.macro_names.insert(ident.name); } - self.builtin_macros.insert(ident.name, ext); + let def_id = DefId { + krate: BUILTIN_MACROS_CRATE, + index: DefIndex::new(self.macro_map.len()), + }; + self.macro_map.insert(def_id, ext); + self.builtin_macros.insert(ident.name, def_id); } fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>) { @@ -147,7 +161,7 @@ impl<'a> base::Resolver for Resolver<'a> { for i in 0..attrs.len() { let name = intern(&attrs[i].name()); match self.builtin_macros.get(&name) { - Some(ext) => match **ext { + Some(&def_id) => match *self.get_macro(Def::Macro(def_id)) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) } @@ -226,7 +240,7 @@ impl<'a> Resolver<'a> { if let Some(scope) = possible_time_travel { self.lexical_macro_resolutions.push((name, scope)); } - self.builtin_macros.get(&name).cloned() + self.builtin_macros.get(&name).cloned().map(|def_id| self.get_macro(Def::Macro(def_id))) } fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 91a7dc4249a..5d66caec31b 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -30,6 +30,7 @@ use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; use std::cell::{Cell, RefCell}; +use std::mem; impl<'a> Resolver<'a> { pub fn resolve_imports(&mut self) { @@ -772,6 +773,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { *module.globs.borrow_mut() = Vec::new(); let mut reexports = Vec::new(); + if module as *const _ == self.graph_root as *const _ { + reexports = mem::replace(&mut self.macro_exports, Vec::new()); + } + for (&(name, ns), resolution) in module.resolutions.borrow().iter() { let resolution = resolution.borrow(); let binding = match resolution.binding { |
