Skip to content

Commit 872943c

Browse files
committed
Improve macro reexports.
1 parent 85f74c0 commit 872943c

File tree

13 files changed

+241
-228
lines changed

13 files changed

+241
-228
lines changed

Diff for: src/librustc/hir/def_id.rs

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ impl Idx for CrateNum {
3434
/// LOCAL_CRATE in their DefId.
3535
pub const LOCAL_CRATE: CrateNum = CrateNum(0);
3636

37+
/// Virtual crate for builtin macros
38+
// FIXME(jseyfried): this is also used for custom derives until proc-macro crates get `CrateNum`s.
39+
pub const BUILTIN_MACROS_CRATE: CrateNum = CrateNum(!0);
40+
3741
impl CrateNum {
3842
pub fn new(x: usize) -> CrateNum {
3943
assert!(x < (u32::MAX as usize));

Diff for: src/librustc/hir/map/collector.rs

+4
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,8 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
226226
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
227227
self.insert(lifetime.id, NodeLifetime(lifetime));
228228
}
229+
230+
fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
231+
self.insert_entry(macro_def.id, NotPresent);
232+
}
229233
}

Diff for: src/librustc/middle/cstore.rs

+3-15
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ pub trait CrateStore<'tcx> {
211211
fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath>;
212212
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
213213
fn item_children(&self, did: DefId) -> Vec<def::Export>;
214+
fn load_macro(&self, did: DefId, sess: &Session) -> ast::MacroDef;
214215

215216
// misc. metadata
216217
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 {
382383
}
383384
fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
384385
fn item_children(&self, did: DefId) -> Vec<def::Export> { bug!("item_children") }
386+
fn load_macro(&self, did: DefId, sess: &Session) -> ast::MacroDef { bug!("load_macro") }
385387

386388
// misc. metadata
387389
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 {
421423
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
422424
}
423425

424-
pub enum LoadedMacros {
425-
MacroRules(Vec<ast::MacroDef>),
426-
ProcMacros(Vec<(ast::Name, SyntaxExtension)>),
427-
}
428-
429-
impl LoadedMacros {
430-
pub fn is_proc_macros(&self) -> bool {
431-
match *self {
432-
LoadedMacros::ProcMacros(_) => true,
433-
_ => false,
434-
}
435-
}
436-
}
437-
438426
pub trait CrateLoader {
439427
fn process_item(&mut self, item: &ast::Item, defs: &Definitions, load_macros: bool)
440-
-> Option<LoadedMacros>;
428+
-> Vec<(ast::Name, SyntaxExtension)>;
441429
fn postprocess(&mut self, krate: &ast::Crate);
442430
}

Diff for: src/librustc_metadata/creader.rs

+35-82
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use schema::CrateRoot;
1616

1717
use rustc::hir::def_id::{CrateNum, DefIndex};
1818
use rustc::hir::svh::Svh;
19-
use rustc::middle::cstore::{DepKind, LoadedMacros};
19+
use rustc::middle::cstore::DepKind;
2020
use rustc::session::{config, Session};
2121
use rustc_back::PanicStrategy;
2222
use rustc::session::search_paths::PathKind;
@@ -33,11 +33,11 @@ use std::{cmp, fs};
3333

3434
use syntax::ast;
3535
use syntax::abi::Abi;
36-
use syntax::parse;
3736
use syntax::attr;
3837
use syntax::ext::base::SyntaxExtension;
38+
use syntax::feature_gate::{self, emit_feature_err};
3939
use syntax::parse::token::{InternedString, intern};
40-
use syntax_pos::{Span, DUMMY_SP, mk_sp};
40+
use syntax_pos::{Span, DUMMY_SP};
4141
use log;
4242

4343
pub struct Library {
@@ -518,91 +518,49 @@ impl<'a> CrateLoader<'a> {
518518
}
519519
}
520520

521-
fn read_macros(&mut self, item: &ast::Item, ekrate: &ExtensionCrate) -> LoadedMacros {
522-
let root = ekrate.metadata.get_root();
523-
let source_name = format!("<{} macros>", item.ident);
524-
let mut macro_rules = Vec::new();
525-
526-
for def in root.macro_defs.decode(&*ekrate.metadata) {
527-
// NB: Don't use parse::parse_tts_from_source_str because it parses with
528-
// quote_depth > 0.
529-
let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
530-
source_name.clone(),
531-
def.body);
532-
let lo = p.span.lo;
533-
let body = match p.parse_all_token_trees() {
534-
Ok(body) => body,
535-
Err(mut err) => {
536-
err.emit();
537-
self.sess.abort_if_errors();
538-
unreachable!();
539-
}
540-
};
541-
let local_span = mk_sp(lo, p.prev_span.hi);
542-
543-
// Mark the attrs as used
544-
for attr in &def.attrs {
545-
attr::mark_used(attr);
546-
}
547-
548-
macro_rules.push(ast::MacroDef {
549-
ident: ast::Ident::with_empty_ctxt(def.name),
550-
id: ast::DUMMY_NODE_ID,
551-
span: local_span,
552-
imported_from: Some(item.ident),
553-
allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"),
554-
attrs: def.attrs,
555-
body: body,
556-
});
557-
self.sess.imported_macro_spans.borrow_mut()
558-
.insert(local_span, (def.name.as_str().to_string(), def.span));
559-
}
560-
561-
if let Some(id) = root.macro_derive_registrar {
562-
let dylib = match ekrate.dylib.clone() {
563-
Some(dylib) => dylib,
564-
None => span_bug!(item.span, "proc-macro crate not dylib"),
565-
};
566-
if ekrate.target_only {
567-
let message = format!("proc-macro crate is not available for \
568-
triple `{}` (only found {})",
569-
config::host_triple(),
570-
self.sess.opts.target_triple);
571-
self.sess.span_fatal(item.span, &message);
572-
}
573-
574-
// custom derive crates currently should not have any macro_rules!
575-
// exported macros, enforced elsewhere
576-
assert_eq!(macro_rules.len(), 0);
577-
LoadedMacros::ProcMacros(self.load_derive_macros(item, id, root.hash, dylib))
578-
} else {
579-
LoadedMacros::MacroRules(macro_rules)
580-
}
581-
}
582-
583521
/// Load custom derive macros.
584522
///
585523
/// Note that this is intentionally similar to how we load plugins today,
586524
/// but also intentionally separate. Plugins are likely always going to be
587525
/// implemented as dynamic libraries, but we have a possible future where
588526
/// custom derive (and other macro-1.1 style features) are implemented via
589527
/// executables and custom IPC.
590-
fn load_derive_macros(&mut self, item: &ast::Item, index: DefIndex, svh: Svh, path: PathBuf)
591-
-> Vec<(ast::Name, SyntaxExtension)> {
528+
fn load_derive_macros(&mut self, item: &ast::Item, ekrate: &ExtensionCrate)
529+
-> Option<Vec<(ast::Name, SyntaxExtension)>> {
592530
use std::{env, mem};
593531
use proc_macro::TokenStream;
594532
use proc_macro::__internal::Registry;
595533
use rustc_back::dynamic_lib::DynamicLibrary;
596534
use syntax_ext::deriving::custom::CustomDerive;
597535

536+
let root = ekrate.metadata.get_root();
537+
let index = match root.macro_derive_registrar {
538+
Some(index) => index,
539+
None => return None,
540+
};
541+
if !self.sess.features.borrow().proc_macro {
542+
let issue = feature_gate::GateIssue::Language;
543+
let msg = "loading custom derive macro crates is experimentally supported";
544+
emit_feature_err(&self.sess.parse_sess, "proc_macro", item.span, issue, msg);
545+
}
546+
547+
if ekrate.target_only {
548+
let msg = format!("proc-macro crate is not available for triple `{}` (only found {})",
549+
config::host_triple(), self.sess.opts.target_triple);
550+
self.sess.span_fatal(item.span, &msg);
551+
}
552+
let path = match ekrate.dylib.clone() {
553+
Some(dylib) => dylib,
554+
None => span_bug!(item.span, "proc-macro crate not dylib"),
555+
};
598556
// Make sure the path contains a / or the linker will search for it.
599557
let path = env::current_dir().unwrap().join(path);
600558
let lib = match DynamicLibrary::open(Some(&path)) {
601559
Ok(lib) => lib,
602560
Err(err) => self.sess.span_fatal(item.span, &err),
603561
};
604562

605-
let sym = self.sess.generate_derive_registrar_symbol(&svh, index);
563+
let sym = self.sess.generate_derive_registrar_symbol(&root.hash, index);
606564
let registrar = unsafe {
607565
let sym = match lib.symbol(&sym) {
608566
Ok(f) => f,
@@ -632,7 +590,7 @@ impl<'a> CrateLoader<'a> {
632590
// Intentionally leak the dynamic library. We can't ever unload it
633591
// since the library can make things that will live arbitrarily long.
634592
mem::forget(lib);
635-
my_registrar.0
593+
Some(my_registrar.0)
636594
}
637595

638596
/// Look for a plugin registrar. Returns library path, crate
@@ -971,24 +929,23 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
971929
}
972930

973931
fn process_item(&mut self, item: &ast::Item, definitions: &Definitions, load_macros: bool)
974-
-> Option<LoadedMacros> {
932+
-> Vec<(ast::Name, SyntaxExtension)> {
975933
match item.node {
976934
ast::ItemKind::ExternCrate(_) => {}
977935
ast::ItemKind::ForeignMod(ref fm) => {
978936
self.process_foreign_mod(item, fm);
979-
return None;
937+
return Vec::new();
980938
}
981-
_ => return None,
939+
_ => return Vec::new(),
982940
}
983941

984942
let info = self.extract_crate_info(item).unwrap();
985-
let loaded_macros = if load_macros {
943+
if load_macros {
986944
let ekrate = self.read_extension_crate(item.span, &info);
987-
let loaded_macros = self.read_macros(item, &ekrate);
988945

989946
// If this is a proc-macro crate, return here to avoid registering.
990-
if loaded_macros.is_proc_macros() {
991-
return Some(loaded_macros);
947+
if let Some(custom_derives) = self.load_derive_macros(item, &ekrate) {
948+
return custom_derives;
992949
}
993950

994951
// Register crate now to avoid double-reading metadata
@@ -998,11 +955,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
998955
self.register_crate(&None, ident, name, item.span, lib, dep_kind);
999956
}
1000957
}
1001-
1002-
Some(loaded_macros)
1003-
} else {
1004-
None
1005-
};
958+
}
1006959

1007960
let (cnum, ..) = self.resolve_crate(
1008961
&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> {
1016969
self.update_extern_crate(cnum, extern_crate, &mut FxHashSet());
1017970
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
1018971

1019-
loaded_macros
972+
Vec::new()
1020973
}
1021974
}

Diff for: src/librustc_metadata/cstore_impl.rs

+40-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, DepKind, Exter
1717
use rustc::middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
1818
use rustc::hir::def::{self, Def};
1919
use rustc::middle::lang_items;
20+
use rustc::session::Session;
2021
use rustc::ty::{self, Ty, TyCtxt};
2122
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
2223

@@ -30,7 +31,8 @@ use rustc_back::PanicStrategy;
3031
use std::path::PathBuf;
3132
use syntax::ast;
3233
use syntax::attr;
33-
use syntax::parse::token;
34+
use syntax::parse::{token, new_parser_from_source_str};
35+
use syntax_pos::mk_sp;
3436
use rustc::hir::svh::Svh;
3537
use rustc_back::target::Target;
3638
use rustc::hir;
@@ -351,6 +353,43 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
351353
result
352354
}
353355

356+
fn load_macro(&self, id: DefId, sess: &Session) -> ast::MacroDef {
357+
let (name, def) = self.get_crate_data(id.krate).get_macro(id.index);
358+
let source_name = format!("<{} macros>", name);
359+
360+
// NB: Don't use parse_tts_from_source_str because it parses with quote_depth > 0.
361+
let mut parser = new_parser_from_source_str(&sess.parse_sess, source_name, def.body);
362+
363+
let lo = parser.span.lo;
364+
let body = match parser.parse_all_token_trees() {
365+
Ok(body) => body,
366+
Err(mut err) => {
367+
err.emit();
368+
sess.abort_if_errors();
369+
unreachable!();
370+
}
371+
};
372+
let local_span = mk_sp(lo, parser.prev_span.hi);
373+
374+
// Mark the attrs as used
375+
for attr in &def.attrs {
376+
attr::mark_used(attr);
377+
}
378+
379+
sess.imported_macro_spans.borrow_mut()
380+
.insert(local_span, (def.name.as_str().to_string(), def.span));
381+
382+
ast::MacroDef {
383+
ident: ast::Ident::with_empty_ctxt(def.name),
384+
id: ast::DUMMY_NODE_ID,
385+
span: local_span,
386+
imported_from: None, // FIXME
387+
allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"),
388+
attrs: def.attrs,
389+
body: body,
390+
}
391+
}
392+
354393
fn maybe_get_item_ast<'a>(&'tcx self,
355394
tcx: TyCtxt<'a, 'tcx, 'tcx>,
356395
def_id: DefId)

Diff for: src/librustc_metadata/decoder.rs

+9
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ impl<'tcx> EntryKind<'tcx> {
468468
EntryKind::Variant(_) => Def::Variant(did),
469469
EntryKind::Trait(_) => Def::Trait(did),
470470
EntryKind::Enum => Def::Enum(did),
471+
EntryKind::MacroDef(_) => Def::Macro(did),
471472

472473
EntryKind::ForeignMod |
473474
EntryKind::Impl(_) |
@@ -1004,6 +1005,14 @@ impl<'a, 'tcx> CrateMetadata {
10041005
self.root.reachable_ids.decode(self).map(|index| self.local_def_id(index)).collect()
10051006
}
10061007

1008+
pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) {
1009+
let entry = self.entry(id);
1010+
match entry.kind {
1011+
EntryKind::MacroDef(macro_def) => (self.item_name(&entry), macro_def.decode(self)),
1012+
_ => bug!(),
1013+
}
1014+
}
1015+
10071016
pub fn is_const_fn(&self, id: DefIndex) -> bool {
10081017
let constness = match self.entry(id).kind {
10091018
EntryKind::Method(data) => data.decode(self).fn_data.constness,

0 commit comments

Comments
 (0)