Skip to content

Commit

Permalink
Load macros from #[macro_use] extern crates in resolve.
Browse files Browse the repository at this point in the history
  • Loading branch information
jseyfried committed Sep 24, 2016
1 parent 1599461 commit b4906a9
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 86 deletions.
8 changes: 7 additions & 1 deletion src/librustc/middle/cstore.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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<MultiItemModifier>),
}

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);
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_driver/driver.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/creader.rs
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_metadata/macro_import.rs
Expand Up @@ -11,20 +11,21 @@
//! 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;
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;
Expand Down Expand Up @@ -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));
}
}

Expand Down
6 changes: 6 additions & 0 deletions src/librustc_resolve/lib.rs
Expand Up @@ -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};
Expand All @@ -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;

Expand Down Expand Up @@ -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<ast::MacroDef>,
pub derive_modes: FnvHashMap<Name, Rc<MultiItemModifier>>,
crate_loader: &'a mut CrateLoader,
macro_names: FnvHashSet<Name>,

Expand Down Expand Up @@ -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,
Expand Down
57 changes: 49 additions & 8 deletions src/librustc_resolve/macros.rs
Expand Up @@ -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 {
Expand All @@ -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<LoadedMacro> {
self.crate_loader.load_macros(extern_crate, allows_macros)
}

fn next_node_id(&mut self) -> ast::NodeId {
self.session.next_node_id()
}
Expand All @@ -52,7 +52,18 @@ impl<'a> base::Resolver for Resolver<'a> {
});
}

fn add_macro(&mut self, scope: Mark, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
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<SyntaxExtension>) {
if let NormalTT(..) = *ext {
self.macro_names.insert(ident.name);
}
Expand Down Expand Up @@ -116,6 +127,10 @@ impl<'a> base::Resolver for Resolver<'a> {
err.emit();
None
}

fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModifier>> {
self.derive_modes.get(&ident.name).cloned()
}
}

impl<'a> Resolver<'a> {
Expand All @@ -128,6 +143,17 @@ impl<'a> Resolver<'a> {
}
}
}

fn insert_custom_derive(&mut self, name: &str, ext: Rc<MultiItemModifier>, 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> {
Expand Down Expand Up @@ -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),
}
}
Expand Down
54 changes: 8 additions & 46 deletions src/libsyntax/ext/base.rs
Expand Up @@ -17,19 +17,15 @@ 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;
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;
Expand Down Expand Up @@ -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<LoadedMacro>;
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<SyntaxExtension>);
fn add_macro(&mut self, scope: Mark, def: ast::MacroDef);
fn add_ext(&mut self, scope: Mark, ident: ast::Ident, ext: Rc<SyntaxExtension>);
fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);

fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
fn resolve_invoc(&mut self, scope: Mark, invoc: &Invocation) -> Option<Rc<SyntaxExtension>>;
}

pub enum LoadedMacro {
Def(ast::MacroDef),
CustomDerive(String, Box<MultiItemModifier>),
fn resolve_derive_mode(&mut self, ident: ast::Ident) -> Option<Rc<MultiItemModifier>>;
}

pub struct DummyResolver;

impl Resolver for DummyResolver {
fn load_crate(&mut self, _extern_crate: &ast::Item, _allows_macros: bool) -> Vec<LoadedMacro> {
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<SyntaxExtension>) {}
fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef) {}
fn add_ext(&mut self, _scope: Mark, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

fn find_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
fn resolve_derive_mode(&mut self, _ident: ast::Ident) -> Option<Rc<MultiItemModifier>> { None }
fn resolve_invoc(&mut self, _scope: Mark, _invoc: &Invocation) -> Option<Rc<SyntaxExtension>> {
None
}
Expand Down Expand Up @@ -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<ast::MacroDef>,
pub derive_modes: HashMap<InternedString, Box<MultiItemModifier>>,
pub current_expansion: ExpansionData,
}

Expand All @@ -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,
Expand Down Expand Up @@ -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<MultiItemModifier>, 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)
Expand Down Expand Up @@ -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 {
Expand Down
19 changes: 0 additions & 19 deletions src/libsyntax/ext/expand.rs
Expand Up @@ -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();
Expand Down Expand Up @@ -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),
}
}
Expand Down

0 comments on commit b4906a9

Please sign in to comment.