5252//! than finding a number of solutions (there are normally quite a few).
5353
5454use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
55- use rustc_hir:: def_id:: CrateNum ;
55+ use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
56+ use rustc_index:: IndexVec ;
5657use rustc_middle:: bug;
5758use rustc_middle:: middle:: dependency_format:: { Dependencies , DependencyList , Linkage } ;
5859use rustc_middle:: ty:: TyCtxt ;
@@ -84,7 +85,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
8485 let sess = & tcx. sess ;
8586
8687 if !sess. opts . output_types . should_codegen ( ) {
87- return Vec :: new ( ) ;
88+ return IndexVec :: new ( ) ;
8889 }
8990
9091 let preferred_linkage = match ty {
@@ -131,7 +132,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
131132
132133 match preferred_linkage {
133134 // If the crate is not linked, there are no link-time dependencies.
134- Linkage :: NotLinked => return Vec :: new ( ) ,
135+ Linkage :: NotLinked => return IndexVec :: new ( ) ,
135136 Linkage :: Static => {
136137 // Attempt static linkage first. For dylibs and executables, we may be
137138 // able to retry below with dynamic linkage.
@@ -156,7 +157,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
156157 }
157158 sess. dcx ( ) . emit_err ( RlibRequired { crate_name : tcx. crate_name ( cnum) } ) ;
158159 }
159- return Vec :: new ( ) ;
160+ return IndexVec :: new ( ) ;
160161 }
161162 }
162163 Linkage :: Dynamic | Linkage :: IncludedFromDylib => { }
@@ -210,19 +211,32 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
210211
211212 // Collect what we've got so far in the return vector.
212213 let last_crate = tcx. crates ( ( ) ) . len ( ) ;
213- let mut ret = ( 1 ..last_crate + 1 )
214- . map ( |cnum| match formats. get ( & CrateNum :: new ( cnum) ) {
215- Some ( & RequireDynamic ) => Linkage :: Dynamic ,
216- Some ( & RequireStatic ) => Linkage :: IncludedFromDylib ,
217- None => Linkage :: NotLinked ,
218- } )
219- . collect :: < Vec < _ > > ( ) ;
214+ let mut ret = IndexVec :: new ( ) ;
215+
216+ // We need to fill in something for LOCAL_CRATE as IndexVec is a dense map.
217+ // Linkage::Static semantically the most correct thing to use as the local
218+ // crate is always statically linked into the linker output, even when
219+ // linking a dylib. Using Linkage::Static also allow avoiding special cases
220+ // for LOCAL_CRATE in some places.
221+ assert_eq ! ( ret. push( Linkage :: Static ) , LOCAL_CRATE ) ;
222+
223+ for cnum in 1 ..last_crate + 1 {
224+ let cnum = CrateNum :: new ( cnum) ;
225+ assert_eq ! (
226+ ret. push( match formats. get( & cnum) {
227+ Some ( & RequireDynamic ) => Linkage :: Dynamic ,
228+ Some ( & RequireStatic ) => Linkage :: IncludedFromDylib ,
229+ None => Linkage :: NotLinked ,
230+ } ) ,
231+ cnum
232+ ) ;
233+ }
220234
221235 // Run through the dependency list again, and add any missing libraries as
222236 // static libraries.
223237 //
224238 // If the crate hasn't been included yet and it's not actually required
225- // (e.g., it's an allocator ) then we skip it here as well.
239+ // (e.g., it's a panic runtime ) then we skip it here as well.
226240 for & cnum in tcx. crates ( ( ) ) . iter ( ) {
227241 let src = tcx. used_crate_source ( cnum) ;
228242 if src. dylib . is_none ( )
@@ -232,16 +246,15 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
232246 assert ! ( src. rlib. is_some( ) || src. rmeta. is_some( ) ) ;
233247 info ! ( "adding staticlib: {}" , tcx. crate_name( cnum) ) ;
234248 add_library ( tcx, cnum, RequireStatic , & mut formats, & mut unavailable_as_static) ;
235- ret[ cnum. as_usize ( ) - 1 ] = Linkage :: Static ;
249+ ret[ cnum] = Linkage :: Static ;
236250 }
237251 }
238252
239253 // We've gotten this far because we're emitting some form of a final
240254 // artifact which means that we may need to inject dependencies of some
241255 // form.
242256 //
243- // Things like allocators and panic runtimes may not have been activated
244- // quite yet, so do so here.
257+ // Things like panic runtimes may not have been activated quite yet, so do so here.
245258 activate_injected_dep ( CStore :: from_tcx ( tcx) . injected_panic_runtime ( ) , & mut ret, & |cnum| {
246259 tcx. is_panic_runtime ( cnum)
247260 } ) ;
@@ -252,8 +265,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
252265 //
253266 // For situations like this, we perform one last pass over the dependencies,
254267 // making sure that everything is available in the requested format.
255- for ( cnum, kind) in ret. iter ( ) . enumerate ( ) {
256- let cnum = CrateNum :: new ( cnum + 1 ) ;
268+ for ( cnum, kind) in ret. iter_enumerated ( ) {
269+ if cnum == LOCAL_CRATE {
270+ continue ;
271+ }
257272 let src = tcx. used_crate_source ( cnum) ;
258273 match * kind {
259274 Linkage :: NotLinked | Linkage :: IncludedFromDylib => { }
@@ -334,18 +349,21 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec<CrateNum>) -> Option<De
334349
335350 // All crates are available in an rlib format, so we're just going to link
336351 // everything in explicitly so long as it's actually required.
337- let mut ret = tcx
338- . crates ( ( ) )
339- . iter ( )
340- . map ( |& cnum| match tcx. dep_kind ( cnum) {
341- CrateDepKind :: Explicit => Linkage :: Static ,
342- CrateDepKind :: MacrosOnly | CrateDepKind :: Implicit => Linkage :: NotLinked ,
343- } )
344- . collect :: < Vec < _ > > ( ) ;
352+ let mut ret = IndexVec :: new ( ) ;
353+ assert_eq ! ( ret. push( Linkage :: Static ) , LOCAL_CRATE ) ;
354+ for & cnum in tcx. crates ( ( ) ) {
355+ assert_eq ! (
356+ ret. push( match tcx. dep_kind( cnum) {
357+ CrateDepKind :: Explicit => Linkage :: Static ,
358+ CrateDepKind :: MacrosOnly | CrateDepKind :: Implicit => Linkage :: NotLinked ,
359+ } ) ,
360+ cnum
361+ ) ;
362+ }
345363
346- // Our allocator/ panic runtime may not have been linked above if it wasn't
347- // explicitly linked, which is the case for any injected dependency. Handle
348- // that here and activate them .
364+ // Our panic runtime may not have been linked above if it wasn't explicitly
365+ // linked, which is the case for any injected dependency. Handle that here
366+ // and activate it .
349367 activate_injected_dep ( CStore :: from_tcx ( tcx) . injected_panic_runtime ( ) , & mut ret, & |cnum| {
350368 tcx. is_panic_runtime ( cnum)
351369 } ) ;
@@ -367,8 +385,7 @@ fn activate_injected_dep(
367385 list : & mut DependencyList ,
368386 replaces_injected : & dyn Fn ( CrateNum ) -> bool ,
369387) {
370- for ( i, slot) in list. iter ( ) . enumerate ( ) {
371- let cnum = CrateNum :: new ( i + 1 ) ;
388+ for ( cnum, slot) in list. iter_enumerated ( ) {
372389 if !replaces_injected ( cnum) {
373390 continue ;
374391 }
@@ -377,25 +394,23 @@ fn activate_injected_dep(
377394 }
378395 }
379396 if let Some ( injected) = injected {
380- let idx = injected. as_usize ( ) - 1 ;
381- assert_eq ! ( list[ idx] , Linkage :: NotLinked ) ;
382- list[ idx] = Linkage :: Static ;
397+ assert_eq ! ( list[ injected] , Linkage :: NotLinked ) ;
398+ list[ injected] = Linkage :: Static ;
383399 }
384400}
385401
386- // After the linkage for a crate has been determined we need to verify that
387- // there's only going to be one allocator in the output.
388- fn verify_ok ( tcx : TyCtxt < ' _ > , list : & [ Linkage ] ) {
402+ /// After the linkage for a crate has been determined we need to verify that
403+ /// there's only going to be one panic runtime in the output.
404+ fn verify_ok ( tcx : TyCtxt < ' _ > , list : & DependencyList ) {
389405 let sess = & tcx. sess ;
390406 if list. is_empty ( ) {
391407 return ;
392408 }
393409 let mut panic_runtime = None ;
394- for ( i , linkage) in list. iter ( ) . enumerate ( ) {
410+ for ( cnum , linkage) in list. iter_enumerated ( ) {
395411 if let Linkage :: NotLinked = * linkage {
396412 continue ;
397413 }
398- let cnum = CrateNum :: new ( i + 1 ) ;
399414
400415 if tcx. is_panic_runtime ( cnum) {
401416 if let Some ( ( prev, _) ) = panic_runtime {
@@ -431,11 +446,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
431446 // strategy. If the dep isn't linked, we ignore it, and if our strategy
432447 // is abort then it's compatible with everything. Otherwise all crates'
433448 // panic strategy must match our own.
434- for ( i , linkage) in list. iter ( ) . enumerate ( ) {
449+ for ( cnum , linkage) in list. iter_enumerated ( ) {
435450 if let Linkage :: NotLinked = * linkage {
436451 continue ;
437452 }
438- let cnum = CrateNum :: new ( i + 1 ) ;
439453 if cnum == runtime_cnum || tcx. is_compiler_builtins ( cnum) {
440454 continue ;
441455 }
@@ -450,13 +464,16 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
450464 } ) ;
451465 }
452466
453- let found_drop_strategy = tcx. panic_in_drop_strategy ( cnum) ;
454- if tcx. sess . opts . unstable_opts . panic_in_drop != found_drop_strategy {
455- sess. dcx ( ) . emit_err ( IncompatiblePanicInDropStrategy {
456- crate_name : tcx. crate_name ( cnum) ,
457- found_strategy : found_drop_strategy,
458- desired_strategy : tcx. sess . opts . unstable_opts . panic_in_drop ,
459- } ) ;
467+ // panic_in_drop_strategy isn't allowed for LOCAL_CRATE
468+ if cnum != LOCAL_CRATE {
469+ let found_drop_strategy = tcx. panic_in_drop_strategy ( cnum) ;
470+ if tcx. sess . opts . unstable_opts . panic_in_drop != found_drop_strategy {
471+ sess. dcx ( ) . emit_err ( IncompatiblePanicInDropStrategy {
472+ crate_name : tcx. crate_name ( cnum) ,
473+ found_strategy : found_drop_strategy,
474+ desired_strategy : tcx. sess . opts . unstable_opts . panic_in_drop ,
475+ } ) ;
476+ }
460477 }
461478 }
462479 }
0 commit comments