From 64025bb168f3ae37428387ca37ba89eb80be6544 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 1 May 2023 10:05:44 -0700 Subject: [PATCH 01/19] bootstrap: enable Cargo `public-dependency` feature for `libstd` --- library/std/Cargo.toml | 10 ++++++---- library/std/tests/common/mod.rs | 2 ++ src/bootstrap/metadata.rs | 1 + src/tools/tidy/src/main.rs | 4 ++++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 824abc72a223d..4765bb5d25a93 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "std" version = "0.0.0" @@ -10,12 +12,12 @@ edition = "2021" crate-type = ["dylib", "rlib"] [dependencies] -alloc = { path = "../alloc" } +alloc = { path = "../alloc", public = true } cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } -core = { path = "../core" } -libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] } +core = { path = "../core", public = true } +libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'], public = true } compiler_builtins = { version = "0.1.92" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } @@ -25,7 +27,7 @@ std_detect = { path = "../stdarch/crates/std_detect", default-features = false, # Dependencies of the `backtrace` crate addr2line = { version = "0.19.0", optional = true, default-features = false } rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] } -miniz_oxide = { version = "0.6.0", optional = true, default-features = false } +miniz_oxide = { version = "0.6.0", optional = true, default-features = false, public = false } [dependencies.object] version = "0.30.0" optional = true diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs index fce220223a055..37336e1c08ff8 100644 --- a/library/std/tests/common/mod.rs +++ b/library/std/tests/common/mod.rs @@ -1,5 +1,7 @@ #![allow(unused)] +#![allow(exported_private_dependencies)] + use std::env; use std::fs; use std::path::{Path, PathBuf}; diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index 8f2c3faca3a48..d8671ef2639f3 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -74,6 +74,7 @@ fn workspace_members(build: &Build) -> impl Iterator { let collect_metadata = |manifest_path| { let mut cargo = Command::new(&build.initial_cargo); cargo + .env("RUSTC_BOOTSTRAP", "1") .arg("metadata") .arg("--format-version") .arg("1") diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index f59406c404bab..2ad0ae527ac67 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -16,6 +16,10 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::thread::{self, scope, ScopedJoinHandle}; fn main() { + // Allow using unstable cargo features in the standard library. + // `setenv` might not be thread safe, so run it before using multiple threads. + env::set_var("RUSTC_BOOTSTRAP", "1"); + let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into(); let output_directory: PathBuf = From e36020cdb33a1c56ec4ff8c9fbb0bf331ade428a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 1 May 2023 11:51:00 -0700 Subject: [PATCH 02/19] rustc_metadata: inherit dependency privacy flag --- compiler/rustc_metadata/src/creader.rs | 9 ++++++--- compiler/rustc_metadata/src/rmeta/decoder.rs | 13 +++++++++---- .../rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 5 ++++- compiler/rustc_metadata/src/rmeta/encoder.rs | 1 + compiler/rustc_metadata/src/rmeta/mod.rs | 1 + 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 491978d7e8fdf..8bd96906f8b4b 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -365,6 +365,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { lib: Library, dep_kind: CrateDepKind, name: Symbol, + private_dep: bool, ) -> Result { let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); @@ -518,15 +519,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { if !name.as_str().is_ascii() { return Err(CrateError::NonAsciiName(name)); } - let (root, hash, host_hash, extra_filename, path_kind) = match dep { + let (root, hash, host_hash, extra_filename, path_kind, private_dep) = match dep { Some((root, dep)) => ( Some(root), Some(dep.hash), dep.host_hash, Some(&dep.extra_filename[..]), PathKind::Dependency, + dep.is_private, ), - None => (None, None, None, None, PathKind::Crate), + None => (None, None, None, None, PathKind::Crate, false), }; let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { (LoadResult::Previous(cnum), None) @@ -562,10 +564,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { dep_kind = CrateDepKind::MacrosOnly; } data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind)); + data.update_private_dep(|private_dep| private_dep && private_dep); Ok(cnum) } (LoadResult::Loaded(library), host_library) => { - self.register_crate(host_library, root, library, dep_kind, name) + self.register_crate(host_library, root, library, dep_kind, name, private_dep) } _ => panic!(), } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index cc4e60cf6ac58..46d469f0703c0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -113,7 +113,7 @@ pub(crate) struct CrateMetadata { source: Lrc, /// Whether or not this crate should be consider a private dependency /// for purposes of the 'exported_private_dependencies' lint - private_dep: bool, + private_dep: Lock, /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. host_hash: Option, @@ -690,12 +690,13 @@ impl MetadataBlob { writeln!(out, "=External Dependencies=")?; for (i, dep) in root.crate_deps.decode(self).enumerate() { - let CrateDep { name, extra_filename, hash, host_hash, kind } = dep; + let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } = dep; let number = i + 1; writeln!( out, - "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?}" + "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}", + privacy = if is_private { "private" } else { "public" } )?; } write!(out, "\n")?; @@ -1617,7 +1618,7 @@ impl CrateMetadata { dependencies, dep_kind: Lock::new(dep_kind), source: Lrc::new(source), - private_dep, + private_dep: Lock::new(private_dep), host_hash, extern_crate: Lock::new(None), hygiene_context: Default::default(), @@ -1665,6 +1666,10 @@ impl CrateMetadata { self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) } + pub(crate) fn update_private_dep(&self, f: impl FnOnce(bool) -> bool) { + self.private_dep.with_lock(|private_dep| *private_dep = f(*private_dep)) + } + pub(crate) fn required_panic_strategy(&self) -> Option { self.root.required_panic_strategy } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7425963d30ff8..9bc25e3e0b7a8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -285,7 +285,10 @@ provide! { tcx, def_id, other, cdata, is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } - is_private_dep => { cdata.private_dep } + is_private_dep => { + let r = *cdata.private_dep.lock(); + r + } is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f067bca4b0b39..59ca0ac6e28fa 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1880,6 +1880,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { host_hash: self.tcx.crate_host_hash(cnum), kind: self.tcx.dep_kind(cnum), extra_filename: self.tcx.extra_filename(cnum).clone(), + is_private: self.tcx.is_private_dep(cnum), }; (cnum, dep) }) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 97e67fcf8fdd0..34ccf00a1e3d9 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -302,6 +302,7 @@ pub(crate) struct CrateDep { pub host_hash: Option, pub kind: CrateDepKind, pub extra_filename: String, + pub is_private: bool, } #[derive(MetadataEncodable, MetadataDecodable)] From 674a3d5c1c898156d7e4bba686593797f44d812a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 1 May 2023 12:05:20 -0700 Subject: [PATCH 03/19] diagnostics: exclude indirect private deps from trait impl suggest Fixes #88696 --- compiler/rustc_middle/src/ty/util.rs | 23 ++++++++++++++++++- .../src/traits/error_reporting/mod.rs | 1 + tests/ui/suggestions/issue-88696.rs | 14 +++++++++++ tests/ui/suggestions/issue-88696.stderr | 11 +++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/ui/suggestions/issue-88696.rs create mode 100644 tests/ui/suggestions/issue-88696.stderr diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index ba05135638e1f..8bf60c40b8528 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -15,7 +15,7 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::{Idx, IndexVec}; use rustc_macros::HashStable; @@ -857,6 +857,27 @@ impl<'tcx> TyCtxt<'tcx> { _ => def_kind.article(), } } + + /// Return `true` if the supplied `CrateNum` is "user-visible," meaning either a [public] + /// dependency, or a [direct] private dependency. This is used to decide whether the crate can + /// be shown in `impl` suggestions. + /// + /// # Panics + /// + /// This function assumes `key` exists. + /// + /// [public]: TyCtxt::is_private_dep + /// [direct]: rustc_session::cstore::ExternCrate::is_direct + pub fn is_user_visible_dep(self, key: CrateNum) -> bool { + // | Private | Direct | Visible | | + // |---------|--------|---------|--------------------| + // | Yes | Yes | Yes | !(true && !true) | + // | No | Yes | Yes | !(false && !true) | + // | Yes | No | No | !(true && !false) | + // | No | No | Yes | !(false && !false) | + !(self.is_private_dep(key) + && !self.extern_crate(key.as_def_id()).expect("crate must exist").is_direct()) + } } struct OpaqueTypeExpander<'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index a10ececbb1ea7..d2cb8971708d6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1775,6 +1775,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { || !trait_pred .skip_binder() .is_constness_satisfied_by(self.tcx.constness(def_id)) + || !self.tcx.is_user_visible_dep(def_id.krate) { return None; } diff --git a/tests/ui/suggestions/issue-88696.rs b/tests/ui/suggestions/issue-88696.rs new file mode 100644 index 0000000000000..745fdef154632 --- /dev/null +++ b/tests/ui/suggestions/issue-88696.rs @@ -0,0 +1,14 @@ +// This test case should ensure that miniz_oxide isn't +// suggested, since it's not a direct dependency. + +fn a() -> Result { + Err(1) +} + +fn b() -> Result { + a().into() //~ERROR [E0277] +} + +fn main() { + let _ = dbg!(b()); +} diff --git a/tests/ui/suggestions/issue-88696.stderr b/tests/ui/suggestions/issue-88696.stderr new file mode 100644 index 0000000000000..4947269d75934 --- /dev/null +++ b/tests/ui/suggestions/issue-88696.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `Result: From>` is not satisfied + --> $DIR/issue-88696.rs:9:9 + | +LL | a().into() + | ^^^^ the trait `From>` is not implemented for `Result` + | + = note: required for `Result` to implement `Into>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From ffef807889c6f759fef3d229b59c3bd9b6e40fd6 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 1 May 2023 13:30:05 -0700 Subject: [PATCH 04/19] Update compiler/rustc_metadata/src/creader.rs Co-authored-by: Camille Gillot --- compiler/rustc_metadata/src/creader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 8bd96906f8b4b..fc8ced3f90007 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -564,7 +564,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { dep_kind = CrateDepKind::MacrosOnly; } data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind)); - data.update_private_dep(|private_dep| private_dep && private_dep); + data.update_private_dep(|p_d| p_d && private_dep); Ok(cnum) } (LoadResult::Loaded(library), host_library) => { From 8488e8aed9eb59e45589974985e7cb377576353c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 1 May 2023 14:02:33 -0700 Subject: [PATCH 05/19] rust-installer: include `RUSTC_BOOTSTRAP` when generating installer --- src/tools/rust-installer/combine-installers.sh | 2 ++ src/tools/rust-installer/gen-installer.sh | 2 ++ src/tools/rust-installer/make-tarballs.sh | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/tools/rust-installer/combine-installers.sh b/src/tools/rust-installer/combine-installers.sh index bee5319fd5502..c2de3385a8081 100755 --- a/src/tools/rust-installer/combine-installers.sh +++ b/src/tools/rust-installer/combine-installers.sh @@ -11,5 +11,7 @@ abs_path() { (unset CDPATH && cd "$path" > /dev/null && pwd) } +export RUSTC_BOOTSTRAP=1 + src_dir="$(abs_path $(dirname "$0"))" $CARGO run --manifest-path="$src_dir/Cargo.toml" -- combine "$@" diff --git a/src/tools/rust-installer/gen-installer.sh b/src/tools/rust-installer/gen-installer.sh index eabd8c95cd849..10a69ff5ac5c5 100755 --- a/src/tools/rust-installer/gen-installer.sh +++ b/src/tools/rust-installer/gen-installer.sh @@ -11,5 +11,7 @@ abs_path() { (unset CDPATH && cd "$path" > /dev/null && pwd) } +export RUSTC_BOOTSTRAP=1 + src_dir="$(abs_path $(dirname "$0"))" $CARGO run --manifest-path="$src_dir/Cargo.toml" -- generate "$@" diff --git a/src/tools/rust-installer/make-tarballs.sh b/src/tools/rust-installer/make-tarballs.sh index e342007da373c..4aadf078ff1ee 100755 --- a/src/tools/rust-installer/make-tarballs.sh +++ b/src/tools/rust-installer/make-tarballs.sh @@ -11,5 +11,7 @@ abs_path() { (unset CDPATH && cd "$path" > /dev/null && pwd) } +export RUSTC_BOOTSTRAP=1 + src_dir="$(abs_path $(dirname "$0"))" $CARGO run --manifest-path="$src_dir/Cargo.toml" -- tarball "$@" From 374024336a0dfed4a5cf5e97ccc99648b18cf00c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 May 2023 12:04:27 -0700 Subject: [PATCH 06/19] Improve comments --- compiler/rustc_metadata/src/rmeta/decoder.rs | 5 +++-- src/bootstrap/metadata.rs | 2 ++ src/tools/rust-installer/combine-installers.sh | 2 ++ src/tools/rust-installer/gen-installer.sh | 2 ++ src/tools/rust-installer/make-tarballs.sh | 2 ++ src/tools/tidy/src/main.rs | 4 +++- 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 46d469f0703c0..ccba77d7aa755 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -111,8 +111,9 @@ pub(crate) struct CrateMetadata { dep_kind: Lock, /// Filesystem location of this crate. source: Lrc, - /// Whether or not this crate should be consider a private dependency - /// for purposes of the 'exported_private_dependencies' lint + /// Whether or not this crate should be consider a private dependency. + /// Used by the 'exported_private_dependencies' lint, and for determining + /// whether to emit suggestions that reference this crate. private_dep: Lock, /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. host_hash: Option, diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index d8671ef2639f3..3b20ceac8759f 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -74,6 +74,8 @@ fn workspace_members(build: &Build) -> impl Iterator { let collect_metadata = |manifest_path| { let mut cargo = Command::new(&build.initial_cargo); cargo + // Will read the libstd Cargo.toml + // which uses the unstable `public-dependency` feature. .env("RUSTC_BOOTSTRAP", "1") .arg("metadata") .arg("--format-version") diff --git a/src/tools/rust-installer/combine-installers.sh b/src/tools/rust-installer/combine-installers.sh index c2de3385a8081..01e5a00af4a23 100755 --- a/src/tools/rust-installer/combine-installers.sh +++ b/src/tools/rust-installer/combine-installers.sh @@ -11,6 +11,8 @@ abs_path() { (unset CDPATH && cd "$path" > /dev/null && pwd) } +# Running cargo will read the libstd Cargo.toml +# which uses the unstable `public-dependency` feature. export RUSTC_BOOTSTRAP=1 src_dir="$(abs_path $(dirname "$0"))" diff --git a/src/tools/rust-installer/gen-installer.sh b/src/tools/rust-installer/gen-installer.sh index 10a69ff5ac5c5..cc45b5e0803f7 100755 --- a/src/tools/rust-installer/gen-installer.sh +++ b/src/tools/rust-installer/gen-installer.sh @@ -11,6 +11,8 @@ abs_path() { (unset CDPATH && cd "$path" > /dev/null && pwd) } +# Running cargo will read the libstd Cargo.toml +# which uses the unstable `public-dependency` feature. export RUSTC_BOOTSTRAP=1 src_dir="$(abs_path $(dirname "$0"))" diff --git a/src/tools/rust-installer/make-tarballs.sh b/src/tools/rust-installer/make-tarballs.sh index 4aadf078ff1ee..374e103e89ca6 100755 --- a/src/tools/rust-installer/make-tarballs.sh +++ b/src/tools/rust-installer/make-tarballs.sh @@ -11,6 +11,8 @@ abs_path() { (unset CDPATH && cd "$path" > /dev/null && pwd) } +# Running cargo will read the libstd Cargo.toml +# which uses the unstable `public-dependency` feature. export RUSTC_BOOTSTRAP=1 src_dir="$(abs_path $(dirname "$0"))" diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 2ad0ae527ac67..a9eada22fc02f 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -16,7 +16,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::thread::{self, scope, ScopedJoinHandle}; fn main() { - // Allow using unstable cargo features in the standard library. + // Running Cargo will read the libstd Cargo.toml + // which uses the unstable `public-dependency` feature. + // // `setenv` might not be thread safe, so run it before using multiple threads. env::set_var("RUSTC_BOOTSTRAP", "1"); From 0ca70be11b6b290d5d7d56dbe9ccd832be5a6809 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 May 2023 12:06:21 -0700 Subject: [PATCH 07/19] rustc_metadata: fix private_dep logic in `register_crate` --- compiler/rustc_metadata/src/creader.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index fc8ced3f90007..63a2dc5aa626f 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -365,7 +365,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { lib: Library, dep_kind: CrateDepKind, name: Symbol, - private_dep: bool, + private_dep: Option, ) -> Result { let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); @@ -373,8 +373,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { 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()).is_some_and(|e| e.is_private_dep); + 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); // Claim this crate number and cache it let cnum = self.cstore.intern_stable_crate_id(&crate_root)?; @@ -526,9 +531,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { dep.host_hash, Some(&dep.extra_filename[..]), PathKind::Dependency, - dep.is_private, + Some(dep.is_private), ), - None => (None, None, None, None, PathKind::Crate, false), + None => (None, None, None, None, PathKind::Crate, None), }; let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { (LoadResult::Previous(cnum), None) @@ -564,7 +569,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { dep_kind = CrateDepKind::MacrosOnly; } data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind)); - data.update_private_dep(|p_d| p_d && private_dep); + if let Some(private_dep) = private_dep { + data.update_private_dep(|p_d| p_d && private_dep); + } Ok(cnum) } (LoadResult::Loaded(library), host_library) => { From d47dc326d63c6ed9cc2cd7f99596b5f1e051906d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 May 2023 13:41:39 -0700 Subject: [PATCH 08/19] diagnostics: don't crash if an injected crate shows up in suggestions --- compiler/rustc_middle/src/ty/util.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8bf60c40b8528..6704f3eeb2add 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -876,7 +876,10 @@ impl<'tcx> TyCtxt<'tcx> { // | Yes | No | No | !(true && !false) | // | No | No | Yes | !(false && !false) | !(self.is_private_dep(key) - && !self.extern_crate(key.as_def_id()).expect("crate must exist").is_direct()) + // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator). + // Treat that kind of crate as "indirect", since it's an implementation detail of + // the language. + && !self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct())) } } From 5a7fffee7150639ba1c68fe41c9365227929f299 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 May 2023 14:12:54 -0700 Subject: [PATCH 09/19] rustc_metadata: use AtomicBool for privateness instead of Lock --- compiler/rustc_metadata/src/rmeta/decoder.rs | 12 ++++++++---- .../rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 7 +++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ccba77d7aa755..ae8423af1124c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -40,6 +40,7 @@ use proc_macro::bridge::client::ProcMacro; use std::iter::TrustedLen; use std::num::NonZeroUsize; use std::path::Path; +use std::sync::atomic::{AtomicBool, Ordering}; use std::{io, iter, mem}; pub(super) use cstore_impl::provide; @@ -114,7 +115,7 @@ pub(crate) struct CrateMetadata { /// Whether or not this crate should be consider a private dependency. /// Used by the 'exported_private_dependencies' lint, and for determining /// whether to emit suggestions that reference this crate. - private_dep: Lock, + private_dep: AtomicBool, /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. host_hash: Option, @@ -1619,7 +1620,7 @@ impl CrateMetadata { dependencies, dep_kind: Lock::new(dep_kind), source: Lrc::new(source), - private_dep: Lock::new(private_dep), + private_dep: AtomicBool::new(private_dep), host_hash, extern_crate: Lock::new(None), hygiene_context: Default::default(), @@ -1667,8 +1668,11 @@ impl CrateMetadata { self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) } - pub(crate) fn update_private_dep(&self, f: impl FnOnce(bool) -> bool) { - self.private_dep.with_lock(|private_dep| *private_dep = f(*private_dep)) + /// `f` must not perform any I/O or take any locks. It may be called more than once. + pub(crate) fn update_private_dep(&self, mut f: impl FnMut(bool) -> bool) { + self.private_dep + .fetch_update(Ordering::Release, Ordering::Acquire, |private_dep| Some(f(private_dep))) + .expect("fetch_update only returns Err if `f` returns None`, which it doesn't"); } pub(crate) fn required_panic_strategy(&self) -> Option { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9bc25e3e0b7a8..24fbc2f64b73a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -286,8 +286,11 @@ provide! { tcx, def_id, other, cdata, dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } is_private_dep => { - let r = *cdata.private_dep.lock(); - r + // Parallel compiler needs to synchronize type checking and linting (which use this flag) + // so that they happen strictly crate loading. Otherwise, the full list of available + // impls aren't loaded yet. + use std::sync::atomic::Ordering; + cdata.private_dep.load(Ordering::Acquire) } is_panic_runtime => { cdata.root.panic_runtime } is_compiler_builtins => { cdata.root.compiler_builtins } From 1c14b0ac0a75526055dd2d0218ec00d2f59c6714 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 May 2023 14:34:17 -0700 Subject: [PATCH 10/19] remove outdated comment from `is_user_visible_dep` docs --- compiler/rustc_middle/src/ty/util.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6704f3eeb2add..06f9d32858c63 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -862,10 +862,6 @@ impl<'tcx> TyCtxt<'tcx> { /// dependency, or a [direct] private dependency. This is used to decide whether the crate can /// be shown in `impl` suggestions. /// - /// # Panics - /// - /// This function assumes `key` exists. - /// /// [public]: TyCtxt::is_private_dep /// [direct]: rustc_session::cstore::ExternCrate::is_direct pub fn is_user_visible_dep(self, key: CrateNum) -> bool { From b537c1f1756b43228c3c392a54ddec91b0f1d205 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 May 2023 14:51:07 -0700 Subject: [PATCH 11/19] std: mark common functions in test crate `pub(crate)` This is not a library, so there's no reason for them to be `pub`. Without doing this, compiling the test crates causes private dep lint errors: error: type `PathBuf` from private dependency 'std' in public interface --> library/std/tests/common/mod.rs:26:5 | 26 | pub fn join(&self, path: &str) -> PathBuf { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D exported-private-dependencies` implied by `-D warnings` error: type `Path` from private dependency 'std' in public interface --> library/std/tests/common/mod.rs:31:5 | 31 | pub fn path(&self) -> &Path { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not compile `std` (test "create_dir_all_bare") due to 2 previous errors This happens because Cargo passes `--extern 'priv:std=...` when compiling the test crate. I'm not sure if these warnings are desirable or not. They seem correct in a very pedantic way (the dependency on `std` is not marked public, since it's implicit), but also pointless (the test crate is not an API, so who cares what it does). --- library/std/tests/common/mod.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs index 37336e1c08ff8..358c2c3f9b2f3 100644 --- a/library/std/tests/common/mod.rs +++ b/library/std/tests/common/mod.rs @@ -1,7 +1,5 @@ #![allow(unused)] -#![allow(exported_private_dependencies)] - use std::env; use std::fs; use std::path::{Path, PathBuf}; @@ -22,15 +20,15 @@ pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng { } // Copied from std::sys_common::io -pub struct TempDir(PathBuf); +pub(crate) struct TempDir(PathBuf); impl TempDir { - pub fn join(&self, path: &str) -> PathBuf { + pub(crate) fn join(&self, path: &str) -> PathBuf { let TempDir(ref p) = *self; p.join(path) } - pub fn path(&self) -> &Path { + pub(crate) fn path(&self) -> &Path { let TempDir(ref p) = *self; p } @@ -51,7 +49,7 @@ impl Drop for TempDir { } #[track_caller] // for `test_rng` -pub fn tmpdir() -> TempDir { +pub(crate) fn tmpdir() -> TempDir { let p = env::temp_dir(); let mut r = test_rng(); let ret = p.join(&format!("rust-{}", r.next_u32())); From a12f50ddc4ed73cbca436827ae3958a104d915d3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 8 May 2023 15:12:45 -0700 Subject: [PATCH 12/19] rustc_metadata: use configurable AtomicBool for privateness flag This switches to using a `Cell` for single-threaded rustc. --- compiler/rustc_data_structures/src/sync.rs | 14 ++++++++++++++ compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 6c3197d8ec2c5..df8285cc7292f 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -143,6 +143,20 @@ cfg_if! { self.0.set(val); result } + pub fn fetch_update( + &self, + _order_set: Ordering, + _order_get: Ordering, + mut f: impl FnMut(bool) -> Option, + ) -> Result { + let prev = self.0.get(); + if let Some(next) = f(prev) { + self.0.set(next); + Ok(prev) + } else { + Err(prev) + } + } } impl Atomic { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ae8423af1124c..325ffcae7e98b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -9,7 +9,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell}; +use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceCell}; use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; @@ -40,7 +40,7 @@ use proc_macro::bridge::client::ProcMacro; use std::iter::TrustedLen; use std::num::NonZeroUsize; use std::path::Path; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::Ordering; use std::{io, iter, mem}; pub(super) use cstore_impl::provide; From bd90868b3f7458fa00dbd6b12927153f28556467 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 9 May 2023 13:27:51 -0700 Subject: [PATCH 13/19] Use De Morgan's law to simplify logic Co-authored-by: Camille Gillot --- compiler/rustc_middle/src/ty/util.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 06f9d32858c63..4820d4d2c77e3 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -867,15 +867,15 @@ impl<'tcx> TyCtxt<'tcx> { pub fn is_user_visible_dep(self, key: CrateNum) -> bool { // | Private | Direct | Visible | | // |---------|--------|---------|--------------------| - // | Yes | Yes | Yes | !(true && !true) | - // | No | Yes | Yes | !(false && !true) | - // | Yes | No | No | !(true && !false) | - // | No | No | Yes | !(false && !false) | - !(self.is_private_dep(key) + // | Yes | Yes | Yes | !true || true | + // | No | Yes | Yes | !false || true | + // | Yes | No | No | !true || false | + // | No | No | Yes | !false || false | + !self.is_private_dep(key) // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator). // Treat that kind of crate as "indirect", since it's an implementation detail of // the language. - && !self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct())) + || self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct()) } } From 6a358960da438efca794020bf5497b41ce3ffe17 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 9 May 2023 13:46:54 -0700 Subject: [PATCH 14/19] rustc_metadata: specialize private_dep flag with `fetch_and` --- compiler/rustc_data_structures/src/sync.rs | 17 ++++------------- compiler/rustc_metadata/src/creader.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 7 ++----- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index df8285cc7292f..96dc187611d76 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -143,19 +143,10 @@ cfg_if! { self.0.set(val); result } - pub fn fetch_update( - &self, - _order_set: Ordering, - _order_get: Ordering, - mut f: impl FnMut(bool) -> Option, - ) -> Result { - let prev = self.0.get(); - if let Some(next) = f(prev) { - self.0.set(next); - Ok(prev) - } else { - Err(prev) - } + pub fn fetch_and(&self, val: bool, _: Ordering) -> bool { + let result = self.0.get() & val; + self.0.set(val); + result } } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 63a2dc5aa626f..4c872664c3dca 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -570,7 +570,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind)); if let Some(private_dep) = private_dep { - data.update_private_dep(|p_d| p_d && private_dep); + data.update_and_private_dep(private_dep); } Ok(cnum) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 325ffcae7e98b..d2995b198f6dd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1668,11 +1668,8 @@ impl CrateMetadata { self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) } - /// `f` must not perform any I/O or take any locks. It may be called more than once. - pub(crate) fn update_private_dep(&self, mut f: impl FnMut(bool) -> bool) { - self.private_dep - .fetch_update(Ordering::Release, Ordering::Acquire, |private_dep| Some(f(private_dep))) - .expect("fetch_update only returns Err if `f` returns None`, which it doesn't"); + pub(crate) fn update_and_private_dep(&self, private_dep: bool) { + self.private_dep.fetch_and(private_dep, Ordering::SeqCst); } pub(crate) fn required_panic_strategy(&self) -> Option { From 2e52f4deb0544480b6aefe2c0cc1e6f3c893b081 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 15 May 2023 22:28:08 -0700 Subject: [PATCH 15/19] bootstrap: use RUSTC_BOOTSTRAP to vendor sources --- src/bootstrap/dist.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index b49845386da17..338667de03aaf 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1013,6 +1013,9 @@ impl Step for PlainSourceTarball { .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml")) .arg("--sync") .arg(builder.src.join("./src/bootstrap/Cargo.toml")) + // Will read the libstd Cargo.toml + // which uses the unstable `public-dependency` feature. + .env("RUSTC_BOOTSTRAP", "1") .current_dir(&plain_dst_src); let config = if !builder.config.dry_run() { From 8c21920cc721de6a75c959168240c3cba4177df5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 17 May 2023 20:30:55 -0700 Subject: [PATCH 16/19] std: make internal-only items `pub(crate)` This works around a weird problem that looks like a bug in the `exported_private_dependencies` lint. --- library/std/src/sys/wasi/fd.rs | 6 +++--- library/std/src/sys/wasi/fs.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs index 9a8b2a0be5b00..1b50c2ea6dd57 100644 --- a/library/std/src/sys/wasi/fd.rs +++ b/library/std/src/sys/wasi/fd.rs @@ -96,7 +96,7 @@ impl WasiFd { unsafe { wasi::fd_sync(self.as_raw_fd() as wasi::Fd).map_err(err2io) } } - pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { + pub(crate) fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { unsafe { wasi::fd_advise(self.as_raw_fd() as wasi::Fd, offset, len, advice).map_err(err2io) } @@ -179,7 +179,7 @@ impl WasiFd { } } - pub fn filestat_get(&self) -> io::Result { + pub(crate) fn filestat_get(&self) -> io::Result { unsafe { wasi::fd_filestat_get(self.as_raw_fd() as wasi::Fd).map_err(err2io) } } @@ -199,7 +199,7 @@ impl WasiFd { unsafe { wasi::fd_filestat_set_size(self.as_raw_fd() as wasi::Fd, size).map_err(err2io) } } - pub fn path_filestat_get( + pub(crate) fn path_filestat_get( &self, flags: wasi::Lookupflags, path: &str, diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 8d1dbf59155a4..437aae3ae7f7f 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -104,7 +104,7 @@ impl FileAttr { Ok(SystemTime::from_wasi_timestamp(self.meta.ctim)) } - pub fn as_wasi(&self) -> &wasi::Filestat { + pub(crate) fn as_wasi(&self) -> &wasi::Filestat { &self.meta } } @@ -142,7 +142,7 @@ impl FileType { self.bits == wasi::FILETYPE_SYMBOLIC_LINK } - pub fn bits(&self) -> wasi::Filetype { + pub(crate) fn bits(&self) -> wasi::Filetype { self.bits } } From 5fb752bdd51b2d40ffbddf3c86e5869b3e816e08 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 20 May 2023 20:14:38 -0700 Subject: [PATCH 17/19] std: make `fortanix-sgx-abi` a public depedenceny It's exported publicly, so it should not be linted. --- library/std/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 4765bb5d25a93..72d910bf95746 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -42,7 +42,7 @@ rand_xorshift = "0.3.0" dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] -fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'] } +fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true } [target.'cfg(target_os = "hermit")'.dependencies] hermit-abi = { version = "0.3.0", features = ['rustc-dep-of-std'] } From 64cfc212890515fe4c41374acbc986034450d3b7 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 25 May 2023 15:12:33 -0700 Subject: [PATCH 18/19] bootstrap: use RUSTC_BOOTSTRAP in distcheck --- src/bootstrap/test.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 2b72d6c48eb75..8b6048464e8b6 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -2514,6 +2514,9 @@ impl Step for Distcheck { let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml"); builder.run( Command::new(&builder.initial_cargo) + // Will read the libstd Cargo.toml + // which uses the unstable `public-dependency` feature. + .env("RUSTC_BOOTSTRAP", "1") .arg("generate-lockfile") .arg("--manifest-path") .arg(&toml) From 52bd82f522c4f3d9bd0dc534c06169285afbc23b Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 25 May 2023 15:18:05 -0700 Subject: [PATCH 19/19] rustc_data_structures: sync and atomic consistency Co-authored-by: @lukas-code --- compiler/rustc_data_structures/src/sync.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 96dc187611d76..25a08237346dd 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -139,14 +139,14 @@ cfg_if! { impl Atomic { pub fn fetch_or(&self, val: bool, _: Ordering) -> bool { - let result = self.0.get() | val; - self.0.set(val); - result + let old = self.0.get(); + self.0.set(val | old); + old } pub fn fetch_and(&self, val: bool, _: Ordering) -> bool { - let result = self.0.get() & val; - self.0.set(val); - result + let old = self.0.get(); + self.0.set(val & old); + old } }