@@ -142,6 +142,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
142142 writeln ! ( fmt, " cnum: {cnum}" ) ?;
143143 writeln ! ( fmt, " hash: {}" , data. hash( ) ) ?;
144144 writeln ! ( fmt, " reqd: {:?}" , data. dep_kind( ) ) ?;
145+ writeln ! ( fmt, " priv: {:?}" , data. is_private_dep( ) ) ?;
145146 let CrateSource { dylib, rlib, rmeta } = data. source ( ) ;
146147 if let Some ( dylib) = dylib {
147148 writeln ! ( fmt, " dylib: {}" , dylib. 0 . display( ) ) ?;
@@ -157,6 +158,43 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
157158 }
158159}
159160
161+ /// Reason that a crate is being sourced as a dependency.
162+ #[ derive( Clone , Copy ) ]
163+ enum CrateOrigin < ' a > {
164+ /// This crate was a dependency of another crate.
165+ Dependency {
166+ dep_root : & ' a CratePaths ,
167+ /// Dependency info about this crate.
168+ dep : & ' a CrateDep ,
169+ } ,
170+ /// Injected by `rustc`.
171+ Injected ,
172+ /// An extern that has been provided with the `force` option.
173+ ForcedExtern ,
174+ /// Part of the extern prelude.
175+ ExternPrelude ,
176+ /// Provided by `extern crate foo`.
177+ AstExtern ,
178+ }
179+
180+ impl < ' a > CrateOrigin < ' a > {
181+ /// Return the dependency root, if any.
182+ fn dep_root ( & self ) -> Option < & ' a CratePaths > {
183+ match self {
184+ CrateOrigin :: Dependency { dep_root, .. } => Some ( dep_root) ,
185+ _ => None ,
186+ }
187+ }
188+
189+ /// Return dependency information, if any.
190+ fn dep ( & self ) -> Option < & ' a CrateDep > {
191+ match self {
192+ CrateOrigin :: Dependency { dep, .. } => Some ( dep) ,
193+ _ => None ,
194+ }
195+ }
196+ }
197+
160198impl CStore {
161199 pub fn from_tcx ( tcx : TyCtxt < ' _ > ) -> FreezeReadGuard < ' _ , CStore > {
162200 FreezeReadGuard :: map ( tcx. untracked ( ) . cstore . read ( ) , |cstore| {
@@ -404,7 +442,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
404442 & self ,
405443 name : Symbol ,
406444 private_dep : Option < bool > ,
407- dep_root : Option < & CratePaths > ,
445+ origin : CrateOrigin < ' _ > ,
408446 ) -> bool {
409447 // Standard library crates are never private.
410448 if STDLIB_STABLE_CRATES . contains ( & name) {
@@ -414,10 +452,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
414452
415453 let extern_private = self . sess . opts . externs . get ( name. as_str ( ) ) . map ( |e| e. is_private_dep ) ;
416454
455+ if matches ! ( origin, CrateOrigin :: Injected ) {
456+ return true ;
457+ }
458+
417459 // Any descendants of `std` should be private. These crates are usually not marked
418460 // private in metadata, so we ignore that field.
419461 if extern_private. is_none ( )
420- && let Some ( dep) = dep_root
462+ && let Some ( dep) = origin . dep_root ( )
421463 && STDLIB_STABLE_CRATES . contains ( & dep. name )
422464 {
423465 return true ;
@@ -435,7 +477,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
435477 fn register_crate (
436478 & mut self ,
437479 host_lib : Option < Library > ,
438- dep_root : Option < & CratePaths > ,
480+ origin : CrateOrigin < ' _ > ,
439481 lib : Library ,
440482 dep_kind : CrateDepKind ,
441483 name : Symbol ,
@@ -447,7 +489,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
447489 let Library { source, metadata } = lib;
448490 let crate_root = metadata. get_root ( ) ;
449491 let host_hash = host_lib. as_ref ( ) . map ( |lib| lib. metadata . get_root ( ) . hash ( ) ) ;
450- let private_dep = self . is_private_dep ( name, private_dep, dep_root ) ;
492+ let private_dep = self . is_private_dep ( name, private_dep, origin ) ;
451493
452494 // Claim this crate number and cache it
453495 let feed = self . cstore . intern_stable_crate_id ( & crate_root, self . tcx ) ?;
@@ -463,7 +505,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
463505 // Maintain a reference to the top most crate.
464506 // Stash paths for top-most crate locally if necessary.
465507 let crate_paths;
466- let dep_root = if let Some ( dep_root) = dep_root {
508+ let dep_root = if let Some ( dep_root) = origin . dep_root ( ) {
467509 dep_root
468510 } else {
469511 crate_paths = CratePaths :: new ( crate_root. name ( ) , source. clone ( ) ) ;
@@ -571,17 +613,23 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
571613 name : Symbol ,
572614 span : Span ,
573615 dep_kind : CrateDepKind ,
616+ origin : CrateOrigin < ' _ > ,
574617 ) -> Option < CrateNum > {
575618 self . used_extern_options . insert ( name) ;
576- match self . maybe_resolve_crate ( name, dep_kind, None ) {
619+ match self . maybe_resolve_crate ( name, dep_kind, origin ) {
577620 Ok ( cnum) => {
578621 self . cstore . set_used_recursively ( cnum) ;
579622 Some ( cnum)
580623 }
581624 Err ( err) => {
582625 debug ! ( "failed to resolve crate {} {:?}" , name, dep_kind) ;
583- let missing_core =
584- self . maybe_resolve_crate ( sym:: core, CrateDepKind :: Explicit , None ) . is_err ( ) ;
626+ let missing_core = self
627+ . maybe_resolve_crate (
628+ sym:: core,
629+ CrateDepKind :: Explicit ,
630+ CrateOrigin :: ExternPrelude ,
631+ )
632+ . is_err ( ) ;
585633 err. report ( self . sess , span, missing_core) ;
586634 None
587635 }
@@ -592,15 +640,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
592640 & ' b mut self ,
593641 name : Symbol ,
594642 mut dep_kind : CrateDepKind ,
595- dep_of : Option < ( & ' b CratePaths , & ' b CrateDep ) > ,
643+ origin : CrateOrigin < ' b > ,
596644 ) -> Result < CrateNum , CrateError > {
597645 info ! ( "resolving crate `{}`" , name) ;
598646 if !name. as_str ( ) . is_ascii ( ) {
599647 return Err ( CrateError :: NonAsciiName ( name) ) ;
600648 }
601649
602- let dep_root = dep_of . map ( |d| d . 0 ) ;
603- let dep = dep_of . map ( |d| d . 1 ) ;
650+ let dep_root = origin . dep_root ( ) ;
651+ let dep = origin . dep ( ) ;
604652 let hash = dep. map ( |d| d. hash ) ;
605653 let host_hash = dep. map ( |d| d. host_hash ) . flatten ( ) ;
606654 let extra_filename = dep. map ( |d| & d. extra_filename [ ..] ) ;
@@ -638,12 +686,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
638686
639687 match result {
640688 ( LoadResult :: Previous ( cnum) , None ) => {
641- info ! ( "library for `{}` was loaded previously" , name) ;
689+ info ! ( "library for `{}` was loaded previously, cnum {cnum} " , name) ;
642690 // When `private_dep` is none, it indicates the directly dependent crate. If it is
643691 // not specified by `--extern` on command line parameters, it may be
644692 // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to
645693 // `public-dependency` here.
646- let private_dep = self . is_private_dep ( name, private_dep, dep_root ) ;
694+ let private_dep = self . is_private_dep ( name, private_dep, origin ) ;
647695 let data = self . cstore . get_crate_data_mut ( cnum) ;
648696 if data. is_proc_macro_crate ( ) {
649697 dep_kind = CrateDepKind :: MacrosOnly ;
@@ -654,7 +702,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
654702 }
655703 ( LoadResult :: Loaded ( library) , host_library) => {
656704 info ! ( "register newly loaded library for `{}`" , name) ;
657- self . register_crate ( host_library, dep_root , library, dep_kind, name, private_dep)
705+ self . register_crate ( host_library, origin , library, dep_kind, name, private_dep)
658706 }
659707 _ => panic ! ( ) ,
660708 }
@@ -730,7 +778,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
730778 CrateDepKind :: MacrosOnly => CrateDepKind :: MacrosOnly ,
731779 _ => dep. kind ,
732780 } ;
733- let cnum = self . maybe_resolve_crate ( dep. name , dep_kind, Some ( ( dep_root, & dep) ) ) ?;
781+ let cnum = self . maybe_resolve_crate ( dep. name , dep_kind, CrateOrigin :: Dependency {
782+ dep_root,
783+ dep : & dep,
784+ } ) ?;
734785 crate_num_map. push ( cnum) ;
735786 }
736787
@@ -824,7 +875,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
824875 } ;
825876 info ! ( "panic runtime not found -- loading {}" , name) ;
826877
827- let Some ( cnum) = self . resolve_crate ( name, DUMMY_SP , CrateDepKind :: Implicit ) else {
878+ let Some ( cnum) =
879+ self . resolve_crate ( name, DUMMY_SP , CrateDepKind :: Implicit , CrateOrigin :: Injected )
880+ else {
828881 return ;
829882 } ;
830883 let data = self . cstore . get_crate_data ( cnum) ;
@@ -853,7 +906,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
853906 info ! ( "loading profiler" ) ;
854907
855908 let name = Symbol :: intern ( & self . sess . opts . unstable_opts . profiler_runtime ) ;
856- let Some ( cnum) = self . resolve_crate ( name, DUMMY_SP , CrateDepKind :: Implicit ) else {
909+ let Some ( cnum) =
910+ self . resolve_crate ( name, DUMMY_SP , CrateDepKind :: Implicit , CrateOrigin :: Injected )
911+ else {
857912 return ;
858913 } ;
859914 let data = self . cstore . get_crate_data ( cnum) ;
@@ -966,12 +1021,54 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
9661021 if entry. force {
9671022 let name_interned = Symbol :: intern ( name) ;
9681023 if !self . used_extern_options . contains ( & name_interned) {
969- self . resolve_crate ( name_interned, DUMMY_SP , CrateDepKind :: Explicit ) ;
1024+ self . resolve_crate (
1025+ name_interned,
1026+ DUMMY_SP ,
1027+ CrateDepKind :: Explicit ,
1028+ CrateOrigin :: ForcedExtern ,
1029+ ) ;
9701030 }
9711031 }
9721032 }
9731033 }
9741034
1035+ /// Inject the `compiler_builtins` crate if it is not already in the graph.
1036+ fn inject_compiler_builtins ( & mut self , krate : & ast:: Crate ) {
1037+ // `compiler_builtins` does not get extern builtins, nor do `#![no_core]` crates
1038+ if attr:: contains_name ( & krate. attrs , sym:: compiler_builtins)
1039+ || attr:: contains_name ( & krate. attrs , sym:: no_core)
1040+ {
1041+ info ! ( "`compiler_builtins` unneeded" ) ;
1042+ return ;
1043+ }
1044+
1045+ // If a `#![compiler_builtins]` crate already exists, avoid injecting it twice. This is
1046+ // the common case since usually it appears as a dependency of `std` or `core`.
1047+ for ( cnum, cmeta) in self . cstore . iter_crate_data ( ) {
1048+ if cmeta. is_compiler_builtins ( ) {
1049+ info ! ( "`compiler_builtins` already exists (cnum = {cnum}); skipping injection" ) ;
1050+ return ;
1051+ }
1052+ }
1053+
1054+ // Allow builtins to remain unresolved, which will just mean linker errors if the
1055+ // relevant symbols aren't otherwise provided.
1056+ let Ok ( cnum) = self . maybe_resolve_crate (
1057+ sym:: compiler_builtins,
1058+ CrateDepKind :: Implicit ,
1059+ CrateOrigin :: Injected ,
1060+ ) else {
1061+ info ! ( "`compiler_builtins` not resolved" ) ;
1062+ return ;
1063+ } ;
1064+
1065+ // Sanity check that the loaded crate is `#![compiler_builtins]`
1066+ let cmeta = self . cstore . get_crate_data ( cnum) ;
1067+ if !cmeta. is_compiler_builtins ( ) {
1068+ self . dcx ( ) . emit_err ( errors:: CrateNotCompilerBuiltins { crate_name : cmeta. name ( ) } ) ;
1069+ }
1070+ }
1071+
9751072 fn inject_dependency_if (
9761073 & mut self ,
9771074 krate : CrateNum ,
@@ -1081,6 +1178,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
10811178 }
10821179
10831180 pub fn postprocess ( & mut self , krate : & ast:: Crate ) {
1181+ self . inject_compiler_builtins ( krate) ;
10841182 self . inject_forced_externs ( ) ;
10851183 self . inject_profiler_runtime ( ) ;
10861184 self . inject_allocator_crate ( krate) ;
@@ -1092,6 +1190,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
10921190 info ! ( "{:?}" , CrateDump ( self . cstore) ) ;
10931191 }
10941192
1193+ /// Process an `extern crate foo` AST node.
10951194 pub fn process_extern_crate (
10961195 & mut self ,
10971196 item : & ast:: Item ,
@@ -1117,7 +1216,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
11171216 CrateDepKind :: Explicit
11181217 } ;
11191218
1120- let cnum = self . resolve_crate ( name, item. span , dep_kind) ?;
1219+ let cnum = self . resolve_crate ( name, item. span , dep_kind, CrateOrigin :: AstExtern ) ?;
11211220
11221221 let path_len = definitions. def_path ( def_id) . data . len ( ) ;
11231222 self . cstore . update_extern_crate ( cnum, ExternCrate {
@@ -1133,7 +1232,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
11331232 }
11341233
11351234 pub fn process_path_extern ( & mut self , name : Symbol , span : Span ) -> Option < CrateNum > {
1136- let cnum = self . resolve_crate ( name, span, CrateDepKind :: Explicit ) ?;
1235+ let cnum =
1236+ self . resolve_crate ( name, span, CrateDepKind :: Explicit , CrateOrigin :: ExternPrelude ) ?;
11371237
11381238 self . cstore . update_extern_crate ( cnum, ExternCrate {
11391239 src : ExternCrateSource :: Path ,
@@ -1147,7 +1247,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
11471247 }
11481248
11491249 pub fn maybe_process_path_extern ( & mut self , name : Symbol ) -> Option < CrateNum > {
1150- self . maybe_resolve_crate ( name, CrateDepKind :: Explicit , None ) . ok ( )
1250+ self . maybe_resolve_crate ( name, CrateDepKind :: Explicit , CrateOrigin :: ExternPrelude ) . ok ( )
11511251 }
11521252}
11531253
0 commit comments