Skip to content

Commit 462fc37

Browse files
committed
Auto merge of #68298 - Mark-Simulacrum:binary-depdep-fix, r=petrochenkov
Avoid declaring a fake dependency edge When we're producing an rlib, we do not need anything more than an rmeta file for each of our dependencies (this is indeed utilized by Cargo for pipelining). Previously, we were still storing the paths of possible rlib/dylib crates, which meant that they could still plausibly be accessed. With -Zbinary-dep-depinfo, that meant that Cargo thought that rustc was using both the rlib and an (earlier emitted) rmeta, and so needed a recompile, as the rlib may have finished writing *after* compilation started (for more detail, see issue 68149). This commit changes metadata loading to not store the filepaths of dylib/rlib if we're going to end up creating an rlib only. Fixes #68149.
2 parents e23dd66 + be663bf commit 462fc37

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

src/librustc_metadata/locator.rs

+38-6
Original file line numberDiff line numberDiff line change
@@ -654,14 +654,36 @@ impl<'a> CrateLocator<'a> {
654654
dylibs: FxHashMap<PathBuf, PathKind>,
655655
) -> Option<(Svh, Library)> {
656656
let mut slot = None;
657+
// Order here matters, rmeta should come first. See comment in
658+
// `extract_one` below.
657659
let source = CrateSource {
658-
rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot),
659660
rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot),
661+
rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot),
660662
dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot),
661663
};
662664
slot.map(|(svh, metadata)| (svh, Library { source, metadata }))
663665
}
664666

667+
fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool {
668+
if flavor == CrateFlavor::Dylib && self.is_proc_macro == Some(true) {
669+
return true;
670+
}
671+
672+
// The all loop is because `--crate-type=rlib --crate-type=rlib` is
673+
// legal and produces both inside this type.
674+
let is_rlib = self.sess.crate_types.borrow().iter().all(|c| *c == config::CrateType::Rlib);
675+
let needs_object_code = self.sess.opts.output_types.should_codegen();
676+
// If we're producing an rlib, then we don't need object code.
677+
// Or, if we're not producing object code, then we don't need it either
678+
// (e.g., if we're a cdylib but emitting just metadata).
679+
if is_rlib || !needs_object_code {
680+
flavor == CrateFlavor::Rmeta
681+
} else {
682+
// we need all flavors (perhaps not true, but what we do for now)
683+
true
684+
}
685+
}
686+
665687
// Attempts to extract *one* library from the set `m`. If the set has no
666688
// elements, `None` is returned. If the set has more than one element, then
667689
// the errors and notes are emitted about the set of libraries.
@@ -679,12 +701,22 @@ impl<'a> CrateLocator<'a> {
679701
let mut ret: Option<(PathBuf, PathKind)> = None;
680702
let mut error = 0;
681703

704+
// If we are producing an rlib, and we've already loaded metadata, then
705+
// we should not attempt to discover further crate sources (unless we're
706+
// locating a proc macro; exact logic is in needs_crate_flavor). This means
707+
// that under -Zbinary-dep-depinfo we will not emit a dependency edge on
708+
// the *unused* rlib, and by returning `None` here immediately we
709+
// guarantee that we do indeed not use it.
710+
//
711+
// See also #68149 which provides more detail on why emitting the
712+
// dependency on the rlib is a bad thing.
713+
//
714+
// We currenty do not verify that these other sources are even in sync,
715+
// and this is arguably a bug (see #10786), but because reading metadata
716+
// is quite slow (especially from dylibs) we currently do not read it
717+
// from the other crate sources.
682718
if slot.is_some() {
683-
// FIXME(#10786): for an optimization, we only read one of the
684-
// libraries' metadata sections. In theory we should
685-
// read both, but reading dylib metadata is quite
686-
// slow.
687-
if m.is_empty() {
719+
if m.is_empty() || !self.needs_crate_flavor(flavor) {
688720
return None;
689721
} else if m.len() == 1 {
690722
return Some(m.into_iter().next().unwrap());

src/test/ui/rmeta-rpass.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// run-pass
22
// Test that using rlibs and rmeta dep crates work together. Specifically, that
3-
// there can be both an rmeta and an rlib file and rustc will prefer the rlib.
3+
// there can be both an rmeta and an rlib file and rustc will prefer the rmeta
4+
// file.
5+
//
6+
// This behavior is simply making sure this doesn't accidentally change; in this
7+
// case we want to make sure that the rlib isn't being used as that would cause
8+
// bugs in -Zbinary-dep-depinfo (see #68298).
49

510
// aux-build:rmeta-rmeta.rs
611
// aux-build:rmeta-rlib-rpass.rs
@@ -9,5 +14,5 @@ extern crate rmeta_aux;
914
use rmeta_aux::Foo;
1015

1116
pub fn main() {
12-
let _ = Foo { field: 42 };
17+
let _ = Foo { field2: 42 };
1318
}

0 commit comments

Comments
 (0)