expand fuzzing support
this allows us to only sometimes disable the global cache.
This commit is contained in:
parent
7b86c98068
commit
51338ca0eb
@ -1,3 +1,4 @@
|
||||
use std::convert::Infallible;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_type_ir::inherent::*;
|
||||
@ -22,6 +23,14 @@ impl<D, I> search_graph::Delegate for SearchGraphDelegate<D>
|
||||
{
|
||||
type Cx = D::Interner;
|
||||
|
||||
type ValidationScope = Infallible;
|
||||
fn enter_validation_scope(
|
||||
_cx: Self::Cx,
|
||||
_input: <Self::Cx as search_graph::Cx>::Input,
|
||||
) -> Option<Self::ValidationScope> {
|
||||
None
|
||||
}
|
||||
|
||||
const FIXPOINT_STEP_LIMIT: usize = FIXPOINT_STEP_LIMIT;
|
||||
|
||||
type ProofTreeBuilder = ProofTreeBuilder<D>;
|
||||
|
@ -44,6 +44,19 @@ fn with_global_cache<R>(
|
||||
|
||||
pub trait Delegate {
|
||||
type Cx: Cx;
|
||||
type ValidationScope;
|
||||
/// Returning `Some` disables the global cache for the current goal.
|
||||
///
|
||||
/// The `ValidationScope` is used when fuzzing the search graph to track
|
||||
/// for which goals the global cache has been disabled. This is necessary
|
||||
/// as we may otherwise ignore the global cache entry for some goal `G`
|
||||
/// only to later use it, failing to detect a cycle goal and potentially
|
||||
/// changing the result.
|
||||
fn enter_validation_scope(
|
||||
cx: Self::Cx,
|
||||
input: <Self::Cx as Cx>::Input,
|
||||
) -> Option<Self::ValidationScope>;
|
||||
|
||||
const FIXPOINT_STEP_LIMIT: usize;
|
||||
|
||||
type ProofTreeBuilder;
|
||||
@ -356,11 +369,21 @@ pub fn with_new_goal(
|
||||
return D::on_stack_overflow(cx, inspect, input);
|
||||
};
|
||||
|
||||
if D::inspect_is_noop(inspect) {
|
||||
if let Some(result) = self.lookup_global_cache(cx, input, available_depth) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
let validate_cache = if !D::inspect_is_noop(inspect) {
|
||||
None
|
||||
} else if let Some(scope) = D::enter_validation_scope(cx, input) {
|
||||
// When validating the global cache we need to track the goals for which the
|
||||
// global cache has been disabled as it may otherwise change the result for
|
||||
// cyclic goals. We don't care about goals which are not on the current stack
|
||||
// so it's fine to drop their scope eagerly.
|
||||
self.lookup_global_cache_untracked(cx, input, available_depth)
|
||||
.inspect(|expected| debug!(?expected, "validate cache entry"))
|
||||
.map(|r| (scope, r))
|
||||
} else if let Some(result) = self.lookup_global_cache(cx, input, available_depth) {
|
||||
return result;
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Check whether the goal is in the provisional cache.
|
||||
// The provisional result may rely on the path to its cycle roots,
|
||||
@ -452,6 +475,7 @@ pub fn with_new_goal(
|
||||
// do not remove it from the provisional cache and update its provisional result.
|
||||
// We only add the root of cycles to the global cache.
|
||||
if let Some(head) = final_entry.non_root_cycle_participant {
|
||||
debug_assert!(validate_cache.is_none());
|
||||
let coinductive_stack = Self::stack_coinductive_from(cx, &self.stack, head);
|
||||
|
||||
let entry = self.provisional_cache.get_mut(&input).unwrap();
|
||||
@ -463,16 +487,29 @@ pub fn with_new_goal(
|
||||
}
|
||||
} else {
|
||||
self.provisional_cache.remove(&input);
|
||||
if D::inspect_is_noop(inspect) {
|
||||
if let Some((_scope, expected)) = validate_cache {
|
||||
// Do not try to move a goal into the cache again if we're testing
|
||||
// the global cache.
|
||||
assert_eq!(result, expected, "input={input:?}");
|
||||
} else if D::inspect_is_noop(inspect) {
|
||||
self.insert_global_cache(cx, input, final_entry, result, dep_node)
|
||||
}
|
||||
}
|
||||
|
||||
self.check_invariants();
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn lookup_global_cache_untracked(
|
||||
&self,
|
||||
cx: X,
|
||||
input: X::Input,
|
||||
available_depth: AvailableDepth,
|
||||
) -> Option<X::Result> {
|
||||
cx.with_global_cache(self.mode, |cache| {
|
||||
cache.get(cx, input, &self.stack, available_depth).map(|c| c.result)
|
||||
})
|
||||
}
|
||||
|
||||
/// Try to fetch a previously computed result from the global cache,
|
||||
/// making sure to only do so if it would match the result of reevaluating
|
||||
/// this goal.
|
||||
@ -496,7 +533,7 @@ fn lookup_global_cache(
|
||||
let reached_depth = self.stack.next_index().plus(additional_depth);
|
||||
self.update_parent_goal(reached_depth, encountered_overflow);
|
||||
|
||||
debug!("global cache hit");
|
||||
debug!(?additional_depth, "global cache hit");
|
||||
Some(result)
|
||||
})
|
||||
}
|
||||
@ -518,6 +555,7 @@ fn insert_global_cache(
|
||||
dep_node: X::DepNodeIndex,
|
||||
) {
|
||||
let additional_depth = final_entry.reached_depth.as_usize() - self.stack.len();
|
||||
debug!(?final_entry, ?result, "insert global cache");
|
||||
cx.with_global_cache(self.mode, |cache| {
|
||||
cache.insert(
|
||||
cx,
|
||||
|
Loading…
Reference in New Issue
Block a user