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