]> git.lizzy.rs Git - rust.git/commitdiff
Separate macro and plugin loading
authorKeegan McAllister <kmcallister@mozilla.com>
Thu, 12 Feb 2015 03:53:10 +0000 (19:53 -0800)
committerKeegan McAllister <kmcallister@mozilla.com>
Thu, 12 Feb 2015 20:44:31 +0000 (12:44 -0800)
Now they just share a bit of code internal to creader.

Resolves #22198 to my satisfaction.

src/librustc/metadata/macro_import.rs [new file with mode: 0644]
src/librustc/metadata/mod.rs
src/librustc/plugin/load.rs
src/librustc_driver/driver.rs

diff --git a/src/librustc/metadata/macro_import.rs b/src/librustc/metadata/macro_import.rs
new file mode 100644 (file)
index 0000000..28c98d4
--- /dev/null
@@ -0,0 +1,186 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Used by `rustc` when loading a crate with exported macros.
+
+use session::Session;
+use metadata::creader::CrateReader;
+
+use std::collections::{HashSet, HashMap};
+use syntax::ast;
+use syntax::attr;
+use syntax::codemap::Span;
+use syntax::parse::token;
+use syntax::visit;
+use syntax::visit::Visitor;
+use syntax::attr::AttrMetaMethods;
+
+struct MacroLoader<'a> {
+    sess: &'a Session,
+    span_whitelist: HashSet<Span>,
+    reader: CrateReader<'a>,
+    macros: Vec<ast::MacroDef>,
+}
+
+impl<'a> MacroLoader<'a> {
+    fn new(sess: &'a Session) -> MacroLoader<'a> {
+        MacroLoader {
+            sess: sess,
+            span_whitelist: HashSet::new(),
+            reader: CrateReader::new(sess),
+            macros: vec![],
+        }
+    }
+}
+
+/// Read exported macros.
+pub fn read_macro_defs(sess: &Session, krate: &ast::Crate) -> Vec<ast::MacroDef> {
+    let mut loader = MacroLoader::new(sess);
+
+    // We need to error on `#[macro_use] extern crate` when it isn't at the
+    // crate root, because `$crate` won't work properly. Identify these by
+    // spans, because the crate map isn't set up yet.
+    for item in &krate.module.items {
+        if let ast::ItemExternCrate(_) = item.node {
+            loader.span_whitelist.insert(item.span);
+        }
+    }
+
+    visit::walk_crate(&mut loader, krate);
+
+    loader.macros
+}
+
+pub type MacroSelection = HashMap<token::InternedString, Span>;
+
+// note that macros aren't expanded yet, and therefore macros can't add macro imports.
+impl<'a, 'v> Visitor<'v> for MacroLoader<'a> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        // We're only interested in `extern crate`.
+        match item.node {
+            ast::ItemExternCrate(_) => {}
+            _ => {
+                visit::walk_item(self, item);
+                return;
+            }
+        }
+
+        // Parse the attributes relating to macros.
+        let mut import = Some(HashMap::new());  // None => load all
+        let mut reexport = HashMap::new();
+
+        for attr in &item.attrs {
+            let mut used = true;
+            match &attr.name()[] {
+                "phase" => {
+                    self.sess.span_err(attr.span, "#[phase] is deprecated");
+                }
+                "plugin" => {
+                    self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated");
+                    self.sess.span_help(attr.span, &format!("use a crate attribute instead, \
+                                                            i.e. #![plugin({})]",
+                                                            item.ident.as_str())[]);
+                }
+                "macro_use" => {
+                    let names = attr.meta_item_list();
+                    if names.is_none() {
+                        // no names => load all
+                        import = None;
+                    }
+                    if let (Some(sel), Some(names)) = (import.as_mut(), names) {
+                        for attr in names {
+                            if let ast::MetaWord(ref name) = attr.node {
+                                sel.insert(name.clone(), attr.span);
+                            } else {
+                                self.sess.span_err(attr.span, "bad macro import");
+                            }
+                        }
+                    }
+                }
+                "macro_reexport" => {
+                    let names = match attr.meta_item_list() {
+                        Some(names) => names,
+                        None => {
+                            self.sess.span_err(attr.span, "bad macro reexport");
+                            continue;
+                        }
+                    };
+
+                    for attr in names {
+                        if let ast::MetaWord(ref name) = attr.node {
+                            reexport.insert(name.clone(), attr.span);
+                        } else {
+                            self.sess.span_err(attr.span, "bad macro reexport");
+                        }
+                    }
+                }
+                _ => used = false,
+            }
+            if used {
+                attr::mark_used(attr);
+            }
+        }
+
+        self.load_macros(item, import, reexport)
+    }
+
+    fn visit_mac(&mut self, _: &ast::Mac) {
+        // bummer... can't see macro imports inside macros.
+        // do nothing.
+    }
+}
+
+impl<'a> MacroLoader<'a> {
+    fn load_macros<'b>(&mut self,
+                       vi: &ast::Item,
+                       import: Option<MacroSelection>,
+                       reexport: MacroSelection) {
+        if let Some(sel) = import.as_ref() {
+            if sel.is_empty() && reexport.is_empty() {
+                return;
+            }
+        }
+
+        if !self.span_whitelist.contains(&vi.span) {
+            self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
+                                         the crate root");
+            return;
+        }
+
+        let macros = self.reader.read_exported_macros(vi);
+        let mut seen = HashSet::new();
+
+        for mut def in macros {
+            let name = token::get_ident(def.ident);
+            seen.insert(name.clone());
+
+            def.use_locally = match import.as_ref() {
+                None => true,
+                Some(sel) => sel.contains_key(&name),
+            };
+            def.export = reexport.contains_key(&name);
+            self.macros.push(def);
+        }
+
+        if let Some(sel) = import.as_ref() {
+            for (name, span) in sel.iter() {
+                if !seen.contains(name) {
+                    self.sess.span_err(*span, "imported macro not found");
+                }
+            }
+        }
+
+        for (name, span) in reexport.iter() {
+            if !seen.contains(name) {
+                self.sess.span_err(*span, "reexported macro not found");
+            }
+        }
+    }
+}
index 24007380feec1b42ace8ec8bb7630bface2f513c..0bf1e6d198fa2ad1fab28f8f611c6d4ae06a7c24 100644 (file)
@@ -18,3 +18,4 @@
 pub mod csearch;
 pub mod loader;
 pub mod filesearch;
+pub mod macro_import;
index 860bfaf4ce27232eb90998d115c55d72997f76ff..1895cbcb5421e341f051dd3b4c6109b8dc6f811e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Used by `rustc` when loading a plugin, or a crate with exported macros.
+//! Used by `rustc` when loading a plugin.
 
 use session::Session;
 use metadata::creader::CrateReader;
 use std::mem;
 use std::env;
 use std::dynamic_lib::DynamicLibrary;
-use std::collections::{HashSet, HashMap};
 use std::borrow::ToOwned;
 use syntax::ast;
-use syntax::attr;
 use syntax::codemap::{Span, COMMAND_LINE_SP};
-use syntax::parse::token;
 use syntax::ptr::P;
-use syntax::visit;
-use syntax::visit::Visitor;
 use syntax::attr::AttrMetaMethods;
 
 /// Pointer to a registrar function.
@@ -37,51 +32,17 @@ pub struct PluginRegistrar {
     pub args: Vec<P<ast::MetaItem>>,
 }
 
-/// Information about loaded plugins.
-pub struct Plugins {
-    /// Imported macros.
-    pub macros: Vec<ast::MacroDef>,
-    /// Registrars, as function pointers.
-    pub registrars: Vec<PluginRegistrar>,
-}
-
-pub struct PluginLoader<'a> {
+struct PluginLoader<'a> {
     sess: &'a Session,
-    span_whitelist: HashSet<Span>,
     reader: CrateReader<'a>,
-    pub plugins: Plugins,
-}
-
-impl<'a> PluginLoader<'a> {
-    fn new(sess: &'a Session) -> PluginLoader<'a> {
-        PluginLoader {
-            sess: sess,
-            reader: CrateReader::new(sess),
-            span_whitelist: HashSet::new(),
-            plugins: Plugins {
-                macros: vec!(),
-                registrars: vec!(),
-            },
-        }
-    }
+    plugins: Vec<PluginRegistrar>,
 }
 
 /// Read plugin metadata and dynamically load registrar functions.
 pub fn load_plugins(sess: &Session, krate: &ast::Crate,
-                    addl_plugins: Option<Vec<String>>) -> Plugins {
+                    addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
     let mut loader = PluginLoader::new(sess);
 
-    // We need to error on `#[macro_use] extern crate` when it isn't at the
-    // crate root, because `$crate` won't work properly. Identify these by
-    // spans, because the crate map isn't set up yet.
-    for item in &krate.module.items {
-        if let ast::ItemExternCrate(_) = item.node {
-            loader.span_whitelist.insert(item.span);
-        }
-    }
-
-    visit::walk_crate(&mut loader, krate);
-
     for attr in &krate.attrs {
         if !attr.check_name("plugin") {
             continue;
@@ -112,140 +73,24 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
         }
     }
 
-    return loader.plugins;
-}
-
-pub type MacroSelection = HashMap<token::InternedString, Span>;
-
-// note that macros aren't expanded yet, and therefore macros can't add plugins.
-impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        // We're only interested in `extern crate`.
-        match item.node {
-            ast::ItemExternCrate(_) => {}
-            _ => {
-                visit::walk_item(self, item);
-                return;
-            }
-        }
-
-        // Parse the attributes relating to macro loading.
-        let mut import = Some(HashMap::new());  // None => load all
-        let mut reexport = HashMap::new();
-        for attr in &item.attrs {
-            let mut used = true;
-            match &attr.name()[] {
-                "phase" => {
-                    self.sess.span_err(attr.span, "#[phase] is deprecated");
-                }
-                "plugin" => {
-                    self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated");
-                    self.sess.span_help(attr.span, &format!("use a crate attribute instead, \
-                                                            i.e. #![plugin({})]",
-                                                            item.ident.as_str())[]);
-                }
-                "macro_use" => {
-                    let names = attr.meta_item_list();
-                    if names.is_none() {
-                        // no names => load all
-                        import = None;
-                    }
-                    if let (Some(sel), Some(names)) = (import.as_mut(), names) {
-                        for attr in names {
-                            if let ast::MetaWord(ref name) = attr.node {
-                                sel.insert(name.clone(), attr.span);
-                            } else {
-                                self.sess.span_err(attr.span, "bad macro import");
-                            }
-                        }
-                    }
-                }
-                "macro_reexport" => {
-                    let names = match attr.meta_item_list() {
-                        Some(names) => names,
-                        None => {
-                            self.sess.span_err(attr.span, "bad macro reexport");
-                            continue;
-                        }
-                    };
-
-                    for attr in names {
-                        if let ast::MetaWord(ref name) = attr.node {
-                            reexport.insert(name.clone(), attr.span);
-                        } else {
-                            self.sess.span_err(attr.span, "bad macro reexport");
-                        }
-                    }
-                }
-                _ => used = false,
-            }
-            if used {
-                attr::mark_used(attr);
-            }
-        }
-
-        self.load_macros(item, import, reexport)
-    }
-
-    fn visit_mac(&mut self, _: &ast::Mac) {
-        // bummer... can't see plugins inside macros.
-        // do nothing.
-    }
+    loader.plugins
 }
 
 impl<'a> PluginLoader<'a> {
-    pub fn load_macros<'b>(&mut self,
-                           vi: &ast::Item,
-                           import: Option<MacroSelection>,
-                           reexport: MacroSelection) {
-        if let Some(sel) = import.as_ref() {
-            if sel.is_empty() && reexport.is_empty() {
-                return;
-            }
-        }
-
-        if !self.span_whitelist.contains(&vi.span) {
-            self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
-                                         the crate root");
-            return;
-        }
-
-        let macros = self.reader.read_exported_macros(vi);
-        let mut seen = HashSet::new();
-
-        for mut def in macros {
-            let name = token::get_ident(def.ident);
-            seen.insert(name.clone());
-
-            def.use_locally = match import.as_ref() {
-                None => true,
-                Some(sel) => sel.contains_key(&name),
-            };
-            def.export = reexport.contains_key(&name);
-            self.plugins.macros.push(def);
-        }
-
-        if let Some(sel) = import.as_ref() {
-            for (name, span) in sel.iter() {
-                if !seen.contains(name) {
-                    self.sess.span_err(*span, "imported macro not found");
-                }
-            }
-        }
-
-        for (name, span) in reexport.iter() {
-            if !seen.contains(name) {
-                self.sess.span_err(*span, "reexported macro not found");
-            }
+    fn new(sess: &'a Session) -> PluginLoader<'a> {
+        PluginLoader {
+            sess: sess,
+            reader: CrateReader::new(sess),
+            plugins: vec![],
         }
     }
 
-    pub fn load_plugin(&mut self, span: Span, name: &str, args: Vec<P<ast::MetaItem>>) {
+    fn load_plugin(&mut self, span: Span, name: &str, args: Vec<P<ast::MetaItem>>) {
         let registrar = self.reader.find_plugin_registrar(span, name);
 
         if let Some((lib, symbol)) = registrar {
             let fun = self.dylink_registrar(span, lib, symbol);
-            self.plugins.registrars.push(PluginRegistrar {
+            self.plugins.push(PluginRegistrar {
                 fun: fun,
                 args: args,
             });
index 12f5041cad14f996bbc2a0c65e0971dc6b09ebc4..5461279f17bfb538b29812c501e521e7c3ae51e3 100644 (file)
 use rustc::session::config::{self, Input, OutputFilenames};
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
+use rustc::metadata;
 use rustc::metadata::creader::CrateReader;
 use rustc::middle::{stability, ty, reachable};
 use rustc::middle::dependency_format;
 use rustc::middle;
-use rustc::plugin::load::Plugins;
 use rustc::plugin::registry::Registry;
 use rustc::plugin;
 use rustc::util::common::time;
@@ -409,10 +409,12 @@ pub fn phase_2_configure_and_expand(sess: &Session,
                  syntax::std_inject::maybe_inject_crates_ref(krate,
                                                              sess.opts.alt_std_name.clone()));
 
+    let macros = time(time_passes, "macro loading", (), |_|
+        metadata::macro_import::read_macro_defs(sess, &krate));
+
     let mut addl_plugins = Some(addl_plugins);
-    let Plugins { macros, registrars }
-        = time(time_passes, "plugin loading", (), |_|
-               plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()));
+    let registrars = time(time_passes, "plugin loading", (), |_|
+        plugin::load::load_plugins(sess, &krate, addl_plugins.take().unwrap()));
 
     let mut registry = Registry::new(sess, &krate);