split GoalEvaluation and CanonicalGoalEvaluation

the unnormalized goal is in the callers inference context, while
anything inside of the `CanonicalGoalEvaluation` is inside of
a new one.
This commit is contained in:
lcnr 2023-08-14 11:29:42 +02:00
parent 7d1e416d32
commit fc452e2ed3
5 changed files with 141 additions and 110 deletions

View File

@ -16,12 +16,15 @@ pub enum CacheHit {
#[derive(Eq, PartialEq, Hash, HashStable)] #[derive(Eq, PartialEq, Hash, HashStable)]
pub struct GoalEvaluation<'tcx> { pub struct GoalEvaluation<'tcx> {
pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>,
pub canonicalized_goal: CanonicalInput<'tcx>,
pub kind: GoalEvaluationKind<'tcx>,
pub is_normalizes_to_hack: IsNormalizesToHack, pub is_normalizes_to_hack: IsNormalizesToHack,
pub evaluation: CanonicalGoalEvaluation<'tcx>,
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>, pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
}
#[derive(Eq, PartialEq, Hash, HashStable)]
pub struct CanonicalGoalEvaluation<'tcx> {
pub goal: CanonicalInput<'tcx>,
pub kind: GoalEvaluationKind<'tcx>,
pub result: QueryResult<'tcx>, pub result: QueryResult<'tcx>,
} }
@ -41,30 +44,20 @@ pub struct AddedGoalsEvaluation<'tcx> {
pub evaluations: Vec<Vec<GoalEvaluation<'tcx>>>, pub evaluations: Vec<Vec<GoalEvaluation<'tcx>>>,
pub result: Result<Certainty, NoSolution>, pub result: Result<Certainty, NoSolution>,
} }
impl Debug for AddedGoalsEvaluation<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
ProofTreeFormatter::new(f).format_nested_goal_evaluation(self)
}
}
#[derive(Eq, PartialEq, Hash, HashStable)] #[derive(Eq, PartialEq, Hash, HashStable)]
pub struct GoalEvaluationStep<'tcx> { pub struct GoalEvaluationStep<'tcx> {
pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>, pub added_goals_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
pub candidates: Vec<GoalCandidate<'tcx>>, pub candidates: Vec<GoalCandidate<'tcx>>,
pub result: QueryResult<'tcx>, pub result: QueryResult<'tcx>,
} }
impl Debug for GoalEvaluationStep<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
ProofTreeFormatter::new(f).format_evaluation_step(self)
}
}
#[derive(Eq, PartialEq, Hash, HashStable)] #[derive(Eq, PartialEq, Hash, HashStable)]
pub struct GoalCandidate<'tcx> { pub struct GoalCandidate<'tcx> {
pub nested_goal_evaluations: Vec<AddedGoalsEvaluation<'tcx>>, pub added_goals_evaluations: Vec<AddedGoalsEvaluation<'tcx>>,
pub candidates: Vec<GoalCandidate<'tcx>>, pub candidates: Vec<GoalCandidate<'tcx>>,
pub kind: CandidateKind<'tcx>, pub kind: CandidateKind<'tcx>,
} }
@ -83,8 +76,3 @@ pub enum CandidateKind<'tcx> {
/// the source type upholds all of the target type's object bounds. /// the source type upholds all of the target type's object bounds.
UpcastProbe, UpcastProbe,
} }
impl Debug for GoalCandidate<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
ProofTreeFormatter::new(f).format_candidate(self)
}
}

View File

@ -39,44 +39,49 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } }) func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } })
} }
pub(super) fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result { pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result {
let goal_text = match goal.is_normalizes_to_hack { let goal_text = match eval.is_normalizes_to_hack {
IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL", IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
IsNormalizesToHack::No => "GOAL", IsNormalizesToHack::No => "GOAL",
}; };
writeln!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?;
self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation))?;
if eval.returned_goals.len() > 0 {
writeln!(self.f, "NESTED GOALS ADDED TO CALLER: [")?;
self.nested(|this| {
for goal in eval.returned_goals.iter() {
writeln!(this.f, "ADDED GOAL: {goal:?},")?;
}
Ok(())
})?;
writeln!(self.f, "{}: {:?}", goal_text, goal.uncanonicalized_goal)?; writeln!(self.f, "]")
writeln!(self.f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?; } else {
Ok(())
}
}
match &goal.kind { pub(super) fn format_canonical_goal_evaluation(
&mut self,
eval: &CanonicalGoalEvaluation<'_>,
) -> std::fmt::Result {
writeln!(self.f, "GOAL: {:?}", eval.goal)?;
match &eval.kind {
GoalEvaluationKind::CacheHit(CacheHit::Global) => { GoalEvaluationKind::CacheHit(CacheHit::Global) => {
writeln!(self.f, "GLOBAL CACHE HIT: {:?}", goal.result) writeln!(self.f, "GLOBAL CACHE HIT: {:?}", eval.result)
} }
GoalEvaluationKind::CacheHit(CacheHit::Provisional) => { GoalEvaluationKind::CacheHit(CacheHit::Provisional) => {
writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", goal.result) writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result)
} }
GoalEvaluationKind::Uncached { revisions } => { GoalEvaluationKind::Uncached { revisions } => {
for (n, step) in revisions.iter().enumerate() { for (n, step) in revisions.iter().enumerate() {
writeln!(self.f, "REVISION {n}: {:?}", step.result)?; writeln!(self.f, "REVISION {n}: {:?}", step.result)?;
self.nested(|this| this.format_evaluation_step(step))?; self.nested(|this| this.format_evaluation_step(step))?;
} }
writeln!(self.f, "RESULT: {:?}", goal.result) writeln!(self.f, "RESULT: {:?}", eval.result)
} }
}?;
if goal.returned_goals.len() > 0 {
writeln!(self.f, "NESTED GOALS ADDED TO CALLER: [")?;
self.nested(|this| {
for goal in goal.returned_goals.iter() {
writeln!(this.f, "ADDED GOAL: {goal:?},")?;
}
Ok(())
})?;
writeln!(self.f, "]")?;
} }
Ok(())
} }
pub(super) fn format_evaluation_step( pub(super) fn format_evaluation_step(
@ -88,8 +93,8 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
for candidate in &evaluation_step.candidates { for candidate in &evaluation_step.candidates {
self.nested(|this| this.format_candidate(candidate))?; self.nested(|this| this.format_candidate(candidate))?;
} }
for nested in &evaluation_step.nested_goal_evaluations { for nested in &evaluation_step.added_goals_evaluations {
self.nested(|this| this.format_nested_goal_evaluation(nested))?; self.nested(|this| this.format_added_goals_evaluation(nested))?;
} }
Ok(()) Ok(())
@ -115,20 +120,20 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
for candidate in &candidate.candidates { for candidate in &candidate.candidates {
this.format_candidate(candidate)?; this.format_candidate(candidate)?;
} }
for nested in &candidate.nested_goal_evaluations { for nested in &candidate.added_goals_evaluations {
this.format_nested_goal_evaluation(nested)?; this.format_added_goals_evaluation(nested)?;
} }
Ok(()) Ok(())
}) })
} }
pub(super) fn format_nested_goal_evaluation( pub(super) fn format_added_goals_evaluation(
&mut self, &mut self,
nested_goal_evaluation: &AddedGoalsEvaluation<'_>, added_goals_evaluation: &AddedGoalsEvaluation<'_>,
) -> std::fmt::Result { ) -> std::fmt::Result {
writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", nested_goal_evaluation.result)?; writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?;
for (n, revision) in nested_goal_evaluation.evaluations.iter().enumerate() { for (n, revision) in added_goals_evaluation.evaluations.iter().enumerate() {
writeln!(self.f, "REVISION {n}")?; writeln!(self.f, "REVISION {n}")?;
self.nested(|this| { self.nested(|this| {
for goal_evaluation in revision { for goal_evaluation in revision {

View File

@ -237,7 +237,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
search_graph: &'a mut search_graph::SearchGraph<'tcx>, search_graph: &'a mut search_graph::SearchGraph<'tcx>,
canonical_input: CanonicalInput<'tcx>, canonical_input: CanonicalInput<'tcx>,
goal_evaluation: &mut ProofTreeBuilder<'tcx>, canonical_goal_evaluation: &mut ProofTreeBuilder<'tcx>,
f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>, Goal<'tcx, ty::Predicate<'tcx>>) -> R, f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>, Goal<'tcx, ty::Predicate<'tcx>>) -> R,
) -> R { ) -> R {
let intercrate = match search_graph.solver_mode() { let intercrate = match search_graph.solver_mode() {
@ -260,7 +260,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
search_graph, search_graph,
nested_goals: NestedGoals::new(), nested_goals: NestedGoals::new(),
tainted: Ok(()), tainted: Ok(()),
inspect: goal_evaluation.new_goal_evaluation_step(input), inspect: canonical_goal_evaluation.new_goal_evaluation_step(input),
}; };
for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
@ -274,7 +274,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
let result = f(&mut ecx, input.goal); let result = f(&mut ecx, input.goal);
goal_evaluation.goal_evaluation_step(ecx.inspect); canonical_goal_evaluation.goal_evaluation_step(ecx.inspect);
// When creating a query response we clone the opaque type constraints // When creating a query response we clone the opaque type constraints
// instead of taking them. This would cause an ICE here, since we have // instead of taking them. This would cause an ICE here, since we have
@ -302,24 +302,25 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
search_graph: &'a mut search_graph::SearchGraph<'tcx>, search_graph: &'a mut search_graph::SearchGraph<'tcx>,
canonical_input: CanonicalInput<'tcx>, canonical_input: CanonicalInput<'tcx>,
mut goal_evaluation: &mut ProofTreeBuilder<'tcx>, goal_evaluation: &mut ProofTreeBuilder<'tcx>,
) -> QueryResult<'tcx> { ) -> QueryResult<'tcx> {
goal_evaluation.canonicalized_goal(canonical_input); let mut canonical_goal_evaluation =
goal_evaluation.new_canonical_goal_evaluation(canonical_input);
// Deal with overflow, caching, and coinduction. // Deal with overflow, caching, and coinduction.
// //
// The actual solver logic happens in `ecx.compute_goal`. // The actual solver logic happens in `ecx.compute_goal`.
ensure_sufficient_stack(|| { let result = ensure_sufficient_stack(|| {
search_graph.with_new_goal( search_graph.with_new_goal(
tcx, tcx,
canonical_input, canonical_input,
goal_evaluation, &mut canonical_goal_evaluation,
|search_graph, goal_evaluation| { |search_graph, canonical_goal_evaluation| {
EvalCtxt::enter_canonical( EvalCtxt::enter_canonical(
tcx, tcx,
search_graph, search_graph,
canonical_input, canonical_input,
goal_evaluation, canonical_goal_evaluation,
|ecx, goal| { |ecx, goal| {
let result = ecx.compute_goal(goal); let result = ecx.compute_goal(goal);
ecx.inspect.query_result(result); ecx.inspect.query_result(result);
@ -328,7 +329,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
) )
}, },
) )
}) });
canonical_goal_evaluation.query_result(result);
goal_evaluation.canonical_goal_evaluation(canonical_goal_evaluation);
result
} }
/// Recursively evaluates `goal`, returning whether any inference vars have /// Recursively evaluates `goal`, returning whether any inference vars have
@ -347,7 +352,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
canonical_goal, canonical_goal,
&mut goal_evaluation, &mut goal_evaluation,
); );
goal_evaluation.query_result(canonical_response);
let canonical_response = match canonical_response { let canonical_response = match canonical_response {
Err(e) => { Err(e) => {
self.inspect.goal_evaluation(goal_evaluation); self.inspect.goal_evaluation(goal_evaluation);

View File

@ -12,36 +12,47 @@ use super::GenerateProofTree;
#[derive(Eq, PartialEq, Debug, Hash, HashStable)] #[derive(Eq, PartialEq, Debug, Hash, HashStable)]
pub struct WipGoalEvaluation<'tcx> { pub struct WipGoalEvaluation<'tcx> {
pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>, pub uncanonicalized_goal: Goal<'tcx, ty::Predicate<'tcx>>,
pub canonicalized_goal: Option<CanonicalInput<'tcx>>, pub evaluation: Option<WipCanonicalGoalEvaluation<'tcx>>,
pub evaluation_steps: Vec<WipGoalEvaluationStep<'tcx>>,
pub cache_hit: Option<CacheHit>,
pub is_normalizes_to_hack: IsNormalizesToHack, pub is_normalizes_to_hack: IsNormalizesToHack,
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>, pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
pub result: Option<QueryResult<'tcx>>,
} }
impl<'tcx> WipGoalEvaluation<'tcx> { impl<'tcx> WipGoalEvaluation<'tcx> {
pub fn finalize(self) -> inspect::GoalEvaluation<'tcx> { pub fn finalize(self) -> inspect::GoalEvaluation<'tcx> {
inspect::GoalEvaluation { inspect::GoalEvaluation {
uncanonicalized_goal: self.uncanonicalized_goal, uncanonicalized_goal: self.uncanonicalized_goal,
canonicalized_goal: self.canonicalized_goal.unwrap(), evaluation: self.evaluation.unwrap().finalize(),
kind: match self.cache_hit { is_normalizes_to_hack: self.is_normalizes_to_hack,
Some(hit) => inspect::GoalEvaluationKind::CacheHit(hit), returned_goals: self.returned_goals,
None => inspect::GoalEvaluationKind::Uncached { }
}
}
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
pub struct WipCanonicalGoalEvaluation<'tcx> {
pub goal: CanonicalInput<'tcx>,
pub cache_hit: Option<CacheHit>,
pub evaluation_steps: Vec<WipGoalEvaluationStep<'tcx>>,
pub result: Option<QueryResult<'tcx>>,
}
impl<'tcx> WipCanonicalGoalEvaluation<'tcx> {
pub fn finalize(self) -> inspect::CanonicalGoalEvaluation<'tcx> {
let kind = match self.cache_hit {
Some(hit) => inspect::GoalEvaluationKind::CacheHit(hit),
None => {
assert!(!self.evaluation_steps.is_empty());
inspect::GoalEvaluationKind::Uncached {
revisions: self revisions: self
.evaluation_steps .evaluation_steps
.into_iter() .into_iter()
.map(WipGoalEvaluationStep::finalize) .map(WipGoalEvaluationStep::finalize)
.collect(), .collect(),
}, }
}, }
is_normalizes_to_hack: self.is_normalizes_to_hack, };
returned_goals: self.returned_goals,
result: self.result.unwrap(), inspect::CanonicalGoalEvaluation { goal: self.goal, kind, result: self.result.unwrap() }
}
} }
} }
@ -70,7 +81,7 @@ impl<'tcx> WipAddedGoalsEvaluation<'tcx> {
pub struct WipGoalEvaluationStep<'tcx> { pub struct WipGoalEvaluationStep<'tcx> {
pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>, pub instantiated_goal: QueryInput<'tcx, ty::Predicate<'tcx>>,
pub nested_goal_evaluations: Vec<WipAddedGoalsEvaluation<'tcx>>, pub added_goals_evaluations: Vec<WipAddedGoalsEvaluation<'tcx>>,
pub candidates: Vec<WipGoalCandidate<'tcx>>, pub candidates: Vec<WipGoalCandidate<'tcx>>,
pub result: Option<QueryResult<'tcx>>, pub result: Option<QueryResult<'tcx>>,
@ -80,8 +91,8 @@ impl<'tcx> WipGoalEvaluationStep<'tcx> {
pub fn finalize(self) -> inspect::GoalEvaluationStep<'tcx> { pub fn finalize(self) -> inspect::GoalEvaluationStep<'tcx> {
inspect::GoalEvaluationStep { inspect::GoalEvaluationStep {
instantiated_goal: self.instantiated_goal, instantiated_goal: self.instantiated_goal,
nested_goal_evaluations: self added_goals_evaluations: self
.nested_goal_evaluations .added_goals_evaluations
.into_iter() .into_iter()
.map(WipAddedGoalsEvaluation::finalize) .map(WipAddedGoalsEvaluation::finalize)
.collect(), .collect(),
@ -93,7 +104,7 @@ impl<'tcx> WipGoalEvaluationStep<'tcx> {
#[derive(Eq, PartialEq, Debug, Hash, HashStable)] #[derive(Eq, PartialEq, Debug, Hash, HashStable)]
pub struct WipGoalCandidate<'tcx> { pub struct WipGoalCandidate<'tcx> {
pub nested_goal_evaluations: Vec<WipAddedGoalsEvaluation<'tcx>>, pub added_goals_evaluations: Vec<WipAddedGoalsEvaluation<'tcx>>,
pub candidates: Vec<WipGoalCandidate<'tcx>>, pub candidates: Vec<WipGoalCandidate<'tcx>>,
pub kind: Option<CandidateKind<'tcx>>, pub kind: Option<CandidateKind<'tcx>>,
} }
@ -101,8 +112,8 @@ pub struct WipGoalCandidate<'tcx> {
impl<'tcx> WipGoalCandidate<'tcx> { impl<'tcx> WipGoalCandidate<'tcx> {
pub fn finalize(self) -> inspect::GoalCandidate<'tcx> { pub fn finalize(self) -> inspect::GoalCandidate<'tcx> {
inspect::GoalCandidate { inspect::GoalCandidate {
nested_goal_evaluations: self added_goals_evaluations: self
.nested_goal_evaluations .added_goals_evaluations
.into_iter() .into_iter()
.map(WipAddedGoalsEvaluation::finalize) .map(WipAddedGoalsEvaluation::finalize)
.collect(), .collect(),
@ -116,6 +127,7 @@ impl<'tcx> WipGoalCandidate<'tcx> {
pub enum DebugSolver<'tcx> { pub enum DebugSolver<'tcx> {
Root, Root,
GoalEvaluation(WipGoalEvaluation<'tcx>), GoalEvaluation(WipGoalEvaluation<'tcx>),
CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<'tcx>),
AddedGoalsEvaluation(WipAddedGoalsEvaluation<'tcx>), AddedGoalsEvaluation(WipAddedGoalsEvaluation<'tcx>),
GoalEvaluationStep(WipGoalEvaluationStep<'tcx>), GoalEvaluationStep(WipGoalEvaluationStep<'tcx>),
GoalCandidate(WipGoalCandidate<'tcx>), GoalCandidate(WipGoalCandidate<'tcx>),
@ -127,6 +139,12 @@ impl<'tcx> From<WipGoalEvaluation<'tcx>> for DebugSolver<'tcx> {
} }
} }
impl<'tcx> From<WipCanonicalGoalEvaluation<'tcx>> for DebugSolver<'tcx> {
fn from(g: WipCanonicalGoalEvaluation<'tcx>) -> DebugSolver<'tcx> {
DebugSolver::CanonicalGoalEvaluation(g)
}
}
impl<'tcx> From<WipAddedGoalsEvaluation<'tcx>> for DebugSolver<'tcx> { impl<'tcx> From<WipAddedGoalsEvaluation<'tcx>> for DebugSolver<'tcx> {
fn from(g: WipAddedGoalsEvaluation<'tcx>) -> DebugSolver<'tcx> { fn from(g: WipAddedGoalsEvaluation<'tcx>) -> DebugSolver<'tcx> {
DebugSolver::AddedGoalsEvaluation(g) DebugSolver::AddedGoalsEvaluation(g)
@ -243,21 +261,35 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
self.nested(WipGoalEvaluation { self.nested(WipGoalEvaluation {
uncanonicalized_goal: goal, uncanonicalized_goal: goal,
canonicalized_goal: None, evaluation: None,
evaluation_steps: vec![],
is_normalizes_to_hack, is_normalizes_to_hack,
cache_hit: None,
returned_goals: vec![], returned_goals: vec![],
})
}
pub fn new_canonical_goal_evaluation(
&mut self,
goal: CanonicalInput<'tcx>,
) -> ProofTreeBuilder<'tcx> {
if self.state.is_none() {
return ProofTreeBuilder { state: None };
}
self.nested(WipCanonicalGoalEvaluation {
goal,
cache_hit: None,
evaluation_steps: vec![],
result: None, result: None,
}) })
} }
pub fn canonicalized_goal(&mut self, canonical_goal: CanonicalInput<'tcx>) { pub fn canonical_goal_evaluation(&mut self, canonical_goal_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() { if let Some(this) = self.as_mut() {
match this { match (this, canonical_goal_evaluation.state.unwrap().tree) {
DebugSolver::GoalEvaluation(goal_evaluation) => { (
assert_eq!(goal_evaluation.canonicalized_goal.replace(canonical_goal), None); DebugSolver::GoalEvaluation(goal_evaluation),
} DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation),
) => goal_evaluation.evaluation = Some(canonical_goal_evaluation),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -266,8 +298,8 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
pub fn cache_hit(&mut self, cache_hit: CacheHit) { pub fn cache_hit(&mut self, cache_hit: CacheHit) {
if let Some(this) = self.as_mut() { if let Some(this) = self.as_mut() {
match this { match this {
DebugSolver::GoalEvaluation(goal_evaluation) => { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
assert_eq!(goal_evaluation.cache_hit.replace(cache_hit), None); assert_eq!(canonical_goal_evaluation.cache_hit.replace(cache_hit), None);
} }
_ => unreachable!(), _ => unreachable!(),
}; };
@ -310,16 +342,19 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
self.nested(WipGoalEvaluationStep { self.nested(WipGoalEvaluationStep {
instantiated_goal, instantiated_goal,
nested_goal_evaluations: vec![], added_goals_evaluations: vec![],
candidates: vec![], candidates: vec![],
result: None, result: None,
}) })
} }
pub fn goal_evaluation_step(&mut self, goal_eval_step: ProofTreeBuilder<'tcx>) { pub fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() { if let Some(this) = self.as_mut() {
match (this, goal_eval_step.state.unwrap().tree) { match (this, goal_evaluation_step.state.unwrap().tree) {
(DebugSolver::GoalEvaluation(goal_eval), DebugSolver::GoalEvaluationStep(step)) => { (
goal_eval.evaluation_steps.push(step); DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations),
DebugSolver::GoalEvaluationStep(goal_evaluation_step),
) => {
canonical_goal_evaluations.evaluation_steps.push(goal_evaluation_step);
} }
_ => unreachable!(), _ => unreachable!(),
} }
@ -332,7 +367,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
} }
self.nested(WipGoalCandidate { self.nested(WipGoalCandidate {
nested_goal_evaluations: vec![], added_goals_evaluations: vec![],
candidates: vec![], candidates: vec![],
kind: None, kind: None,
}) })
@ -392,19 +427,19 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
} }
} }
pub fn added_goals_evaluation(&mut self, goals_evaluation: ProofTreeBuilder<'tcx>) { pub fn added_goals_evaluation(&mut self, added_goals_evaluation: ProofTreeBuilder<'tcx>) {
if let Some(this) = self.as_mut() { if let Some(this) = self.as_mut() {
match (this, goals_evaluation.state.unwrap().tree) { match (this, added_goals_evaluation.state.unwrap().tree) {
( (
DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep { DebugSolver::GoalEvaluationStep(WipGoalEvaluationStep {
nested_goal_evaluations, added_goals_evaluations,
.. ..
}) })
| DebugSolver::GoalCandidate(WipGoalCandidate { | DebugSolver::GoalCandidate(WipGoalCandidate {
nested_goal_evaluations, .. added_goals_evaluations, ..
}), }),
DebugSolver::AddedGoalsEvaluation(added_goals_evaluation), DebugSolver::AddedGoalsEvaluation(added_goals_evaluation),
) => nested_goal_evaluations.push(added_goals_evaluation), ) => added_goals_evaluations.push(added_goals_evaluation),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -413,15 +448,13 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
pub fn query_result(&mut self, result: QueryResult<'tcx>) { pub fn query_result(&mut self, result: QueryResult<'tcx>) {
if let Some(this) = self.as_mut() { if let Some(this) = self.as_mut() {
match this { match this {
DebugSolver::GoalEvaluation(goal_evaluation) => { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
assert_eq!(goal_evaluation.result.replace(result), None); assert_eq!(canonical_goal_evaluation.result.replace(result), None);
} }
DebugSolver::GoalEvaluationStep(evaluation_step) => { DebugSolver::GoalEvaluationStep(evaluation_step) => {
assert_eq!(evaluation_step.result.replace(result), None); assert_eq!(evaluation_step.result.replace(result), None);
} }
DebugSolver::Root _ => unreachable!(),
| DebugSolver::AddedGoalsEvaluation(_)
| DebugSolver::GoalCandidate(_) => unreachable!(),
} }
} }
} }

View File

@ -200,6 +200,7 @@ impl<'tcx> SearchGraph<'tcx> {
available_depth, available_depth,
) )
{ {
inspect.cache_hit(CacheHit::Global);
self.on_cache_hit(reached_depth, encountered_overflow); self.on_cache_hit(reached_depth, encountered_overflow);
return result; return result;
} }