Skip to content

Commit e4baeaa

Browse files
committed
Import macros in resolve instead of in metadata::macro_import.
1 parent 4845add commit e4baeaa

File tree

7 files changed

+410
-491
lines changed

7 files changed

+410
-491
lines changed

src/librustc/middle/cstore.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use util::nodemap::{NodeSet, DefIdMap};
3737
use std::path::PathBuf;
3838
use syntax::ast;
3939
use syntax::attr;
40-
use syntax::ext::base::MultiItemModifier;
40+
use syntax::ext::base::SyntaxExtension;
4141
use syntax::ptr::P;
4242
use syntax::parse::token::InternedString;
4343
use syntax_pos::Span;
@@ -417,18 +417,13 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
417417
fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
418418
}
419419

420-
pub struct LoadedMacro {
421-
pub import_site: Span,
422-
pub kind: LoadedMacroKind,
423-
}
424-
425-
pub enum LoadedMacroKind {
426-
Def(ast::MacroDef),
427-
CustomDerive(String, Box<MultiItemModifier>),
420+
pub enum LoadedMacros {
421+
MacroRules(Vec<ast::MacroDef>),
422+
ProcMacros(Vec<(ast::Name, SyntaxExtension)>),
428423
}
429424

430425
pub trait CrateLoader {
431-
fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro>;
426+
fn load_macros(&mut self, extern_crate: &ast::Item) -> LoadedMacros;
432427
fn process_item(&mut self, item: &ast::Item, defs: &Definitions);
433428
fn postprocess(&mut self, krate: &ast::Crate);
434429
}

src/librustc_metadata/creader.rs

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@
1212
1313
use cstore::{self, CStore, CrateSource, MetadataBlob};
1414
use locator::{self, CratePaths};
15-
use macro_import;
1615
use schema::CrateRoot;
1716

1817
use rustc::hir::def_id::{CrateNum, DefIndex};
1918
use rustc::hir::svh::Svh;
20-
use rustc::middle::cstore::LoadedMacro;
19+
use rustc::middle::cstore::LoadedMacros;
2120
use rustc::session::{config, Session};
2221
use rustc_back::PanicStrategy;
2322
use rustc::session::search_paths::PathKind;
@@ -36,7 +35,8 @@ use syntax::ast;
3635
use syntax::abi::Abi;
3736
use syntax::parse;
3837
use syntax::attr;
39-
use syntax::parse::token::InternedString;
38+
use syntax::ext::base::SyntaxExtension;
39+
use syntax::parse::token::{InternedString, intern};
4040
use syntax_pos::{self, Span, mk_sp};
4141
use log;
4242

@@ -591,15 +591,14 @@ impl<'a> CrateLoader<'a> {
591591

592592
ret.macro_rules.push(ast::MacroDef {
593593
ident: ast::Ident::with_empty_ctxt(def.name),
594-
attrs: def.attrs,
595594
id: ast::DUMMY_NODE_ID,
596595
span: local_span,
597596
imported_from: Some(item.ident),
598597
// overridden in plugin/load.rs
599598
export: false,
600599
use_locally: false,
601-
allow_internal_unstable: false,
602-
600+
allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"),
601+
attrs: def.attrs,
603602
body: body,
604603
});
605604
self.sess.imported_macro_spans.borrow_mut()
@@ -639,6 +638,58 @@ impl<'a> CrateLoader<'a> {
639638
return ret
640639
}
641640

641+
/// Load custom derive macros.
642+
///
643+
/// Note that this is intentionally similar to how we load plugins today,
644+
/// but also intentionally separate. Plugins are likely always going to be
645+
/// implemented as dynamic libraries, but we have a possible future where
646+
/// custom derive (and other macro-1.1 style features) are implemented via
647+
/// executables and custom IPC.
648+
fn load_derive_macros(&mut self, span: Span, macros: &Macros, index: DefIndex)
649+
-> Vec<(ast::Name, SyntaxExtension)> {
650+
use std::{env, mem};
651+
use proc_macro::TokenStream;
652+
use proc_macro::__internal::Registry;
653+
use rustc_back::dynamic_lib::DynamicLibrary;
654+
use syntax_ext::deriving::custom::CustomDerive;
655+
656+
// Make sure the path contains a / or the linker will search for it.
657+
let path = macros.dylib.as_ref().unwrap();
658+
let path = env::current_dir().unwrap().join(path);
659+
let lib = match DynamicLibrary::open(Some(&path)) {
660+
Ok(lib) => lib,
661+
Err(err) => self.sess.span_fatal(span, &err),
662+
};
663+
664+
let sym = self.sess.generate_derive_registrar_symbol(&macros.svh, index);
665+
let registrar = unsafe {
666+
let sym = match lib.symbol(&sym) {
667+
Ok(f) => f,
668+
Err(err) => self.sess.span_fatal(span, &err),
669+
};
670+
mem::transmute::<*mut u8, fn(&mut Registry)>(sym)
671+
};
672+
673+
struct MyRegistrar(Vec<(ast::Name, SyntaxExtension)>);
674+
675+
impl Registry for MyRegistrar {
676+
fn register_custom_derive(&mut self,
677+
trait_name: &str,
678+
expand: fn(TokenStream) -> TokenStream) {
679+
let derive = SyntaxExtension::CustomDerive(Box::new(CustomDerive::new(expand)));
680+
self.0.push((intern(trait_name), derive));
681+
}
682+
}
683+
684+
let mut my_registrar = MyRegistrar(Vec::new());
685+
registrar(&mut my_registrar);
686+
687+
// Intentionally leak the dynamic library. We can't ever unload it
688+
// since the library can make things that will live arbitrarily long.
689+
mem::forget(lib);
690+
my_registrar.0
691+
}
692+
642693
/// Look for a plugin registrar. Returns library path, crate
643694
/// SVH and DefIndex of the registrar function.
644695
pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
@@ -1030,7 +1081,17 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
10301081
}
10311082
}
10321083

1033-
fn load_macros(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<LoadedMacro> {
1034-
macro_import::load_macros(self, extern_crate, allows_macros)
1084+
fn load_macros(&mut self, extern_crate: &ast::Item) -> LoadedMacros {
1085+
let macros = self.read_macros(extern_crate);
1086+
1087+
if let Some(index) = macros.custom_derive_registrar {
1088+
// custom derive crates currently should not have any macro_rules!
1089+
// exported macros, enforced elsewhere
1090+
assert_eq!(macros.macro_rules.len(), 0);
1091+
let custom_derives = self.load_derive_macros(extern_crate.span, &macros, index);
1092+
LoadedMacros::ProcMacros(custom_derives)
1093+
} else {
1094+
LoadedMacros::MacroRules(macros.macro_rules)
1095+
}
10351096
}
10361097
}

src/librustc_metadata/diagnostics.rs

Lines changed: 0 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -91,185 +91,6 @@ You need to link your code to the relevant crate in order to be able to use it
9191
well, and you link to them the same way.
9292
"##,
9393

94-
E0466: r##"
95-
Macro import declarations were malformed.
96-
97-
Erroneous code examples:
98-
99-
```compile_fail,E0466
100-
#[macro_use(a_macro(another_macro))] // error: invalid import declaration
101-
extern crate core as some_crate;
102-
103-
#[macro_use(i_want = "some_macros")] // error: invalid import declaration
104-
extern crate core as another_crate;
105-
```
106-
107-
This is a syntax error at the level of attribute declarations. The proper
108-
syntax for macro imports is the following:
109-
110-
```ignore
111-
// In some_crate:
112-
#[macro_export]
113-
macro_rules! get_tacos {
114-
...
115-
}
116-
117-
#[macro_export]
118-
macro_rules! get_pimientos {
119-
...
120-
}
121-
122-
// In your crate:
123-
#[macro_use(get_tacos, get_pimientos)] // It imports `get_tacos` and
124-
extern crate some_crate; // `get_pimientos` macros from some_crate
125-
```
126-
127-
If you would like to import all exported macros, write `macro_use` with no
128-
arguments.
129-
"##,
130-
131-
E0467: r##"
132-
Macro reexport declarations were empty or malformed.
133-
134-
Erroneous code examples:
135-
136-
```compile_fail,E0467
137-
#[macro_reexport] // error: no macros listed for export
138-
extern crate core as macros_for_good;
139-
140-
#[macro_reexport(fun_macro = "foo")] // error: not a macro identifier
141-
extern crate core as other_macros_for_good;
142-
```
143-
144-
This is a syntax error at the level of attribute declarations.
145-
146-
Currently, `macro_reexport` requires at least one macro name to be listed.
147-
Unlike `macro_use`, listing no names does not reexport all macros from the
148-
given crate.
149-
150-
Decide which macros you would like to export and list them properly.
151-
152-
These are proper reexport declarations:
153-
154-
```ignore
155-
#[macro_reexport(some_macro, another_macro)]
156-
extern crate macros_for_good;
157-
```
158-
"##,
159-
160-
E0468: r##"
161-
A non-root module attempts to import macros from another crate.
162-
163-
Example of erroneous code:
164-
165-
```compile_fail,E0468
166-
mod foo {
167-
#[macro_use(helpful_macro)] // error: must be at crate root to import
168-
extern crate core; // macros from another crate
169-
helpful_macro!(...);
170-
}
171-
```
172-
173-
Only `extern crate` imports at the crate root level are allowed to import
174-
macros.
175-
176-
Either move the macro import to crate root or do without the foreign macros.
177-
This will work:
178-
179-
```ignore
180-
#[macro_use(helpful_macro)]
181-
extern crate some_crate;
182-
183-
mod foo {
184-
helpful_macro!(...)
185-
}
186-
```
187-
"##,
188-
189-
E0469: r##"
190-
A macro listed for import was not found.
191-
192-
Erroneous code example:
193-
194-
```compile_fail,E0469
195-
#[macro_use(drink, be_merry)] // error: imported macro not found
196-
extern crate collections;
197-
198-
fn main() {
199-
// ...
200-
}
201-
```
202-
203-
Either the listed macro is not contained in the imported crate, or it is not
204-
exported from the given crate.
205-
206-
This could be caused by a typo. Did you misspell the macro's name?
207-
208-
Double-check the names of the macros listed for import, and that the crate
209-
in question exports them.
210-
211-
A working version would be:
212-
213-
```ignore
214-
// In some_crate crate:
215-
#[macro_export]
216-
macro_rules! eat {
217-
...
218-
}
219-
220-
#[macro_export]
221-
macro_rules! drink {
222-
...
223-
}
224-
225-
// In your crate:
226-
#[macro_use(eat, drink)]
227-
extern crate some_crate; //ok!
228-
```
229-
"##,
230-
231-
E0470: r##"
232-
A macro listed for reexport was not found.
233-
234-
Erroneous code example:
235-
236-
```compile_fail,E0470
237-
#[macro_reexport(drink, be_merry)]
238-
extern crate collections;
239-
240-
fn main() {
241-
// ...
242-
}
243-
```
244-
245-
Either the listed macro is not contained in the imported crate, or it is not
246-
exported from the given crate.
247-
248-
This could be caused by a typo. Did you misspell the macro's name?
249-
250-
Double-check the names of the macros listed for reexport, and that the crate
251-
in question exports them.
252-
253-
A working version:
254-
255-
```ignore
256-
// In some_crate crate:
257-
#[macro_export]
258-
macro_rules! eat {
259-
...
260-
}
261-
262-
#[macro_export]
263-
macro_rules! drink {
264-
...
265-
}
266-
267-
// In your_crate:
268-
#[macro_reexport(eat, drink)]
269-
extern crate some_crate;
270-
```
271-
"##,
272-
27394
}
27495

27596
register_diagnostics! {

src/librustc_metadata/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,5 @@ mod schema;
5959
pub mod creader;
6060
pub mod cstore;
6161
pub mod locator;
62-
pub mod macro_import;
6362

6463
__build_diagnostic_array! { librustc_metadata, DIAGNOSTICS }

0 commit comments

Comments
 (0)