From b4906a93a04fe2659b6b0c3de49a0c5442248585 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 21 Sep 2016 06:25:09 +0000 Subject: [PATCH] Load macros from `#[macro_use]` extern crates in `resolve`. --- src/librustc/middle/cstore.rs | 8 +++- src/librustc_driver/driver.rs | 3 ++ src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/macro_import.rs | 8 ++-- src/librustc_resolve/lib.rs | 6 +++ src/librustc_resolve/macros.rs | 57 +++++++++++++++++++++++---- src/libsyntax/ext/base.rs | 54 ++++--------------------- src/libsyntax/ext/expand.rs | 19 --------- src/libsyntax/ext/tt/macro_rules.rs | 9 +++-- src/libsyntax_ext/deriving/mod.rs | 4 +- src/libsyntax_ext/lib.rs | 2 +- 11 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 62e0de1ba67..107cf9b6cae 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -36,9 +36,10 @@ use session::config::PanicStrategy; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; use std::path::PathBuf; +use std::rc::Rc; use syntax::ast; use syntax::attr; -use syntax::ext::base::LoadedMacro; +use syntax::ext::base::MultiItemModifier; use syntax::ptr::P; use syntax::parse::token::InternedString; use syntax_pos::Span; @@ -422,6 +423,11 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } } +pub enum LoadedMacro { + Def(ast::MacroDef), + CustomDerive(String, Rc), +} + pub trait CrateLoader { fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec; fn process_item(&mut self, item: &ast::Item, defs: &Definitions); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ae80bc53c4c..9d5dce7ad05 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -43,6 +43,7 @@ use super::Compilation; use serialize::json; use std::env; +use std::mem; use std::ffi::{OsString, OsStr}; use std::fs; use std::io::{self, Write}; @@ -686,6 +687,8 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, ret }); + krate.exported_macros = mem::replace(&mut resolver.exported_macros, Vec::new()); + krate = time(time_passes, "maybe building test harness", || { syntax::test::modify_for_testing(&sess.parse_sess, &mut resolver, diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 71cc13aebb3..2e03b7868a3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -17,6 +17,7 @@ use schema::CrateRoot; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; +use rustc::middle::cstore::LoadedMacro; use rustc::session::{config, Session}; use rustc::session::config::PanicStrategy; use rustc::session::search_paths::PathKind; @@ -32,7 +33,6 @@ use std::rc::Rc; use std::fs; use syntax::ast; -use syntax::ext::base::LoadedMacro; use syntax::abi::Abi; use syntax::parse; use syntax::attr; diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs index 3fe44045256..2ff7a6c41b5 100644 --- a/src/librustc_metadata/macro_import.rs +++ b/src/librustc_metadata/macro_import.rs @@ -11,12 +11,14 @@ //! Used by `rustc` when loading a crate with exported macros. use std::collections::HashSet; +use std::rc::Rc; use std::env; use std::mem; use creader::{CrateLoader, Macros}; use rustc::hir::def_id::DefIndex; +use rustc::middle::cstore::LoadedMacro; use rustc::session::Session; use rustc::util::nodemap::FnvHashMap; use rustc_back::dynamic_lib::DynamicLibrary; @@ -24,7 +26,6 @@ use rustc_macro::TokenStream; use rustc_macro::__internal::Registry; use syntax::ast; use syntax::attr; -use syntax::ext::base::LoadedMacro; use syntax::parse::token; use syntax_ext::deriving::custom::CustomDerive; use syntax_pos::Span; @@ -204,9 +205,8 @@ impl<'a> CrateLoader<'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::CustomDerive(trait_name.to_string(), - derive)); + let derive = Rc::new(CustomDerive::new(expand)); + self.0.push(LoadedMacro::CustomDerive(trait_name.to_string(), derive)); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 63ff9de2be2..fb9819b72ab 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -53,6 +53,7 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; +use syntax::ext::base::MultiItemModifier; use syntax::ext::hygiene::Mark; use syntax::ast::{self, FloatTy}; use syntax::ast::{CRATE_NODE_ID, Name, NodeId, IntTy, UintTy}; @@ -71,6 +72,7 @@ use syntax_pos::{Span, DUMMY_SP}; use errors::DiagnosticBuilder; use std::cell::{Cell, RefCell}; +use std::rc::Rc; use std::fmt; use std::mem::replace; @@ -1066,6 +1068,8 @@ pub struct Resolver<'a> { dummy_binding: &'a NameBinding<'a>, new_import_semantics: bool, // true if `#![feature(item_like_imports)]` + pub exported_macros: Vec, + pub derive_modes: FnvHashMap>, crate_loader: &'a mut CrateLoader, macro_names: FnvHashSet, @@ -1240,6 +1244,8 @@ impl<'a> Resolver<'a> { }), new_import_semantics: session.features.borrow().item_like_imports, + exported_macros: Vec::new(), + derive_modes: FnvHashMap(), crate_loader: crate_loader, macro_names: FnvHashSet(), expansion_data: expansion_data, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0b2a70bf4a6..37cb2861c1c 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -9,19 +9,23 @@ // except according to those terms. use Resolver; +use rustc::middle::cstore::LoadedMacro; use rustc::util::nodemap::FnvHashMap; use std::cell::RefCell; use std::mem; use std::rc::Rc; use syntax::ast::{self, Name}; use syntax::errors::DiagnosticBuilder; -use syntax::ext::base::{self, LoadedMacro, MultiModifier, MultiDecorator}; -use syntax::ext::base::{NormalTT, SyntaxExtension}; +use syntax::ext::base::{self, MultiModifier, MultiDecorator, MultiItemModifier}; +use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension}; use syntax::ext::expand::{Expansion, Invocation, InvocationKind}; use syntax::ext::hygiene::Mark; -use syntax::parse::token::intern; +use syntax::ext::tt::macro_rules; +use syntax::feature_gate::{self, emit_feature_err}; +use syntax::parse::token::{self, intern}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::{self, Visitor}; +use syntax_pos::Span; #[derive(Clone, Default)] pub struct ExpansionData { @@ -37,10 +41,6 @@ struct ModuleData { } impl<'a> base::Resolver for Resolver<'a> { - fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec { - self.crate_loader.load_macros(extern_crate, allows_macros) - } - fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() } @@ -52,7 +52,18 @@ impl<'a> base::Resolver for Resolver<'a> { }); } - fn add_macro(&mut self, scope: Mark, ident: ast::Ident, ext: Rc) { + fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef) { + if def.use_locally { + let ext = macro_rules::compile(&self.session.parse_sess, &def); + self.add_ext(scope, def.ident, Rc::new(ext)); + } + if def.export { + def.id = self.next_node_id(); + self.exported_macros.push(def); + } + } + + fn add_ext(&mut self, scope: Mark, ident: ast::Ident, ext: Rc) { if let NormalTT(..) = *ext { self.macro_names.insert(ident.name); } @@ -116,6 +127,10 @@ impl<'a> base::Resolver for Resolver<'a> { err.emit(); None } + + fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option> { + self.derive_modes.get(&ident.name).cloned() + } } impl<'a> Resolver<'a> { @@ -128,6 +143,17 @@ impl<'a> Resolver<'a> { } } } + + fn insert_custom_derive(&mut self, name: &str, ext: Rc, sp: Span) { + if !self.session.features.borrow().rustc_macro { + let diagnostic = &self.session.parse_sess.span_diagnostic; + let msg = "loading custom derive macro crates is experimentally supported"; + emit_feature_err(diagnostic, "rustc_macro", sp, feature_gate::GateIssue::Language, msg); + } + if self.derive_modes.insert(token::intern(name), ext).is_some() { + self.session.span_err(sp, &format!("cannot shadow existing derive mode `{}`", name)); + } + } } struct ExpansionVisitor<'b, 'a: 'b> { @@ -201,6 +227,21 @@ impl<'a, 'b> Visitor for ExpansionVisitor<'a, 'b> { visit::walk_item(self, item); self.current_module = orig_module; } + ast::ItemKind::ExternCrate(..) => { + // We need to error on `#[macro_use] extern crate` when it isn't at the + // crate root, because `$crate` won't work properly. + // FIXME(jseyfried): This will be nicer once `ModuleData` is merged with `ModuleS`. + let is_crate_root = self.current_module.parent.as_ref().unwrap().parent.is_none(); + for def in self.resolver.crate_loader.load_macros(item, is_crate_root) { + match def { + LoadedMacro::Def(def) => self.resolver.add_macro(Mark::root(), def), + LoadedMacro::CustomDerive(name, ext) => { + self.resolver.insert_custom_derive(&name, ext, item.span); + } + } + } + visit::walk_item(self, item); + } _ => visit::walk_item(self, item), } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 48a56e876d1..3e85565beb6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -17,8 +17,7 @@ use syntax_pos::{Span, ExpnId, NO_EXPANSION}; use errors::DiagnosticBuilder; use ext::expand::{self, Invocation, Expansion}; use ext::hygiene::Mark; -use ext::tt::macro_rules; -use fold; +use fold::{self, Folder}; use parse; use parse::parser::{self, Parser}; use parse::token; @@ -26,10 +25,7 @@ use parse::token::{InternedString, str_to_ident}; use ptr::P; use std_inject; use util::small_vector::SmallVector; -use fold::Folder; -use feature_gate; -use std::collections::HashMap; use std::path::PathBuf; use std::rc::Rc; use std::default::Default; @@ -659,35 +655,30 @@ pub enum SyntaxExtension { pub type NamedSyntaxExtension = (Name, SyntaxExtension); pub trait Resolver { - fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec; fn next_node_id(&mut self) -> ast::NodeId; fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion); - fn add_macro(&mut self, scope: Mark, ident: ast::Ident, ext: Rc); + fn add_macro(&mut self, scope: Mark, def: ast::MacroDef); + fn add_ext(&mut self, scope: Mark, ident: ast::Ident, ext: Rc); fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec); fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option; fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option>; -} - -pub enum LoadedMacro { - Def(ast::MacroDef), - CustomDerive(String, Box), + fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option>; } pub struct DummyResolver; impl Resolver for DummyResolver { - fn load_crate(&mut self, _extern_crate: &ast::Item, _allows_macros: bool) -> Vec { - Vec::new() - } fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {} - fn add_macro(&mut self, _scope: Mark, _ident: ast::Ident, _ext: Rc) {} + fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef) {} + fn add_ext(&mut self, _scope: Mark, _ident: ast::Ident, _ext: Rc) {} fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec) {} fn find_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } + fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option> { None } fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation) -> Option> { None } @@ -717,8 +708,6 @@ pub struct ExtCtxt<'a> { pub ecfg: expand::ExpansionConfig<'a>, pub crate_root: Option<&'static str>, pub resolver: &'a mut Resolver, - pub exported_macros: Vec, - pub derive_modes: HashMap>, pub current_expansion: ExpansionData, } @@ -732,9 +721,7 @@ impl<'a> ExtCtxt<'a> { cfg: cfg, ecfg: ecfg, crate_root: None, - exported_macros: Vec::new(), resolver: resolver, - derive_modes: HashMap::new(), current_expansion: ExpansionData { mark: Mark::root(), depth: 0, @@ -811,31 +798,6 @@ impl<'a> ExtCtxt<'a> { } pub fn bt_pop(&mut self) {} - pub fn insert_macro(&mut self, def: ast::MacroDef) { - if def.export { - self.exported_macros.push(def.clone()); - } - if def.use_locally { - let ext = macro_rules::compile(self.parse_sess, &def); - self.resolver.add_macro(self.current_expansion.mark, def.ident, Rc::new(ext)); - } - } - - pub fn insert_custom_derive(&mut self, name: &str, ext: Box, sp: Span) { - if !self.ecfg.enable_rustc_macro() { - feature_gate::emit_feature_err(&self.parse_sess.span_diagnostic, - "rustc_macro", - sp, - feature_gate::GateIssue::Language, - "loading custom derive macro crates \ - is experimentally supported"); - } - let name = token::intern_and_get_ident(name); - if self.derive_modes.insert(name.clone(), ext).is_some() { - self.span_err(sp, &format!("cannot shadow existing derive mode `{}`", name)); - } - } - pub fn struct_span_warn(&self, sp: Span, msg: &str) @@ -922,7 +884,7 @@ impl<'a> ExtCtxt<'a> { for (name, extension) in user_exts { let ident = ast::Ident::with_empty_ctxt(name); - self.resolver.add_macro(Mark::root(), ident, Rc::new(extension)); + self.resolver.add_ext(Mark::root(), ident, Rc::new(extension)); } let mut module = ModuleData { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index a30109f0051..7359c21eccc 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -199,11 +199,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }, _ => unreachable!(), }; - krate.exported_macros = mem::replace(&mut self.cx.exported_macros, Vec::new()); - - for def in &mut krate.exported_macros { - def.id = self.cx.resolver.next_node_id() - } if self.cx.parse_sess.span_diagnostic.err_count() > err_count { self.cx.parse_sess.span_diagnostic.abort_if_errors(); @@ -672,20 +667,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { self.cx.current_expansion.module = orig_module; return result; } - ast::ItemKind::ExternCrate(..) => { - // We need to error on `#[macro_use] extern crate` when it isn't at the - // crate root, because `$crate` won't work properly. - let is_crate_root = self.cx.current_expansion.module.mod_path.len() == 1; - for def in self.cx.resolver.load_crate(&*item, is_crate_root) { - match def { - LoadedMacro::Def(def) => self.cx.insert_macro(def), - LoadedMacro::CustomDerive(name, ext) => { - self.cx.insert_custom_derive(&name, ext, item.span); - } - } - } - noop_fold_item(item, self) - }, _ => noop_fold_item(item, self), } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 09edd39c061..0eed3e5898c 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -262,14 +262,15 @@ impl IdentMacroExpander for MacroRulesExpander { attrs: attrs, }; - cx.insert_macro(def.clone()); - // If keep_macs is true, expands to a MacEager::items instead. - if cx.ecfg.keep_macs { + let result = if cx.ecfg.keep_macs { MacEager::items(placeholders::reconstructed_macro_rules(&def).make_items()) } else { MacEager::items(placeholders::macro_scope_placeholder().make_items()) - } + }; + + cx.resolver.add_macro(cx.current_expansion.mark, def); + result } } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 6162beb80ec..c3c2f7eabb9 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -195,7 +195,8 @@ pub fn expand_derive(cx: &mut ExtCtxt, // If custom derive extensions end up threading through the `#[derive]` // attribute, we'll get called again later on to continue expanding // those modes. - } else if let Some(ext) = cx.derive_modes.remove(&tname) { + } else if let Some(ext) = + cx.resolver.resolve_derive_mode(ast::Ident::with_empty_ctxt(intern(&tname))) { let remaining_derives = iter.cloned().collect::>(); if remaining_derives.len() > 0 { let list = cx.meta_list(titem.span, @@ -214,7 +215,6 @@ pub fn expand_derive(cx: &mut ExtCtxt, let item = Annotatable::Item(item); let mut items = ext.expand(cx, mitem.span, &mitem, item); items.extend(other_items); - cx.derive_modes.insert(tname.clone(), ext); return items // If we've gotten this far then it means that we're in the territory of diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index e0c028195ba..bd9f1cf0d77 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -57,7 +57,7 @@ use syntax::parse::token::intern; pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, enable_quotes: bool) { let mut register = |name, ext| { - resolver.add_macro(Mark::root(), ast::Ident::with_empty_ctxt(intern(name)), Rc::new(ext)); + resolver.add_ext(Mark::root(), ast::Ident::with_empty_ctxt(intern(name)), Rc::new(ext)); }; register("macro_rules", IdentTT(Box::new(MacroRulesExpander), None, false));