From f5c3e83013700835cfd64215b482b8dffe1f71be Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 30 May 2021 17:24:54 +0200 Subject: [PATCH] Avoid a branch on key being local for queries that use the same local and extern providers --- .../src/back/symbol_export.rs | 4 +- compiler/rustc_codegen_ssa/src/lib.rs | 4 +- .../rustc_codegen_ssa/src/traits/backend.rs | 4 +- compiler/rustc_interface/src/interface.rs | 4 +- compiler/rustc_interface/src/passes.rs | 7 +- compiler/rustc_macros/src/query.rs | 23 +++++ .../src/rmeta/decoder/cstore_impl.rs | 6 +- compiler/rustc_middle/src/query/mod.rs | 86 ++++++++++++++++++- compiler/rustc_middle/src/ty/query.rs | 50 +++++++++++ compiler/rustc_query_impl/src/lib.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 26 ++++-- 11 files changed, 189 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 4a7090b31b4..f80f9965f4d 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -11,7 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{ metadata_symbol_name, ExportedSymbol, SymbolExportLevel, }; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; use rustc_middle::ty::{SymbolName, TyCtxt}; @@ -363,7 +363,7 @@ pub fn provide(providers: &mut Providers) { providers.wasm_import_module_map = wasm_import_module_map; } -pub fn provide_extern(providers: &mut Providers) { +pub fn provide_extern(providers: &mut ExternProviders) { providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern; providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider; } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 9f3c2f0c7ce..b2b0629c4b7 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -28,7 +28,7 @@ use rustc_hir::def_id::CrateNum; use rustc_hir::LangItem; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::dependency_format::Dependencies; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; use rustc_session::utils::NativeLibKind; @@ -170,7 +170,7 @@ pub fn provide(providers: &mut Providers) { crate::target_features::provide(providers); } -pub fn provide_extern(providers: &mut Providers) { +pub fn provide_extern(providers: &mut ExternProviders) { crate::back::symbol_export::provide_extern(providers); } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 8129a14fcfd..8fef8314a5c 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -9,7 +9,7 @@ use rustc_errors::ErrorReported; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout}; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_session::{ config::{self, OutputFilenames, PrintRequest}, @@ -80,7 +80,7 @@ pub trait CodegenBackend { } fn provide(&self, _providers: &mut Providers) {} - fn provide_extern(&self, _providers: &mut Providers) {} + fn provide_extern(&self, _providers: &mut ExternProviders) {} fn codegen_crate<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 81585f8f4e4..7a6a643e3d0 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -38,7 +38,7 @@ pub struct Compiler { pub(crate) output_file: Option, pub(crate) register_lints: Option>, pub(crate) override_queries: - Option, + Option, } impl Compiler { @@ -155,7 +155,7 @@ pub struct Config { /// /// The second parameter is local providers and the third parameter is external providers. pub override_queries: - Option, + Option, /// This is a callback from the driver that is called to create a codegen backend. pub make_codegen_backend: diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index eea32083568..62f5f09aa48 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -19,7 +19,7 @@ use rustc_metadata::creader::CStore; use rustc_metadata::{encode_metadata, EncodedMetadata}; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; @@ -764,8 +764,8 @@ pub static DEFAULT_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { *providers }); -pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { - let mut extern_providers = *DEFAULT_QUERY_PROVIDERS; +pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy = SyncLazy::new(|| { + let mut extern_providers = ExternProviders::default(); rustc_metadata::provide_extern(&mut extern_providers); rustc_codegen_ssa::provide_extern(&mut extern_providers); extern_providers @@ -816,7 +816,6 @@ pub fn create_global_ctxt<'tcx>( codegen_backend.provide(&mut local_providers); let mut extern_providers = *DEFAULT_EXTERN_QUERY_PROVIDERS; - codegen_backend.provide(&mut extern_providers); codegen_backend.provide_extern(&mut extern_providers); if let Some(callback) = compiler.override_queries { diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 5ff12a17887..6dbba274360 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -55,6 +55,9 @@ enum QueryModifier { /// Always evaluate the query, ignoring its dependencies EvalAlways(Ident), + + /// Use a separate query provider for local and extern crates + SeparateProvideExtern(Ident), } impl Parse for QueryModifier { @@ -118,6 +121,8 @@ impl Parse for QueryModifier { Ok(QueryModifier::Anon(modifier)) } else if modifier == "eval_always" { Ok(QueryModifier::EvalAlways(modifier)) + } else if modifier == "separate_provide_extern" { + Ok(QueryModifier::SeparateProvideExtern(modifier)) } else { Err(Error::new(modifier.span(), "unknown query modifier")) } @@ -214,6 +219,9 @@ struct QueryModifiers { // Always evaluate the query, ignoring its dependencies eval_always: Option, + + /// Use a separate query provider for local and extern crates + separate_provide_extern: Option, } /// Process query modifiers into a struct, erroring on duplicates @@ -227,6 +235,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut no_hash = None; let mut anon = None; let mut eval_always = None; + let mut separate_provide_extern = None; for modifier in query.modifiers.0.drain(..) { match modifier { QueryModifier::LoadCached(tcx, id, block) => { @@ -317,6 +326,15 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } eval_always = Some(ident); } + QueryModifier::SeparateProvideExtern(ident) => { + if separate_provide_extern.is_some() { + panic!( + "duplicate modifier `separate_provide_extern` for query `{}`", + query.name + ); + } + separate_provide_extern = Some(ident); + } } } let desc = desc.unwrap_or_else(|| { @@ -332,6 +350,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { no_hash, anon, eval_always, + separate_provide_extern, } } @@ -462,6 +481,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if let Some(eval_always) = &modifiers.eval_always { attributes.push(quote! { (#eval_always) }); }; + // Pass on the separate_provide_extern modifier + if let Some(separate_provide_extern) = &modifiers.separate_provide_extern { + attributes.push(quote! { (#separate_provide_extern) }); + } // This uses the span of the query definition for the commas, // which can be important if we later encounter any ambiguity diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index e12f049a90b..7ea004b16f2 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -10,7 +10,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_middle::hir::exports::Export; use rustc_middle::middle::exported_symbols::ExportedSymbol; use rustc_middle::middle::stability::DeprecationEntry; -use rustc_middle::ty::query::Providers; +use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::cstore::{CrateSource, CrateStore, ForeignModule}; use rustc_session::utils::NativeLibKind; @@ -26,7 +26,7 @@ use std::any::Any; macro_rules! provide { (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $($name:ident => $compute:block)*) => { - pub fn provide_extern(providers: &mut Providers) { + pub fn provide_extern(providers: &mut ExternProviders) { $(fn $name<$lt>( $tcx: TyCtxt<$lt>, def_id_arg: ty::query::query_keys::$name<$lt>, @@ -51,7 +51,7 @@ macro_rules! provide { $compute })* - *providers = Providers { + *providers = ExternProviders { $($name,)* ..*providers }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index c6c0fdc8851..6d384f5f3d6 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -107,6 +107,7 @@ rustc_queries! { /// parameter. e.g. `fn example` called on `N` would return `3`. query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> { desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } + separate_provide_extern } query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> { @@ -128,6 +129,7 @@ rustc_queries! { path = tcx.def_path_str(key), } cache_on_disk_if { key.is_local() } + separate_provide_extern } query analysis(key: ()) -> Result<(), ErrorReported> { @@ -141,6 +143,7 @@ rustc_queries! { desc { |tcx| "computing generics of `{}`", tcx.def_path_str(key) } storage(ArenaCacheSelector<'tcx>) cache_on_disk_if { key.is_local() } + separate_provide_extern } /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the @@ -181,6 +184,7 @@ rustc_queries! { /// Bounds from the parent (e.g. with nested impl trait) are not included. query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Elaborated version of the predicates from `explicit_item_bounds`. @@ -209,6 +213,7 @@ rustc_queries! { query native_libraries(_: CrateNum) -> Lrc> { desc { "looking up the native libraries of a linked crate" } + separate_provide_extern } query lint_levels(_: ()) -> LintLevelMap { @@ -226,11 +231,13 @@ rustc_queries! { // This query reads from untracked data in definitions. eval_always desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) } + separate_provide_extern } query is_panic_runtime(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate is_panic_runtime" } + separate_provide_extern } /// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`. @@ -260,6 +267,7 @@ rustc_queries! { query mir_const_qualif(key: DefId) -> mir::ConstQualifs { desc { |tcx| "const checking `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } query mir_const_qualif_const_arg( key: (LocalDefId, DefId) @@ -296,6 +304,7 @@ rustc_queries! { desc { |tcx| "building an abstract representation for {}", tcx.def_path_str(key), } + separate_provide_extern } /// Try to build an abstract representation of the given constant. query thir_abstract_const_of_const_arg( @@ -329,6 +338,7 @@ rustc_queries! { ) -> &'tcx mir::Body<'tcx> { desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> { @@ -366,6 +376,7 @@ rustc_queries! { query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> { desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` @@ -404,6 +415,7 @@ rustc_queries! { query promoted_mir(key: DefId) -> &'tcx IndexVec> { desc { |tcx| "optimizing promoted MIR for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } + separate_provide_extern } query promoted_mir_of_const_arg( key: (LocalDefId, DefId) @@ -462,12 +474,14 @@ rustc_queries! { /// Returns the predicates written explicitly by the user. query explicit_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). query inferred_outlives_of(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Maps from the `DefId` of a trait to the list of @@ -478,6 +492,7 @@ rustc_queries! { /// additional acyclicity requirements). query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the super predicates of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// The `Option` is the name of an associated type. If it is `None`, then this query @@ -503,12 +518,15 @@ rustc_queries! { query trait_def(key: DefId) -> ty::TraitDef { desc { |tcx| "computing trait definition for `{}`", tcx.def_path_str(key) } storage(ArenaCacheSelector<'tcx>) + separate_provide_extern } query adt_def(key: DefId) -> &'tcx ty::AdtDef { desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } + separate_provide_extern } query adt_destructor(key: DefId) -> Option { desc { |tcx| "computing `Drop` impl for `{}`", tcx.def_path_str(key) } + separate_provide_extern } // The cycle error here should be reported as an error by `check_representable`. @@ -537,10 +555,12 @@ rustc_queries! { /// `is_const_fn` function. query is_const_fn_raw(key: DefId) -> bool { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } + separate_provide_extern } query asyncness(key: DefId) -> hir::IsAsync { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Returns `true` if calls to the function may be promoted. @@ -557,16 +577,19 @@ rustc_queries! { /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`). query is_foreign_item(key: DefId) -> bool { desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) } + separate_provide_extern } /// Returns `Some(mutability)` if the node pointed to by `def_id` is a static item. query static_mutability(def_id: DefId) -> Option { desc { |tcx| "looking up static mutability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator. query generator_kind(def_id: DefId) -> Option { desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Gets a map with the variance of every item; use `item_variance` instead. @@ -578,6 +601,7 @@ rustc_queries! { /// Maps from the `DefId` of a type or region parameter to its (inferred) variance. query variances_of(def_id: DefId) -> &'tcx [ty::Variance] { desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Maps from thee `DefId` of a type to its (inferred) outlives. @@ -589,12 +613,14 @@ rustc_queries! { /// Maps from an impl/trait `DefId` to a list of the `DefId`s of its items. query associated_item_def_ids(key: DefId) -> &'tcx [DefId] { desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) } + separate_provide_extern } /// Maps from a trait item to the trait item "descriptor". query associated_item(key: DefId) -> ty::AssocItem { desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) } storage(ArenaCacheSelector<'tcx>) + separate_provide_extern } /// Collects the associated items defined on a trait or impl. @@ -607,9 +633,11 @@ rustc_queries! { /// Return `None` if this is an inherent impl. query impl_trait_ref(impl_id: DefId) -> Option> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } + separate_provide_extern } query impl_polarity(impl_id: DefId) -> ty::ImplPolarity { desc { |tcx| "computing implementation polarity of `{}`", tcx.def_path_str(impl_id) } + separate_provide_extern } query issue33140_self_ty(key: DefId) -> Option> { @@ -622,6 +650,7 @@ rustc_queries! { query inherent_impls(key: DefId) -> &'tcx [DefId] { desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) } eval_always + separate_provide_extern } /// The result of unsafety-checking this `LocalDefId`. @@ -661,6 +690,7 @@ rustc_queries! { /// The signature of functions. query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> { desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } + separate_provide_extern } query lint_mod(key: LocalDefId) -> () { @@ -715,10 +745,10 @@ rustc_queries! { } /// Caches `CoerceUnsized` kinds for impls on custom types. - query coerce_unsized_info(key: DefId) - -> ty::adjustment::CoerceUnsizedInfo { - desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } - } + query coerce_unsized_info(key: DefId) -> ty::adjustment::CoerceUnsizedInfo { + desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) } + separate_provide_extern + } query typeck_item_bodies(_: ()) -> () { desc { "type-checking all item bodies" } @@ -913,22 +943,27 @@ rustc_queries! { query opt_def_kind(def_id: DefId) -> Option { desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query def_span(def_id: DefId) -> Span { desc { |tcx| "looking up span for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query def_ident_span(def_id: DefId) -> Option { desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) } + separate_provide_extern } query lookup_stability(def_id: DefId) -> Option<&'tcx attr::Stability> { desc { |tcx| "looking up stability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query lookup_const_stability(def_id: DefId) -> Option<&'tcx attr::ConstStability> { desc { |tcx| "looking up const stability of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query should_inherit_track_caller(def_id: DefId) -> bool { @@ -937,10 +972,12 @@ rustc_queries! { query lookup_deprecation_entry(def_id: DefId) -> Option { desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) } + separate_provide_extern } query item_attrs(def_id: DefId) -> &'tcx [ast::Attribute] { desc { |tcx| "collecting attributes of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query codegen_fn_attrs(def_id: DefId) -> CodegenFnAttrs { @@ -951,27 +988,33 @@ rustc_queries! { query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] { desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Gets the rendered value of the specified constant or associated constant. /// Used by rustdoc. query rendered_const(def_id: DefId) -> String { desc { |tcx| "rendering constant intializer of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query impl_parent(def_id: DefId) -> Option { desc { |tcx| "computing specialization parent impl of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Given an `associated_item`, find the trait it belongs to. /// Return `None` if the `DefId` is not an associated item. query trait_of_item(associated_item: DefId) -> Option { desc { |tcx| "finding trait defining `{}`", tcx.def_path_str(associated_item) } + separate_provide_extern } query is_ctfe_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) } + separate_provide_extern } query is_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) } + separate_provide_extern } query own_existential_vtable_entries( @@ -1137,6 +1180,7 @@ rustc_queries! { query dylib_dependency_formats(_: CrateNum) -> &'tcx [(CrateNum, LinkagePreference)] { desc { "dylib dependency formats of crate" } + separate_provide_extern } query dependency_formats(_: ()) -> Lrc { @@ -1146,41 +1190,50 @@ rustc_queries! { query is_compiler_builtins(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate is_compiler_builtins" } + separate_provide_extern } query has_global_allocator(_: CrateNum) -> bool { // This query depends on untracked global state in CStore eval_always fatal_cycle desc { "checking if the crate has_global_allocator" } + separate_provide_extern } query has_panic_handler(_: CrateNum) -> bool { fatal_cycle desc { "checking if the crate has_panic_handler" } + separate_provide_extern } query is_profiler_runtime(_: CrateNum) -> bool { fatal_cycle desc { "query a crate is `#![profiler_runtime]`" } + separate_provide_extern } query panic_strategy(_: CrateNum) -> PanicStrategy { fatal_cycle desc { "query a crate's configured panic strategy" } + separate_provide_extern } query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy { fatal_cycle desc { "query a crate's configured panic-in-drop strategy" } + separate_provide_extern } query is_no_builtins(_: CrateNum) -> bool { fatal_cycle desc { "test whether a crate has `#![no_builtins]`" } + separate_provide_extern } query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion { fatal_cycle desc { "query a crate's symbol mangling version" } + separate_provide_extern } query extern_crate(def_id: DefId) -> Option<&'tcx ExternCrate> { eval_always desc { "getting crate's ExternCrateData" } + separate_provide_extern } query specializes(_: (DefId, DefId)) -> bool { @@ -1197,10 +1250,12 @@ rustc_queries! { query impl_defaultness(def_id: DefId) -> hir::Defaultness { desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) } + separate_provide_extern } query impl_constness(def_id: DefId) -> hir::Constness { desc { |tcx| "looking up whether `{}` is a const impl", tcx.def_path_str(def_id) } + separate_provide_extern } query check_item_well_formed(key: LocalDefId) -> () { @@ -1229,9 +1284,11 @@ rustc_queries! { -> DefIdMap { storage(ArenaCacheSelector<'tcx>) desc { "looking up the exported symbols of a crate" } + separate_provide_extern } query is_reachable_non_generic(def_id: DefId) -> bool { desc { |tcx| "checking whether `{}` is an exported symbol", tcx.def_path_str(def_id) } + separate_provide_extern } query is_unreachable_local_definition(def_id: LocalDefId) -> bool { desc { |tcx| @@ -1264,6 +1321,7 @@ rustc_queries! { "collecting available upstream monomorphizations for `{}`", tcx.def_path_str(def_id), } + separate_provide_extern } /// Returns the upstream crate that exports drop-glue for the given @@ -1287,6 +1345,7 @@ rustc_queries! { query foreign_modules(_: CrateNum) -> Lrc> { desc { "looking up the foreign modules of a linked crate" } + separate_provide_extern } /// Identifies the entry-point (e.g., the `main` function) for a given @@ -1302,18 +1361,22 @@ rustc_queries! { query crate_hash(_: CrateNum) -> Svh { eval_always desc { "looking up the hash a crate" } + separate_provide_extern } query crate_host_hash(_: CrateNum) -> Option { eval_always desc { "looking up the hash of a host version of a crate" } + separate_provide_extern } query extra_filename(_: CrateNum) -> String { eval_always desc { "looking up the extra filename for a crate" } + separate_provide_extern } query crate_extern_paths(_: CrateNum) -> Vec { eval_always desc { "looking up the paths for extern crates" } + separate_provide_extern } /// Given a crate and a trait, look up all impls of that trait in the crate. @@ -1321,6 +1384,7 @@ rustc_queries! { query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { desc { "looking up implementations of a trait in a crate" } + separate_provide_extern } /// Given a crate, look up all trait impls in that crate. @@ -1328,6 +1392,7 @@ rustc_queries! { query all_trait_implementations(_: CrateNum) -> &'tcx [(DefId, Option)] { desc { "looking up all (?) trait implementations" } + separate_provide_extern } query is_dllimport_foreign_item(def_id: DefId) -> bool { @@ -1384,6 +1449,7 @@ rustc_queries! { query visibility(def_id: DefId) -> ty::Visibility { desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } /// Computes the set of modules from which this type is visibly uninhabited. @@ -1398,13 +1464,16 @@ rustc_queries! { query dep_kind(_: CrateNum) -> CrateDepKind { eval_always desc { "fetching what a dependency looks like" } + separate_provide_extern } query crate_name(_: CrateNum) -> Symbol { eval_always desc { "fetching what a crate is named" } + separate_provide_extern } query item_children(def_id: DefId) -> &'tcx [Export] { desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) } + separate_provide_extern } query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option { desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) } @@ -1418,6 +1487,7 @@ rustc_queries! { query defined_lib_features(_: CrateNum) -> &'tcx [(Symbol, Option)] { desc { "calculating the lib features defined in a crate" } + separate_provide_extern } /// Returns the lang items defined in another crate by loading it from metadata. query get_lang_items(_: ()) -> LanguageItems { @@ -1436,16 +1506,19 @@ rustc_queries! { /// Returns the lang items defined in another crate by loading it from metadata. query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] { desc { "calculating the lang items defined in a crate" } + separate_provide_extern } /// Returns the diagnostic items defined in a crate. query diagnostic_items(_: CrateNum) -> rustc_hir::diagnostic_items::DiagnosticItems { storage(ArenaCacheSelector<'tcx>) desc { "calculating the diagnostic items map in a crate" } + separate_provide_extern } query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] { desc { "calculating the missing lang items in a crate" } + separate_provide_extern } query visible_parent_map(_: ()) -> DefIdMap { storage(ArenaCacheSelector<'tcx>) @@ -1458,10 +1531,12 @@ rustc_queries! { query missing_extern_crate_item(_: CrateNum) -> bool { eval_always desc { "seeing if we're missing an `extern crate` item for this crate" } + separate_provide_extern } query used_crate_source(_: CrateNum) -> Lrc { eval_always desc { "looking at the source for a crate" } + separate_provide_extern } query postorder_cnums(_: ()) -> &'tcx [CrateNum] { eval_always @@ -1472,6 +1547,7 @@ rustc_queries! { query is_private_dep(c: CrateNum) -> bool { eval_always desc { "check whether crate {} is a private dependency", c } + separate_provide_extern } query allocator_kind(_: ()) -> Option { eval_always @@ -1517,6 +1593,7 @@ rustc_queries! { query exported_symbols(_: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] { desc { "exported_symbols" } + separate_provide_extern } query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) { @@ -1542,6 +1619,7 @@ rustc_queries! { |tcx| "determining which generic parameters are unused by `{}`", tcx.def_path_str(key.def_id()) } + separate_provide_extern } query backend_optimization_level(_: ()) -> OptLevel { desc { "optimization level used by backend" } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 6c1175ebdb4..34f80627197 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -123,6 +123,39 @@ macro_rules! query_storage { }; } +macro_rules! separate_provide_extern_decl { + ([][$name:ident]) => { + () + }; + ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { + for<'tcx> fn( + TyCtxt<'tcx>, + query_keys::$name<'tcx>, + ) -> query_values::$name<'tcx> + }; + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + separate_provide_extern_decl!([$($modifiers)*][$($args)*]) + }; +} + +macro_rules! separate_provide_extern_default { + ([][$name:ident]) => { + () + }; + ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => { + |_, key| bug!( + "`tcx.{}({:?})` unsupported by its crate; \ + perhaps the `{}` query was never assigned a provider function", + stringify!($name), + key, + stringify!($name), + ) + }; + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + separate_provide_extern_default!([$($modifiers)*][$($args)*]) + }; +} + macro_rules! define_callbacks { (<$tcx:tt> $($(#[$attr:meta])* @@ -214,6 +247,10 @@ macro_rules! define_callbacks { ) -> query_values::$name<'tcx>,)* } + pub struct ExternProviders { + $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)* + } + impl Default for Providers { fn default() -> Self { Providers { @@ -228,11 +265,24 @@ macro_rules! define_callbacks { } } + impl Default for ExternProviders { + fn default() -> Self { + ExternProviders { + $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)* + } + } + } + impl Copy for Providers {} impl Clone for Providers { fn clone(&self) -> Self { *self } } + impl Copy for ExternProviders {} + impl Clone for ExternProviders { + fn clone(&self) -> Self { *self } + } + pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync { fn as_any(&'tcx self) -> &'tcx dyn std::any::Any; diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index c6e753e4662..9cd36a77b70 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -19,7 +19,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::{self, DepKindStruct, SerializedDepNodeIndex}; use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values}; -use rustc_middle::ty::query::{Providers, QueryEngine}; +use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::Span; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 6282a9dcd52..81a36e0d59e 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -215,6 +215,22 @@ macro_rules! hash_result { }; } +macro_rules! get_provider { + ([][$tcx:expr, $name:ident, $key:expr]) => {{ + $tcx.queries.local_providers.$name + }}; + ([(separate_provide_extern) $($rest:tt)*][$tcx:expr, $name:ident, $key:expr]) => {{ + if $key.query_crate_is_local() { + $tcx.queries.local_providers.$name + } else { + $tcx.queries.extern_providers.$name + } + }}; + ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => { + get_provider!([$($modifiers)*][$($args)*]) + }; +} + macro_rules! define_queries { (<$tcx:tt> $($(#[$attr:meta])* @@ -310,11 +326,7 @@ macro_rules! define_queries { fn make_vtable(tcx: QueryCtxt<'tcx>, key: &Self::Key) -> QueryVtable, Self::Key, Self::Value> { - let compute = if key.query_crate_is_local() { - tcx.queries.local_providers.$name - } else { - tcx.queries.extern_providers.$name - }; + let compute = get_provider!([$($modifiers)*][tcx, $name, key]); let cache_on_disk = Self::cache_on_disk(tcx.tcx, key); QueryVtable { anon: is_anon!([$($modifiers)*]), @@ -444,7 +456,7 @@ macro_rules! define_queries_struct { input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => { pub struct Queries<$tcx> { local_providers: Box, - extern_providers: Box, + extern_providers: Box, pub on_disk_cache: Option>, @@ -457,7 +469,7 @@ macro_rules! define_queries_struct { impl<$tcx> Queries<$tcx> { pub fn new( local_providers: Providers, - extern_providers: Providers, + extern_providers: ExternProviders, on_disk_cache: Option>, ) -> Self { Queries {