]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_metadata/locator.rs
Auto merge of #68435 - tmandry:llvmup-2-the-return-of-phibitcast-transform-fixes...
[rust.git] / src / librustc_metadata / locator.rs
index 4745ad02a3aa4adcb10b0db6f3a8d7362e815a93..2157b8ce15931e836453a7f929994a19d83b487f 100644 (file)
 
 use log::{debug, info, warn};
 
-use rustc_error_codes::*;
-
 #[derive(Clone)]
 struct CrateMismatch {
     path: PathBuf,
@@ -656,14 +654,36 @@ fn extract_lib(
         dylibs: FxHashMap<PathBuf, PathKind>,
     ) -> Option<(Svh, Library)> {
         let mut slot = None;
+        // Order here matters, rmeta should come first. See comment in
+        // `extract_one` below.
         let source = CrateSource {
-            rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot),
             rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot),
+            rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot),
             dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot),
         };
         slot.map(|(svh, metadata)| (svh, Library { source, metadata }))
     }
 
+    fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool {
+        if flavor == CrateFlavor::Dylib && self.is_proc_macro == Some(true) {
+            return true;
+        }
+
+        // The all loop is because `--crate-type=rlib --crate-type=rlib` is
+        // legal and produces both inside this type.
+        let is_rlib = self.sess.crate_types.borrow().iter().all(|c| *c == config::CrateType::Rlib);
+        let needs_object_code = self.sess.opts.output_types.should_codegen();
+        // If we're producing an rlib, then we don't need object code.
+        // Or, if we're not producing object code, then we don't need it either
+        // (e.g., if we're a cdylib but emitting just metadata).
+        if is_rlib || !needs_object_code {
+            flavor == CrateFlavor::Rmeta
+        } else {
+            // we need all flavors (perhaps not true, but what we do for now)
+            true
+        }
+    }
+
     // Attempts to extract *one* library from the set `m`. If the set has no
     // elements, `None` is returned. If the set has more than one element, then
     // the errors and notes are emitted about the set of libraries.
@@ -681,12 +701,22 @@ fn extract_one(
         let mut ret: Option<(PathBuf, PathKind)> = None;
         let mut error = 0;
 
+        // If we are producing an rlib, and we've already loaded metadata, then
+        // we should not attempt to discover further crate sources (unless we're
+        // locating a proc macro; exact logic is in needs_crate_flavor). This means
+        // that under -Zbinary-dep-depinfo we will not emit a dependency edge on
+        // the *unused* rlib, and by returning `None` here immediately we
+        // guarantee that we do indeed not use it.
+        //
+        // See also #68149 which provides more detail on why emitting the
+        // dependency on the rlib is a bad thing.
+        //
+        // We currenty do not verify that these other sources are even in sync,
+        // and this is arguably a bug (see #10786), but because reading metadata
+        // is quite slow (especially from dylibs) we currently do not read it
+        // from the other crate sources.
         if slot.is_some() {
-            // FIXME(#10786): for an optimization, we only read one of the
-            //                libraries' metadata sections. In theory we should
-            //                read both, but reading dylib metadata is quite
-            //                slow.
-            if m.is_empty() {
+            if m.is_empty() || !self.needs_crate_flavor(flavor) {
                 return None;
             } else if m.len() == 1 {
                 return Some(m.into_iter().next().unwrap());