52
52
//! than finding a number of solutions (there are normally quite a few).
53
53
54
54
use 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 ;
56
57
use rustc_middle:: bug;
57
58
use rustc_middle:: middle:: dependency_format:: { Dependencies , DependencyList , Linkage } ;
58
59
use rustc_middle:: ty:: TyCtxt ;
@@ -84,7 +85,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
84
85
let sess = & tcx. sess ;
85
86
86
87
if !sess. opts . output_types . should_codegen ( ) {
87
- return Vec :: new ( ) ;
88
+ return IndexVec :: new ( ) ;
88
89
}
89
90
90
91
let preferred_linkage = match ty {
@@ -131,7 +132,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
131
132
132
133
match preferred_linkage {
133
134
// If the crate is not linked, there are no link-time dependencies.
134
- Linkage :: NotLinked => return Vec :: new ( ) ,
135
+ Linkage :: NotLinked => return IndexVec :: new ( ) ,
135
136
Linkage :: Static => {
136
137
// Attempt static linkage first. For dylibs and executables, we may be
137
138
// able to retry below with dynamic linkage.
@@ -156,7 +157,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
156
157
}
157
158
sess. dcx ( ) . emit_err ( RlibRequired { crate_name : tcx. crate_name ( cnum) } ) ;
158
159
}
159
- return Vec :: new ( ) ;
160
+ return IndexVec :: new ( ) ;
160
161
}
161
162
}
162
163
Linkage :: Dynamic | Linkage :: IncludedFromDylib => { }
@@ -210,19 +211,32 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
210
211
211
212
// Collect what we've got so far in the return vector.
212
213
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
+ }
220
234
221
235
// Run through the dependency list again, and add any missing libraries as
222
236
// static libraries.
223
237
//
224
238
// 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.
226
240
for & cnum in tcx. crates ( ( ) ) . iter ( ) {
227
241
let src = tcx. used_crate_source ( cnum) ;
228
242
if src. dylib . is_none ( )
@@ -232,16 +246,15 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
232
246
assert ! ( src. rlib. is_some( ) || src. rmeta. is_some( ) ) ;
233
247
info ! ( "adding staticlib: {}" , tcx. crate_name( cnum) ) ;
234
248
add_library ( tcx, cnum, RequireStatic , & mut formats, & mut unavailable_as_static) ;
235
- ret[ cnum. as_usize ( ) - 1 ] = Linkage :: Static ;
249
+ ret[ cnum] = Linkage :: Static ;
236
250
}
237
251
}
238
252
239
253
// We've gotten this far because we're emitting some form of a final
240
254
// artifact which means that we may need to inject dependencies of some
241
255
// form.
242
256
//
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.
245
258
activate_injected_dep ( CStore :: from_tcx ( tcx) . injected_panic_runtime ( ) , & mut ret, & |cnum| {
246
259
tcx. is_panic_runtime ( cnum)
247
260
} ) ;
@@ -252,8 +265,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
252
265
//
253
266
// For situations like this, we perform one last pass over the dependencies,
254
267
// 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
+ }
257
272
let src = tcx. used_crate_source ( cnum) ;
258
273
match * kind {
259
274
Linkage :: NotLinked | Linkage :: IncludedFromDylib => { }
@@ -334,18 +349,21 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec<CrateNum>) -> Option<De
334
349
335
350
// All crates are available in an rlib format, so we're just going to link
336
351
// 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
+ }
345
363
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 .
349
367
activate_injected_dep ( CStore :: from_tcx ( tcx) . injected_panic_runtime ( ) , & mut ret, & |cnum| {
350
368
tcx. is_panic_runtime ( cnum)
351
369
} ) ;
@@ -367,8 +385,7 @@ fn activate_injected_dep(
367
385
list : & mut DependencyList ,
368
386
replaces_injected : & dyn Fn ( CrateNum ) -> bool ,
369
387
) {
370
- for ( i, slot) in list. iter ( ) . enumerate ( ) {
371
- let cnum = CrateNum :: new ( i + 1 ) ;
388
+ for ( cnum, slot) in list. iter_enumerated ( ) {
372
389
if !replaces_injected ( cnum) {
373
390
continue ;
374
391
}
@@ -377,25 +394,23 @@ fn activate_injected_dep(
377
394
}
378
395
}
379
396
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 ;
383
399
}
384
400
}
385
401
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 ) {
389
405
let sess = & tcx. sess ;
390
406
if list. is_empty ( ) {
391
407
return ;
392
408
}
393
409
let mut panic_runtime = None ;
394
- for ( i , linkage) in list. iter ( ) . enumerate ( ) {
410
+ for ( cnum , linkage) in list. iter_enumerated ( ) {
395
411
if let Linkage :: NotLinked = * linkage {
396
412
continue ;
397
413
}
398
- let cnum = CrateNum :: new ( i + 1 ) ;
399
414
400
415
if tcx. is_panic_runtime ( cnum) {
401
416
if let Some ( ( prev, _) ) = panic_runtime {
@@ -431,11 +446,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
431
446
// strategy. If the dep isn't linked, we ignore it, and if our strategy
432
447
// is abort then it's compatible with everything. Otherwise all crates'
433
448
// panic strategy must match our own.
434
- for ( i , linkage) in list. iter ( ) . enumerate ( ) {
449
+ for ( cnum , linkage) in list. iter_enumerated ( ) {
435
450
if let Linkage :: NotLinked = * linkage {
436
451
continue ;
437
452
}
438
- let cnum = CrateNum :: new ( i + 1 ) ;
439
453
if cnum == runtime_cnum || tcx. is_compiler_builtins ( cnum) {
440
454
continue ;
441
455
}
@@ -450,13 +464,16 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
450
464
} ) ;
451
465
}
452
466
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
+ }
460
477
}
461
478
}
462
479
}
0 commit comments