@@ -29,7 +29,7 @@ use rustc_session::lint::{self, BuiltinLintDiag};
29
29
use rustc_session:: output:: validate_crate_name;
30
30
use rustc_session:: search_paths:: PathKind ;
31
31
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} ;
33
33
use rustc_target:: spec:: { PanicStrategy , Target , TargetTuple } ;
34
34
use tracing:: { debug, info, trace} ;
35
35
@@ -390,15 +390,45 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
390
390
None
391
391
}
392
392
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).
395
399
///
396
400
/// Sometimes the directly dependent crate is not specified by `--extern`, in this case,
397
401
/// `private-dep` is none during loading. This is equivalent to the scenario where the
398
402
/// 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
+ // Any descendants of `std` should be private. These crates are usually not marked
418
+ // private in metadata, so we ignore that field.
419
+ if extern_private. is_none ( )
420
+ && dep_root. map_or ( false , |d| STDLIB_STABLE_CRATES . contains ( & d. name ) )
421
+ {
422
+ return true ;
423
+ }
424
+
425
+ match ( extern_private, private_dep) {
426
+ // Explicit non-private via `--extern`, explicit non-private from metadata, or
427
+ // unspecified with default to public.
428
+ ( Some ( false ) , _) | ( _, Some ( false ) ) | ( None , None ) => false ,
429
+ // Marked private via `--extern priv:mycrate` or in metadata.
430
+ ( Some ( true ) | None , Some ( true ) | None ) => true ,
431
+ }
402
432
}
403
433
404
434
fn register_crate (
@@ -416,7 +446,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
416
446
let Library { source, metadata } = lib;
417
447
let crate_root = metadata. get_root ( ) ;
418
448
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) ;
449
+ let private_dep = self . is_private_dep ( name, private_dep, dep_root ) ;
420
450
421
451
// Claim this crate number and cache it
422
452
let feed = self . cstore . intern_stable_crate_id ( & crate_root, self . tcx ) ?;
@@ -567,17 +597,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
567
597
if !name. as_str ( ) . is_ascii ( ) {
568
598
return Err ( CrateError :: NonAsciiName ( name) ) ;
569
599
}
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
- } ;
600
+
601
+ let dep_root = dep_of. map ( |d| d. 0 ) ;
602
+ let dep = dep_of. map ( |d| d. 1 ) ;
603
+ let hash = dep. map ( |d| d. hash ) ;
604
+ let host_hash = dep. map ( |d| d. host_hash ) . flatten ( ) ;
605
+ let extra_filename = dep. map ( |d| & d. extra_filename [ ..] ) ;
606
+ let path_kind = if dep. is_some ( ) { PathKind :: Dependency } else { PathKind :: Crate } ;
607
+ let private_dep = dep. map ( |d| d. is_private ) ;
608
+
581
609
let result = if let Some ( cnum) = self . existing_match ( name, hash, path_kind) {
582
610
( LoadResult :: Previous ( cnum) , None )
583
611
} else {
@@ -614,7 +642,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
614
642
// not specified by `--extern` on command line parameters, it may be
615
643
// `private-dependency` when `register_crate` is called for the first time. Then it must be updated to
616
644
// `public-dependency` here.
617
- let private_dep = self . is_private_dep ( name. as_str ( ) , private_dep) ;
645
+ let private_dep = self . is_private_dep ( name, private_dep, dep_root ) ;
618
646
let data = self . cstore . get_crate_data_mut ( cnum) ;
619
647
if data. is_proc_macro_crate ( ) {
620
648
dep_kind = CrateDepKind :: MacrosOnly ;
0 commit comments