From 711338bd9f957b7bd345323033e9037c0e1ca535 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 10 May 2024 17:29:02 +0300 Subject: [PATCH] rustc: Use `tcx.used_crates(())` more And explain when it should be used. --- .../rustc_codegen_ssa/src/back/symbol_export.rs | 2 +- compiler/rustc_codegen_ssa/src/base.rs | 4 ++-- compiler/rustc_interface/src/passes.rs | 2 +- .../rustc_metadata/src/dependency_format.rs | 12 ++++++------ .../src/rmeta/decoder/cstore_impl.rs | 4 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 6 +++--- compiler/rustc_middle/src/query/mod.rs | 17 +++++++++++++---- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 4 ++-- compiler/rustc_passes/src/diagnostic_items.rs | 2 +- compiler/rustc_passes/src/stability.rs | 4 ++-- compiler/rustc_passes/src/weak_lang_items.rs | 2 +- compiler/rustc_smir/src/rustc_smir/context.rs | 11 ++++++++--- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/core.rs | 2 +- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/passes/collect_trait_impls.rs | 2 +- src/librustdoc/scrape_examples.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- src/tools/miri/src/helpers.rs | 4 ++-- tests/ui/extern-flag/empty-extern-arg.stderr | 9 +-------- 23 files changed, 54 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 0e335bf00cf05..897ec2a804254 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -399,7 +399,7 @@ fn upstream_monomorphizations_provider( tcx: TyCtxt<'_>, (): (), ) -> DefIdMap, CrateNum>> { - let cnums = tcx.crates(()); + let cnums = tcx.used_crates(()); let mut instances: DefIdMap> = Default::default(); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 877e5b75912ea..89edadbd25259 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -539,7 +539,7 @@ pub fn collect_debugger_visualizers_transitive( tcx.debugger_visualizers(LOCAL_CRATE) .iter() .chain( - tcx.crates(()) + tcx.used_crates(()) .iter() .filter(|&cnum| { let used_crate_source = tcx.used_crate_source(*cnum); @@ -849,7 +849,7 @@ impl CrateInfo { // `compiler_builtins` are always placed last to ensure that they're linked correctly. used_crates.extend(compiler_builtins); - let crates = tcx.crates(()); + let crates = tcx.used_crates(()); let n_crates = crates.len(); let mut info = CrateInfo { target_cpu, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 76d5d7a3ac2fd..f1f9b74385129 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -458,7 +458,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } } - for &cnum in tcx.crates(()) { + for &cnum in tcx.crates_including_speculative(()) { let source = tcx.used_crate_source(cnum); if let Some((path, _)) = &source.dylib { files.push(escape_dep_filename(&path.display().to_string())); diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 99181f9c8605c..8afeb43071979 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -143,7 +143,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { && sess.crt_static(Some(ty)) && !sess.target.crt_static_allows_dylibs) { - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -164,7 +164,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -182,7 +182,7 @@ 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 last_crate = tcx.used_crates(()).len(); let mut ret = (1..last_crate + 1) .map(|cnum| match formats.get(&CrateNum::new(cnum)) { Some(&RequireDynamic) => Linkage::Dynamic, @@ -196,7 +196,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // // 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. - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && !formats.contains_key(&cnum) @@ -284,7 +284,7 @@ fn add_library( fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option { let all_crates_available_as_rlib = tcx - .crates(()) + .used_crates(()) .iter() .copied() .filter_map(|cnum| { @@ -305,7 +305,7 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option Linkage::Static, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index c783149a69514..4cad317ce80cd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -435,7 +435,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // traversal, but not globally minimal across all crates. let bfs_queue = &mut VecDeque::new(); - for &cnum in tcx.crates(()) { + for &cnum in tcx.crates_including_speculative(()) { // Ignore crates without a corresponding local `extern crate` item. if tcx.missing_extern_crate_item(cnum) { continue; @@ -505,7 +505,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, - crates: |tcx, ()| { + crates_including_speculative: |tcx, ()| { // The list of loaded crates is now frozen in query cache, // so make sure cstore is not mutably accessed from here on. tcx.untracked().cstore.freeze(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index db0dc6d9064b7..fbe70d4604c45 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1898,7 +1898,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let deps = self .tcx - .crates(()) + .crates_including_speculative(()) .iter() .map(|&cnum| { let dep = CrateDep { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index f3f24f7717701..b17af47fbcd4f 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1016,7 +1016,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { let krate = tcx.hir_crate(()); let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash"); - let upstream_crates = upstream_crates(tcx); + let upstream_crates = upstream_crates_for_hashing(tcx); let resolutions = tcx.resolutions(()); @@ -1085,9 +1085,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { Svh::new(crate_hash) } -fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { +fn upstream_crates_for_hashing(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { let mut upstream_crates: Vec<_> = tcx - .crates(()) + .crates_including_speculative(()) .iter() .map(|&cnum| { let stable_crate_id = tcx.stable_crate_id(cnum); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c2f7a227f6661..0654d82838c9d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1860,13 +1860,22 @@ rustc_queries! { eval_always desc { "calculating the stability index for the local crate" } } - query crates(_: ()) -> &'tcx [CrateNum] { + /// All loaded crates, including those loaded purely for doc links or diagnostics. + /// (Diagnostics include lints, so speculatively loaded crates may occur in successful + /// compilation even without doc links.) + /// Should be used when encoding crate metadata (and therefore when generating crate hash, + /// depinfo and similar things), to avoid dangling crate references in other encoded data, + /// like source maps. + /// May also be used for diagnostics - if we are loading a crate anyway we can suggest some + /// items from it as well. + /// But otherwise, `used_crates` should generally be used. + query crates_including_speculative(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching all foreign CrateNum instances" } } - // Crates that are loaded non-speculatively (not for diagnostics or doc links). - // FIXME: This is currently only used for collecting lang items, but should be used instead of - // `crates` in most other cases too. + /// Crates that are loaded non-speculatively (not for diagnostics or doc links). + /// Should be used to maintain observable language behavior, for example when collecting lang + /// items or impls from all crates, or collecting libraries to link. query used_crates(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching `CrateNum`s for all crates loaded non-speculatively" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 896114e2483c7..e0d1b5a62f732 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1611,7 +1611,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn all_traits(self) -> impl Iterator + 'tcx { iter::once(LOCAL_CRATE) - .chain(self.crates(()).iter().copied()) + .chain(self.used_crates(()).iter().copied()) .flat_map(move |cnum| self.traits(cnum).iter().copied()) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index a1ead1bb59f54..0bcd02aaa3acf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3258,7 +3258,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N let queue = &mut Vec::new(); let mut seen_defs: DefIdSet = Default::default(); - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.crates_including_speculative(()).iter() { let def_id = cnum.as_def_id(); // Ignore crates that are not direct dependencies. diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index cf1cbb934105b..d2bcab1493f08 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -205,7 +205,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait // Traits defined in the current crate can't have impls in upstream // crates, so we don't bother querying the cstore. if !trait_id.is_local() { - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { for &(impl_def_id, simplified_self_ty) in tcx.implementations_of_trait((cnum, trait_id)).iter() { @@ -247,7 +247,7 @@ pub(super) fn incoherent_impls_provider( let mut impls = Vec::new(); let mut res = Ok(()); - for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) { + for cnum in iter::once(LOCAL_CRATE).chain(tcx.used_crates(()).iter().copied()) { let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) { Ok(impls) => impls, Err(e) => { diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 906ecdfe5abae..78653e5f95a6d 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -82,7 +82,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems { let mut items = DiagnosticItems::default(); // Collect diagnostic items in other crates. - for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { + for &cnum in tcx.crates_including_speculative(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id { collect_item(tcx, &mut items, name, def_id); } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 05c833cdfb657..4ed0e6abc77ee 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -1020,7 +1020,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // stabilization diagnostic, but it can be avoided when there are no // `remaining_lib_features`. let mut all_implications = remaining_implications.clone(); - for &cnum in tcx.crates(()) { + for &cnum in tcx.used_crates(()) { all_implications .extend_unord(tcx.stability_implications(cnum).items().map(|(k, v)| (*k, *v))); } @@ -1033,7 +1033,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { &all_implications, ); - for &cnum in tcx.crates(()) { + for &cnum in tcx.used_crates(()) { if remaining_lib_features.is_empty() && remaining_implications.is_empty() { break; } diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 90691ca17908b..d80addf12364d 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -68,7 +68,7 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { } let mut missing = FxHashSet::default(); - for &cnum in tcx.crates(()).iter() { + for &cnum in tcx.used_crates(()).iter() { for &item in tcx.missing_lang_items(cnum).iter() { missing.insert(item); } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index fd31c020f899a..242a48b3ca5f6 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -126,7 +126,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; iter::once(LOCAL_CRATE) - .chain(tables.tcx.crates(()).iter().copied()) + .chain(tables.tcx.used_crates(()).iter().copied()) .flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter()) .map(|impl_def_id| tables.impl_def(*impl_def_id)) .collect() @@ -201,14 +201,19 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn external_crates(&self) -> Vec { let tables = self.0.borrow(); - tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect() + tables + .tcx + .used_crates(()) + .iter() + .map(|crate_num| smir_crate(tables.tcx, *crate_num)) + .collect() } fn find_crates(&self, name: &str) -> Vec { let tables = self.0.borrow(); let crates: Vec = [LOCAL_CRATE] .iter() - .chain(tables.tcx.crates(()).iter()) + .chain(tables.tcx.used_crates(()).iter()) .filter_map(|crate_num| { let crate_name = tables.tcx.crate_name(*crate_num).to_string(); (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num)) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b54ec62452476..7aab07c06a33c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1937,7 +1937,7 @@ impl PrimitiveType { let mut primitive_locations = FxHashMap::default(); // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate. // This is a degenerate case that I don't plan to support. - for &crate_num in tcx.crates(()) { + for &crate_num in tcx.crates_including_speculative(()) { let e = ExternalCrate { crate_num }; let crate_name = e.name(tcx); debug!(?crate_num, ?crate_name); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index feb03b9a823e8..462b31f159b35 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -347,7 +347,7 @@ pub(crate) fn run_global_ctxt( show_coverage, }; - for cnum in tcx.crates(()) { + for cnum in tcx.crates_including_speculative(()) { crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id()); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index a3b88a880f2af..28ddf76a3a695 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -155,7 +155,7 @@ impl Cache { // Cache where all our extern crates are located // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code - for &crate_num in tcx.crates(()) { + for &crate_num in tcx.crates_including_speculative(()) { let e = ExternalCrate { crate_num }; let name = e.name(tcx); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index c92cf9d3e80d3..22daac9efb152 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -47,7 +47,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // External trait impls. { let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls"); - for &cnum in tcx.crates(()) { + for &cnum in tcx.crates_including_speculative(()) { for &impl_def_id in tcx.trait_impls_in_crate(cnum) { cx.with_param_env(impl_def_id, |cx| { inline::build_impl(cx, impl_def_id, None, &mut new_items_external); diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 9c9b386edda7c..19b0e045f0496 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -283,7 +283,7 @@ pub(crate) fn run( // Collect CrateIds corresponding to provided target crates // If two different versions of the crate in the dependency tree, then examples will be collected from both. let all_crates = tcx - .crates(()) + .crates_including_speculative(()) .iter() .chain([&LOCAL_CRATE]) .map(|crate_num| (crate_num, tcx.crate_name(*crate_num))) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 4c603bda770a9..94d4656377f98 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -647,7 +647,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec, path: &[&str]) -> Vec { fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator + '_ { - tcx.crates(()) + tcx.crates_including_speculative(()) .iter() .copied() .filter(move |&num| tcx.crate_name(num) == name) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 4050ae3c4bf97..bd160380cd524 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -126,7 +126,7 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option) // the one in the sysroot and the one locally built by `cargo test`.) // FIXME: can we prefer the one from the sysroot? 'crates: for krate in - tcx.crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name) + tcx.used_crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name) { let mut cur_item = DefId { krate: *krate, index: CRATE_DEF_INDEX }; // Go over the modules. @@ -1365,7 +1365,7 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec { .map(|crates| crates.split(',').map(|krate| krate.to_string()).collect::>()) .unwrap_or_default(); let mut local_crates = Vec::new(); - for &crate_num in tcx.crates(()) { + for &crate_num in tcx.crates_including_speculative(()) { let name = tcx.crate_name(crate_num); let name = name.as_str(); if local_crate_names.iter().any(|local_name| local_name == name) { diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 2785b12a0aef4..6ad3effe0e26e 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -1,13 +1,6 @@ error: extern location for std does not exist: -error: `#[panic_handler]` function required, but not found - -error: unwinding panics are not supported without std - | - = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - error: requires `sized` lang_item -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors