mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
Rollup merge of #69475 - Zoxc:no-no-force, r=michaelwoerister
Remove the `no_force` query attribute This removes the `no_force` query attribute and instead uses the `DepNodeParams` trait to find out if a query can be forced. Also the `analysis` query is moved to the query macro. r? @eddyb
This commit is contained in:
@@ -360,33 +360,9 @@ pub fn to_dep_node(self, kind: DepKind) -> DepNode {
|
||||
[anon] TraitSelect,
|
||||
|
||||
[] CompileCodegenUnit(Symbol),
|
||||
|
||||
[eval_always] Analysis(CrateNum),
|
||||
]);
|
||||
|
||||
pub trait RecoverKey<'tcx>: Sized {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl RecoverKey<'tcx> for CrateNum {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.krate)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverKey<'tcx> for DefId {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverKey<'tcx> for DefIndex {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.index)
|
||||
}
|
||||
}
|
||||
|
||||
trait DepNodeParams<'tcx>: fmt::Debug {
|
||||
pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized {
|
||||
const CAN_RECONSTRUCT_QUERY_KEY: bool;
|
||||
|
||||
/// This method turns the parameters of a DepNodeConstructor into an opaque
|
||||
@@ -400,6 +376,14 @@ fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
|
||||
fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
/// This method tries to recover the query key from the given `DepNode`,
|
||||
/// something which is needed when forcing `DepNode`s during red-green
|
||||
/// evaluation. The query system will only call this method if
|
||||
/// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
|
||||
/// It is always valid to return `None` here, in which case incremental
|
||||
/// compilation will treat the query as having changed instead of forcing it.
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl<'tcx, T> DepNodeParams<'tcx> for T
|
||||
@@ -420,6 +404,10 @@ impl<'tcx, T> DepNodeParams<'tcx> for T
|
||||
default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
|
||||
format!("{:?}", *self)
|
||||
}
|
||||
|
||||
default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for DefId {
|
||||
@@ -432,6 +420,10 @@ fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
tcx.def_path_str(*self)
|
||||
}
|
||||
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for DefIndex {
|
||||
@@ -444,6 +436,10 @@ fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
tcx.def_path_str(DefId::local(*self))
|
||||
}
|
||||
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for CrateNum {
|
||||
@@ -457,6 +453,10 @@ fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint {
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
tcx.crate_name(*self).to_string()
|
||||
}
|
||||
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.krate)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) {
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
mod safe;
|
||||
mod serialized;
|
||||
|
||||
pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, RecoverKey, WorkProductId};
|
||||
pub(crate) use self::dep_node::DepNodeParams;
|
||||
pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, WorkProductId};
|
||||
pub use self::graph::WorkProductFileKind;
|
||||
pub use self::graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
|
||||
pub use self::prev::PreviousDepGraph;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex};
|
||||
use crate::dep_graph::SerializedDepNodeIndex;
|
||||
use crate::mir;
|
||||
use crate::mir::interpret::{GlobalId, LitToConstInput};
|
||||
use crate::traits;
|
||||
@@ -60,6 +60,11 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
|
||||
query analysis(key: CrateNum) -> Result<(), ErrorReported> {
|
||||
eval_always
|
||||
desc { "running analysis passes on this crate" }
|
||||
}
|
||||
|
||||
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
|
||||
/// associated generics.
|
||||
query generics_of(key: DefId) -> &'tcx ty::Generics {
|
||||
@@ -195,7 +200,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
// queries). Making it anonymous avoids hashing the result, which
|
||||
// may save a bit of time.
|
||||
anon
|
||||
no_force
|
||||
desc { "erasing regions from `{:?}`", ty }
|
||||
}
|
||||
|
||||
@@ -204,7 +208,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
}
|
||||
|
||||
query program_clauses_for_env(_: traits::Environment<'tcx>) -> Clauses<'tcx> {
|
||||
no_force
|
||||
desc { "generating chalk-style clauses for environment" }
|
||||
}
|
||||
|
||||
@@ -247,7 +250,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
/// To avoid cycles within the predicates of a single item we compute
|
||||
/// per-type-parameter predicates for resolving `T::AssocTy`.
|
||||
query type_param_predicates(key: (DefId, DefId)) -> ty::GenericPredicates<'tcx> {
|
||||
no_force
|
||||
desc { |tcx| "computing the bounds for type parameter `{}`", {
|
||||
let id = tcx.hir().as_local_hir_id(key.1).unwrap();
|
||||
tcx.hir().ty_param_name(id)
|
||||
@@ -503,7 +505,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
/// form to be used outside of const eval.
|
||||
query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> ConstEvalRawResult<'tcx> {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
"const-evaluating `{}`",
|
||||
tcx.def_path_str(key.value.instance.def.def_id())
|
||||
@@ -520,7 +521,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
|
||||
query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> ConstEvalResult<'tcx> {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
"const-evaluating + checking `{}`",
|
||||
tcx.def_path_str(key.value.instance.def.def_id())
|
||||
@@ -535,7 +535,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query const_field(
|
||||
key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
|
||||
) -> ConstValue<'tcx> {
|
||||
no_force
|
||||
desc { "extract field of const" }
|
||||
}
|
||||
|
||||
@@ -544,19 +543,16 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query destructure_const(
|
||||
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
|
||||
) -> mir::DestructuredConst<'tcx> {
|
||||
no_force
|
||||
desc { "destructure constant" }
|
||||
}
|
||||
|
||||
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
|
||||
no_force
|
||||
desc { "get a &core::panic::Location referring to a span" }
|
||||
}
|
||||
|
||||
query lit_to_const(
|
||||
key: LitToConstInput<'tcx>
|
||||
) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
|
||||
no_force
|
||||
desc { "converting literal to const" }
|
||||
}
|
||||
}
|
||||
@@ -587,7 +583,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
|
||||
|
||||
query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyAndCache<'tcx> {
|
||||
no_force
|
||||
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
|
||||
}
|
||||
|
||||
@@ -595,7 +590,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
/// given instance from the local crate. In particular, it will also
|
||||
/// look up the correct symbol name of instances from upstream crates.
|
||||
query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
|
||||
no_force
|
||||
desc { "computing the symbol for `{}`", key }
|
||||
cache_on_disk_if { true }
|
||||
}
|
||||
@@ -642,7 +636,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
Other {
|
||||
query vtable_methods(key: ty::PolyTraitRef<'tcx>)
|
||||
-> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
|
||||
no_force
|
||||
desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) }
|
||||
}
|
||||
}
|
||||
@@ -651,7 +644,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query codegen_fulfill_obligation(
|
||||
key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
|
||||
) -> Option<Vtable<'tcx, ()>> {
|
||||
no_force
|
||||
cache_on_disk_if { true }
|
||||
desc { |tcx|
|
||||
"checking if `{}` fulfills its obligations",
|
||||
@@ -683,22 +675,18 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
/// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
|
||||
/// `ty.is_copy()`, etc, since that will prune the environment where possible.
|
||||
query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` is `Copy`", env.value }
|
||||
}
|
||||
/// Query backing `TyS::is_sized`.
|
||||
query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` is `Sized`", env.value }
|
||||
}
|
||||
/// Query backing `TyS::is_freeze`.
|
||||
query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` is freeze", env.value }
|
||||
}
|
||||
/// Query backing `TyS::needs_drop`.
|
||||
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` needs drop", env.value }
|
||||
}
|
||||
|
||||
@@ -712,7 +700,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query layout_raw(
|
||||
env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
|
||||
) -> Result<&'tcx ty::layout::LayoutDetails, ty::layout::LayoutError<'tcx>> {
|
||||
no_force
|
||||
desc { "computing layout of `{}`", env.value }
|
||||
}
|
||||
}
|
||||
@@ -768,7 +755,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
|
||||
TypeChecking {
|
||||
query specializes(_: (DefId, DefId)) -> bool {
|
||||
no_force
|
||||
desc { "computing whether impls specialize one another" }
|
||||
}
|
||||
query in_scope_traits_map(_: DefIndex)
|
||||
@@ -853,7 +839,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
/// (like `Clone::clone` for example).
|
||||
query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option<CrateNum> {
|
||||
desc { "available upstream drop-glue for `{:?}`", substs }
|
||||
no_force
|
||||
}
|
||||
}
|
||||
|
||||
@@ -898,7 +883,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
TypeChecking {
|
||||
query implementations_of_trait(_: (CrateNum, DefId))
|
||||
-> &'tcx [DefId] {
|
||||
no_force
|
||||
desc { "looking up implementations of a trait in a crate" }
|
||||
}
|
||||
query all_trait_implementations(_: CrateNum)
|
||||
@@ -1065,7 +1049,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
}
|
||||
query is_codegened_item(_: DefId) -> bool {}
|
||||
query codegen_unit(_: Symbol) -> Arc<CodegenUnit<'tcx>> {
|
||||
no_force
|
||||
desc { "codegen_unit" }
|
||||
}
|
||||
query backend_optimization_level(_: CrateNum) -> OptLevel {
|
||||
@@ -1088,7 +1071,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1096,7 +1078,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query normalize_ty_after_erasing_regions(
|
||||
goal: ParamEnvAnd<'tcx, Ty<'tcx>>
|
||||
) -> Ty<'tcx> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1106,7 +1087,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "computing implied outlives bounds for `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1117,7 +1097,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "computing dropck types for `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1126,7 +1105,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query evaluate_obligation(
|
||||
goal: CanonicalPredicateGoal<'tcx>
|
||||
) -> Result<traits::EvaluationResult, traits::OverflowError> {
|
||||
no_force
|
||||
desc { "evaluating trait selection obligation `{}`", goal.value.value }
|
||||
}
|
||||
|
||||
@@ -1137,7 +1115,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1148,7 +1125,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_eq` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1159,7 +1135,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_subtype` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1170,7 +1145,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_prove_predicate` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1181,7 +1155,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1192,7 +1165,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1203,7 +1175,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@@ -1214,12 +1185,10 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
"testing substituted normalized predicates:`{}`",
|
||||
tcx.def_path_str(key.0)
|
||||
@@ -1229,7 +1198,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
query method_autoderef_steps(
|
||||
goal: CanonicalTyGoal<'tcx>
|
||||
) -> MethodAutoderefStepsResult<'tcx> {
|
||||
no_force
|
||||
desc { "computing autoderef types for `{:?}`", goal }
|
||||
}
|
||||
}
|
||||
@@ -1243,7 +1211,6 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
|
||||
// Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
|
||||
query instance_def_size_estimate(def: ty::InstanceDef<'tcx>)
|
||||
-> usize {
|
||||
no_force
|
||||
desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
use crate::dep_graph::{DepKind, DepNode};
|
||||
use crate::ty::query::caches::QueryCache;
|
||||
use crate::ty::query::plumbing::CycleError;
|
||||
use crate::ty::query::queries;
|
||||
use crate::ty::query::{Query, QueryState};
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_data_structures::profiling::ProfileCategory;
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
||||
use crate::ich::StableHashingContext;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
@@ -87,9 +86,3 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M
|
||||
bug!("QueryDescription::load_from_disk() called for an unsupported query.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
|
||||
fn describe(_tcx: TyCtxt<'_>, _: CrateNum) -> Cow<'static, str> {
|
||||
"running analysis passes on this crate".into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::dep_graph::{self, DepConstructor, DepNode};
|
||||
use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams};
|
||||
use crate::hir::exports::Export;
|
||||
use crate::infer::canonical::{self, Canonical};
|
||||
use crate::lint::LintLevelMap;
|
||||
@@ -60,8 +60,8 @@
|
||||
|
||||
#[macro_use]
|
||||
mod plumbing;
|
||||
pub use self::plumbing::CycleError;
|
||||
use self::plumbing::*;
|
||||
pub use self::plumbing::{force_from_dep_node, CycleError};
|
||||
|
||||
mod stats;
|
||||
pub use self::stats::print_stats;
|
||||
@@ -104,9 +104,105 @@
|
||||
// Queries marked with `fatal_cycle` do not need the latter implementation,
|
||||
// as they will raise an fatal error on query cycles instead.
|
||||
|
||||
rustc_query_append! { [define_queries!][ <'tcx>
|
||||
Other {
|
||||
/// Runs analysis passes on the crate.
|
||||
[eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
|
||||
},
|
||||
]}
|
||||
rustc_query_append! { [define_queries!][<'tcx>] }
|
||||
|
||||
/// The red/green evaluation system will try to mark a specific DepNode in the
|
||||
/// dependency graph as green by recursively trying to mark the dependencies of
|
||||
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
|
||||
/// where we don't know if it is red or green and we therefore actually have
|
||||
/// to recompute its value in order to find out. Since the only piece of
|
||||
/// information that we have at that point is the `DepNode` we are trying to
|
||||
/// re-evaluate, we need some way to re-run a query from just that. This is what
|
||||
/// `force_from_dep_node()` implements.
|
||||
///
|
||||
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
|
||||
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
|
||||
/// is usually constructed by computing a stable hash of the query-key that the
|
||||
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
|
||||
/// back from hash to query-key (since hash functions are not reversible). For
|
||||
/// this reason `force_from_dep_node()` is expected to fail from time to time
|
||||
/// because we just cannot find out, from the `DepNode` alone, what the
|
||||
/// corresponding query-key is and therefore cannot re-run the query.
|
||||
///
|
||||
/// The system deals with this case letting `try_mark_green` fail which forces
|
||||
/// the root query to be re-evaluated.
|
||||
///
|
||||
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
|
||||
/// Fortunately, we can use some contextual information that will allow us to
|
||||
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
|
||||
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
|
||||
/// valid `DefPathHash`. Since we also always build a huge table that maps every
|
||||
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
|
||||
/// everything we need to re-run the query.
|
||||
///
|
||||
/// Take the `mir_validated` query as an example. Like many other queries, it
|
||||
/// just has a single parameter: the `DefId` of the item it will compute the
|
||||
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
|
||||
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
|
||||
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
|
||||
/// `DefId` in `tcx.def_path_hash_to_def_id`.
|
||||
///
|
||||
/// When you implement a new query, it will likely have a corresponding new
|
||||
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
|
||||
/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
|
||||
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
|
||||
/// add it to the "We don't have enough information to reconstruct..." group in
|
||||
/// the match below.
|
||||
pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
|
||||
use crate::dep_graph::DepKind;
|
||||
|
||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||
// `DepNode::codegen_unit`:
|
||||
// Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
|
||||
// would always end up having to evaluate the first caller of the
|
||||
// `codegen_unit` query that *is* reconstructible. This might very well be
|
||||
// the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
|
||||
// to re-trigger calling the `codegen_unit` query with the right key. At
|
||||
// that point we would already have re-done all the work we are trying to
|
||||
// avoid doing in the first place.
|
||||
// The solution is simple: Just explicitly call the `codegen_unit` query for
|
||||
// each CGU, right after partitioning. This way `try_mark_green` will always
|
||||
// hit the cache instead of having to go through `force_from_dep_node`.
|
||||
// This assertion makes sure, we actually keep applying the solution above.
|
||||
debug_assert!(
|
||||
dep_node.kind != DepKind::codegen_unit,
|
||||
"calling force_from_dep_node() on DepKind::codegen_unit"
|
||||
);
|
||||
|
||||
if !dep_node.kind.can_reconstruct_query_key() {
|
||||
return false;
|
||||
}
|
||||
|
||||
rustc_dep_node_force!([dep_node, tcx]
|
||||
// These are inputs that are expected to be pre-allocated and that
|
||||
// should therefore always be red or green already.
|
||||
DepKind::AllLocalTraitImpls |
|
||||
DepKind::CrateMetadata |
|
||||
DepKind::HirBody |
|
||||
DepKind::Hir |
|
||||
|
||||
// These are anonymous nodes.
|
||||
DepKind::TraitSelect |
|
||||
|
||||
// We don't have enough information to reconstruct the query key of
|
||||
// these.
|
||||
DepKind::CompileCodegenUnit => {
|
||||
bug!("force_from_dep_node: encountered {:?}", dep_node)
|
||||
}
|
||||
);
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
impl DepNode {
|
||||
/// Check whether the query invocation corresponding to the given
|
||||
/// DepNode is eligible for on-disk-caching. If so, this is method
|
||||
/// will execute the query corresponding to the given DepNode.
|
||||
/// Also, as a sanity check, it expects that the corresponding query
|
||||
/// invocation has been marked as green already.
|
||||
pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) {
|
||||
use crate::dep_graph::DepKind;
|
||||
|
||||
rustc_dep_node_try_load_from_on_disk_cache!(self, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! generate the actual methods on tcx which find and execute the provider,
|
||||
//! manage the caches, and so forth.
|
||||
|
||||
use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
|
||||
use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
|
||||
use crate::ty::query::caches::QueryCache;
|
||||
use crate::ty::query::config::{QueryAccessors, QueryDescription};
|
||||
use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId};
|
||||
@@ -720,7 +720,7 @@ pub(super) fn ensure_query<Q: QueryDescription<'tcx> + 'tcx>(self, key: Q::Key)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
|
||||
pub(super) fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
|
||||
self,
|
||||
key: Q::Key,
|
||||
span: Span,
|
||||
@@ -1162,105 +1162,3 @@ fn default() -> Self {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// The red/green evaluation system will try to mark a specific DepNode in the
|
||||
/// dependency graph as green by recursively trying to mark the dependencies of
|
||||
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
|
||||
/// where we don't know if it is red or green and we therefore actually have
|
||||
/// to recompute its value in order to find out. Since the only piece of
|
||||
/// information that we have at that point is the `DepNode` we are trying to
|
||||
/// re-evaluate, we need some way to re-run a query from just that. This is what
|
||||
/// `force_from_dep_node()` implements.
|
||||
///
|
||||
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
|
||||
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
|
||||
/// is usually constructed by computing a stable hash of the query-key that the
|
||||
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
|
||||
/// back from hash to query-key (since hash functions are not reversible). For
|
||||
/// this reason `force_from_dep_node()` is expected to fail from time to time
|
||||
/// because we just cannot find out, from the `DepNode` alone, what the
|
||||
/// corresponding query-key is and therefore cannot re-run the query.
|
||||
///
|
||||
/// The system deals with this case letting `try_mark_green` fail which forces
|
||||
/// the root query to be re-evaluated.
|
||||
///
|
||||
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
|
||||
/// Fortunately, we can use some contextual information that will allow us to
|
||||
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
|
||||
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
|
||||
/// valid `DefPathHash`. Since we also always build a huge table that maps every
|
||||
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
|
||||
/// everything we need to re-run the query.
|
||||
///
|
||||
/// Take the `mir_validated` query as an example. Like many other queries, it
|
||||
/// just has a single parameter: the `DefId` of the item it will compute the
|
||||
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
|
||||
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
|
||||
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
|
||||
/// `DefId` in `tcx.def_path_hash_to_def_id`.
|
||||
///
|
||||
/// When you implement a new query, it will likely have a corresponding new
|
||||
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
|
||||
/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
|
||||
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
|
||||
/// add it to the "We don't have enough information to reconstruct..." group in
|
||||
/// the match below.
|
||||
pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
|
||||
use crate::dep_graph::RecoverKey;
|
||||
|
||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||
// `DepNode::codegen_unit`:
|
||||
// Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
|
||||
// would always end up having to evaluate the first caller of the
|
||||
// `codegen_unit` query that *is* reconstructible. This might very well be
|
||||
// the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
|
||||
// to re-trigger calling the `codegen_unit` query with the right key. At
|
||||
// that point we would already have re-done all the work we are trying to
|
||||
// avoid doing in the first place.
|
||||
// The solution is simple: Just explicitly call the `codegen_unit` query for
|
||||
// each CGU, right after partitioning. This way `try_mark_green` will always
|
||||
// hit the cache instead of having to go through `force_from_dep_node`.
|
||||
// This assertion makes sure, we actually keep applying the solution above.
|
||||
debug_assert!(
|
||||
dep_node.kind != DepKind::codegen_unit,
|
||||
"calling force_from_dep_node() on DepKind::codegen_unit"
|
||||
);
|
||||
|
||||
if !dep_node.kind.can_reconstruct_query_key() {
|
||||
return false;
|
||||
}
|
||||
|
||||
rustc_dep_node_force!([dep_node, tcx]
|
||||
// These are inputs that are expected to be pre-allocated and that
|
||||
// should therefore always be red or green already.
|
||||
DepKind::AllLocalTraitImpls |
|
||||
DepKind::CrateMetadata |
|
||||
DepKind::HirBody |
|
||||
DepKind::Hir |
|
||||
|
||||
// These are anonymous nodes.
|
||||
DepKind::TraitSelect |
|
||||
|
||||
// We don't have enough information to reconstruct the query key of
|
||||
// these.
|
||||
DepKind::CompileCodegenUnit => {
|
||||
bug!("force_from_dep_node: encountered {:?}", dep_node)
|
||||
}
|
||||
|
||||
DepKind::Analysis => {
|
||||
let def_id = if let Some(def_id) = dep_node.extract_def_id(tcx) {
|
||||
def_id
|
||||
} else {
|
||||
// Return from the whole function.
|
||||
return false
|
||||
};
|
||||
tcx.force_query::<crate::ty::query::queries::analysis<'_>>(
|
||||
def_id.krate,
|
||||
DUMMY_SP,
|
||||
*dep_node
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
@@ -51,9 +51,6 @@ enum QueryModifier {
|
||||
/// Don't hash the result, instead just mark a query red if it runs
|
||||
NoHash,
|
||||
|
||||
/// Don't force the query
|
||||
NoForce,
|
||||
|
||||
/// Generate a dep node based on the dependencies of the query
|
||||
Anon,
|
||||
|
||||
@@ -118,8 +115,6 @@ fn parse(input: ParseStream<'_>) -> Result<Self> {
|
||||
Ok(QueryModifier::CycleDelayBug)
|
||||
} else if modifier == "no_hash" {
|
||||
Ok(QueryModifier::NoHash)
|
||||
} else if modifier == "no_force" {
|
||||
Ok(QueryModifier::NoForce)
|
||||
} else if modifier == "anon" {
|
||||
Ok(QueryModifier::Anon)
|
||||
} else if modifier == "eval_always" {
|
||||
@@ -222,9 +217,6 @@ struct QueryModifiers {
|
||||
/// Don't hash the result, instead just mark a query red if it runs
|
||||
no_hash: bool,
|
||||
|
||||
/// Don't force the query
|
||||
no_force: bool,
|
||||
|
||||
/// Generate a dep node based on the dependencies of the query
|
||||
anon: bool,
|
||||
|
||||
@@ -241,7 +233,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||
let mut fatal_cycle = false;
|
||||
let mut cycle_delay_bug = false;
|
||||
let mut no_hash = false;
|
||||
let mut no_force = false;
|
||||
let mut anon = false;
|
||||
let mut eval_always = false;
|
||||
for modifier in query.modifiers.0.drain(..) {
|
||||
@@ -288,12 +279,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||
}
|
||||
no_hash = true;
|
||||
}
|
||||
QueryModifier::NoForce => {
|
||||
if no_force {
|
||||
panic!("duplicate modifier `no_force` for query `{}`", query.name);
|
||||
}
|
||||
no_force = true;
|
||||
}
|
||||
QueryModifier::Anon => {
|
||||
if anon {
|
||||
panic!("duplicate modifier `anon` for query `{}`", query.name);
|
||||
@@ -316,7 +301,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||
fatal_cycle,
|
||||
cycle_delay_bug,
|
||||
no_hash,
|
||||
no_force,
|
||||
anon,
|
||||
eval_always,
|
||||
}
|
||||
@@ -425,7 +409,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
let mut dep_node_def_stream = quote! {};
|
||||
let mut dep_node_force_stream = quote! {};
|
||||
let mut try_load_from_on_disk_cache_stream = quote! {};
|
||||
let mut no_force_queries = Vec::new();
|
||||
let mut cached_queries = quote! {};
|
||||
|
||||
for group in groups.0 {
|
||||
@@ -444,19 +427,19 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
cached_queries.extend(quote! {
|
||||
#name,
|
||||
});
|
||||
}
|
||||
|
||||
if modifiers.cache.is_some() && !modifiers.no_force {
|
||||
try_load_from_on_disk_cache_stream.extend(quote! {
|
||||
DepKind::#name => {
|
||||
debug_assert!(tcx.dep_graph
|
||||
.node_color(self)
|
||||
.map(|c| c.is_green())
|
||||
.unwrap_or(false));
|
||||
if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
|
||||
debug_assert!($tcx.dep_graph
|
||||
.node_color($dep_node)
|
||||
.map(|c| c.is_green())
|
||||
.unwrap_or(false));
|
||||
|
||||
let key = RecoverKey::recover(tcx, self).unwrap();
|
||||
if queries::#name::cache_on_disk(tcx, key, None) {
|
||||
let _ = tcx.#name(key);
|
||||
let key = <#arg as DepNodeParams>::recover($tcx, $dep_node).unwrap();
|
||||
if queries::#name::cache_on_disk($tcx, key, None) {
|
||||
let _ = $tcx.#name(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -501,24 +484,21 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
[#attribute_stream] #name(#arg),
|
||||
});
|
||||
|
||||
if modifiers.no_force {
|
||||
no_force_queries.push(name.clone());
|
||||
} else {
|
||||
// Add a match arm to force the query given the dep node
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::#name => {
|
||||
if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
|
||||
// Add a match arm to force the query given the dep node
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::#name => {
|
||||
if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
|
||||
if let Some(key) = <#arg as DepNodeParams>::recover($tcx, $dep_node) {
|
||||
$tcx.force_query::<crate::ty::query::queries::#name<'_>>(
|
||||
key,
|
||||
DUMMY_SP,
|
||||
*$dep_node
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_query_description_impl(&query, modifiers, &mut query_description_stream);
|
||||
}
|
||||
@@ -528,12 +508,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
});
|
||||
}
|
||||
|
||||
// Add an arm for the no force queries to panic when trying to force them
|
||||
for query in no_force_queries {
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::#query |
|
||||
});
|
||||
}
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::Null => {
|
||||
bug!("Cannot force dep node: {:?}", $dep_node)
|
||||
@@ -577,14 +551,9 @@ macro_rules! rustc_cached_queries {
|
||||
|
||||
#query_description_stream
|
||||
|
||||
impl DepNode {
|
||||
/// Check whether the query invocation corresponding to the given
|
||||
/// DepNode is eligible for on-disk-caching. If so, this is method
|
||||
/// will execute the query corresponding to the given DepNode.
|
||||
/// Also, as a sanity check, it expects that the corresponding query
|
||||
/// invocation has been marked as green already.
|
||||
pub fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) {
|
||||
match self.kind {
|
||||
macro_rules! rustc_dep_node_try_load_from_on_disk_cache {
|
||||
($dep_node:expr, $tcx:expr) => {
|
||||
match $dep_node.kind {
|
||||
#try_load_from_on_disk_cache_stream
|
||||
_ => (),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user