From 92325a95b3830e693e11c3575254d133f6dd7c5b Mon Sep 17 00:00:00 2001 From: h1467792822 <1467792822@qq.com> Date: Tue, 19 Mar 2024 19:50:07 +0800 Subject: [PATCH] Fixed the `private-dependency` bug: If the directly dependent crate is loaded last and is not configured with `--extern`, it may be incorrectly set to `private-dependency` --- compiler/rustc_metadata/src/creader.rs | 27 +++++++++++-------- .../ui/privacy/pub-priv-dep/auxiliary/bar.rs | 6 +++++ .../ui/privacy/pub-priv-dep/auxiliary/foo.rs | 2 ++ .../pub-priv-dep/priv-dep-issue-122756.rs | 12 +++++++++ 4 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs create mode 100644 tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs create mode 100644 tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 72757d90e4238..f61248aa731c1 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -388,6 +388,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { None } + // The `dependency` type is determined by the command line arguments(`--extern`) and + // `private_dep`. However, sometimes the directly dependent crate is not specified by + // `--extern`, in this case, `private-dep` is none during loading. This is equivalent to the + // scenario where the command parameter is set to `public-dependency` + fn is_private_dep(&self, name: &str, private_dep: Option) -> bool { + self.sess.opts.externs.get(name).map_or(private_dep.unwrap_or(false), |e| e.is_private_dep) + && private_dep.unwrap_or(true) + } + fn register_crate( &mut self, host_lib: Option, @@ -402,14 +411,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - - let private_dep = self - .sess - .opts - .externs - .get(name.as_str()) - .map_or(private_dep.unwrap_or(false), |e| e.is_private_dep) - && private_dep.unwrap_or(true); + let private_dep = self.is_private_dep(name.as_str(), private_dep); // Claim this crate number and cache it let cnum = self.cstore.intern_stable_crate_id(&crate_root)?; @@ -599,14 +601,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { match result { (LoadResult::Previous(cnum), None) => { + // When `private_dep` is none, it indicates the directly dependent crate. If it is + // not specified by `--extern` on command line parameters, it may be + // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to + // `public-dependency` here. + let private_dep = self.is_private_dep(name.as_str(), private_dep); let data = self.cstore.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; } data.set_dep_kind(cmp::max(data.dep_kind(), dep_kind)); - if let Some(private_dep) = private_dep { - data.update_and_private_dep(private_dep); - } + data.update_and_private_dep(private_dep); Ok(cnum) } (LoadResult::Loaded(library), host_library) => { diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs new file mode 100644 index 0000000000000..58297c926932b --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/bar.rs @@ -0,0 +1,6 @@ +//@ aux-crate:priv:foo=foo.rs +//@ compile-flags: -Zunstable-options + +#![crate_type = "rlib"] +extern crate foo; +pub struct Bar(pub i32); diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs new file mode 100644 index 0000000000000..6fd950619e6d8 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/auxiliary/foo.rs @@ -0,0 +1,2 @@ +#![crate_type = "rlib"] +pub struct Foo(pub i32); diff --git a/tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs b/tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs new file mode 100644 index 0000000000000..d7ade7f0e96c5 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/priv-dep-issue-122756.rs @@ -0,0 +1,12 @@ +//@ aux-build: bar.rs +//@ aux-build: foo.rs +//@ build-pass + +#![deny(exported_private_dependencies)] + +// Ensure the libbar.rlib is loaded first. If the command line parameter `--extern foo` does not +// exist, previus version would fail to compile +#![crate_type = "rlib"] +extern crate bar; +extern crate foo; +pub fn baz() -> (Option, Option) { (None, None) }