Inform the query system about properties of queries at compile time
This commit is contained in:
parent
c877989655
commit
11221d120f
5 changed files with 58 additions and 32 deletions
|
@ -142,9 +142,6 @@ macro_rules! define_dep_nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Make `is_anon`, `is_eval_always` and `has_params` properties
|
|
||||||
// of queries
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn is_anon(&self) -> bool {
|
pub fn is_anon(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
$(
|
$(
|
||||||
|
@ -163,7 +160,6 @@ macro_rules! define_dep_nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
#[inline(always)]
|
|
||||||
pub fn has_params(&self) -> bool {
|
pub fn has_params(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
$(
|
$(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::dep_graph::SerializedDepNodeIndex;
|
use crate::dep_graph::SerializedDepNodeIndex;
|
||||||
use crate::dep_graph::DepNode;
|
use crate::dep_graph::{DepKind, DepNode};
|
||||||
use crate::hir::def_id::{CrateNum, DefId};
|
use crate::hir::def_id::{CrateNum, DefId};
|
||||||
use crate::ty::TyCtxt;
|
use crate::ty::TyCtxt;
|
||||||
use crate::ty::query::queries;
|
use crate::ty::query::queries;
|
||||||
|
@ -28,6 +28,9 @@ pub trait QueryConfig<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
|
pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
|
||||||
|
const ANON: bool;
|
||||||
|
const EVAL_ALWAYS: bool;
|
||||||
|
|
||||||
fn query(key: Self::Key) -> Query<'tcx>;
|
fn query(key: Self::Key) -> Query<'tcx>;
|
||||||
|
|
||||||
// Don't use this method to access query results, instead use the methods on TyCtxt
|
// Don't use this method to access query results, instead use the methods on TyCtxt
|
||||||
|
@ -35,6 +38,8 @@ pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
|
||||||
|
|
||||||
fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;
|
fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;
|
||||||
|
|
||||||
|
fn dep_kind() -> DepKind;
|
||||||
|
|
||||||
// Don't use this method to compute query results, instead use the methods on TyCtxt
|
// Don't use this method to compute query results, instead use the methods on TyCtxt
|
||||||
fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value;
|
fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value;
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,6 @@ pub use self::on_disk_cache::OnDiskCache;
|
||||||
rustc_query_append! { [define_queries!][ <'tcx>
|
rustc_query_append! { [define_queries!][ <'tcx>
|
||||||
Other {
|
Other {
|
||||||
/// Runs analysis passes on the crate.
|
/// Runs analysis passes on the crate.
|
||||||
[] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
|
[eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
|
|
@ -376,15 +376,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
return self.force_query_with_job::<Q>(key, job, null_dep_node).0;
|
return self.force_query_with_job::<Q>(key, job, null_dep_node).0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dep_node = Q::to_dep_node(self, &key);
|
if Q::ANON {
|
||||||
|
|
||||||
if dep_node.kind.is_anon() {
|
|
||||||
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
|
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
|
||||||
self.sess.profiler(|p| p.start_query(Q::NAME));
|
self.sess.profiler(|p| p.start_query(Q::NAME));
|
||||||
|
|
||||||
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
|
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
|
||||||
self.start_query(job.job.clone(), diagnostics, |tcx| {
|
self.start_query(job.job.clone(), diagnostics, |tcx| {
|
||||||
tcx.dep_graph.with_anon_task(dep_node.kind, || {
|
tcx.dep_graph.with_anon_task(Q::dep_kind(), || {
|
||||||
Q::compute(tcx.global_tcx(), key)
|
Q::compute(tcx.global_tcx(), key)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -405,7 +403,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dep_node.kind.is_eval_always() {
|
let dep_node = Q::to_dep_node(self, &key);
|
||||||
|
|
||||||
|
if !Q::EVAL_ALWAYS {
|
||||||
// The diagnostics for this query will be
|
// The diagnostics for this query will be
|
||||||
// promoted to the current session during
|
// promoted to the current session during
|
||||||
// try_mark_green(), so we can ignore them here.
|
// try_mark_green(), so we can ignore them here.
|
||||||
|
@ -546,7 +546,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
|
|
||||||
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
|
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
|
||||||
self.start_query(job.job.clone(), diagnostics, |tcx| {
|
self.start_query(job.job.clone(), diagnostics, |tcx| {
|
||||||
if dep_node.kind.is_eval_always() {
|
if Q::EVAL_ALWAYS {
|
||||||
tcx.dep_graph.with_eval_always_task(dep_node,
|
tcx.dep_graph.with_eval_always_task(dep_node,
|
||||||
tcx,
|
tcx,
|
||||||
key,
|
key,
|
||||||
|
@ -569,8 +569,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
|
self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if dep_node.kind != crate::dep_graph::DepKind::Null {
|
if unlikely!(!diagnostics.is_empty()) {
|
||||||
if unlikely!(!diagnostics.is_empty()) {
|
if dep_node.kind != crate::dep_graph::DepKind::Null {
|
||||||
self.queries.on_disk_cache
|
self.queries.on_disk_cache
|
||||||
.store_diagnostics(dep_node_index, diagnostics);
|
.store_diagnostics(dep_node_index, diagnostics);
|
||||||
}
|
}
|
||||||
|
@ -589,15 +589,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
///
|
///
|
||||||
/// Note: The optimization is only available during incr. comp.
|
/// Note: The optimization is only available during incr. comp.
|
||||||
pub(super) fn ensure_query<Q: QueryDescription<'tcx>>(self, key: Q::Key) -> () {
|
pub(super) fn ensure_query<Q: QueryDescription<'tcx>>(self, key: Q::Key) -> () {
|
||||||
let dep_node = Q::to_dep_node(self, &key);
|
if Q::EVAL_ALWAYS {
|
||||||
|
|
||||||
if dep_node.kind.is_eval_always() {
|
|
||||||
let _ = self.get_query::<Q>(DUMMY_SP, key);
|
let _ = self.get_query::<Q>(DUMMY_SP, key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensuring an anonymous query makes no sense
|
// Ensuring an anonymous query makes no sense
|
||||||
assert!(!dep_node.kind.is_anon());
|
assert!(!Q::ANON);
|
||||||
|
|
||||||
|
let dep_node = Q::to_dep_node(self, &key);
|
||||||
|
|
||||||
if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
|
if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
|
||||||
// A None return from `try_mark_green_and_read` means that this is either
|
// A None return from `try_mark_green_and_read` means that this is either
|
||||||
// a new dep node or that the dep node has already been marked red.
|
// a new dep node or that the dep node has already been marked red.
|
||||||
|
@ -653,6 +654,30 @@ macro_rules! handle_cycle_error {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! is_anon {
|
||||||
|
([]) => {{
|
||||||
|
false
|
||||||
|
}};
|
||||||
|
([anon$(, $modifiers:ident)*]) => {{
|
||||||
|
true
|
||||||
|
}};
|
||||||
|
([$other:ident$(, $modifiers:ident)*]) => {
|
||||||
|
is_anon!([$($modifiers),*])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! is_eval_always {
|
||||||
|
([]) => {{
|
||||||
|
false
|
||||||
|
}};
|
||||||
|
([eval_always$(, $modifiers:ident)*]) => {{
|
||||||
|
true
|
||||||
|
}};
|
||||||
|
([$other:ident$(, $modifiers:ident)*]) => {
|
||||||
|
is_eval_always!([$($modifiers),*])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! hash_result {
|
macro_rules! hash_result {
|
||||||
([][$hcx:expr, $result:expr]) => {{
|
([][$hcx:expr, $result:expr]) => {{
|
||||||
dep_graph::hash_result($hcx, &$result)
|
dep_graph::hash_result($hcx, &$result)
|
||||||
|
@ -933,6 +958,9 @@ macro_rules! define_queries_inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> {
|
impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> {
|
||||||
|
const ANON: bool = is_anon!([$($modifiers)*]);
|
||||||
|
const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]);
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn query(key: Self::Key) -> Query<'tcx> {
|
fn query(key: Self::Key) -> Query<'tcx> {
|
||||||
Query::$name(key)
|
Query::$name(key)
|
||||||
|
@ -951,6 +979,11 @@ macro_rules! define_queries_inner {
|
||||||
DepNode::new(tcx, $node(*key))
|
DepNode::new(tcx, $node(*key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn dep_kind() -> dep_graph::DepKind {
|
||||||
|
dep_graph::DepKind::$node
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
|
fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
|
||||||
__query_compute::$name(move || {
|
__query_compute::$name(move || {
|
||||||
|
|
|
@ -423,20 +423,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||||
if modifiers.no_hash {
|
if modifiers.no_hash {
|
||||||
attributes.push(quote! { no_hash });
|
attributes.push(quote! { no_hash });
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut attribute_stream = quote! {};
|
|
||||||
|
|
||||||
for e in attributes.into_iter().intersperse(quote! {,}) {
|
|
||||||
attribute_stream.extend(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the query to the group
|
|
||||||
group_stream.extend(quote! {
|
|
||||||
[#attribute_stream] fn #name: #name(#arg) #result,
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut attributes = Vec::new();
|
|
||||||
|
|
||||||
// Pass on the anon modifier
|
// Pass on the anon modifier
|
||||||
if modifiers.anon {
|
if modifiers.anon {
|
||||||
attributes.push(quote! { anon });
|
attributes.push(quote! { anon });
|
||||||
|
@ -450,6 +436,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||||
for e in attributes.into_iter().intersperse(quote! {,}) {
|
for e in attributes.into_iter().intersperse(quote! {,}) {
|
||||||
attribute_stream.extend(e);
|
attribute_stream.extend(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the query to the group
|
||||||
|
group_stream.extend(quote! {
|
||||||
|
[#attribute_stream] fn #name: #name(#arg) #result,
|
||||||
|
});
|
||||||
|
|
||||||
// Create a dep node for the query
|
// Create a dep node for the query
|
||||||
dep_node_def_stream.extend(quote! {
|
dep_node_def_stream.extend(quote! {
|
||||||
[#attribute_stream] #name(#arg),
|
[#attribute_stream] #name(#arg),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue