Skip to content

Commit 1ca103a

Browse files
committed
Ensure value is on the on-disk cache before returning.
1 parent 8a73f50 commit 1ca103a

File tree

5 files changed

+53
-9
lines changed

5 files changed

+53
-9
lines changed

compiler/rustc_query_impl/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use rustc_span::Span;
3131
#[macro_use]
3232
mod plumbing;
3333
pub use plumbing::QueryCtxt;
34+
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
3435
use rustc_query_system::query::*;
3536
#[cfg(parallel_compiler)]
3637
pub use rustc_query_system::query::{deadlock, QueryContext};

compiler/rustc_query_impl/src/on_disk_cache.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,12 @@ impl<'sess> OnDiskCache<'sess> {
388388
debug_assert!(prev.is_none());
389389
}
390390

391+
/// Return whether the cached query result can be decoded.
392+
pub fn loadable_from_disk(&self, dep_node_index: SerializedDepNodeIndex) -> bool {
393+
self.query_result_index.contains_key(&dep_node_index)
394+
// with_decoder is infallible, so we can stop here
395+
}
396+
391397
/// Returns the cached query result if there is something in the cache for
392398
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
393399
pub fn try_load_query_result<'tcx, T>(
@@ -398,7 +404,9 @@ impl<'sess> OnDiskCache<'sess> {
398404
where
399405
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
400406
{
401-
self.load_indexed(tcx, dep_node_index, &self.query_result_index)
407+
let opt_value = self.load_indexed(tcx, dep_node_index, &self.query_result_index);
408+
debug_assert_eq!(opt_value.is_some(), self.loadable_from_disk(dep_node_index));
409+
opt_value
402410
}
403411

404412
/// Stores side effect emitted during computation of an anonymous query.
@@ -428,8 +436,8 @@ impl<'sess> OnDiskCache<'sess> {
428436
T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
429437
{
430438
let pos = index.get(&dep_node_index).cloned()?;
431-
432-
self.with_decoder(tcx, pos, |decoder| Some(decode_tagged(decoder, dep_node_index)))
439+
let value = self.with_decoder(tcx, pos, |decoder| decode_tagged(decoder, dep_node_index));
440+
Some(value)
433441
}
434442

435443
fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>(

compiler/rustc_query_impl/src/plumbing.rs

+23
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,14 @@ where
364364
}
365365
}
366366

367+
pub(crate) fn loadable_from_disk<'tcx>(tcx: QueryCtxt<'tcx>, id: SerializedDepNodeIndex) -> bool {
368+
if let Some(cache) = tcx.on_disk_cache().as_ref() {
369+
cache.loadable_from_disk(id)
370+
} else {
371+
false
372+
}
373+
}
374+
367375
pub(crate) fn try_load_from_disk<'tcx, V>(
368376
tcx: QueryCtxt<'tcx>,
369377
id: SerializedDepNodeIndex,
@@ -535,6 +543,21 @@ macro_rules! define_queries {
535543
})
536544
}
537545

546+
#[inline]
547+
fn loadable_from_disk(
548+
self,
549+
_qcx: QueryCtxt<'tcx>,
550+
_key: &Self::Key,
551+
_index: SerializedDepNodeIndex,
552+
) -> bool {
553+
should_ever_cache_on_disk!([$($modifiers)*] {
554+
self.cache_on_disk(_qcx.tcx, _key) &&
555+
$crate::plumbing::loadable_from_disk(_qcx, _index)
556+
} {
557+
false
558+
})
559+
}
560+
538561
#[inline(always)]
539562
fn anon(self) -> bool {
540563
is_anon!([$($modifiers)*])

compiler/rustc_query_system/src/query/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ pub trait QueryConfig<Qcx: QueryContext>: Copy {
4343

4444
fn try_load_from_disk(self, qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self::Value>;
4545

46+
fn loadable_from_disk(self, qcx: Qcx, key: &Self::Key, idx: SerializedDepNodeIndex) -> bool;
47+
4648
fn anon(self) -> bool;
4749
fn eval_always(self) -> bool;
4850
fn depth_limit(self) -> bool;

compiler/rustc_query_system/src/query/plumbing.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -557,10 +557,17 @@ where
557557
// can be forced from `DepNode`.
558558
debug_assert!(
559559
!qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(),
560-
"missing on-disk cache entry for {dep_node:?}"
560+
"missing on-disk cache entry for reconstructible {dep_node:?}"
561561
);
562562
}
563563

564+
// Sanity check for the logic in `ensure`: if the node is green and the result loadable,
565+
// we should actually be able to load it.
566+
debug_assert!(
567+
!query.loadable_from_disk(qcx, &key, prev_dep_node_index),
568+
"missing on-disk cache entry for loadable {dep_node:?}"
569+
);
570+
564571
// We could not load a result from the on-disk cache, so
565572
// recompute.
566573
let prof_timer = qcx.dep_context().profiler().query_provider();
@@ -719,22 +726,25 @@ where
719726
let dep_node = query.construct_dep_node(*qcx.dep_context(), key);
720727

721728
let dep_graph = qcx.dep_context().dep_graph();
722-
match dep_graph.try_mark_green(qcx, &dep_node) {
729+
let serialized_dep_node_index = match dep_graph.try_mark_green(qcx, &dep_node) {
723730
None => {
724731
// A None return from `try_mark_green` means that this is either
725732
// a new dep node or that the dep node has already been marked red.
726733
// Either way, we can't call `dep_graph.read()` as we don't have the
727734
// DepNodeIndex. We must invoke the query itself. The performance cost
728735
// this introduces should be negligible as we'll immediately hit the
729736
// in-memory cache, or another query down the line will.
730-
(true, Some(dep_node))
737+
return (true, Some(dep_node));
731738
}
732-
Some((_, dep_node_index)) => {
739+
Some((serialized_dep_node_index, dep_node_index)) => {
733740
dep_graph.read_index(dep_node_index);
734741
qcx.dep_context().profiler().query_cache_hit(dep_node_index.into());
735-
(false, None)
742+
serialized_dep_node_index
736743
}
737-
}
744+
};
745+
746+
let loadable = query.loadable_from_disk(qcx, key, serialized_dep_node_index);
747+
(!loadable, Some(dep_node))
738748
}
739749

740750
#[derive(Debug)]

0 commit comments

Comments
 (0)