Skip to content

Commit a7c4b62

Browse files
committed
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: #135232 [1]
1 parent 122a0d0 commit a7c4b62

File tree

3 files changed

+56
-21
lines changed

3 files changed

+56
-21
lines changed

compiler/rustc_metadata/src/creader.rs

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc_session::lint::{self, BuiltinLintDiag};
2929
use rustc_session::output::validate_crate_name;
3030
use rustc_session::search_paths::PathKind;
3131
use rustc_span::edition::Edition;
32-
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
32+
use rustc_span::{DUMMY_SP, Ident, STDLIB_STABLE_CRATES, Span, Symbol, sym};
3333
use rustc_target::spec::{PanicStrategy, Target, TargetTuple};
3434
use tracing::{debug, info, trace};
3535

@@ -390,15 +390,52 @@ 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`.
393+
/// Determine whether a dependency should be considered private.
394+
///
395+
/// Dependencies are private if they get extern option specified, e.g. `--extern priv:mycrate`.
396+
/// This is stored in metadata, so `private_dep` can be correctly set during load. A `Some`
397+
/// value for `private_dep` indicates that the crate is known to be private or public (note
398+
/// that any `None` or `Some(false)` use of the same crate will make it public).
395399
///
396400
/// Sometimes the directly dependent crate is not specified by `--extern`, in this case,
397401
/// `private-dep` is none during loading. This is equivalent to the scenario where the
398402
/// command parameter is set to `public-dependency`
399-
fn is_private_dep(&self, name: &str, private_dep: Option<bool>) -> bool {
400-
self.sess.opts.externs.get(name).map_or(private_dep.unwrap_or(false), |e| e.is_private_dep)
401-
&& private_dep.unwrap_or(true)
403+
fn is_private_dep(
404+
&self,
405+
name: Symbol,
406+
private_dep: Option<bool>,
407+
dep_root: Option<&CratePaths>,
408+
) -> bool {
409+
// Standard library crates are never private.
410+
if STDLIB_STABLE_CRATES.contains(&name) {
411+
tracing::info!("returning false for {name} is private");
412+
return false;
413+
}
414+
415+
let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep);
416+
417+
match (extern_private, private_dep) {
418+
// If the crate is marked private via extern and the crate would also otherwise
419+
// be private, then keep this crate private.
420+
(Some(true), Some(true) | None) => true,
421+
422+
// Any descendants of `std` should be private. These crates are usually not marked
423+
// private in metadata, so we ignore that field.
424+
(None, _) if dep_root.map_or(false, |d| STDLIB_STABLE_CRATES.contains(&d.name)) => true,
425+
426+
// If no visibility override is given via extern, defer to what the parent requests.
427+
(None, Some(v)) => v,
428+
429+
// Crate was requested via `--extern` and should be public.
430+
(Some(false), _) => false,
431+
432+
// Not a private dependency, keep it public.
433+
(_, Some(false)) => false,
434+
435+
// Not passed via extern and no metadata available. Not sure how we got here, but
436+
// default to public.
437+
(None, None) => false,
438+
}
402439
}
403440

404441
fn register_crate(
@@ -416,7 +453,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
416453
let Library { source, metadata } = lib;
417454
let crate_root = metadata.get_root();
418455
let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
419-
let private_dep = self.is_private_dep(name.as_str(), private_dep);
456+
let private_dep = self.is_private_dep(name, private_dep, dep_root);
420457

421458
// Claim this crate number and cache it
422459
let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?;
@@ -567,17 +604,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
567604
if !name.as_str().is_ascii() {
568605
return Err(CrateError::NonAsciiName(name));
569606
}
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),
573-
Some(dep.hash),
574-
dep.host_hash,
575-
Some(&dep.extra_filename[..]),
576-
PathKind::Dependency,
577-
Some(dep.is_private),
578-
),
579-
None => (None, None, None, None, PathKind::Crate, None),
580-
};
607+
608+
let dep_root = dep_of.map(|d| d.0);
609+
let dep = dep_of.map(|d| d.1);
610+
let hash = dep.map(|d| d.hash);
611+
let host_hash = dep.map(|d| d.host_hash).flatten();
612+
let extra_filename = dep.map(|d| &d.extra_filename[..]);
613+
let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate };
614+
let private_dep = dep.map(|d| d.is_private);
615+
581616
let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
582617
(LoadResult::Previous(cnum), None)
583618
} else {
@@ -614,7 +649,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
614649
// not specified by `--extern` on command line parameters, it may be
615650
// `private-dependency` when `register_crate` is called for the first time. Then it must be updated to
616651
// `public-dependency` here.
617-
let private_dep = self.is_private_dep(name.as_str(), private_dep);
652+
let private_dep = self.is_private_dep(name, private_dep, dep_root);
618653
let data = self.cstore.get_crate_data_mut(cnum);
619654
if data.is_proc_macro_crate() {
620655
dep_kind = CrateDepKind::MacrosOnly;

tests/ui/privacy/sysroot-private.default.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ error[E0220]: associated type `ExpressionStack` not found for `Trait`
2525
--> $DIR/sysroot-private.rs:20:31
2626
|
2727
LL | type AssociatedTy = dyn Trait<ExpressionStack = i32, Bar = i32>;
28-
| ^^^^^^^^^^^^^^^ there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage`
28+
| ^^^^^^^^^^^^^^^ help: `Trait` has the following associated type: `Bar`
2929

3030
error[E0425]: cannot find function `memchr2` in this scope
3131
--> $DIR/sysroot-private.rs:38:5

tests/ui/privacy/sysroot-private.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ trait Trait { type Bar; }
1919
// present in diagnostics (it is a dependency of the compiler).
2020
type AssociatedTy = dyn Trait<ExpressionStack = i32, Bar = i32>;
2121
//~^ ERROR associated type `ExpressionStack` not found
22-
//~| NOTE there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage`
22+
//[rustc_private_enabled]~| NOTE there is an associated type `ExpressionStack` in the trait `gimli::read::op::EvaluationStorage`
2323

2424
// Attempt to get a suggestion for `hashbrown::Equivalent`
2525
trait Trait2<K>: Equivalent<K> {}

0 commit comments

Comments
 (0)