From 0a4d948b4a8c69de0e3fdb231fdb14097849f6ce Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 7 Jun 2020 18:45:10 +0200 Subject: [PATCH 01/18] Remove unused ProfileCategory. --- compiler/rustc_data_structures/src/profiling.rs | 11 ----------- compiler/rustc_middle/src/ty/query/mod.rs | 1 - compiler/rustc_middle/src/ty/query/plumbing.rs | 2 -- compiler/rustc_query_system/src/query/config.rs | 2 -- 4 files changed, 16 deletions(-) diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 363879cbb1d19..0ae3c75fcc2cb 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -111,17 +111,6 @@ cfg_if! { type Profiler = measureme::Profiler; -#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)] -pub enum ProfileCategory { - Parsing, - Expansion, - TypeChecking, - BorrowChecking, - Codegen, - Linking, - Other, -} - bitflags::bitflags! { struct EventFilter: u32 { const GENERIC_ACTIVITIES = 1 << 0; diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index d3a7412ef14e7..0becd7326b19c 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -34,7 +34,6 @@ use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_data_structures::profiling::ProfileCategory::*; use rustc_data_structures::stable_hasher::StableVec; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; diff --git a/compiler/rustc_middle/src/ty/query/plumbing.rs b/compiler/rustc_middle/src/ty/query/plumbing.rs index 1a8aacc486986..df79c4c9601d9 100644 --- a/compiler/rustc_middle/src/ty/query/plumbing.rs +++ b/compiler/rustc_middle/src/ty/query/plumbing.rs @@ -268,7 +268,6 @@ macro_rules! define_queries_inner { rustc_data_structures::stable_hasher::StableHasher, ich::StableHashingContext }; - use rustc_data_structures::profiling::ProfileCategory; define_queries_struct! { tcx: $tcx, @@ -362,7 +361,6 @@ macro_rules! define_queries_inner { as QueryStorage >::Stored; const NAME: &'static str = stringify!($name); - const CATEGORY: ProfileCategory = $category; } impl<$tcx> QueryAccessors> for queries::$name<$tcx> { diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 6c9849e8708b7..0f0684b354791 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -5,7 +5,6 @@ use crate::dep_graph::SerializedDepNodeIndex; use crate::query::caches::QueryCache; use crate::query::plumbing::CycleError; use crate::query::{QueryContext, QueryState}; -use rustc_data_structures::profiling::ProfileCategory; use rustc_data_structures::fingerprint::Fingerprint; use std::borrow::Cow; @@ -14,7 +13,6 @@ use std::hash::Hash; pub trait QueryConfig { const NAME: &'static str; - const CATEGORY: ProfileCategory; type Key: Eq + Hash + Clone + Debug; type Value; From de763701e19945866b540c8c0b105b78d83917ce Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 11 Oct 2020 20:44:24 +0200 Subject: [PATCH 02/18] Remove unused category from macros. --- compiler/rustc_macros/src/query.rs | 11 +++++------ compiler/rustc_middle/src/ty/query/plumbing.rs | 14 ++------------ compiler/rustc_middle/src/ty/query/stats.rs | 8 ++++---- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index e7c054653accb..df569566f76d5 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -190,7 +190,11 @@ impl Parse for List { } /// A named group containing queries. +/// +/// For now, the name is not used any more, but the capability remains interesting for future +/// developments of the query system. struct Group { + #[allow(unused)] name: Ident, queries: List, } @@ -422,7 +426,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let mut cached_queries = quote! {}; for group in groups.0 { - let mut group_stream = quote! {}; for mut query in group.queries.0 { let modifiers = process_modifiers(&mut query); let name = &query.name; @@ -485,7 +488,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let attribute_stream = quote! {#(#attributes),*}; let doc_comments = query.doc_comments.iter(); // Add the query to the group - group_stream.extend(quote! { + query_stream.extend(quote! { #(#doc_comments)* [#attribute_stream] fn #name: #name(#arg) #result, }); @@ -514,10 +517,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { add_query_description_impl(&query, modifiers, &mut query_description_stream); } - let name = &group.name; - query_stream.extend(quote! { - #name { #group_stream }, - }); } dep_node_force_stream.extend(quote! { diff --git a/compiler/rustc_middle/src/ty/query/plumbing.rs b/compiler/rustc_middle/src/ty/query/plumbing.rs index df79c4c9601d9..7c8e7cd0182d0 100644 --- a/compiler/rustc_middle/src/ty/query/plumbing.rs +++ b/compiler/rustc_middle/src/ty/query/plumbing.rs @@ -242,24 +242,14 @@ macro_rules! hash_result { }; } -macro_rules! define_queries { - (<$tcx:tt> $($category:tt { - $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($($K:tt)*) -> $V:ty,)* - },)*) => { - define_queries_inner! { <$tcx> - $($( $(#[$attr])* category<$category> [$($modifiers)*] fn $name: $node($($K)*) -> $V,)*)* - } - } -} - macro_rules! query_helper_param_ty { (DefId) => { impl IntoQueryParam }; ($K:ty) => { $K }; } -macro_rules! define_queries_inner { +macro_rules! define_queries { (<$tcx:tt> - $($(#[$attr:meta])* category<$category:tt> + $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($($K:tt)*) -> $V:ty,)*) => { use std::mem; diff --git a/compiler/rustc_middle/src/ty/query/stats.rs b/compiler/rustc_middle/src/ty/query/stats.rs index 877f88d380a39..f6df83c912394 100644 --- a/compiler/rustc_middle/src/ty/query/stats.rs +++ b/compiler/rustc_middle/src/ty/query/stats.rs @@ -120,13 +120,13 @@ pub fn print_stats(tcx: TyCtxt<'_>) { } macro_rules! print_stats { - (<$tcx:tt> $($category:tt { + (<$tcx:tt> $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)* - },)*) => { + ) => { fn query_stats(tcx: TyCtxt<'_>) -> Vec { let mut queries = Vec::new(); - $($( + $( queries.push(stats::< crate::dep_graph::DepKind, as QueryContext>::Query, @@ -135,7 +135,7 @@ macro_rules! print_stats { stringify!($name), &tcx.queries.$name, )); - )*)* + )* queries } From de7da7fd3db58e5f58f82635c794bb8bdf9b269f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 11 Oct 2020 20:46:46 +0200 Subject: [PATCH 03/18] Unify query name and node name. --- compiler/rustc_macros/src/query.rs | 2 +- compiler/rustc_middle/src/ty/query/plumbing.rs | 4 ++-- compiler/rustc_middle/src/ty/query/stats.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index df569566f76d5..21e7655dcd84e 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -490,7 +490,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { // Add the query to the group query_stream.extend(quote! { #(#doc_comments)* - [#attribute_stream] fn #name: #name(#arg) #result, + [#attribute_stream] fn #name(#arg) #result, }); // Create a dep node for the query diff --git a/compiler/rustc_middle/src/ty/query/plumbing.rs b/compiler/rustc_middle/src/ty/query/plumbing.rs index 7c8e7cd0182d0..d038695283c10 100644 --- a/compiler/rustc_middle/src/ty/query/plumbing.rs +++ b/compiler/rustc_middle/src/ty/query/plumbing.rs @@ -250,7 +250,7 @@ macro_rules! query_helper_param_ty { macro_rules! define_queries { (<$tcx:tt> $($(#[$attr:meta])* - [$($modifiers:tt)*] fn $name:ident: $node:ident($($K:tt)*) -> $V:ty,)*) => { + [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => { use std::mem; use crate::{ @@ -356,7 +356,7 @@ macro_rules! define_queries { impl<$tcx> QueryAccessors> for queries::$name<$tcx> { const ANON: bool = is_anon!([$($modifiers)*]); const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); - const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$node; + const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$name; type Cache = query_storage!([$($modifiers)*][$($K)*, $V]); diff --git a/compiler/rustc_middle/src/ty/query/stats.rs b/compiler/rustc_middle/src/ty/query/stats.rs index f6df83c912394..e0b44ce23c912 100644 --- a/compiler/rustc_middle/src/ty/query/stats.rs +++ b/compiler/rustc_middle/src/ty/query/stats.rs @@ -121,7 +121,7 @@ pub fn print_stats(tcx: TyCtxt<'_>) { macro_rules! print_stats { (<$tcx:tt> - $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)* + $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty,)* ) => { fn query_stats(tcx: TyCtxt<'_>) -> Vec { let mut queries = Vec::new(); From e853cc0b2886cf01942df71f524025af1c94f812 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 11 Oct 2020 20:58:31 +0200 Subject: [PATCH 04/18] Retire rustc_dep_node_force. --- compiler/rustc_macros/src/query.rs | 33 --------------- compiler/rustc_middle/src/ty/query/mod.rs | 49 +++++++++++++++++------ 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 21e7655dcd84e..3b27b68b8549c 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -421,7 +421,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let mut query_stream = quote! {}; let mut query_description_stream = quote! {}; 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 cached_queries = quote! {}; @@ -498,33 +497,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { [#attribute_stream] #name(#arg), }); - // Add a match arm to force the query given the dep node - dep_node_force_stream.extend(quote! { - ::rustc_middle::dep_graph::DepKind::#name => { - if <#arg as DepNodeParams>>::can_reconstruct_query_key() { - if let Some(key) = <#arg as DepNodeParams>>::recover($tcx, $dep_node) { - force_query::, _>( - $tcx, - key, - DUMMY_SP, - *$dep_node - ); - return true; - } - } - } - }); - add_query_description_impl(&query, modifiers, &mut query_description_stream); } } - dep_node_force_stream.extend(quote! { - ::rustc_middle::dep_graph::DepKind::Null => { - bug!("Cannot force dep node: {:?}", $dep_node) - } - }); - TokenStream::from(quote! { macro_rules! rustc_query_append { ([$($macro:tt)*][$($other:tt)*]) => { @@ -545,15 +521,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { ); } } - macro_rules! rustc_dep_node_force { - ([$dep_node:expr, $tcx:expr] $($other:tt)*) => { - match $dep_node.kind { - $($other)* - - #dep_node_force_stream - } - } - } macro_rules! rustc_cached_queries { ($($macro:tt)*) => { $($macro)*(#cached_queries); diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 0becd7326b19c..858a7c8b8a05c 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -168,20 +168,43 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool 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::CrateMetadata | - - // 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) + macro_rules! force_from_dep_node { + ($($(#[$attr:meta])* [$($modifiers:tt)*] $name:ident($K:ty),)*) => { + match dep_node.kind { + // These are inputs that are expected to be pre-allocated and that + // should therefore always be red or green already. + DepKind::CrateMetadata | + + // These are anonymous nodes. + DepKind::TraitSelect | + + // We don't have enough information to reconstruct the query key of + // these. + DepKind::CompileCodegenUnit | + + // Forcing this makes no sense. + DepKind::Null => { + bug!("force_from_dep_node: encountered {:?}", dep_node) + } + + $(DepKind::$name => { + debug_assert!(<$K as DepNodeParams>>::can_reconstruct_query_key()); + + if let Some(key) = <$K as DepNodeParams>>::recover(tcx, dep_node) { + force_query::, _>( + tcx, + key, + DUMMY_SP, + *dep_node + ); + return true; + } + })* + } } - ); + } + + rustc_dep_node_append! { [force_from_dep_node!][] } false } From 57ba8edb9eb7a805f63ab425fb5b1b7baa2e9fb3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 11 Oct 2020 21:18:59 +0200 Subject: [PATCH 05/18] Retire rustc_dep_node_try_load_from_on_disk_cache. --- compiler/rustc_macros/src/query.rs | 26 ----------------------- compiler/rustc_middle/src/ty/query/mod.rs | 24 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 3b27b68b8549c..fd85919636949 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -421,7 +421,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let mut query_stream = quote! {}; let mut query_description_stream = quote! {}; let mut dep_node_def_stream = quote! {}; - let mut try_load_from_on_disk_cache_stream = quote! {}; let mut cached_queries = quote! {}; for group in groups.0 { @@ -439,22 +438,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { cached_queries.extend(quote! { #name, }); - - try_load_from_on_disk_cache_stream.extend(quote! { - ::rustc_middle::dep_graph::DepKind::#name => { - 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 = <#arg as DepNodeParams>>::recover($tcx, $dep_node).unwrap(); - if queries::#name::cache_on_disk($tcx, &key, None) { - let _ = $tcx.#name(key); - } - } - } - }); } let mut attributes = Vec::new(); @@ -528,14 +511,5 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { } #query_description_stream - - 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 - _ => (), - } - } - } }) } diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 858a7c8b8a05c..7ba4d5a14dffb 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -210,7 +210,29 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool } pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) { - rustc_dep_node_try_load_from_on_disk_cache!(dep_node, tcx) + macro_rules! try_load_from_on_disk_cache { + ($($name:ident,)*) => { + match dep_node.kind { + $(DepKind::$name => { + if 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 = as DepNodeParams>>::recover(tcx, dep_node).unwrap(); + if queries::$name::cache_on_disk(tcx, &key, None) { + let _ = tcx.$name(key); + } + } + })* + + _ => (), + } + } + } + + rustc_cached_queries!(try_load_from_on_disk_cache!); } mod sealed { From 276d0e3cc5494257184061d17a7852f5efce94e5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 23 Oct 2020 23:25:23 +0200 Subject: [PATCH 06/18] Implement DepKind through unit structs. --- .../rustc_middle/src/dep_graph/dep_node.rs | 90 +++++++++++-------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index a61b9af9bace4..9585d2f759917 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -110,6 +110,56 @@ macro_rules! define_dep_nodes { $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* ,)* ) => ( + pub mod dep_kind { + use super::*; + + $( + #[allow(non_camel_case_types)] + pub struct $variant; + + impl $variant { + #[inline] + #[allow(unreachable_code)] + #[allow(unused_lifetimes)] // inside `tuple_arg_ty` + pub fn can_reconstruct_query_key<$tcx>(&self) -> bool { + if contains_anon_attr!($($attrs)*) { + return false; + } + + // tuple args + $({ + return <$tuple_arg_ty as DepNodeParams>> + ::can_reconstruct_query_key(); + })* + + true + } + + #[inline] + pub fn is_anon(&self) -> bool { + contains_anon_attr!($($attrs)*) + } + + #[inline] + pub fn is_eval_always(&self) -> bool { + contains_eval_always_attr!($($attrs)*) + } + + #[inline] + #[allow(unreachable_code)] + pub fn has_params(&self) -> bool { + // tuple args + $({ + erase!($tuple_arg_ty); + return true; + })* + + false + } + } + )* + } + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[allow(non_camel_case_types)] pub enum DepKind { @@ -117,57 +167,27 @@ macro_rules! define_dep_nodes { } impl DepKind { - #[allow(unreachable_code)] - pub fn can_reconstruct_query_key<$tcx>(&self) -> bool { + pub fn can_reconstruct_query_key(&self) -> bool { match *self { - $( - DepKind :: $variant => { - if contains_anon_attr!($($attrs)*) { - return false; - } - - // tuple args - $({ - return <$tuple_arg_ty as DepNodeParams>> - ::can_reconstruct_query_key(); - })* - - true - } - )* + $(DepKind::$variant => dep_kind::$variant.can_reconstruct_query_key()),* } } pub fn is_anon(&self) -> bool { match *self { - $( - DepKind :: $variant => { contains_anon_attr!($($attrs)*) } - )* + $(DepKind::$variant => dep_kind::$variant.is_anon()),* } } pub fn is_eval_always(&self) -> bool { match *self { - $( - DepKind :: $variant => { contains_eval_always_attr!($($attrs)*) } - )* + $(DepKind::$variant => dep_kind::$variant.is_eval_always()),* } } - #[allow(unreachable_code)] pub fn has_params(&self) -> bool { match *self { - $( - DepKind :: $variant => { - // tuple args - $({ - erase!($tuple_arg_ty); - return true; - })* - - false - } - )* + $(DepKind::$variant => dep_kind::$variant.has_params()),* } } } From dd9ce3eeddcc138fe339f1f823f697446f5f8a9a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 23 Oct 2020 23:54:36 +0200 Subject: [PATCH 07/18] Same for query loading. --- compiler/rustc_middle/src/dep_graph/mod.rs | 2 +- compiler/rustc_middle/src/ty/query/mod.rs | 58 ++++++++++++++-------- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 6697524279874..338a9624fdae1 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -15,7 +15,7 @@ pub use rustc_query_system::dep_graph::{ WorkProduct, WorkProductId, }; -pub use dep_node::{label_strs, DepConstructor, DepKind, DepNode, DepNodeExt}; +pub use dep_node::{dep_kind, label_strs, DepConstructor, DepKind, DepNode, DepNodeExt}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 7ba4d5a14dffb..4f30a591308a7 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -164,12 +164,32 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool "calling force_from_dep_node() on DepKind::codegen_unit" ); - if !dep_node.kind.can_reconstruct_query_key() { - return false; - } - macro_rules! force_from_dep_node { ($($(#[$attr:meta])* [$($modifiers:tt)*] $name:ident($K:ty),)*) => { + use rustc_middle::dep_graph::dep_kind; + + $(impl dep_kind::$name { + fn force_from_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool { + if !self.can_reconstruct_query_key() { + return false; + } + + debug_assert!(<$K as DepNodeParams>>::can_reconstruct_query_key()); + + if let Some(key) = <$K as DepNodeParams>>::recover(tcx, dep_node) { + force_query::, _>( + tcx, + key, + DUMMY_SP, + *dep_node + ); + return true; + } + + false + } + })* + match dep_node.kind { // These are inputs that are expected to be pre-allocated and that // should therefore always be red or green already. @@ -184,22 +204,14 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool // Forcing this makes no sense. DepKind::Null => { + if !dep_node.kind.can_reconstruct_query_key() { + return false; + } + bug!("force_from_dep_node: encountered {:?}", dep_node) } - $(DepKind::$name => { - debug_assert!(<$K as DepNodeParams>>::can_reconstruct_query_key()); - - if let Some(key) = <$K as DepNodeParams>>::recover(tcx, dep_node) { - force_query::, _>( - tcx, - key, - DUMMY_SP, - *dep_node - ); - return true; - } - })* + $(DepKind::$name => dep_kind::$name.force_from_dep_node(tcx, dep_node)),* } } } @@ -212,8 +224,10 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) { macro_rules! try_load_from_on_disk_cache { ($($name:ident,)*) => { - match dep_node.kind { - $(DepKind::$name => { + use rustc_middle::dep_graph::dep_kind; + + $(impl dep_kind::$name { + fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) { if as DepNodeParams>>::can_reconstruct_query_key() { debug_assert!(tcx.dep_graph .node_color(dep_node) @@ -225,7 +239,11 @@ pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &De let _ = tcx.$name(key); } } - })* + } + })* + + match dep_node.kind { + $(DepKind::$name => dep_kind::$name.try_load_from_on_disk_cache(tcx, dep_node),)* _ => (), } From 9249a52b0df2ec142a9ddb037f5b961897980a2c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 01:48:59 +0200 Subject: [PATCH 08/18] Make DepKind into a trait object. --- .../rustc_incremental/src/assert_dep_graph.rs | 4 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 2 +- .../rustc_middle/src/dep_graph/dep_node.rs | 410 ++++++++++++++---- compiler/rustc_middle/src/dep_graph/mod.rs | 23 +- compiler/rustc_middle/src/ty/query/mod.rs | 90 +--- .../rustc_middle/src/ty/query/plumbing.rs | 2 +- .../rustc_query_system/src/dep_graph/mod.rs | 2 +- .../src/traits/select/mod.rs | 4 +- 8 files changed, 351 insertions(+), 186 deletions(-) diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index e17396422f13f..9430446c12d02 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -41,7 +41,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_middle::dep_graph::debug::{DepNodeFilter, EdgeFilter}; -use rustc_middle::dep_graph::{DepGraphQuery, DepKind, DepNode, DepNodeExt}; +use rustc_middle::dep_graph::{dep_kind, DepGraphQuery, DepNode, DepNodeExt}; use rustc_middle::hir::map::Map; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{sym, Symbol}; @@ -120,7 +120,7 @@ impl IfThisChanged<'tcx> { if self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner), + None => DepNode::from_def_path_hash(def_path_hash, &dep_kind::hir_owner), Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index b01a55b48da66..8106da25b9856 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1598,7 +1598,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX); let dep_node = - DepNode::from_def_path_hash(def_path_hash, dep_graph::DepKind::CrateMetadata); + DepNode::from_def_path_hash(def_path_hash, &dep_graph::dep_kind::CrateMetadata); dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); assert!(dep_node_index != DepNodeIndex::INVALID); diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 9585d2f759917..4f67d8323b4cb 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -65,11 +65,28 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::definitions::DefPathHash; use rustc_hir::HirId; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::symbol::Symbol; use std::hash::Hash; pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams}; +pub trait DepKindTrait: std::fmt::Debug + Sync { + fn index(&self) -> DepKindIndex; + + fn can_reconstruct_query_key(&self) -> bool; + + fn is_anon(&self) -> bool; + + fn is_eval_always(&self) -> bool; + + fn has_params(&self) -> bool; + + fn force_from_dep_node(&self, tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool; + + fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>, dep_node: &DepNode); +} + // erase!() just makes tokens go away. It's used to specify which macro argument // is repeated (i.e., which sub-expression of the macro we are in) but don't need // to actually use any of the arguments. @@ -103,95 +120,136 @@ macro_rules! contains_eval_always_attr { ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false}); } -macro_rules! define_dep_nodes { +macro_rules! define_dep_kinds { (<$tcx:tt> $( [$($attrs:tt)*] $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* ,)* ) => ( - pub mod dep_kind { - use super::*; + $(impl DepKindTrait for dep_kind::$variant { + #[inline] + fn index(&self) -> DepKindIndex { + DepKindIndex::$variant + } - $( - #[allow(non_camel_case_types)] - pub struct $variant; + #[inline] + #[allow(unreachable_code)] + #[allow(unused_lifetimes)] // inside `tuple_arg_ty` + fn can_reconstruct_query_key<$tcx>(&self) -> bool { + if contains_anon_attr!($($attrs)*) { + return false; + } - impl $variant { - #[inline] - #[allow(unreachable_code)] - #[allow(unused_lifetimes)] // inside `tuple_arg_ty` - pub fn can_reconstruct_query_key<$tcx>(&self) -> bool { - if contains_anon_attr!($($attrs)*) { - return false; - } + // tuple args + $({ + return <$tuple_arg_ty as DepNodeParams>> + ::can_reconstruct_query_key(); + })* - // tuple args - $({ - return <$tuple_arg_ty as DepNodeParams>> - ::can_reconstruct_query_key(); - })* - - true - } - - #[inline] - pub fn is_anon(&self) -> bool { - contains_anon_attr!($($attrs)*) - } - - #[inline] - pub fn is_eval_always(&self) -> bool { - contains_eval_always_attr!($($attrs)*) - } - - #[inline] - #[allow(unreachable_code)] - pub fn has_params(&self) -> bool { - // tuple args - $({ - erase!($tuple_arg_ty); - return true; - })* - - false - } - } - )* - } + true + } - #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] - #[allow(non_camel_case_types)] - pub enum DepKind { - $($variant),* - } + #[inline] + fn is_anon(&self) -> bool { + contains_anon_attr!($($attrs)*) + } - impl DepKind { - pub fn can_reconstruct_query_key(&self) -> bool { - match *self { - $(DepKind::$variant => dep_kind::$variant.can_reconstruct_query_key()),* - } + #[inline] + fn is_eval_always(&self) -> bool { + contains_eval_always_attr!($($attrs)*) } - pub fn is_anon(&self) -> bool { - match *self { - $(DepKind::$variant => dep_kind::$variant.is_anon()),* - } + #[inline] + #[allow(unreachable_code)] + fn has_params(&self) -> bool { + // tuple args + $({ + erase!($tuple_arg_ty); + return true; + })* + + false } - pub fn is_eval_always(&self) -> bool { - match *self { - $(DepKind::$variant => dep_kind::$variant.is_eval_always()),* + #[inline] + fn force_from_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool { + use rustc_query_system::query::force_query; + use rustc_middle::ty::query::queries; + #[allow(unused_parens)] + #[allow(unused_lifetimes)] + type Key<$tcx> = ($($tuple_arg_ty),*); + + if !self.can_reconstruct_query_key() { + return false; } + + debug_assert!( as DepNodeParams>>::can_reconstruct_query_key()); + + if let Some(key) = as DepNodeParams>>::recover(tcx, dep_node) { + force_query::, _>( + tcx, + key, + rustc_span::DUMMY_SP, + *dep_node + ); + return true; + } + + false } - pub fn has_params(&self) -> bool { - match *self { - $(DepKind::$variant => dep_kind::$variant.has_params()),* + #[inline] + fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) { + use rustc_query_system::query::QueryDescription; + use rustc_middle::ty::query::queries; + #[allow(unused_parens)] + #[allow(unused_lifetimes)] + type Key<$tcx> = ($($tuple_arg_ty),*); + + if ! as DepNodeParams>>::can_reconstruct_query_key() { + return; + } + + debug_assert!(tcx.dep_graph + .node_color(dep_node) + .map(|c| c.is_green()) + .unwrap_or(false)); + + let key = as DepNodeParams>>::recover(tcx, dep_node).unwrap(); + if queries::$variant::cache_on_disk(tcx, &key, None) { + let _ = tcx.$variant(key); } } + })* + ) +} + +rustc_dep_node_append!([define_dep_kinds!][ <'tcx> ]); + +macro_rules! define_dep_nodes { + (<$tcx:tt> + $( + [$($attrs:tt)*] + $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* + ,)* + ) => ( + pub mod dep_kind { + $( + #[allow(non_camel_case_types)] + #[derive(Debug)] + pub struct $variant; + )* } + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] + #[allow(non_camel_case_types)] + pub enum DepKindIndex { + $($variant),* + } + + pub static DEP_KINDS: &[DepKind] = &[ $(&dep_kind::$variant),* ]; + pub struct DepConstructor; #[allow(non_camel_case_types)] @@ -203,10 +261,10 @@ macro_rules! define_dep_nodes { // tuple args $({ erase!($tuple_arg_ty); - return DepNode::construct(_tcx, DepKind::$variant, &arg) + return DepNode::construct(_tcx, &dep_kind::$variant, &arg) })* - return DepNode::construct(_tcx, DepKind::$variant, &()) + return DepNode::construct(_tcx, &dep_kind::$variant, &()) } )* } @@ -272,21 +330,19 @@ macro_rules! define_dep_nodes { /// Used in testing fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result { - let kind = match label { - $( - stringify!($variant) => DepKind::$variant, - )* - _ => return Err(()), - }; - - if !kind.can_reconstruct_query_key() { - return Err(()); - } - - if kind.has_params() { - Ok(DepNode::from_def_path_hash(def_path_hash, kind)) - } else { - Ok(DepNode::new_no_params(kind)) + match label { + $(stringify!($variant) => { + let kind = &dep_kind::$variant; + + if !kind.can_reconstruct_query_key() { + Err(()) + } else if kind.has_params() { + Ok(DepNode::from_def_path_hash(def_path_hash, kind)) + } else { + Ok(DepNode::new_no_params(kind)) + } + })* + _ => Err(()), } } @@ -324,6 +380,192 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] CompileCodegenUnit(Symbol), ]); +impl DepKindTrait for dep_kind::Null { + #[inline] + fn index(&self) -> DepKindIndex { + DepKindIndex::Null + } + + #[inline] + fn can_reconstruct_query_key(&self) -> bool { + true + } + + #[inline] + fn is_anon(&self) -> bool { + false + } + + #[inline] + fn is_eval_always(&self) -> bool { + false + } + + #[inline] + fn has_params(&self) -> bool { + false + } + + #[inline] + fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { + // Forcing this makes no sense. + bug!("force_from_dep_node: encountered {:?}", _dep_node); + } + + #[inline] + fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} +} + +impl DepKindTrait for dep_kind::CrateMetadata { + #[inline] + fn index(&self) -> DepKindIndex { + DepKindIndex::CrateMetadata + } + + #[inline] + fn can_reconstruct_query_key(&self) -> bool { + >>::can_reconstruct_query_key() + } + + #[inline] + fn is_anon(&self) -> bool { + false + } + + #[inline] + fn is_eval_always(&self) -> bool { + true + } + + #[inline] + fn has_params(&self) -> bool { + true + } + + #[inline] + fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { + // These are inputs that are expected to be pre-allocated and that + // should therefore always be red or green already. + if !self.can_reconstruct_query_key() { + return false; + } + + bug!("force_from_dep_node: encountered {:?}", _dep_node); + } + + #[inline] + fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} +} + +impl DepKindTrait for dep_kind::TraitSelect { + #[inline] + fn index(&self) -> DepKindIndex { + DepKindIndex::TraitSelect + } + + #[inline] + fn can_reconstruct_query_key(&self) -> bool { + false + } + + #[inline] + fn is_anon(&self) -> bool { + true + } + + #[inline] + fn is_eval_always(&self) -> bool { + false + } + + #[inline] + fn has_params(&self) -> bool { + false + } + + #[inline] + fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { + // These are anonymous nodes. + if !self.can_reconstruct_query_key() { + return false; + } + + bug!("force_from_dep_node: encountered {:?}", _dep_node); + } + + #[inline] + fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} +} + +impl DepKindTrait for dep_kind::CompileCodegenUnit { + #[inline] + fn index(&self) -> DepKindIndex { + DepKindIndex::CompileCodegenUnit + } + + #[inline] + fn can_reconstruct_query_key(&self) -> bool { + >>::can_reconstruct_query_key() + } + + #[inline] + fn is_anon(&self) -> bool { + false + } + + #[inline] + fn is_eval_always(&self) -> bool { + false + } + + #[inline] + #[allow(unreachable_code)] + fn has_params(&self) -> bool { + true + } + + #[inline] + fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { + // We don't have enough information to reconstruct the query key of these. + if !self.can_reconstruct_query_key() { + return false; + } + + bug!("force_from_dep_node: encountered {:?}", _dep_node); + } + + #[inline] + fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} +} + +pub type DepKind = &'static dyn DepKindTrait; + +impl PartialEq for &dyn DepKindTrait { + fn eq(&self, other: &Self) -> bool { + self.index() == other.index() + } +} +impl Eq for &dyn DepKindTrait {} + +impl Hash for &dyn DepKindTrait { + fn hash(&self, hasher: &mut H) { + self.index().hash(hasher) + } +} + +impl Encodable for &dyn DepKindTrait { + fn encode(&self, enc: &mut E) -> Result<(), E::Error> { + self.index().encode(enc) + } +} + +impl Decodable for &dyn DepKindTrait { + fn decode(dec: &mut D) -> Result { + let idx = DepKindIndex::decode(dec)?; + Ok(DEP_KINDS[idx as usize]) + } +} + impl<'tcx> DepNodeParams> for DefId { #[inline] fn can_reconstruct_query_key() -> bool { diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 338a9624fdae1..055d8cf7a2f12 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -9,13 +9,14 @@ use rustc_hir::def_id::LocalDefId; mod dep_node; -pub(crate) use rustc_query_system::dep_graph::DepNodeParams; pub use rustc_query_system::dep_graph::{ debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex, WorkProduct, WorkProductId, }; -pub use dep_node::{dep_kind, label_strs, DepConstructor, DepKind, DepNode, DepNodeExt}; +pub use dep_node::{ + dep_kind, label_strs, DepConstructor, DepKind, DepKindIndex, DepKindTrait, DepNode, DepNodeExt, +}; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps; @@ -24,14 +25,14 @@ pub type PreviousDepGraph = rustc_query_system::dep_graph::PreviousDepGraph; impl rustc_query_system::dep_graph::DepKind for DepKind { - const NULL: Self = DepKind::Null; + const NULL: Self = &dep_kind::Null; fn is_eval_always(&self) -> bool { - DepKind::is_eval_always(self) + DepKindTrait::is_eval_always(*self) } fn has_params(&self) -> bool { - DepKind::has_params(self) + DepKindTrait::has_params(*self) } fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -83,7 +84,7 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { } fn can_reconstruct_query_key(&self) -> bool { - DepKind::can_reconstruct_query_key(self) + DepKindTrait::can_reconstruct_query_key(*self) } } @@ -104,14 +105,18 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { } fn try_force_from_dep_node(&self, dep_node: &DepNode) -> bool { + let index = dep_node.kind.index(); + // FIXME: This match is just a workaround for incremental bugs and should // be removed. https://github.com/rust-lang/rust/issues/62649 is one such // bug that must be fixed before removing this. - match dep_node.kind { - DepKind::hir_owner | DepKind::hir_owner_nodes | DepKind::CrateMetadata => { + match index { + DepKindIndex::hir_owner + | DepKindIndex::hir_owner_nodes + | DepKindIndex::CrateMetadata => { if let Some(def_id) = dep_node.extract_def_id(*self) { if def_id_corresponds_to_hir_dep_node(*self, def_id.expect_local()) { - if dep_node.kind == DepKind::CrateMetadata { + if index == DepKindIndex::CrateMetadata { // The `DefPath` has corresponding node, // and that node should have been marked // either red or green in `data.colors`. diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 4f30a591308a7..9dae921d6647a 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::{self, DepKind, DepNode, DepNodeParams}; +use crate::dep_graph::{self, dep_kind, DepNode}; use crate::hir::exports::Export; use crate::hir::map; use crate::infer::canonical::{self, Canonical}; @@ -160,97 +160,15 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool // 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, + dep_node.kind != &dep_kind::codegen_unit, "calling force_from_dep_node() on DepKind::codegen_unit" ); - macro_rules! force_from_dep_node { - ($($(#[$attr:meta])* [$($modifiers:tt)*] $name:ident($K:ty),)*) => { - use rustc_middle::dep_graph::dep_kind; - - $(impl dep_kind::$name { - fn force_from_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool { - if !self.can_reconstruct_query_key() { - return false; - } - - debug_assert!(<$K as DepNodeParams>>::can_reconstruct_query_key()); - - if let Some(key) = <$K as DepNodeParams>>::recover(tcx, dep_node) { - force_query::, _>( - tcx, - key, - DUMMY_SP, - *dep_node - ); - return true; - } - - false - } - })* - - match dep_node.kind { - // These are inputs that are expected to be pre-allocated and that - // should therefore always be red or green already. - DepKind::CrateMetadata | - - // These are anonymous nodes. - DepKind::TraitSelect | - - // We don't have enough information to reconstruct the query key of - // these. - DepKind::CompileCodegenUnit | - - // Forcing this makes no sense. - DepKind::Null => { - if !dep_node.kind.can_reconstruct_query_key() { - return false; - } - - bug!("force_from_dep_node: encountered {:?}", dep_node) - } - - $(DepKind::$name => dep_kind::$name.force_from_dep_node(tcx, dep_node)),* - } - } - } - - rustc_dep_node_append! { [force_from_dep_node!][] } - - false + dep_node.kind.force_from_dep_node(tcx, dep_node) } pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) { - macro_rules! try_load_from_on_disk_cache { - ($($name:ident,)*) => { - use rustc_middle::dep_graph::dep_kind; - - $(impl dep_kind::$name { - fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) { - if 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 = as DepNodeParams>>::recover(tcx, dep_node).unwrap(); - if queries::$name::cache_on_disk(tcx, &key, None) { - let _ = tcx.$name(key); - } - } - } - })* - - match dep_node.kind { - $(DepKind::$name => dep_kind::$name.try_load_from_on_disk_cache(tcx, dep_node),)* - - _ => (), - } - } - } - - rustc_cached_queries!(try_load_from_on_disk_cache!); + dep_node.kind.try_load_from_on_disk_cache(tcx, dep_node) } mod sealed { diff --git a/compiler/rustc_middle/src/ty/query/plumbing.rs b/compiler/rustc_middle/src/ty/query/plumbing.rs index d038695283c10..f64bedd9634f0 100644 --- a/compiler/rustc_middle/src/ty/query/plumbing.rs +++ b/compiler/rustc_middle/src/ty/query/plumbing.rs @@ -356,7 +356,7 @@ macro_rules! define_queries { impl<$tcx> QueryAccessors> for queries::$name<$tcx> { const ANON: bool = is_anon!([$($modifiers)*]); const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); - const DEP_KIND: dep_graph::DepKind = dep_graph::DepKind::$name; + const DEP_KIND: dep_graph::DepKind = &dep_graph::dep_kind::$name; type Cache = query_storage!([$($modifiers)*][$($K)*, $V]); diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index e8d02692f37ba..c6bd4eee3df23 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -59,7 +59,7 @@ pub trait DepContext: Copy { } /// Describe the different families of dependency nodes. -pub trait DepKind: Copy + fmt::Debug + Eq + Ord + Hash { +pub trait DepKind: Copy + fmt::Debug + Eq + Hash { const NULL: Self; /// Return whether this kind always require evaluation. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b838602e76ca3..635370fd4c0aa 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -31,7 +31,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; +use rustc_middle::dep_graph::{dep_kind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::fast_reject; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -972,7 +972,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { OP: FnOnce(&mut Self) -> R, { let (result, dep_node) = - self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || op(self)); + self.tcx().dep_graph.with_anon_task(&dep_kind::TraitSelect, || op(self)); self.tcx().dep_graph.read_index(dep_node); (result, dep_node) } From f74b0b9cae2488eb829e0829c3bb8203c6d477ee Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 02:19:17 +0200 Subject: [PATCH 09/18] Type-erase query stats. --- .../rustc_middle/src/dep_graph/dep_node.rs | 36 +++++++++++++++ compiler/rustc_middle/src/dep_graph/mod.rs | 1 + compiler/rustc_middle/src/ty/query/mod.rs | 2 +- .../rustc_middle/src/ty/query/plumbing.rs | 2 +- compiler/rustc_middle/src/ty/query/stats.rs | 45 ++++++------------- 5 files changed, 52 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 4f67d8323b4cb..eac9f0b6bc99f 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -60,11 +60,13 @@ use crate::traits::query::{ }; use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt}; +use rustc_middle::ty::query; use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::definitions::DefPathHash; use rustc_hir::HirId; +use rustc_query_system::query::QueryAccessors; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::symbol::Symbol; use std::hash::Hash; @@ -84,6 +86,8 @@ pub trait DepKindTrait: std::fmt::Debug + Sync { fn force_from_dep_node(&self, tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool; + fn query_stats(&self, tcx: TyCtxt<'_>) -> Option; + fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>, dep_node: &DepNode); } @@ -199,6 +203,18 @@ macro_rules! define_dep_kinds { false } + #[inline] + fn query_stats(&self, tcx: TyCtxt<'_>) -> Option { + let ret = query::stats::stats::< + query::Query<'_>, + as QueryAccessors>>::Cache, + >( + stringify!($variant), + &tcx.queries.$variant, + ); + Some(ret) + } + #[inline] fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) { use rustc_query_system::query::QueryDescription; @@ -412,6 +428,11 @@ impl DepKindTrait for dep_kind::Null { bug!("force_from_dep_node: encountered {:?}", _dep_node); } + #[inline] + fn query_stats(&self, _tcx: TyCtxt<'_>) -> Option { + None + } + #[inline] fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} } @@ -453,6 +474,11 @@ impl DepKindTrait for dep_kind::CrateMetadata { bug!("force_from_dep_node: encountered {:?}", _dep_node); } + #[inline] + fn query_stats(&self, _tcx: TyCtxt<'_>) -> Option { + None + } + #[inline] fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} } @@ -493,6 +519,11 @@ impl DepKindTrait for dep_kind::TraitSelect { bug!("force_from_dep_node: encountered {:?}", _dep_node); } + #[inline] + fn query_stats(&self, _tcx: TyCtxt<'_>) -> Option { + None + } + #[inline] fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} } @@ -534,6 +565,11 @@ impl DepKindTrait for dep_kind::CompileCodegenUnit { bug!("force_from_dep_node: encountered {:?}", _dep_node); } + #[inline] + fn query_stats(&self, _tcx: TyCtxt<'_>) -> Option { + None + } + #[inline] fn try_load_from_on_disk_cache<'tcx>(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) {} } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 055d8cf7a2f12..061698289e11e 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -16,6 +16,7 @@ pub use rustc_query_system::dep_graph::{ pub use dep_node::{ dep_kind, label_strs, DepConstructor, DepKind, DepKindIndex, DepKindTrait, DepNode, DepNodeExt, + DEP_KINDS, }; pub type DepGraph = rustc_query_system::dep_graph::DepGraph; diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 9dae921d6647a..8d76a6e9e452f 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -64,7 +64,7 @@ mod plumbing; pub(crate) use rustc_query_system::query::CycleError; use rustc_query_system::query::*; -mod stats; +crate mod stats; pub use self::stats::print_stats; #[cfg(parallel_compiler)] diff --git a/compiler/rustc_middle/src/ty/query/plumbing.rs b/compiler/rustc_middle/src/ty/query/plumbing.rs index f64bedd9634f0..fef586b4b3f1f 100644 --- a/compiler/rustc_middle/src/ty/query/plumbing.rs +++ b/compiler/rustc_middle/src/ty/query/plumbing.rs @@ -515,7 +515,7 @@ macro_rules! define_queries_struct { providers: IndexVec, fallback_extern_providers: Box, - $($(#[$attr])* $name: QueryState< + $($(#[$attr])* pub(crate) $name: QueryState< crate::dep_graph::DepKind, as QueryContext>::Query, as QueryAccessors>>::Cache, diff --git a/compiler/rustc_middle/src/ty/query/stats.rs b/compiler/rustc_middle/src/ty/query/stats.rs index e0b44ce23c912..430175efab6a7 100644 --- a/compiler/rustc_middle/src/ty/query/stats.rs +++ b/compiler/rustc_middle/src/ty/query/stats.rs @@ -1,10 +1,9 @@ -use crate::ty::query::queries; +use crate::dep_graph::{self, DepKind}; use crate::ty::TyCtxt; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_query_system::query::{QueryAccessors, QueryCache, QueryContext, QueryState}; +use rustc_query_system::query::{QueryCache, QueryState}; use std::any::type_name; -use std::hash::Hash; use std::mem; #[cfg(debug_assertions)] use std::sync::atomic::Ordering; @@ -26,7 +25,7 @@ impl KeyStats for DefId { } #[derive(Clone)] -struct QueryStats { +pub struct QueryStats { name: &'static str, cache_hits: usize, key_size: usize, @@ -37,9 +36,8 @@ struct QueryStats { local_def_id_keys: Option, } -fn stats(name: &'static str, map: &QueryState) -> QueryStats +crate fn stats(name: &'static str, map: &QueryState) -> QueryStats where - D: Copy + Clone + Eq + Hash, Q: Clone, C: QueryCache, { @@ -65,7 +63,15 @@ where } pub fn print_stats(tcx: TyCtxt<'_>) { - let queries = query_stats(tcx); + let mut queries = Vec::new(); + + for dk in dep_graph::DEP_KINDS { + if let Some(fragment) = dk.query_stats(tcx) { + queries.push(fragment) + } + } + + let queries = queries; if cfg!(debug_assertions) { let hits: usize = queries.iter().map(|s| s.cache_hits).sum(); @@ -118,28 +124,3 @@ pub fn print_stats(tcx: TyCtxt<'_>) { println!(" {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total); } } - -macro_rules! print_stats { - (<$tcx:tt> - $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($K:ty) -> $V:ty,)* - ) => { - fn query_stats(tcx: TyCtxt<'_>) -> Vec { - let mut queries = Vec::new(); - - $( - queries.push(stats::< - crate::dep_graph::DepKind, - as QueryContext>::Query, - as QueryAccessors>>::Cache, - >( - stringify!($name), - &tcx.queries.$name, - )); - )* - - queries - } - } -} - -rustc_query_append! { [print_stats!][<'tcx>] } From f8c6f42c9fba49d2991a563dfc9c2cd4b22ac510 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 20 Oct 2020 22:55:39 +0200 Subject: [PATCH 10/18] Monomorphize query serialisation. --- compiler/rustc_middle/src/ty/context.rs | 6 ++---- .../src/ty/query/on_disk_cache.rs | 20 +++++++++---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index ab92e5b745bcd..ba3934fedae64 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -45,6 +45,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; +use rustc_serialize::opaque; use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames}; use rustc_session::lint::{Level, Lint}; use rustc_session::Session; @@ -1323,10 +1324,7 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn serialize_query_result_cache(self, encoder: &mut E) -> Result<(), E::Error> - where - E: ty::codec::OpaqueEncoder, - { + pub fn serialize_query_result_cache(self, encoder: &mut opaque::Encoder) -> Result<(), !> { self.queries.on_disk_cache.serialize(self, encoder) } diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 173e9a31928b5..62352a886e455 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -176,10 +176,11 @@ impl<'sess> OnDiskCache<'sess> { } } - pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(), E::Error> - where - E: OpaqueEncoder, - { + pub fn serialize<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + encoder: &mut opaque::Encoder, + ) -> Result<(), !> { // Serializing the `DepGraph` should not modify it. tcx.dep_graph.with_ignore(|| { // Allocate `SourceFileIndex`es. @@ -228,7 +229,7 @@ impl<'sess> OnDiskCache<'sess> { macro_rules! encode_queries { ($($query:ident,)*) => { $( - encode_query_results::, _>( + encode_query_results::>( tcx, enc, qri @@ -987,15 +988,14 @@ impl<'a> Decodable> for IntEncodedWithFixedSize { } } -fn encode_query_results<'a, 'tcx, Q, E>( +fn encode_query_results<'a, 'tcx, Q>( tcx: TyCtxt<'tcx>, - encoder: &mut CacheEncoder<'a, 'tcx, E>, + encoder: &mut CacheEncoder<'a, 'tcx, opaque::Encoder>, query_result_index: &mut EncodedQueryResultIndex, -) -> Result<(), E::Error> +) -> Result<(), !> where Q: super::QueryDescription> + super::QueryAccessors>, - Q::Value: Encodable>, - E: 'a + OpaqueEncoder, + Q::Value: Encodable>, { let _timer = tcx .sess From 5e3cea6ff32a6422f7290d46540a2f7b45d36d01 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 21 Oct 2020 21:31:10 +0200 Subject: [PATCH 11/18] Make OpaqueEncoder private. --- compiler/rustc_middle/src/ty/codec.rs | 16 ---------------- .../src/ty/query/on_disk_cache.rs | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index aaf6a8570437c..52f25780ead07 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -50,22 +50,6 @@ impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::Predicate } } -pub trait OpaqueEncoder: Encoder { - fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder; - fn encoder_position(&self) -> usize; -} - -impl OpaqueEncoder for rustc_serialize::opaque::Encoder { - #[inline] - fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder { - self - } - #[inline] - fn encoder_position(&self) -> usize { - self.position() - } -} - pub trait TyEncoder<'tcx>: Encoder { const CLEAR_CROSS_CRATE: bool; diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 62352a886e455..ae1424b1dbe9b 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -1,7 +1,7 @@ use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use crate::mir::{self, interpret}; -use crate::ty::codec::{OpaqueEncoder, RefDecodable, TyDecoder, TyEncoder}; +use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder}; @@ -764,6 +764,23 @@ impl<'a, 'tcx> Decodable> for &'tcx [Span] { //- ENCODING ------------------------------------------------------------------- +/// This trait is a hack to work around specialization bug #55243. +trait OpaqueEncoder: Encoder { + fn opaque(&mut self) -> &mut opaque::Encoder; + fn encoder_position(&self) -> usize; +} + +impl OpaqueEncoder for opaque::Encoder { + #[inline] + fn opaque(&mut self) -> &mut opaque::Encoder { + self + } + #[inline] + fn encoder_position(&self) -> usize { + self.position() + } +} + /// An encoder that can write the incr. comp. cache. struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { tcx: TyCtxt<'tcx>, From 253da5dbd9a0853ff6989ca8ca15b428cbb1a61c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 21 Oct 2020 21:48:19 +0200 Subject: [PATCH 12/18] Reduce visibilities. --- compiler/rustc_middle/src/ty/query/on_disk_cache.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index ae1424b1dbe9b..7414f25513689 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -176,7 +176,7 @@ impl<'sess> OnDiskCache<'sess> { } } - pub fn serialize<'tcx>( + crate fn serialize<'tcx>( &self, tcx: TyCtxt<'tcx>, encoder: &mut opaque::Encoder, @@ -349,7 +349,7 @@ impl<'sess> OnDiskCache<'sess> { } /// Loads a diagnostic emitted during the previous compilation session. - pub fn load_diagnostics( + crate fn load_diagnostics( &self, tcx: TyCtxt<'_>, dep_node_index: SerializedDepNodeIndex, @@ -365,7 +365,7 @@ impl<'sess> OnDiskCache<'sess> { /// the next compilation session. #[inline(never)] #[cold] - pub fn store_diagnostics( + crate fn store_diagnostics( &self, dep_node_index: DepNodeIndex, diagnostics: ThinVec, @@ -394,7 +394,7 @@ impl<'sess> OnDiskCache<'sess> { /// 1:1 relationship between query-key and `DepNode`. #[inline(never)] #[cold] - pub fn store_diagnostics_for_anon_node( + crate fn store_diagnostics_for_anon_node( &self, dep_node_index: DepNodeIndex, diagnostics: ThinVec, @@ -973,7 +973,7 @@ where struct IntEncodedWithFixedSize(u64); impl IntEncodedWithFixedSize { - pub const ENCODED_SIZE: usize = 8; + const ENCODED_SIZE: usize = 8; } impl Encodable for IntEncodedWithFixedSize { From 6d818bd1a58109664ff6974add1ea5a623acd2d0 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 03:07:50 +0200 Subject: [PATCH 13/18] Type-erase query caching. --- compiler/rustc_macros/src/query.rs | 4 ++ .../rustc_middle/src/dep_graph/dep_node.rs | 68 ++++++++++++++++++- compiler/rustc_middle/src/ty/query/mod.rs | 2 +- .../src/ty/query/on_disk_cache.rs | 28 +++----- 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index fd85919636949..e174425737d25 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -466,6 +466,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if modifiers.eval_always { attributes.push(quote! { eval_always }); }; + // Pass on the cache modifier + if modifiers.cache.is_some() { + attributes.push(quote! { cached }); + }; let attribute_stream = quote! {#(#attributes),*}; let doc_comments = query.doc_comments.iter(); diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index eac9f0b6bc99f..50f545db3a54a 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -67,7 +67,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::definitions::DefPathHash; use rustc_hir::HirId; use rustc_query_system::query::QueryAccessors; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; use rustc_span::symbol::Symbol; use std::hash::Hash; @@ -84,6 +84,13 @@ pub trait DepKindTrait: std::fmt::Debug + Sync { fn has_params(&self) -> bool; + fn encode_query_results<'a, 'tcx>( + &self, + tcx: TyCtxt<'tcx>, + encoder: &mut query::on_disk_cache::CacheEncoder<'a, 'tcx, opaque::Encoder>, + query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, + ); + fn force_from_dep_node(&self, tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool; fn query_stats(&self, tcx: TyCtxt<'_>) -> Option; @@ -124,6 +131,19 @@ macro_rules! contains_eval_always_attr { ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false}); } +macro_rules! encode_query_results { + ([][$variant:ident][$($args:expr),*]) => {{}}; + ([cached $($rest:tt)*][$variant:ident][$($args:expr),*]) => {{ + let ret = query::on_disk_cache::encode_query_results::< + query::queries::$variant<'_> + >($($args),*); + match ret { Ok(()) => (), Err(_) => () } + }}; + ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$variant:ident][$($args:expr),*]) => { + encode_query_results!([$($($modifiers)*)*][$variant][$($args),*]) + }; +} + macro_rules! define_dep_kinds { (<$tcx:tt> $( @@ -176,6 +196,16 @@ macro_rules! define_dep_kinds { false } + #[inline] + fn encode_query_results<'a, 'tcx>( + &self, + _tcx: TyCtxt<'tcx>, + _encoder: &mut query::on_disk_cache::CacheEncoder<'a, 'tcx, opaque::Encoder>, + _query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, + ) { + encode_query_results!([$($attrs)*][$variant][_tcx, _encoder, _query_result_index]); + } + #[inline] fn force_from_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool { use rustc_query_system::query::force_query; @@ -422,6 +452,15 @@ impl DepKindTrait for dep_kind::Null { false } + #[inline] + fn encode_query_results<'a, 'tcx>( + &self, + _tcx: TyCtxt<'tcx>, + _encoder: &mut query::on_disk_cache::CacheEncoder<'a, 'tcx, opaque::Encoder>, + _query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, + ) { + } + #[inline] fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { // Forcing this makes no sense. @@ -463,6 +502,15 @@ impl DepKindTrait for dep_kind::CrateMetadata { true } + #[inline] + fn encode_query_results<'a, 'tcx>( + &self, + _tcx: TyCtxt<'tcx>, + _encoder: &mut query::on_disk_cache::CacheEncoder<'a, 'tcx, opaque::Encoder>, + _query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, + ) { + } + #[inline] fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { // These are inputs that are expected to be pre-allocated and that @@ -509,6 +557,15 @@ impl DepKindTrait for dep_kind::TraitSelect { false } + #[inline] + fn encode_query_results<'a, 'tcx>( + &self, + _tcx: TyCtxt<'tcx>, + _encoder: &mut query::on_disk_cache::CacheEncoder<'a, 'tcx, opaque::Encoder>, + _query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, + ) { + } + #[inline] fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { // These are anonymous nodes. @@ -555,6 +612,15 @@ impl DepKindTrait for dep_kind::CompileCodegenUnit { true } + #[inline] + fn encode_query_results<'a, 'tcx>( + &self, + _tcx: TyCtxt<'tcx>, + _encoder: &mut query::on_disk_cache::CacheEncoder<'a, 'tcx, opaque::Encoder>, + _query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, + ) { + } + #[inline] fn force_from_dep_node(&self, _tcx: TyCtxt<'tcx>, _dep_node: &DepNode) -> bool { // We don't have enough information to reconstruct the query key of these. diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index 8d76a6e9e452f..cdb236f734427 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -83,7 +83,7 @@ use rustc_query_system::query::QueryAccessors; pub use rustc_query_system::query::QueryConfig; pub(crate) use rustc_query_system::query::QueryDescription; -mod on_disk_cache; +pub mod on_disk_cache; pub use self::on_disk_cache::OnDiskCache; mod profiling_support; diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index 7414f25513689..dd654ffce36d1 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -97,7 +97,7 @@ struct Footer { expn_data: FxHashMap, } -type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; +pub type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>; type EncodedDiagnostics = Vec; @@ -105,7 +105,7 @@ type EncodedDiagnostics = Vec; struct SourceFileIndex(u32); #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)] -struct AbsoluteBytePos(u32); +pub struct AbsoluteBytePos(u32); impl AbsoluteBytePos { fn new(pos: usize) -> AbsoluteBytePos { @@ -226,22 +226,10 @@ impl<'sess> OnDiskCache<'sess> { let enc = &mut encoder; let qri = &mut query_result_index; - macro_rules! encode_queries { - ($($query:ident,)*) => { - $( - encode_query_results::>( - tcx, - enc, - qri - )?; - )* - } + for dk in rustc_middle::dep_graph::DEP_KINDS { + dk.encode_query_results(tcx, enc, qri) } - - rustc_cached_queries!(encode_queries!); - - Ok(()) - })?; + }); // Encode diagnostics. let diagnostics_index: EncodedDiagnosticsIndex = self @@ -765,7 +753,7 @@ impl<'a, 'tcx> Decodable> for &'tcx [Span] { //- ENCODING ------------------------------------------------------------------- /// This trait is a hack to work around specialization bug #55243. -trait OpaqueEncoder: Encoder { +pub trait OpaqueEncoder: Encoder { fn opaque(&mut self) -> &mut opaque::Encoder; fn encoder_position(&self) -> usize; } @@ -782,7 +770,7 @@ impl OpaqueEncoder for opaque::Encoder { } /// An encoder that can write the incr. comp. cache. -struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { +pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { tcx: TyCtxt<'tcx>, encoder: &'a mut E, type_shorthands: FxHashMap, usize>, @@ -1005,7 +993,7 @@ impl<'a> Decodable> for IntEncodedWithFixedSize { } } -fn encode_query_results<'a, 'tcx, Q>( +pub fn encode_query_results<'a, 'tcx, Q>( tcx: TyCtxt<'tcx>, encoder: &mut CacheEncoder<'a, 'tcx, opaque::Encoder>, query_result_index: &mut EncodedQueryResultIndex, From c0ccc7dfc6f253815af82ff0c84272157d8c1c0c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 03:11:44 +0200 Subject: [PATCH 14/18] Remove rustc_cached_queries. --- compiler/rustc_macros/src/query.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index e174425737d25..e5da621b2908c 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -421,7 +421,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let mut query_stream = quote! {}; let mut query_description_stream = quote! {}; let mut dep_node_def_stream = quote! {}; - let mut cached_queries = quote! {}; for group in groups.0 { for mut query in group.queries.0 { @@ -434,12 +433,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { _ => quote! { #result_full }, }; - if modifiers.cache.is_some() { - cached_queries.extend(quote! { - #name, - }); - } - let mut attributes = Vec::new(); // Pass on the fatal_cycle modifier @@ -508,11 +501,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { ); } } - macro_rules! rustc_cached_queries { - ($($macro:tt)*) => { - $($macro)*(#cached_queries); - } - } #query_description_stream }) From 908d735b93827635bdf5afc60c2b854b1d91c9c0 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 03:22:16 +0200 Subject: [PATCH 15/18] Remove one-liners. --- .../rustc_middle/src/dep_graph/dep_node.rs | 60 ++++++++++++++++ compiler/rustc_middle/src/dep_graph/mod.rs | 5 +- compiler/rustc_middle/src/ty/query/mod.rs | 70 +------------------ 3 files changed, 63 insertions(+), 72 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 50f545db3a54a..be999a9b63ebb 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -91,6 +91,48 @@ pub trait DepKindTrait: std::fmt::Debug + Sync { query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, ); + /// 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_promoted` 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 `LocalDefId` 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. fn force_from_dep_node(&self, tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool; fn query_stats(&self, tcx: TyCtxt<'_>) -> Option; @@ -214,6 +256,24 @@ macro_rules! define_dep_kinds { #[allow(unused_lifetimes)] type Key<$tcx> = ($($tuple_arg_ty),*); + // 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 != &dep_kind::codegen_unit, + "calling force_from_dep_node() on DepKind::codegen_unit" + ); + if !self.can_reconstruct_query_key() { return false; } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 061698289e11e..29dd7441b6a2e 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -1,5 +1,4 @@ use crate::ich::StableHashingContext; -use crate::ty::query::try_load_from_on_disk_cache; use crate::ty::{self, TyCtxt}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::Lock; @@ -153,7 +152,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { } debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node); - ty::query::force_from_dep_node(*self, dep_node) + dep_node.kind.force_from_dep_node(*self, dep_node) } fn has_errors_or_delayed_span_bugs(&self) -> bool { @@ -166,7 +165,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> { // Interactions with on_disk_cache fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) { - try_load_from_on_disk_cache(*self, dep_node) + dep_node.kind.try_load_from_on_disk_cache(*self, dep_node) } fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec { diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index cdb236f734427..c2420c60f34ec 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::{self, dep_kind, DepNode}; +use crate::dep_graph; use crate::hir::exports::Export; use crate::hir::map; use crate::infer::canonical::{self, Canonical}; @@ -103,74 +103,6 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder 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_promoted` 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 `LocalDefId` 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 { - // 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 != &dep_kind::codegen_unit, - "calling force_from_dep_node() on DepKind::codegen_unit" - ); - - dep_node.kind.force_from_dep_node(tcx, dep_node) -} - -pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) { - dep_node.kind.try_load_from_on_disk_cache(tcx, dep_node) -} - mod sealed { use super::{DefId, LocalDefId}; From f06e3d96de446dc1e9ac27df1c40e1f7caf4f5f0 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 17:17:41 +0200 Subject: [PATCH 16/18] Rename macro parameter. --- .../rustc_middle/src/dep_graph/dep_node.rs | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index be999a9b63ebb..c62ea38c0f7e5 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -174,15 +174,15 @@ macro_rules! contains_eval_always_attr { } macro_rules! encode_query_results { - ([][$variant:ident][$($args:expr),*]) => {{}}; - ([cached $($rest:tt)*][$variant:ident][$($args:expr),*]) => {{ + ([][$name:ident][$($args:expr),*]) => {{}}; + ([cached $($rest:tt)*][$name:ident][$($args:expr),*]) => {{ let ret = query::on_disk_cache::encode_query_results::< - query::queries::$variant<'_> + query::queries::$name<'_> >($($args),*); match ret { Ok(()) => (), Err(_) => () } }}; - ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$variant:ident][$($args:expr),*]) => { - encode_query_results!([$($($modifiers)*)*][$variant][$($args),*]) + ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$name:ident][$($args:expr),*]) => { + encode_query_results!([$($($modifiers)*)*][$name][$($args),*]) }; } @@ -190,13 +190,13 @@ macro_rules! define_dep_kinds { (<$tcx:tt> $( [$($attrs:tt)*] - $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* + $name:ident $(( $tuple_arg_ty:ty $(,)? ))* ,)* ) => ( - $(impl DepKindTrait for dep_kind::$variant { + $(impl DepKindTrait for dep_kind::$name { #[inline] fn index(&self) -> DepKindIndex { - DepKindIndex::$variant + DepKindIndex::$name } #[inline] @@ -245,7 +245,7 @@ macro_rules! define_dep_kinds { _encoder: &mut query::on_disk_cache::CacheEncoder<'a, 'tcx, opaque::Encoder>, _query_result_index: &mut query::on_disk_cache::EncodedQueryResultIndex, ) { - encode_query_results!([$($attrs)*][$variant][_tcx, _encoder, _query_result_index]); + encode_query_results!([$($attrs)*][$name][_tcx, _encoder, _query_result_index]); } #[inline] @@ -281,7 +281,7 @@ macro_rules! define_dep_kinds { debug_assert!( as DepNodeParams>>::can_reconstruct_query_key()); if let Some(key) = as DepNodeParams>>::recover(tcx, dep_node) { - force_query::, _>( + force_query::, _>( tcx, key, rustc_span::DUMMY_SP, @@ -297,10 +297,10 @@ macro_rules! define_dep_kinds { fn query_stats(&self, tcx: TyCtxt<'_>) -> Option { let ret = query::stats::stats::< query::Query<'_>, - as QueryAccessors>>::Cache, + as QueryAccessors>>::Cache, >( - stringify!($variant), - &tcx.queries.$variant, + stringify!($name), + &tcx.queries.$name, ); Some(ret) } @@ -323,8 +323,8 @@ macro_rules! define_dep_kinds { .unwrap_or(false)); let key = as DepNodeParams>>::recover(tcx, dep_node).unwrap(); - if queries::$variant::cache_on_disk(tcx, &key, None) { - let _ = tcx.$variant(key); + if queries::$name::cache_on_disk(tcx, &key, None) { + let _ = tcx.$name(key); } } })* @@ -337,24 +337,24 @@ macro_rules! define_dep_nodes { (<$tcx:tt> $( [$($attrs:tt)*] - $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* + $name:ident $(( $tuple_arg_ty:ty $(,)? ))* ,)* ) => ( pub mod dep_kind { $( #[allow(non_camel_case_types)] #[derive(Debug)] - pub struct $variant; + pub struct $name; )* } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[allow(non_camel_case_types)] pub enum DepKindIndex { - $($variant),* + $($name),* } - pub static DEP_KINDS: &[DepKind] = &[ $(&dep_kind::$variant),* ]; + pub static DEP_KINDS: &[DepKind] = &[ $(&dep_kind::$name),* ]; pub struct DepConstructor; @@ -363,14 +363,14 @@ macro_rules! define_dep_nodes { $( #[inline(always)] #[allow(unreachable_code, non_snake_case)] - pub fn $variant(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode { + pub fn $name(_tcx: TyCtxt<'_>, $(arg: $tuple_arg_ty)*) -> DepNode { // tuple args $({ erase!($tuple_arg_ty); - return DepNode::construct(_tcx, &dep_kind::$variant, &arg) + return DepNode::construct(_tcx, &dep_kind::$name, &arg) })* - return DepNode::construct(_tcx, &dep_kind::$variant, &()) + return DepNode::construct(_tcx, &dep_kind::$name, &()) } )* } @@ -437,8 +437,8 @@ macro_rules! define_dep_nodes { /// Used in testing fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result { match label { - $(stringify!($variant) => { - let kind = &dep_kind::$variant; + $(stringify!($name) => { + let kind = &dep_kind::$name; if !kind.can_reconstruct_query_key() { Err(()) @@ -456,7 +456,7 @@ macro_rules! define_dep_nodes { fn has_label_string(label: &str) -> bool { match label { $( - stringify!($variant) => true, + stringify!($name) => true, )* _ => false, } @@ -468,7 +468,7 @@ macro_rules! define_dep_nodes { #[allow(dead_code, non_upper_case_globals)] pub mod label_strs { $( - pub const $variant: &str = stringify!($variant); + pub const $name: &str = stringify!($name); )* } ); From 42baef9e8ba83040c021d4cd0b3ba6528aea56b6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 17:37:26 +0200 Subject: [PATCH 17/18] Move DepNodeExt outside of the macro. --- .../rustc_middle/src/dep_graph/dep_node.rs | 163 +++++++++--------- 1 file changed, 78 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index c62ea38c0f7e5..4a991ad282282 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -375,91 +375,10 @@ macro_rules! define_dep_nodes { )* } - pub type DepNode = rustc_query_system::dep_graph::DepNode; - - pub trait DepNodeExt: Sized { - /// Construct a DepNode from the given DepKind and DefPathHash. This - /// method will assert that the given DepKind actually requires a - /// single DefId/DefPathHash parameter. - fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self; - - /// Extracts the DefId corresponding to this DepNode. This will work - /// if two conditions are met: - /// - /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and - /// 2. the item that the DefPath refers to exists in the current tcx. - /// - /// Condition (1) is determined by the DepKind variant of the - /// DepNode. Condition (2) might not be fulfilled if a DepNode - /// refers to something from the previous compilation session that - /// has been removed. - fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option; - - /// Used in testing - fn from_label_string(label: &str, def_path_hash: DefPathHash) - -> Result; - - /// Used in testing - fn has_label_string(label: &str) -> bool; - } - - impl DepNodeExt for DepNode { - /// Construct a DepNode from the given DepKind and DefPathHash. This - /// method will assert that the given DepKind actually requires a - /// single DefId/DefPathHash parameter. - fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode { - debug_assert!(kind.can_reconstruct_query_key() && kind.has_params()); - DepNode { - kind, - hash: def_path_hash.0, - } - } - - /// Extracts the DefId corresponding to this DepNode. This will work - /// if two conditions are met: - /// - /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and - /// 2. the item that the DefPath refers to exists in the current tcx. - /// - /// Condition (1) is determined by the DepKind variant of the - /// DepNode. Condition (2) might not be fulfilled if a DepNode - /// refers to something from the previous compilation session that - /// has been removed. - fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option { - if self.kind.can_reconstruct_query_key() { - let def_path_hash = DefPathHash(self.hash); - tcx.def_path_hash_to_def_id.as_ref()?.get(&def_path_hash).cloned() - } else { - None - } - } - - /// Used in testing - fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result { - match label { - $(stringify!($name) => { - let kind = &dep_kind::$name; - - if !kind.can_reconstruct_query_key() { - Err(()) - } else if kind.has_params() { - Ok(DepNode::from_def_path_hash(def_path_hash, kind)) - } else { - Ok(DepNode::new_no_params(kind)) - } - })* - _ => Err(()), - } - } - - /// Used in testing - fn has_label_string(label: &str) -> bool { - match label { - $( - stringify!($name) => true, - )* - _ => false, - } + fn dep_kind_from_label_string(label: &str) -> Result { + match label { + $(stringify!($name) => Ok(&dep_kind::$name),)* + _ => Err(()), } } @@ -728,6 +647,80 @@ impl Decodable for &dyn DepKindTrait { } } +pub type DepNode = rustc_query_system::dep_graph::DepNode; + +pub trait DepNodeExt: Sized { + /// Construct a DepNode from the given DepKind and DefPathHash. This + /// method will assert that the given DepKind actually requires a + /// single DefId/DefPathHash parameter. + fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self; + + /// Extracts the DefId corresponding to this DepNode. This will work + /// if two conditions are met: + /// + /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and + /// 2. the item that the DefPath refers to exists in the current tcx. + /// + /// Condition (1) is determined by the DepKind variant of the + /// DepNode. Condition (2) might not be fulfilled if a DepNode + /// refers to something from the previous compilation session that + /// has been removed. + fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option; + + /// Used in testing + fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result; + + /// Used in testing + fn has_label_string(label: &str) -> bool; +} + +impl DepNodeExt for DepNode { + /// Construct a DepNode from the given DepKind and DefPathHash. This + /// method will assert that the given DepKind actually requires a + /// single DefId/DefPathHash parameter. + fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode { + debug_assert!(kind.can_reconstruct_query_key() && kind.has_params()); + DepNode { kind, hash: def_path_hash.0 } + } + + /// Extracts the DefId corresponding to this DepNode. This will work + /// if two conditions are met: + /// + /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and + /// 2. the item that the DefPath refers to exists in the current tcx. + /// + /// Condition (1) is determined by the DepKind variant of the + /// DepNode. Condition (2) might not be fulfilled if a DepNode + /// refers to something from the previous compilation session that + /// has been removed. + fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option { + if self.kind.can_reconstruct_query_key() { + let def_path_hash = DefPathHash(self.hash); + tcx.def_path_hash_to_def_id.as_ref()?.get(&def_path_hash).cloned() + } else { + None + } + } + + /// Used in testing + fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result { + let kind = dep_kind_from_label_string(label)?; + + if !kind.can_reconstruct_query_key() { + Err(()) + } else if kind.has_params() { + Ok(DepNode::from_def_path_hash(def_path_hash, kind)) + } else { + Ok(DepNode::new_no_params(kind)) + } + } + + /// Used in testing + fn has_label_string(label: &str) -> bool { + dep_kind_from_label_string(label).is_ok() + } +} + impl<'tcx> DepNodeParams> for DefId { #[inline] fn can_reconstruct_query_key() -> bool { From 41720afcc71bcd3e52ce3910e811b0f8910b6123 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 24 Oct 2020 17:47:44 +0200 Subject: [PATCH 18/18] Sanitize DEP_KINDS arrays. --- compiler/rustc_middle/src/dep_graph/dep_node.rs | 7 +++++-- compiler/rustc_middle/src/dep_graph/mod.rs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 4a991ad282282..495ed6482abc7 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -348,13 +348,14 @@ macro_rules! define_dep_nodes { )* } + /// This enum serves as an index into the `DEP_KINDS` array. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[allow(non_camel_case_types)] pub enum DepKindIndex { $($name),* } - pub static DEP_KINDS: &[DepKind] = &[ $(&dep_kind::$name),* ]; + crate static DEP_KINDS: &[DepKind] = &[ $(&dep_kind::$name),* ]; pub struct DepConstructor; @@ -643,7 +644,9 @@ impl Encodable for &dyn DepKindTrait { impl Decodable for &dyn DepKindTrait { fn decode(dec: &mut D) -> Result { let idx = DepKindIndex::decode(dec)?; - Ok(DEP_KINDS[idx as usize]) + let dk = DEP_KINDS[idx as usize]; + debug_assert!(dk.index() == idx); + Ok(dk) } } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 29dd7441b6a2e..fcb124ace01a4 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -13,9 +13,9 @@ pub use rustc_query_system::dep_graph::{ WorkProduct, WorkProductId, }; +crate use dep_node::DEP_KINDS; pub use dep_node::{ dep_kind, label_strs, DepConstructor, DepKind, DepKindIndex, DepKindTrait, DepNode, DepNodeExt, - DEP_KINDS, }; pub type DepGraph = rustc_query_system::dep_graph::DepGraph;