From 4896a65d18ddd4038f44cf13f25eff80c734bc93 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 13 Jan 2025 01:41:49 +0000 Subject: [PATCH 1/5] Add a UI test for stdlib-private dependencies Introduce a test that shows stdlib-private dependencies leaking into diagnostics. This is resolved by a later commit. --- .../ui/privacy/sysroot-private.default.stderr | 39 +++++++++++++++++ tests/ui/privacy/sysroot-private.rs | 42 +++++++++++++++++++ ...sroot-private.rustc_private_enabled.stderr | 39 +++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 tests/ui/privacy/sysroot-private.default.stderr create mode 100644 tests/ui/privacy/sysroot-private.rs create mode 100644 tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr diff --git a/tests/ui/privacy/sysroot-private.default.stderr b/tests/ui/privacy/sysroot-private.default.stderr new file mode 100644 index 0000000000000..98e6922428a90 --- /dev/null +++ b/tests/ui/privacy/sysroot-private.default.stderr @@ -0,0 +1,39 @@ +error[E0405]: cannot find trait `Equivalent` in this scope + --> $DIR/sysroot-private.rs:26:18 + | +LL | trait Trait2: Equivalent {} + | ^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `K` in this scope + --> $DIR/sysroot-private.rs:31:35 + | +LL | fn trait_member(val: &T, key: &K) -> bool { + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | fn trait_member(val: &T, key: &T) -> bool { + | ~ +help: you might be missing a type parameter + | +LL | fn trait_member(val: &T, key: &K) -> bool { + | +++ + +error[E0220]: associated type `ExpressionStack` not found for `Trait` + --> $DIR/sysroot-private.rs:21:31 + | +LL | type AssociatedTy = dyn Trait; + | ^^^^^^^^^^^^^^^ there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` + +error[E0425]: cannot find function `memchr2` in this scope + --> $DIR/sysroot-private.rs:39:5 + | +LL | memchr2(b'a', b'b', buf) + | ^^^^^^^ not found in this scope + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0220, E0405, E0412, E0425. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/privacy/sysroot-private.rs b/tests/ui/privacy/sysroot-private.rs new file mode 100644 index 0000000000000..190a3598108ef --- /dev/null +++ b/tests/ui/privacy/sysroot-private.rs @@ -0,0 +1,42 @@ +//! Test that private dependencies of `std` that live in the sysroot do not reach through to +//! diagnostics. +//! +//! This test would be more robust if we could patch the sysroot with an "evil" crate that +//! provided known types that we control; however, this would effectively require rebuilding +//! `std` (or patching crate metadata). So, this test relies on what is currently public API +//! of `std`'s dependencies, but may not be robust against dependency upgrades/changes. + +//@ only-unix Windows sysroots seem to not expose this dependency +//@ revisions: default rustc_private_enabled + +// Enabling `rustc_private` should `std`'s dependencies accessible, so they should show up +// in diagnostics. NB: not all diagnostics are affected by this. +#![cfg_attr(rustc_private_enabled, feature(rustc_private))] +#![crate_type = "lib"] + +trait Trait { type Bar; } + +// Attempt to get a suggestion for `gimli::read::op::EvaluationStoreage`, which should not be +// present in diagnostics (it is a dependency of the compiler). +type AssociatedTy = dyn Trait; +//~^ ERROR associated type `ExpressionStack` not found +//~| NOTE there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` + +// Attempt to get a suggestion for `hashbrown::Equivalent` +trait Trait2: Equivalent {} +//~^ ERROR cannot find trait +//~| NOTE not found + +// Attempt to get a suggestion for `hashbrown::Equivalent::equivalent` +fn trait_member(val: &T, key: &K) -> bool { + //~^ ERROR cannot find type `K` + //~| NOTE similarly named + val.equivalent(key) +} + +// Attempt to get a suggestion for `memchr::memchr2` +fn free_function(buf: &[u8]) -> Option { + memchr2(b'a', b'b', buf) + //~^ ERROR cannot find function + //~| NOTE not found +} diff --git a/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr b/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr new file mode 100644 index 0000000000000..98e6922428a90 --- /dev/null +++ b/tests/ui/privacy/sysroot-private.rustc_private_enabled.stderr @@ -0,0 +1,39 @@ +error[E0405]: cannot find trait `Equivalent` in this scope + --> $DIR/sysroot-private.rs:26:18 + | +LL | trait Trait2: Equivalent {} + | ^^^^^^^^^^ not found in this scope + +error[E0412]: cannot find type `K` in this scope + --> $DIR/sysroot-private.rs:31:35 + | +LL | fn trait_member(val: &T, key: &K) -> bool { + | - ^ + | | + | similarly named type parameter `T` defined here + | +help: a type parameter with a similar name exists + | +LL | fn trait_member(val: &T, key: &T) -> bool { + | ~ +help: you might be missing a type parameter + | +LL | fn trait_member(val: &T, key: &K) -> bool { + | +++ + +error[E0220]: associated type `ExpressionStack` not found for `Trait` + --> $DIR/sysroot-private.rs:21:31 + | +LL | type AssociatedTy = dyn Trait; + | ^^^^^^^^^^^^^^^ there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` + +error[E0425]: cannot find function `memchr2` in this scope + --> $DIR/sysroot-private.rs:39:5 + | +LL | memchr2(b'a', b'b', buf) + | ^^^^^^^ not found in this scope + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0220, E0405, E0412, E0425. +For more information about an error, try `rustc --explain E0220`. From 4dc866c642e20949a74e7344964ce179a5daf448 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 9 Jan 2025 04:57:29 +0000 Subject: [PATCH 2/5] rustc_metadata: Rename `root` to `dep_root` Currently `root` or `crate_root` is used to refer to an instance of `CrateRoot` (representation of a crate's serialized metadata), but the name `root` sometimes also refers to a `CratePath` representing a "root" node in the dependency graph. In order to disambiguate, rename all instances of the latter to `dep_root`. --- compiler/rustc_metadata/src/creader.rs | 49 +++++++++++++++----------- compiler/rustc_metadata/src/locator.rs | 12 +++---- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 1ea075c2cb368..70ea2925d0676 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -390,10 +390,12 @@ 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` + /// The `dependency` type is determined by the command line arguments(`--extern`) and + /// `private_dep`. + /// + /// 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) @@ -402,7 +404,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { fn register_crate( &mut self, host_lib: Option, - root: Option<&CratePaths>, + dep_root: Option<&CratePaths>, lib: Library, dep_kind: CrateDepKind, name: Symbol, @@ -430,14 +432,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Maintain a reference to the top most crate. // Stash paths for top-most crate locally if necessary. let crate_paths; - let root = if let Some(root) = root { - root + let dep_root = if let Some(dep_root) = dep_root { + dep_root } else { crate_paths = CratePaths::new(crate_root.name(), source.clone()); &crate_paths }; - let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?; + let cnum_map = self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind)?; let raw_proc_macros = if crate_root.is_proc_macro_crate() { let temp_root; @@ -559,15 +561,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &'b mut self, name: Symbol, mut dep_kind: CrateDepKind, - dep: Option<(&'b CratePaths, &'b CrateDep)>, + dep_of: Option<(&'b CratePaths, &'b CrateDep)>, ) -> Result { info!("resolving crate `{}`", name); if !name.as_str().is_ascii() { return Err(CrateError::NonAsciiName(name)); } - let (root, hash, host_hash, extra_filename, path_kind, private_dep) = match dep { - Some((root, dep)) => ( - Some(root), + let (dep_root, hash, host_hash, extra_filename, path_kind, private_dep) = match dep_of { + Some((dep_root, dep)) => ( + Some(dep_root), Some(dep.hash), dep.host_hash, Some(&dep.extra_filename[..]), @@ -599,7 +601,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { dep_kind = CrateDepKind::MacrosOnly; match self.load_proc_macro(&mut locator, path_kind, host_hash)? { Some(res) => res, - None => return Err(locator.into_error(root.cloned())), + None => return Err(locator.into_error(dep_root.cloned())), } } } @@ -623,7 +625,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } (LoadResult::Loaded(library), host_library) => { info!("register newly loaded library for `{}`", name); - self.register_crate(host_library, root, library, dep_kind, name, private_dep) + self.register_crate(host_library, dep_root, library, dep_kind, name, private_dep) } _ => panic!(), } @@ -663,16 +665,20 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { })) } - // Go through the crate metadata and load any crates that it references + /// Go through the crate metadata and load any crates that it references. fn resolve_crate_deps( &mut self, - root: &CratePaths, + dep_root: &CratePaths, crate_root: &CrateRoot, metadata: &MetadataBlob, krate: CrateNum, dep_kind: CrateDepKind, ) -> Result { - debug!("resolving deps of external crate"); + debug!( + "resolving deps of external crate `{}` with dep root `{}`", + crate_root.name(), + dep_root.name + ); if crate_root.is_proc_macro_crate() { return Ok(CrateNumMap::new()); } @@ -685,14 +691,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { crate_num_map.push(krate); for dep in deps { info!( - "resolving dep crate {} hash: `{}` extra filename: `{}`", - dep.name, dep.hash, dep.extra_filename + "resolving dep `{}`->`{}` hash: `{}` extra filename: `{}`", + crate_root.name(), + dep.name, + dep.hash, + dep.extra_filename ); let dep_kind = match dep_kind { CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly, _ => dep.kind, }; - let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?; + let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((dep_root, &dep)))?; crate_num_map.push(cnum); } diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index b9ebf17af248f..2ddabeb49f70d 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -262,7 +262,7 @@ pub(crate) struct CrateLocator<'a> { #[derive(Clone)] pub(crate) struct CratePaths { - name: Symbol, + pub(crate) name: Symbol, source: CrateSource, } @@ -765,10 +765,10 @@ impl<'a> CrateLocator<'a> { self.extract_lib(rlibs, rmetas, dylibs).map(|opt| opt.map(|(_, lib)| lib)) } - pub(crate) fn into_error(self, root: Option) -> CrateError { + pub(crate) fn into_error(self, dep_root: Option) -> CrateError { CrateError::LocatorCombined(Box::new(CombinedLocatorError { crate_name: self.crate_name, - root, + dep_root, triple: self.tuple, dll_prefix: self.target.dll_prefix.to_string(), dll_suffix: self.target.dll_suffix.to_string(), @@ -914,7 +914,7 @@ struct CrateRejections { /// otherwise they are ignored. pub(crate) struct CombinedLocatorError { crate_name: Symbol, - root: Option, + dep_root: Option, triple: TargetTuple, dll_prefix: String, dll_suffix: String, @@ -987,7 +987,7 @@ impl CrateError { } CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; - let add_info = match &locator.root { + let add_info = match &locator.dep_root { None => String::new(), Some(r) => format!(" which `{}` depends on", r.name), }; @@ -1012,7 +1012,7 @@ impl CrateError { path.display() )); } - if let Some(r) = locator.root { + if let Some(r) = locator.dep_root { for path in r.source.paths() { found_crates.push_str(&format!( "\ncrate `{}`: {}", From 9c3425376243966476d07d4a35a87ff228fb890b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 13 Jan 2025 04:59:38 +0000 Subject: [PATCH 3/5] Make `#[rustc_private]` override dependency visibility Really this is always-visible override only needs to happen when the crate is a dependency of itself. However, this is a very internal feature, so it doesn't seem worth doing any additional filtering here. --- compiler/rustc_middle/src/ty/util.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4272893df306c..75893da0e5836 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -876,6 +876,11 @@ impl<'tcx> TyCtxt<'tcx> { /// [public]: TyCtxt::is_private_dep /// [direct]: rustc_session::cstore::ExternCrate::is_direct pub fn is_user_visible_dep(self, key: CrateNum) -> bool { + // `#![rustc_private]` overrides defaults to make private dependencies usable. + if self.features().enabled(sym::rustc_private) { + return true; + } + // | Private | Direct | Visible | | // |---------|--------|---------|--------------------| // | Yes | Yes | Yes | !true || true | From 2da9accab989b8640c7b345371b08886e9332f7e Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 13 Jan 2025 04:44:58 +0000 Subject: [PATCH 4/5] Add `tcx.visible_traits()` and use it for producing diagnostics Add an alternative to `tcx.all_traits()` that only shows traits that the user might be able to use, for diagnostic purposes. With this available, make use of it for diagnostics including associated type errors, which is part of the problem with [1]. Includes a few comment updates for related API. [1]: https://github.com/rust-lang/rust/issues/135232 --- .../rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 ++ compiler/rustc_middle/src/ty/context.rs | 11 +++++++++++ compiler/rustc_passes/src/diagnostic_items.rs | 10 ++++++++-- .../src/error_reporting/traits/fulfillment_errors.rs | 2 +- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 0623d35853e32..7a3d921f00e6e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -179,7 +179,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // all visible traits. If there's one clear winner, just suggest that. let visible_traits: Vec<_> = tcx - .all_traits() + .visible_traits() .filter(|trait_def_id| { let viz = tcx.visibility(*trait_def_id); let def_id = self.item_def_id(); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7d334847d44b1..dd1b2d5111e51 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2128,6 +2128,8 @@ rustc_queries! { eval_always desc { "calculating the stability index for the local crate" } } + /// All available crates in the graph, including those that should not be user-facing + /// (such as private crates). query crates(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching all foreign CrateNum instances" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 24f10b4fbe784..fab0047babfd0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2078,12 +2078,23 @@ impl<'tcx> TyCtxt<'tcx> { self.limits(()).move_size_limit } + /// All traits in the crate graph, including those not visible to the user. pub fn all_traits(self) -> impl Iterator + 'tcx { iter::once(LOCAL_CRATE) .chain(self.crates(()).iter().copied()) .flat_map(move |cnum| self.traits(cnum).iter().copied()) } + /// All traits that are visible within the crate graph (i.e. excluding private dependencies). + pub fn visible_traits(self) -> impl Iterator + 'tcx { + let visible_crates = + self.crates(()).iter().copied().filter(move |cnum| self.is_user_visible_dep(*cnum)); + + iter::once(LOCAL_CRATE) + .chain(visible_crates) + .flat_map(move |cnum| self.traits(cnum).iter().copied()) + } + #[inline] pub fn local_visibility(self, def_id: LocalDefId) -> Visibility { self.visibility(def_id).expect_local() diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 7b02aecdfae1f..323b414cca04c 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -79,8 +79,14 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems { // Initialize the collector. let mut items = DiagnosticItems::default(); - // Collect diagnostic items in other crates. - for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { + // Collect diagnostic items in visible crates. + for cnum in tcx + .crates(()) + .iter() + .copied() + .filter(|cnum| tcx.is_user_visible_dep(*cnum)) + .chain(std::iter::once(LOCAL_CRATE)) + { for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id { collect_item(tcx, &mut items, name, def_id); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 405c26b5b3b58..6076c999086bf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2189,7 +2189,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); let traits_with_same_path: UnordSet<_> = self .tcx - .all_traits() + .visible_traits() .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) .map(|trait_def_id| (self.tcx.def_path_str(trait_def_id), trait_def_id)) .filter(|(p, _)| *p == required_trait_path) From ed63539282b7c087bfd6ef5e41584d1cf61f13f6 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 14 Jan 2025 06:44:20 +0000 Subject: [PATCH 5/5] Mark dependencies of the standard library as private by default In order to avoid diagnostics suggesting stdlib-private dependencies, make everything that is a direct dependency of any `std` crates private by default. Note that this will be overridden, if the same crate is public elsewhere in the crate graph then that overrides the private default. It may also be feasible to do this in the library crate, marking `std`'s dependencies private via Cargo. However, given that the feature is still rather unstable, doing this within the compiler seems more straightforward. Fixes: https://github.com/rust-lang/rust/issues/135232 [1] --- compiler/rustc_metadata/src/creader.rs | 66 +++++++++++++------ .../ui/privacy/sysroot-private.default.stderr | 2 +- tests/ui/privacy/sysroot-private.rs | 2 +- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 70ea2925d0676..6512176cc4a90 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -29,7 +29,7 @@ use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; use rustc_span::edition::Edition; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, Ident, STDLIB_STABLE_CRATES, Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, Target, TargetTuple}; use tracing::{debug, info, trace}; @@ -390,15 +390,45 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { None } - /// The `dependency` type is determined by the command line arguments(`--extern`) and - /// `private_dep`. + /// Determine whether a dependency should be considered private. + /// + /// Dependencies are private if they get extern option specified, e.g. `--extern priv:mycrate`. + /// This is stored in metadata, so `private_dep` can be correctly set during load. A `Some` + /// value for `private_dep` indicates that the crate is known to be private or public (note + /// that any `None` or `Some(false)` use of the same crate will make it public). /// /// 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 is_private_dep( + &self, + name: Symbol, + private_dep: Option, + dep_root: Option<&CratePaths>, + ) -> bool { + // Standard library crates are never private. + if STDLIB_STABLE_CRATES.contains(&name) { + tracing::info!("returning false for {name} is private"); + return false; + } + + let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep); + + // Any descendants of `std` should be private. These crates are usually not marked + // private in metadata, so we ignore that field. + if extern_private.is_none() + && dep_root.map_or(false, |d| STDLIB_STABLE_CRATES.contains(&d.name)) + { + return true; + } + + match (extern_private, private_dep) { + // Explicit non-private via `--extern`, explicit non-private from metadata, or + // unspecified with default to public. + (Some(false), _) | (_, Some(false)) | (None, None) => false, + // Marked private via `--extern priv:mycrate` or in metadata. + (Some(true) | None, Some(true) | None) => true, + } } fn register_crate( @@ -416,7 +446,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.is_private_dep(name.as_str(), private_dep); + let private_dep = self.is_private_dep(name, private_dep, dep_root); // Claim this crate number and cache it let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?; @@ -567,17 +597,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { if !name.as_str().is_ascii() { return Err(CrateError::NonAsciiName(name)); } - let (dep_root, hash, host_hash, extra_filename, path_kind, private_dep) = match dep_of { - Some((dep_root, dep)) => ( - Some(dep_root), - Some(dep.hash), - dep.host_hash, - Some(&dep.extra_filename[..]), - PathKind::Dependency, - Some(dep.is_private), - ), - None => (None, None, None, None, PathKind::Crate, None), - }; + + let dep_root = dep_of.map(|d| d.0); + let dep = dep_of.map(|d| d.1); + let hash = dep.map(|d| d.hash); + let host_hash = dep.map(|d| d.host_hash).flatten(); + let extra_filename = dep.map(|d| &d.extra_filename[..]); + let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; + let private_dep = dep.map(|d| d.is_private); + let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { (LoadResult::Previous(cnum), None) } else { @@ -614,7 +642,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // 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 private_dep = self.is_private_dep(name, private_dep, dep_root); let data = self.cstore.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; diff --git a/tests/ui/privacy/sysroot-private.default.stderr b/tests/ui/privacy/sysroot-private.default.stderr index 98e6922428a90..845d4558d13a0 100644 --- a/tests/ui/privacy/sysroot-private.default.stderr +++ b/tests/ui/privacy/sysroot-private.default.stderr @@ -25,7 +25,7 @@ error[E0220]: associated type `ExpressionStack` not found for `Trait` --> $DIR/sysroot-private.rs:21:31 | LL | type AssociatedTy = dyn Trait; - | ^^^^^^^^^^^^^^^ there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` + | ^^^^^^^^^^^^^^^ help: `Trait` has the following associated type: `Bar` error[E0425]: cannot find function `memchr2` in this scope --> $DIR/sysroot-private.rs:39:5 diff --git a/tests/ui/privacy/sysroot-private.rs b/tests/ui/privacy/sysroot-private.rs index 190a3598108ef..67ab67c7f5c53 100644 --- a/tests/ui/privacy/sysroot-private.rs +++ b/tests/ui/privacy/sysroot-private.rs @@ -20,7 +20,7 @@ trait Trait { type Bar; } // present in diagnostics (it is a dependency of the compiler). type AssociatedTy = dyn Trait; //~^ ERROR associated type `ExpressionStack` not found -//~| NOTE there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` +//[rustc_private_enabled]~| NOTE there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage` // Attempt to get a suggestion for `hashbrown::Equivalent` trait Trait2: Equivalent {}