about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-01-13 09:18:37 +0100
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>2019-03-05 00:36:23 +0100
commitc3c1c8d4e0f01c869f8381e70fbd4d103534493f (patch)
tree8cc535c809f249b602f9372ca4dca0b6d9b56e02
parent97431a40908a32db31fbc1f10af365e653309a90 (diff)
downloadrust-c3c1c8d4e0f01c869f8381e70fbd4d103534493f.tar.gz
rust-c3c1c8d4e0f01c869f8381e70fbd4d103534493f.zip
Allow linking to a proc macro on the target in metadata and still use a host proc macro to execute them
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc/session/filesearch.rs1
-rw-r--r--src/librustc_metadata/creader.rs159
-rw-r--r--src/librustc_metadata/locator.rs16
4 files changed, 122 insertions, 56 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 774ab0333db..a4c587b5ca7 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1232,6 +1232,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
          Use with RUST_REGION_GRAPH=help for more info"),
     parse_only: bool = (false, parse_bool, [UNTRACKED],
         "parse only; do not compile, assemble, or link"),
+    dual_proc_macros: bool = (false, parse_bool, [TRACKED],
+        "load proc macros for both target and host, but only link to the target"),
     no_codegen: bool = (false, parse_bool, [TRACKED],
         "run all passes except codegen; no output"),
     treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs
index 77f190e2812..cf09d45ca38 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc/session/filesearch.rs
@@ -18,6 +18,7 @@ pub enum FileMatch {
 
 // A module for searching for libraries
 
+#[derive(Clone)]
 pub struct FileSearch<'a> {
     sysroot: &'a Path,
     triple: &'a str,
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 6f2718381c2..600ec8d65b6 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -188,13 +188,15 @@ impl<'a> CrateLoader<'a> {
         });
     }
 
-    fn register_crate(&mut self,
-                      root: &Option<CratePaths>,
-                      ident: Symbol,
-                      span: Span,
-                      lib: Library,
-                      dep_kind: DepKind)
-                      -> (CrateNum, Lrc<cstore::CrateMetadata>) {
+    fn register_crate(
+        &mut self,
+        host_lib: Option<Library>,
+        root: &Option<CratePaths>,
+        ident: Symbol,
+        span: Span,
+        lib: Library,
+        dep_kind: DepKind
+    ) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
         let crate_root = lib.metadata.get_root();
         info!("register crate `extern crate {} as {}`", crate_root.name, ident);
         self.verify_no_symbol_conflicts(span, &crate_root);
@@ -222,7 +224,16 @@ impl<'a> CrateLoader<'a> {
         let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
 
         let proc_macros = crate_root.proc_macro_decls_static.map(|_| {
-            self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
+            if self.sess.opts.debugging_opts.dual_proc_macros {
+                let host_lib = host_lib.unwrap();
+                self.load_derive_macros(
+                    &host_lib.metadata.get_root(),
+                    host_lib.dylib.clone().map(|p| p.0),
+                    span
+                )
+            } else {
+                self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
+            }
         });
 
         let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
@@ -269,6 +280,61 @@ impl<'a> CrateLoader<'a> {
         (cnum, cmeta)
     }
 
+    fn load_proc_macro<'b> (
+        &mut self,
+        locate_ctxt: &mut locator::Context<'b>,
+        path_kind: PathKind,
+    ) -> Option<(LoadResult, Option<Library>)>
+    where
+        'a: 'b
+    {
+        // Use a new locator Context so trying to load a proc macro doesn't affect the error
+        // message we emit
+        let mut proc_macro_locator = locate_ctxt.clone();
+
+        // Try to load a proc macro
+        proc_macro_locator.is_proc_macro = Some(true);
+
+        // Load the proc macro crate for the target
+        let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros {
+            proc_macro_locator.reset();
+            let result = match self.load(&mut proc_macro_locator)? {
+                LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)),
+                LoadResult::Loaded(library) => Some(LoadResult::Loaded(library))
+            };
+            // Don't look for a matching hash when looking for the host crate.
+            // It won't be the same as the target crate hash
+            locate_ctxt.hash = None;
+            // Use the locate_ctxt when looking for the host proc macro crate, as that is required
+            // so we want it to affect the error message
+            (locate_ctxt, result)
+        } else {
+            (&mut proc_macro_locator, None)
+        };
+
+        // Load the proc macro crate for the host
+
+        locator.reset();
+        locator.is_proc_macro = Some(true);
+        locator.target = &self.sess.host;
+        locator.triple = TargetTriple::from_triple(config::host_triple());
+        locator.filesearch = self.sess.host_filesearch(path_kind);
+
+        let host_result = self.load(locator)?;
+
+        Some(if self.sess.opts.debugging_opts.dual_proc_macros {
+            let host_result = match host_result {
+                LoadResult::Previous(..) => {
+                    panic!("host and target proc macros must be loaded in lock-step")
+                }
+                LoadResult::Loaded(library) => library
+            };
+            (target_result.unwrap(), Some(host_result))
+        } else {
+            (host_result, None)
+        })
+    }
+
     fn resolve_crate<'b>(
         &'b mut self,
         root: &'b Option<CratePaths>,
@@ -281,53 +347,39 @@ impl<'a> CrateLoader<'a> {
         mut dep_kind: DepKind,
     ) -> Result<(CrateNum, Lrc<cstore::CrateMetadata>), LoadError<'b>> {
         info!("resolving crate `extern crate {} as {}`", name, ident);
+        let mut locate_ctxt = locator::Context {
+            sess: self.sess,
+            span,
+            ident,
+            crate_name: name,
+            hash: hash.map(|a| &*a),
+            extra_filename: extra_filename,
+            filesearch: self.sess.target_filesearch(path_kind),
+            target: &self.sess.target.target,
+            triple: self.sess.opts.target_triple.clone(),
+            root,
+            rejected_via_hash: vec![],
+            rejected_via_triple: vec![],
+            rejected_via_kind: vec![],
+            rejected_via_version: vec![],
+            rejected_via_filename: vec![],
+            should_match_name: true,
+            is_proc_macro: Some(false),
+            metadata_loader: &*self.cstore.metadata_loader,
+        };
+
         let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
-            LoadResult::Previous(cnum)
+            (LoadResult::Previous(cnum), None)
         } else {
             info!("falling back to a load");
-            let mut locate_ctxt = locator::Context {
-                sess: self.sess,
-                span,
-                ident,
-                crate_name: name,
-                hash: hash.map(|a| &*a),
-                extra_filename: extra_filename,
-                filesearch: self.sess.target_filesearch(path_kind),
-                target: &self.sess.target.target,
-                triple: &self.sess.opts.target_triple,
-                root,
-                rejected_via_hash: vec![],
-                rejected_via_triple: vec![],
-                rejected_via_kind: vec![],
-                rejected_via_version: vec![],
-                rejected_via_filename: vec![],
-                should_match_name: true,
-                is_proc_macro: Some(false),
-                metadata_loader: &*self.cstore.metadata_loader,
-            };
-
-            self.load(&mut locate_ctxt).or_else(|| {
+            self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| {
                 dep_kind = DepKind::UnexportedMacrosOnly;
-
-                let mut proc_macro_locator = locator::Context {
-                    target: &self.sess.host,
-                    triple: &TargetTriple::from_triple(config::host_triple()),
-                    filesearch: self.sess.host_filesearch(path_kind),
-                    rejected_via_hash: vec![],
-                    rejected_via_triple: vec![],
-                    rejected_via_kind: vec![],
-                    rejected_via_version: vec![],
-                    rejected_via_filename: vec![],
-                    is_proc_macro: Some(true),
-                    ..locate_ctxt
-                };
-
-                self.load(&mut proc_macro_locator)
+                self.load_proc_macro(&mut locate_ctxt, path_kind)
             }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))?
         };
 
         match result {
-            LoadResult::Previous(cnum) => {
+            (LoadResult::Previous(cnum), None) => {
                 let data = self.cstore.get_crate_data(cnum);
                 if data.root.proc_macro_decls_static.is_some() {
                     dep_kind = DepKind::UnexportedMacrosOnly;
@@ -337,9 +389,10 @@ impl<'a> CrateLoader<'a> {
                 });
                 Ok((cnum, data))
             }
-            LoadResult::Loaded(library) => {
-                Ok(self.register_crate(root, ident, span, library, dep_kind))
+            (LoadResult::Loaded(library), host_library) => {
+                Ok(self.register_crate(host_library, root, ident, span, library, dep_kind))
             }
+            _ => panic!()
         }
     }
 
@@ -355,7 +408,7 @@ impl<'a> CrateLoader<'a> {
         // don't want to match a host crate against an equivalent target one
         // already loaded.
         let root = library.metadata.get_root();
-        if locate_ctxt.triple == &self.sess.opts.target_triple {
+        if locate_ctxt.triple == self.sess.opts.target_triple {
             let mut result = LoadResult::Loaded(library);
             self.cstore.iter_crate_data(|cnum, data| {
                 if data.root.name == root.name && root.hash == data.root.hash {
@@ -451,9 +504,9 @@ impl<'a> CrateLoader<'a> {
     fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol)
                             -> ExtensionCrate {
         info!("read extension crate `extern crate {} as {}`", orig_name, rename);
-        let target_triple = &self.sess.opts.target_triple;
+        let target_triple = self.sess.opts.target_triple.clone();
         let host_triple = TargetTriple::from_triple(config::host_triple());
-        let is_cross = target_triple != &host_triple;
+        let is_cross = target_triple != host_triple;
         let mut target_only = false;
         let mut locate_ctxt = locator::Context {
             sess: self.sess,
@@ -464,7 +517,7 @@ impl<'a> CrateLoader<'a> {
             extra_filename: None,
             filesearch: self.sess.host_filesearch(PathKind::Crate),
             target: &self.sess.host,
-            triple: &host_triple,
+            triple: host_triple,
             root: &None,
             rejected_via_hash: vec![],
             rejected_via_triple: vec![],
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 6a1aada5ac7..81878c4f687 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -244,11 +244,13 @@ use rustc_data_structures::owning_ref::OwningRef;
 
 use log::{debug, info, warn};
 
+#[derive(Clone)]
 pub struct CrateMismatch {
     path: PathBuf,
     got: String,
 }
 
+#[derive(Clone)]
 pub struct Context<'a> {
     pub sess: &'a Session,
     pub span: Span,
@@ -258,7 +260,7 @@ pub struct Context<'a> {
     pub extra_filename: Option<&'a str>,
     // points to either self.sess.target.target or self.sess.host, must match triple
     pub target: &'a Target,
-    pub triple: &'a TargetTriple,
+    pub triple: TargetTriple,
     pub filesearch: FileSearch<'a>,
     pub root: &'a Option<CratePaths>,
     pub rejected_via_hash: Vec<CrateMismatch>,
@@ -302,6 +304,14 @@ impl CratePaths {
 }
 
 impl<'a> Context<'a> {
+    pub fn reset(&mut self) {
+        self.rejected_via_hash.clear();
+        self.rejected_via_triple.clear();
+        self.rejected_via_kind.clear();
+        self.rejected_via_version.clear();
+        self.rejected_via_filename.clear();
+    }
+
     pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
         let mut seen_paths = FxHashSet::default();
         match self.extra_filename {
@@ -399,7 +409,7 @@ impl<'a> Context<'a> {
                                            add);
 
             if (self.ident == "std" || self.ident == "core")
-                && self.triple != &TargetTriple::from_triple(config::host_triple()) {
+                && self.triple != TargetTriple::from_triple(config::host_triple()) {
                 err.note(&format!("the `{}` target may not be installed", self.triple));
             }
             err.span_label(self.span, "can't find crate");
@@ -718,7 +728,7 @@ impl<'a> Context<'a> {
             }
         }
 
-        if &root.triple != self.triple {
+        if root.triple != self.triple {
             info!("Rejecting via crate triple: expected {} got {}",
                   self.triple,
                   root.triple);