diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 4be4291021dfa..eaab3362c7e83 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -294,7 +294,7 @@ fn dep_symbol_lookup_fn( // search path. for &cnum in crate_info.used_crates.iter().rev() { let src = &crate_info.used_crate_source[&cnum]; - match data[cnum.as_usize() - 1] { + match data[cnum] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { let name = crate_info.crate_name[&cnum]; diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f4f6161ebbccd..562af0777f52f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -234,8 +234,6 @@ pub fn each_linked_rlib( crate_type: Option, f: &mut dyn FnMut(CrateNum, &Path), ) -> Result<(), errors::LinkRlibError> { - let crates = info.used_crates.iter(); - let fmts = if let Some(crate_type) = crate_type { let Some(fmts) = info.dependency_formats.get(&crate_type) else { return Err(errors::LinkRlibError::MissingFormat); @@ -261,8 +259,9 @@ pub fn each_linked_rlib( info.dependency_formats.first().unwrap().1 }; - for &cnum in crates { - match fmts.get(cnum.as_usize() - 1) { + let used_dep_crates = info.used_crates.iter(); + for &cnum in used_dep_crates { + match fmts.get(cnum) { Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue, Some(_) => {} None => return Err(errors::LinkRlibError::MissingFormat), @@ -624,7 +623,7 @@ fn link_staticlib( let mut all_rust_dylibs = vec![]; for &cnum in crates { - match fmts.get(cnum.as_usize() - 1) { + match fmts.get(cnum) { Some(&Linkage::Dynamic) => {} _ => continue, } @@ -2361,8 +2360,8 @@ fn linker_with_args( .crate_info .native_libraries .iter() - .filter_map(|(cnum, libraries)| { - (dependency_linkage[cnum.as_usize() - 1] != Linkage::Static).then_some(libraries) + .filter_map(|(&cnum, libraries)| { + (dependency_linkage[cnum] != Linkage::Static).then_some(libraries) }) .flatten() .collect::>(); @@ -2754,7 +2753,7 @@ fn add_upstream_rust_crates( // (e.g. `libstd` when `-C prefer-dynamic` is used). // FIXME: `dependency_formats` can report `profiler_builtins` as `NotLinked` for some // reason, it shouldn't do that because `profiler_builtins` should indeed be linked. - let linkage = data[cnum.as_usize() - 1]; + let linkage = data[cnum]; let link_static_crate = linkage == Linkage::Static || (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked) && (codegen_results.crate_info.compiler_builtins == Some(cnum) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8a2f3d73bc15c..3c6513ca26bb1 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1744,15 +1744,10 @@ fn for_each_exported_symbols_include_dep<'tcx>( crate_type: CrateType, mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum), ) { - for &(symbol, info) in tcx.exported_symbols(LOCAL_CRATE).iter() { - callback(symbol, info, LOCAL_CRATE); - } - let formats = tcx.dependency_formats(()); let deps = &formats[&crate_type]; - for (index, dep_format) in deps.iter().enumerate() { - let cnum = CrateNum::new(index + 1); + for (cnum, dep_format) in deps.iter_enumerated() { // For each dependency that we are linking to statically ... if *dep_format == Linkage::Static { for &(symbol, info) in tcx.exported_symbols(cnum).iter() { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 02905e632ab87..aff66e48fbbee 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -19,7 +19,7 @@ use rustc_incremental::setup_dep_graph; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; -use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; +use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; use rustc_parse::{ new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr, @@ -770,15 +770,14 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( // subtyping for GlobalCtxt::enter to be allowed. let inner: Box< dyn for<'tcx> FnOnce( - &'tcx Compiler, + &'tcx Session, + CurrentGcx, &'tcx OnceLock>, &'tcx WorkerLocal>, &'tcx WorkerLocal>, F, ) -> T, - > = Box::new(move |compiler, gcx_cell, arena, hir_arena, f| { - let sess = &compiler.sess; - + > = Box::new(move |sess, current_gcx, gcx_cell, arena, hir_arena, f| { TyCtxt::create_global_ctxt( gcx_cell, sess, @@ -796,7 +795,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( incremental, ), providers.hooks, - compiler.current_gcx.clone(), + current_gcx, |tcx| { let feed = tcx.create_crate_num(stable_crate_id).unwrap(); assert_eq!(feed.key(), LOCAL_CRATE); @@ -804,7 +803,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( let feed = tcx.feed_unit_query(); feed.features_query(tcx.arena.alloc(rustc_expand::config::features( - sess, + tcx.sess, &pre_configured_attrs, crate_name, ))); @@ -819,7 +818,7 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( ) }); - inner(compiler, &gcx_cell, &arena, &hir_arena, f) + inner(&compiler.sess, compiler.current_gcx.clone(), &gcx_cell, &arena, &hir_arena, f) } /// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses. diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index e8de0acb7c9fe..582c2215d92e1 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -52,7 +52,8 @@ //! than finding a number of solutions (there are normally quite a few). use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir::def_id::CrateNum; +use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_index::IndexVec; use rustc_middle::bug; use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage}; use rustc_middle::ty::TyCtxt; @@ -84,7 +85,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { let sess = &tcx.sess; if !sess.opts.output_types.should_codegen() { - return Vec::new(); + return IndexVec::new(); } let preferred_linkage = match ty { @@ -131,7 +132,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { match preferred_linkage { // If the crate is not linked, there are no link-time dependencies. - Linkage::NotLinked => return Vec::new(), + Linkage::NotLinked => return IndexVec::new(), Linkage::Static => { // Attempt static linkage first. For dylibs and executables, we may be // able to retry below with dynamic linkage. @@ -156,7 +157,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { } sess.dcx().emit_err(RlibRequired { crate_name: tcx.crate_name(cnum) }); } - return Vec::new(); + return IndexVec::new(); } } Linkage::Dynamic | Linkage::IncludedFromDylib => {} @@ -210,19 +211,32 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // Collect what we've got so far in the return vector. let last_crate = tcx.crates(()).len(); - let mut ret = (1..last_crate + 1) - .map(|cnum| match formats.get(&CrateNum::new(cnum)) { - Some(&RequireDynamic) => Linkage::Dynamic, - Some(&RequireStatic) => Linkage::IncludedFromDylib, - None => Linkage::NotLinked, - }) - .collect::>(); + let mut ret = IndexVec::new(); + + // We need to fill in something for LOCAL_CRATE as IndexVec is a dense map. + // Linkage::Static semantically the most correct thing to use as the local + // crate is always statically linked into the linker output, even when + // linking a dylib. Using Linkage::Static also allow avoiding special cases + // for LOCAL_CRATE in some places. + assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE); + + for cnum in 1..last_crate + 1 { + let cnum = CrateNum::new(cnum); + assert_eq!( + ret.push(match formats.get(&cnum) { + Some(&RequireDynamic) => Linkage::Dynamic, + Some(&RequireStatic) => Linkage::IncludedFromDylib, + None => Linkage::NotLinked, + }), + cnum + ); + } // Run through the dependency list again, and add any missing libraries as // static libraries. // // If the crate hasn't been included yet and it's not actually required - // (e.g., it's an allocator) then we skip it here as well. + // (e.g., it's a panic runtime) then we skip it here as well. for &cnum in tcx.crates(()).iter() { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() @@ -232,7 +246,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { assert!(src.rlib.is_some() || src.rmeta.is_some()); info!("adding staticlib: {}", tcx.crate_name(cnum)); add_library(tcx, cnum, RequireStatic, &mut formats, &mut unavailable_as_static); - ret[cnum.as_usize() - 1] = Linkage::Static; + ret[cnum] = Linkage::Static; } } @@ -240,8 +254,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // artifact which means that we may need to inject dependencies of some // form. // - // Things like allocators and panic runtimes may not have been activated - // quite yet, so do so here. + // Things like panic runtimes may not have been activated quite yet, so do so here. activate_injected_dep(CStore::from_tcx(tcx).injected_panic_runtime(), &mut ret, &|cnum| { tcx.is_panic_runtime(cnum) }); @@ -252,8 +265,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // // For situations like this, we perform one last pass over the dependencies, // making sure that everything is available in the requested format. - for (cnum, kind) in ret.iter().enumerate() { - let cnum = CrateNum::new(cnum + 1); + for (cnum, kind) in ret.iter_enumerated() { + if cnum == LOCAL_CRATE { + continue; + } let src = tcx.used_crate_source(cnum); match *kind { Linkage::NotLinked | Linkage::IncludedFromDylib => {} @@ -334,18 +349,21 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option Linkage::Static, - CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked, - }) - .collect::>(); + let mut ret = IndexVec::new(); + assert_eq!(ret.push(Linkage::Static), LOCAL_CRATE); + for &cnum in tcx.crates(()) { + assert_eq!( + ret.push(match tcx.dep_kind(cnum) { + CrateDepKind::Explicit => Linkage::Static, + CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked, + }), + cnum + ); + } - // Our allocator/panic runtime may not have been linked above if it wasn't - // explicitly linked, which is the case for any injected dependency. Handle - // that here and activate them. + // Our panic runtime may not have been linked above if it wasn't explicitly + // linked, which is the case for any injected dependency. Handle that here + // and activate it. activate_injected_dep(CStore::from_tcx(tcx).injected_panic_runtime(), &mut ret, &|cnum| { tcx.is_panic_runtime(cnum) }); @@ -367,8 +385,7 @@ fn activate_injected_dep( list: &mut DependencyList, replaces_injected: &dyn Fn(CrateNum) -> bool, ) { - for (i, slot) in list.iter().enumerate() { - let cnum = CrateNum::new(i + 1); + for (cnum, slot) in list.iter_enumerated() { if !replaces_injected(cnum) { continue; } @@ -377,25 +394,23 @@ fn activate_injected_dep( } } if let Some(injected) = injected { - let idx = injected.as_usize() - 1; - assert_eq!(list[idx], Linkage::NotLinked); - list[idx] = Linkage::Static; + assert_eq!(list[injected], Linkage::NotLinked); + list[injected] = Linkage::Static; } } -// After the linkage for a crate has been determined we need to verify that -// there's only going to be one allocator in the output. -fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { +/// After the linkage for a crate has been determined we need to verify that +/// there's only going to be one panic runtime in the output. +fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) { let sess = &tcx.sess; if list.is_empty() { return; } let mut panic_runtime = None; - for (i, linkage) in list.iter().enumerate() { + for (cnum, linkage) in list.iter_enumerated() { if let Linkage::NotLinked = *linkage { continue; } - let cnum = CrateNum::new(i + 1); if tcx.is_panic_runtime(cnum) { if let Some((prev, _)) = panic_runtime { @@ -431,11 +446,10 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { // strategy. If the dep isn't linked, we ignore it, and if our strategy // is abort then it's compatible with everything. Otherwise all crates' // panic strategy must match our own. - for (i, linkage) in list.iter().enumerate() { + for (cnum, linkage) in list.iter_enumerated() { if let Linkage::NotLinked = *linkage { continue; } - let cnum = CrateNum::new(i + 1); if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) { continue; } @@ -450,13 +464,16 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { }); } - let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); - if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy { - sess.dcx().emit_err(IncompatiblePanicInDropStrategy { - crate_name: tcx.crate_name(cnum), - found_strategy: found_drop_strategy, - desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, - }); + // panic_in_drop_strategy isn't allowed for LOCAL_CRATE + if cnum != LOCAL_CRATE { + let found_drop_strategy = tcx.panic_in_drop_strategy(cnum); + if tcx.sess.opts.unstable_opts.panic_in_drop != found_drop_strategy { + sess.dcx().emit_err(IncompatiblePanicInDropStrategy { + crate_name: tcx.crate_name(cnum), + found_strategy: found_drop_strategy, + desired_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, + }); + } } } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 90b1d2952c599..c2b5e318bda72 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1474,7 +1474,7 @@ impl<'a> CrateMetadataRef<'a> { ) -> &'tcx [(CrateNum, LinkagePreference)] { tcx.arena.alloc_from_iter( self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| { - let cnum = CrateNum::new(i + 1); + let cnum = CrateNum::new(i + 1); // We skipped LOCAL_CRATE when encoding link.map(|link| (self.cnum_map[cnum], link)) }), ) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index fff6f3f804fc3..c538ab99fb54b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2165,12 +2165,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { empty_proc_macro!(self); let formats = self.tcx.dependency_formats(()); if let Some(arr) = formats.get(&CrateType::Dylib) { - return self.lazy_array(arr.iter().map(|slot| match *slot { - Linkage::NotLinked | Linkage::IncludedFromDylib => None, + return self.lazy_array(arr.iter().skip(1 /* skip LOCAL_CRATE */).map( + |slot| match *slot { + Linkage::NotLinked | Linkage::IncludedFromDylib => None, - Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), - Linkage::Static => Some(LinkagePreference::RequireStatic), - })); + Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), + Linkage::Static => Some(LinkagePreference::RequireStatic), + }, + )); } LazyArray::default() } diff --git a/compiler/rustc_middle/src/middle/dependency_format.rs b/compiler/rustc_middle/src/middle/dependency_format.rs index e3b40b6415784..4f613e97631d0 100644 --- a/compiler/rustc_middle/src/middle/dependency_format.rs +++ b/compiler/rustc_middle/src/middle/dependency_format.rs @@ -8,13 +8,13 @@ // this will introduce circular dependency between rustc_metadata and rustc_middle use rustc_data_structures::fx::FxIndexMap; +use rustc_hir::def_id::CrateNum; +use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::config::CrateType; /// A list of dependencies for a certain crate type. -/// -/// The length of this vector is the same as the number of external crates used. -pub type DependencyList = Vec; +pub type DependencyList = IndexVec; /// A mapping of all required dependencies for a particular flavor of output. /// diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index beae9dc278c15..c8a5c22ad1230 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -42,7 +42,7 @@ pub enum CrateDepKind { /// A dependency that is only used for its macros. MacrosOnly, /// A dependency that is always injected into the dependency list and so - /// doesn't need to be linked to an rlib, e.g., the injected allocator. + /// doesn't need to be linked to an rlib, e.g., the injected panic runtime. Implicit, /// A dependency that is required by an rlib version of this crate. /// Ordinary `extern crate`s result in `Explicit` dependencies. diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 2b27400e9e362..e817e0f90dccd 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -152,12 +152,14 @@ pub fn iter_exported_symbols<'tcx>( let dependency_format = dependency_formats .get(&CrateType::Executable) .expect("interpreting a non-executable crate"); - for cnum in dependency_format.iter().enumerate().filter_map(|(num, &linkage)| { - // We add 1 to the number because that's what rustc also does everywhere it - // calls `CrateNum::new`... - #[expect(clippy::arithmetic_side_effects)] - (linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1)) - }) { + for cnum in dependency_format + .iter_enumerated() + .filter_map(|(num, &linkage)| (linkage != Linkage::NotLinked).then_some(num)) + { + if cnum == LOCAL_CRATE { + continue; // Already handled above + } + // We can ignore `_export_info` here: we are a Rust crate, and everything is exported // from a Rust crate. for &(symbol, _export_info) in tcx.exported_symbols(cnum) {