Skip to content

Commit dbe10d0

Browse files
committed
Auto merge of #135278 - tgross35:ignore-std-dep-crates, r=<try>
Exclude dependencies of `std` for diagnostics Currently crates in the sysroot can show up in diagnostic suggestions, such as in #135232. To prevent this, introduce a query `visible_crates` that excludes crates marked `is_private_dep` and use this query in user-facing areas of code. Setting `#![feature(rustc_private)]` overrides this to just use all crates, since `rustc_private` enables use of `std`'s private dependencies. Notably, this changes `all_traits` to use `.visible_crates(())` rather than `.crates(())`. This is not strictly required and filtering could happen later as-needed; however, I cannot think of any cases where traits from private dependencies should be relevant in trait selection or diagnostics, so filtering at this earlier point seems more likely to avoid similar issues in the future. This may be reviewed per-commit. Fixes: #135232
2 parents e7ad3ae + a04ed09 commit dbe10d0

File tree

9 files changed

+186
-29
lines changed

9 files changed

+186
-29
lines changed

compiler/rustc_metadata/src/creader.rs

+29-20
Original file line numberDiff line numberDiff line change
@@ -390,10 +390,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
390390
None
391391
}
392392

393-
// The `dependency` type is determined by the command line arguments(`--extern`) and
394-
// `private_dep`. However, sometimes the directly dependent crate is not specified by
395-
// `--extern`, in this case, `private-dep` is none during loading. This is equivalent to the
396-
// scenario where the command parameter is set to `public-dependency`
393+
/// The `dependency` type is determined by the command line arguments(`--extern`) and
394+
/// `private_dep`.
395+
///
396+
/// Sometimes the directly dependent crate is not specified by `--extern`, in this case,
397+
/// `private-dep` is none during loading. This is equivalent to the scenario where the
398+
/// command parameter is set to `public-dependency`
397399
fn is_private_dep(&self, name: &str, private_dep: Option<bool>) -> bool {
398400
self.sess.opts.externs.get(name).map_or(private_dep.unwrap_or(false), |e| e.is_private_dep)
399401
&& private_dep.unwrap_or(true)
@@ -402,7 +404,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
402404
fn register_crate(
403405
&mut self,
404406
host_lib: Option<Library>,
405-
root: Option<&CratePaths>,
407+
dep_root: Option<&CratePaths>,
406408
lib: Library,
407409
dep_kind: CrateDepKind,
408410
name: Symbol,
@@ -430,14 +432,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
430432
// Maintain a reference to the top most crate.
431433
// Stash paths for top-most crate locally if necessary.
432434
let crate_paths;
433-
let root = if let Some(root) = root {
434-
root
435+
let dep_root = if let Some(dep_root) = dep_root {
436+
dep_root
435437
} else {
436438
crate_paths = CratePaths::new(crate_root.name(), source.clone());
437439
&crate_paths
438440
};
439441

440-
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?;
442+
let cnum_map = self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind)?;
441443

442444
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
443445
let temp_root;
@@ -559,15 +561,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
559561
&'b mut self,
560562
name: Symbol,
561563
mut dep_kind: CrateDepKind,
562-
dep: Option<(&'b CratePaths, &'b CrateDep)>,
564+
dep_of: Option<(&'b CratePaths, &'b CrateDep)>,
563565
) -> Result<CrateNum, CrateError> {
564566
info!("resolving crate `{}`", name);
565567
if !name.as_str().is_ascii() {
566568
return Err(CrateError::NonAsciiName(name));
567569
}
568-
let (root, hash, host_hash, extra_filename, path_kind, private_dep) = match dep {
569-
Some((root, dep)) => (
570-
Some(root),
570+
let (dep_root, hash, host_hash, extra_filename, path_kind, private_dep) = match dep_of {
571+
Some((dep_root, dep)) => (
572+
Some(dep_root),
571573
Some(dep.hash),
572574
dep.host_hash,
573575
Some(&dep.extra_filename[..]),
@@ -599,7 +601,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
599601
dep_kind = CrateDepKind::MacrosOnly;
600602
match self.load_proc_macro(&mut locator, path_kind, host_hash)? {
601603
Some(res) => res,
602-
None => return Err(locator.into_error(root.cloned())),
604+
None => return Err(locator.into_error(dep_root.cloned())),
603605
}
604606
}
605607
}
@@ -623,7 +625,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
623625
}
624626
(LoadResult::Loaded(library), host_library) => {
625627
info!("register newly loaded library for `{}`", name);
626-
self.register_crate(host_library, root, library, dep_kind, name, private_dep)
628+
self.register_crate(host_library, dep_root, library, dep_kind, name, private_dep)
627629
}
628630
_ => panic!(),
629631
}
@@ -663,16 +665,20 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
663665
}))
664666
}
665667

666-
// Go through the crate metadata and load any crates that it references
668+
/// Go through the crate metadata and load any crates that it references.
667669
fn resolve_crate_deps(
668670
&mut self,
669-
root: &CratePaths,
671+
dep_root: &CratePaths,
670672
crate_root: &CrateRoot,
671673
metadata: &MetadataBlob,
672674
krate: CrateNum,
673675
dep_kind: CrateDepKind,
674676
) -> Result<CrateNumMap, CrateError> {
675-
debug!("resolving deps of external crate");
677+
debug!(
678+
"resolving deps of external crate `{}` with dep root `{}`",
679+
crate_root.name(),
680+
dep_root.name
681+
);
676682
if crate_root.is_proc_macro_crate() {
677683
return Ok(CrateNumMap::new());
678684
}
@@ -685,14 +691,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
685691
crate_num_map.push(krate);
686692
for dep in deps {
687693
info!(
688-
"resolving dep crate {} hash: `{}` extra filename: `{}`",
689-
dep.name, dep.hash, dep.extra_filename
694+
"resolving dep `{}`->`{}` hash: `{}` extra filename: `{}`",
695+
crate_root.name(),
696+
dep.name,
697+
dep.hash,
698+
dep.extra_filename
690699
);
691700
let dep_kind = match dep_kind {
692701
CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly,
693702
_ => dep.kind,
694703
};
695-
let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?;
704+
let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((dep_root, &dep)))?;
696705
crate_num_map.push(cnum);
697706
}
698707

compiler/rustc_metadata/src/locator.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ pub(crate) struct CrateLocator<'a> {
262262

263263
#[derive(Clone)]
264264
pub(crate) struct CratePaths {
265-
name: Symbol,
265+
pub(crate) name: Symbol,
266266
source: CrateSource,
267267
}
268268

@@ -765,10 +765,10 @@ impl<'a> CrateLocator<'a> {
765765
self.extract_lib(rlibs, rmetas, dylibs).map(|opt| opt.map(|(_, lib)| lib))
766766
}
767767

768-
pub(crate) fn into_error(self, root: Option<CratePaths>) -> CrateError {
768+
pub(crate) fn into_error(self, dep_root: Option<CratePaths>) -> CrateError {
769769
CrateError::LocatorCombined(Box::new(CombinedLocatorError {
770770
crate_name: self.crate_name,
771-
root,
771+
dep_root,
772772
triple: self.tuple,
773773
dll_prefix: self.target.dll_prefix.to_string(),
774774
dll_suffix: self.target.dll_suffix.to_string(),
@@ -914,7 +914,7 @@ struct CrateRejections {
914914
/// otherwise they are ignored.
915915
pub(crate) struct CombinedLocatorError {
916916
crate_name: Symbol,
917-
root: Option<CratePaths>,
917+
dep_root: Option<CratePaths>,
918918
triple: TargetTuple,
919919
dll_prefix: String,
920920
dll_suffix: String,
@@ -987,7 +987,7 @@ impl CrateError {
987987
}
988988
CrateError::LocatorCombined(locator) => {
989989
let crate_name = locator.crate_name;
990-
let add_info = match &locator.root {
990+
let add_info = match &locator.dep_root {
991991
None => String::new(),
992992
Some(r) => format!(" which `{}` depends on", r.name),
993993
};
@@ -1012,7 +1012,7 @@ impl CrateError {
10121012
path.display()
10131013
));
10141014
}
1015-
if let Some(r) = locator.root {
1015+
if let Some(r) = locator.dep_root {
10161016
for path in r.source.paths() {
10171017
found_crates.push_str(&format!(
10181018
"\ncrate `{}`: {}",

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_middle::util::Providers;
1818
use rustc_session::cstore::{CrateStore, ExternCrate};
1919
use rustc_session::{Session, StableCrateId};
2020
use rustc_span::hygiene::ExpnId;
21-
use rustc_span::{Span, Symbol, kw};
21+
use rustc_span::{Span, Symbol, kw, sym};
2222

2323
use super::{Decodable, DecodeContext, DecodeIterator};
2424
use crate::creader::{CStore, LoadedMacro};
@@ -561,6 +561,23 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
561561
tcx.untracked().cstore.freeze();
562562
tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum))
563563
},
564+
visible_crates: |tcx, ()| {
565+
// The list of loaded crates is now frozen in query cache,
566+
// so make sure cstore is not mutably accessed from here on.
567+
tcx.untracked().cstore.freeze();
568+
569+
// if `#![feature(rustc_private)]` is enabled in the current crate, include private
570+
// dependencies (e.g. of `std`.)
571+
if tcx.features().enabled(sym::rustc_private) {
572+
tcx.crates(())
573+
} else {
574+
tcx.arena.alloc_from_iter(
575+
CStore::from_tcx(tcx)
576+
.iter_crate_data()
577+
.filter_map(|(cnum, meta)| (!meta.private_dep).then_some(cnum)),
578+
)
579+
}
580+
},
564581
used_crates: |tcx, ()| {
565582
// The list of loaded crates is now frozen in query cache,
566583
// so make sure cstore is not mutably accessed from here on.

compiler/rustc_middle/src/query/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -2128,10 +2128,21 @@ rustc_queries! {
21282128
eval_always
21292129
desc { "calculating the stability index for the local crate" }
21302130
}
2131+
/// All available crates in the graph. Use `.visible_crates(())` instead if results should only
2132+
/// include user-visible crates (such as for diagnostics).
21312133
query crates(_: ()) -> &'tcx [CrateNum] {
21322134
eval_always
21332135
desc { "fetching all foreign CrateNum instances" }
21342136
}
2137+
/// Crates that are meant to be accessible by the user. Use `.crates(())` if the entire crate
2138+
/// graph is required.
2139+
///
2140+
/// This excludes e.g. private dependencies of the standard library, unless `rustc_private` is
2141+
/// enabled.
2142+
query visible_crates(_: ()) -> &'tcx [CrateNum] {
2143+
eval_always
2144+
desc { "fetching all user-reachable CrateNum instances" }
2145+
}
21352146
// Crates that are loaded non-speculatively (not for diagnostics or doc links).
21362147
// FIXME: This is currently only used for collecting lang items, but should be used instead of
21372148
// `crates` in most other cases too.

compiler/rustc_middle/src/ty/context.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2078,9 +2078,10 @@ impl<'tcx> TyCtxt<'tcx> {
20782078
self.limits(()).move_size_limit
20792079
}
20802080

2081+
/// All traits that are visible within the crate graph (i.e. excluding private dependencies).
20812082
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
20822083
iter::once(LOCAL_CRATE)
2083-
.chain(self.crates(()).iter().copied())
2084+
.chain(self.visible_crates(()).iter().copied())
20842085
.flat_map(move |cnum| self.traits(cnum).iter().copied())
20852086
}
20862087

compiler/rustc_passes/src/diagnostic_items.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems {
8080
let mut items = DiagnosticItems::default();
8181

8282
// Collect diagnostic items in other crates.
83-
for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
83+
for &cnum in tcx.visible_crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) {
8484
for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id {
8585
collect_item(tcx, &mut items, name, def_id);
8686
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0405]: cannot find trait `Equivalent` in this scope
2+
--> $DIR/sysroot-private.rs:25:18
3+
|
4+
LL | trait Trait2<K>: Equivalent<K> {}
5+
| ^^^^^^^^^^ not found in this scope
6+
7+
error[E0412]: cannot find type `K` in this scope
8+
--> $DIR/sysroot-private.rs:30:35
9+
|
10+
LL | fn trait_member<T>(val: &T, key: &K) -> bool {
11+
| - ^
12+
| |
13+
| similarly named type parameter `T` defined here
14+
|
15+
help: a type parameter with a similar name exists
16+
|
17+
LL | fn trait_member<T>(val: &T, key: &T) -> bool {
18+
| ~
19+
help: you might be missing a type parameter
20+
|
21+
LL | fn trait_member<T, K>(val: &T, key: &K) -> bool {
22+
| +++
23+
24+
error[E0220]: associated type `Buf` not found for `Trait`
25+
--> $DIR/sysroot-private.rs:20:31
26+
|
27+
LL | type AssociatedTy = dyn Trait<Buf = i32, Bar = i32>;
28+
| ^^^ help: `Trait` has the following associated type: `Bar`
29+
30+
error[E0425]: cannot find function `memchr2` in this scope
31+
--> $DIR/sysroot-private.rs:38:5
32+
|
33+
LL | memchr2(b'a', b'b', buf)
34+
| ^^^^^^^ not found in this scope
35+
36+
error: aborting due to 4 previous errors
37+
38+
Some errors have detailed explanations: E0220, E0405, E0412, E0425.
39+
For more information about an error, try `rustc --explain E0220`.

tests/ui/std/sysroot-private.rs

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//! Test that private dependencies of `std` that live in the sysroot do not reach through to
2+
//! diagnostics.
3+
//!
4+
//! This test would be more robust if we could patch the sysroot with an "evil" crate that
5+
//! provided known types that we control; however, this would effectively require rebuilding
6+
//! `std` (or patching crate metadata). So, this test relies on what is currently public API
7+
//! of `std`'s dependencies, but may not be robust against dependency upgrades/changes.
8+
9+
//@ revisions: default rustc_private_enabled
10+
11+
// Enabling `rustc_private` should `std`'s dependencies accessible, so they should show up
12+
// in diagnostics. NB: not all diagnostics are affected by this.
13+
#![cfg_attr(rustc_private_enabled, feature(rustc_private))]
14+
#![crate_type = "lib"]
15+
16+
trait Trait { type Bar; }
17+
18+
// Attempt to get a suggestion for `addr2line::LookupContinuation`, which has member `Buf`
19+
// Note that the suggestion only happens when `rustc_private` is enabled.
20+
type AssociatedTy = dyn Trait<Buf = i32, Bar = i32>;
21+
//~^ ERROR associated type `Buf` not found
22+
//[rustc_private_enabled]~| NOTE there is an associated type `Buf` in the trait `addr2line::lookup::LookupContinuation`
23+
24+
// Attempt to get a suggestion for `hashbrown::Equivalent`
25+
trait Trait2<K>: Equivalent<K> {}
26+
//~^ ERROR cannot find trait
27+
//~| NOTE not found
28+
29+
// Attempt to get a suggestion for `hashbrown::Equivalent::equivalent`
30+
fn trait_member<T>(val: &T, key: &K) -> bool {
31+
//~^ ERROR cannot find type `K`
32+
//~| NOTE similarly named
33+
val.equivalent(key)
34+
}
35+
36+
// Attempt to get a suggestion for `memchr::memchr2`
37+
fn free_function(buf: &[u8]) -> Option<usize> {
38+
memchr2(b'a', b'b', buf)
39+
//~^ ERROR cannot find function
40+
//~| NOTE not found
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0405]: cannot find trait `Equivalent` in this scope
2+
--> $DIR/sysroot-private.rs:25:18
3+
|
4+
LL | trait Trait2<K>: Equivalent<K> {}
5+
| ^^^^^^^^^^ not found in this scope
6+
7+
error[E0412]: cannot find type `K` in this scope
8+
--> $DIR/sysroot-private.rs:30:35
9+
|
10+
LL | fn trait_member<T>(val: &T, key: &K) -> bool {
11+
| - ^
12+
| |
13+
| similarly named type parameter `T` defined here
14+
|
15+
help: a type parameter with a similar name exists
16+
|
17+
LL | fn trait_member<T>(val: &T, key: &T) -> bool {
18+
| ~
19+
help: you might be missing a type parameter
20+
|
21+
LL | fn trait_member<T, K>(val: &T, key: &K) -> bool {
22+
| +++
23+
24+
error[E0220]: associated type `Buf` not found for `Trait`
25+
--> $DIR/sysroot-private.rs:20:31
26+
|
27+
LL | type AssociatedTy = dyn Trait<Buf = i32, Bar = i32>;
28+
| ^^^ there is an associated type `Buf` in the trait `addr2line::lookup::LookupContinuation`
29+
30+
error[E0425]: cannot find function `memchr2` in this scope
31+
--> $DIR/sysroot-private.rs:38:5
32+
|
33+
LL | memchr2(b'a', b'b', buf)
34+
| ^^^^^^^ not found in this scope
35+
36+
error: aborting due to 4 previous errors
37+
38+
Some errors have detailed explanations: E0220, E0405, E0412, E0425.
39+
For more information about an error, try `rustc --explain E0220`.

0 commit comments

Comments
 (0)