show normalizes-to hack and response instantiation goals
This commit is contained in:
parent
e367c04dc6
commit
51090b962f
4 changed files with 71 additions and 18 deletions
|
@ -991,3 +991,9 @@ pub enum DefiningAnchor {
|
||||||
/// Used to catch type mismatch errors when handling opaque types.
|
/// Used to catch type mismatch errors when handling opaque types.
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
||||||
|
pub enum IsNormalizesToHack {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{CanonicalInput, Certainty, Goal, NoSolution, QueryInput, QueryResult};
|
use super::{CanonicalInput, Certainty, Goal, NoSolution, QueryInput, QueryResult};
|
||||||
use crate::ty;
|
use crate::{traits::IsNormalizesToHack, ty};
|
||||||
use std::fmt::{Debug, Write};
|
use std::fmt::{Debug, Write};
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
|
#[derive(Eq, PartialEq, Debug, Hash, HashStable)]
|
||||||
|
@ -14,6 +14,8 @@ pub struct GoalEvaluation<'tcx> {
|
||||||
pub canonicalized_goal: CanonicalInput<'tcx>,
|
pub canonicalized_goal: CanonicalInput<'tcx>,
|
||||||
|
|
||||||
pub kind: GoalEvaluationKind<'tcx>,
|
pub kind: GoalEvaluationKind<'tcx>,
|
||||||
|
pub is_normalizes_to_hack: IsNormalizesToHack,
|
||||||
|
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||||
|
|
||||||
pub result: QueryResult<'tcx>,
|
pub result: QueryResult<'tcx>,
|
||||||
}
|
}
|
||||||
|
@ -99,7 +101,13 @@ impl ProofTreeFormatter<'_, '_> {
|
||||||
|
|
||||||
fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
|
fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
|
||||||
let f = &mut *self.f;
|
let f = &mut *self.f;
|
||||||
writeln!(f, "GOAL: {:?}", goal.uncanonicalized_goal)?;
|
|
||||||
|
let goal_text = match goal.is_normalizes_to_hack {
|
||||||
|
IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
|
||||||
|
IsNormalizesToHack::No => "GOAL",
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(f, "{}: {:?}", goal_text, goal.uncanonicalized_goal,)?;
|
||||||
writeln!(f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?;
|
writeln!(f, "CANONICALIZED: {:?}", goal.canonicalized_goal)?;
|
||||||
|
|
||||||
match &goal.kind {
|
match &goal.kind {
|
||||||
|
@ -120,7 +128,19 @@ impl ProofTreeFormatter<'_, '_> {
|
||||||
let f = &mut *self.f;
|
let f = &mut *self.f;
|
||||||
writeln!(f, "RESULT: {:?}", goal.result)
|
writeln!(f, "RESULT: {:?}", goal.result)
|
||||||
}
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
if goal.returned_goals.len() > 0 {
|
||||||
|
let f = &mut *self.f;
|
||||||
|
writeln!(f, "NESTED GOALS ADDED TO CALLER: [")?;
|
||||||
|
let mut f = self.nested();
|
||||||
|
for goal in goal.returned_goals.iter() {
|
||||||
|
writeln!(f, "ADDED GOAL: {:?},", goal)?;
|
||||||
|
}
|
||||||
|
writeln!(self.f, "]")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_evaluation_step(
|
fn format_evaluation_step(
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc_middle::traits::solve::{
|
||||||
CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
|
CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
|
||||||
PredefinedOpaquesData, QueryResult,
|
PredefinedOpaquesData, QueryResult,
|
||||||
};
|
};
|
||||||
use rustc_middle::traits::DefiningAnchor;
|
use rustc_middle::traits::{DefiningAnchor, IsNormalizesToHack};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
|
||||||
TypeVisitableExt, TypeVisitor,
|
TypeVisitableExt, TypeVisitor,
|
||||||
|
@ -79,12 +79,6 @@ pub struct EvalCtxt<'a, 'tcx> {
|
||||||
inspect: ProofTreeBuilder<'tcx>,
|
inspect: ProofTreeBuilder<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
|
||||||
pub(super) enum IsNormalizesToHack {
|
|
||||||
Yes,
|
|
||||||
No,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(super) struct NestedGoals<'tcx> {
|
pub(super) struct NestedGoals<'tcx> {
|
||||||
/// This normalizes-to goal that is treated specially during the evaluation
|
/// This normalizes-to goal that is treated specially during the evaluation
|
||||||
|
@ -262,7 +256,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||||
) -> Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> {
|
) -> Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> {
|
||||||
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
|
let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
|
||||||
let mut goal_evaluation = self.inspect.new_goal_evaluation(goal);
|
let mut goal_evaluation = self.inspect.new_goal_evaluation(goal, is_normalizes_to_hack);
|
||||||
let canonical_response = EvalCtxt::evaluate_canonical_goal(
|
let canonical_response = EvalCtxt::evaluate_canonical_goal(
|
||||||
self.tcx(),
|
self.tcx(),
|
||||||
self.search_graph,
|
self.search_graph,
|
||||||
|
@ -270,16 +264,29 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
|
||||||
&mut goal_evaluation,
|
&mut goal_evaluation,
|
||||||
);
|
);
|
||||||
goal_evaluation.query_result(canonical_response);
|
goal_evaluation.query_result(canonical_response);
|
||||||
self.inspect.goal_evaluation(goal_evaluation);
|
let canonical_response = match canonical_response {
|
||||||
let canonical_response = canonical_response?;
|
Err(e) => {
|
||||||
|
self.inspect.goal_evaluation(goal_evaluation);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
Ok(response) => response,
|
||||||
|
};
|
||||||
|
|
||||||
let has_changed = !canonical_response.value.var_values.is_identity()
|
let has_changed = !canonical_response.value.var_values.is_identity()
|
||||||
|| !canonical_response.value.external_constraints.opaque_types.is_empty();
|
|| !canonical_response.value.external_constraints.opaque_types.is_empty();
|
||||||
let (certainty, nested_goals) = self.instantiate_and_apply_query_response(
|
let (certainty, nested_goals) = match self.instantiate_and_apply_query_response(
|
||||||
goal.param_env,
|
goal.param_env,
|
||||||
orig_values,
|
orig_values,
|
||||||
canonical_response,
|
canonical_response,
|
||||||
)?;
|
) {
|
||||||
|
Err(e) => {
|
||||||
|
self.inspect.goal_evaluation(goal_evaluation);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
Ok(response) => response,
|
||||||
|
};
|
||||||
|
goal_evaluation.returned_goals(&nested_goals);
|
||||||
|
self.inspect.goal_evaluation(goal_evaluation);
|
||||||
|
|
||||||
if !has_changed && !nested_goals.is_empty() {
|
if !has_changed && !nested_goals.is_empty() {
|
||||||
bug!("an unchanged goal shouldn't have any side-effects on instantiation");
|
bug!("an unchanged goal shouldn't have any side-effects on instantiation");
|
||||||
|
|
|
@ -5,6 +5,7 @@ use rustc_middle::{
|
||||||
inspect::{self, CacheHit, CandidateKind},
|
inspect::{self, CacheHit, CandidateKind},
|
||||||
CanonicalInput, Certainty, Goal, QueryInput, QueryResult,
|
CanonicalInput, Certainty, Goal, QueryInput, QueryResult,
|
||||||
},
|
},
|
||||||
|
IsNormalizesToHack,
|
||||||
},
|
},
|
||||||
ty,
|
ty,
|
||||||
};
|
};
|
||||||
|
@ -17,6 +18,8 @@ pub struct WipGoalEvaluation<'tcx> {
|
||||||
pub evaluation_steps: Vec<WipGoalEvaluationStep<'tcx>>,
|
pub evaluation_steps: Vec<WipGoalEvaluationStep<'tcx>>,
|
||||||
|
|
||||||
pub cache_hit: Option<CacheHit>,
|
pub cache_hit: Option<CacheHit>,
|
||||||
|
pub is_normalizes_to_hack: IsNormalizesToHack,
|
||||||
|
pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||||
|
|
||||||
pub result: Option<QueryResult<'tcx>>,
|
pub result: Option<QueryResult<'tcx>>,
|
||||||
}
|
}
|
||||||
|
@ -35,6 +38,8 @@ impl<'tcx> WipGoalEvaluation<'tcx> {
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
is_normalizes_to_hack: self.is_normalizes_to_hack,
|
||||||
|
returned_goals: self.returned_goals,
|
||||||
result: self.result.unwrap(),
|
result: self.result.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,13 +121,11 @@ pub enum DebugSolver<'tcx> {
|
||||||
pub struct ProofTreeBuilder<'tcx>(Option<Box<DebugSolver<'tcx>>>);
|
pub struct ProofTreeBuilder<'tcx>(Option<Box<DebugSolver<'tcx>>>);
|
||||||
impl<'tcx> ProofTreeBuilder<'tcx> {
|
impl<'tcx> ProofTreeBuilder<'tcx> {
|
||||||
pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> {
|
pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> {
|
||||||
let wip_tree = *(self.0?);
|
match *(self.0?) {
|
||||||
|
|
||||||
match wip_tree {
|
|
||||||
DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
|
DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
|
||||||
Some(wip_goal_evaluation.finalize())
|
Some(wip_goal_evaluation.finalize())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
root => unreachable!("unexpected proof tree builder root node: {:?}", root),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +144,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
||||||
pub fn new_goal_evaluation(
|
pub fn new_goal_evaluation(
|
||||||
&mut self,
|
&mut self,
|
||||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||||
|
is_normalizes_to_hack: IsNormalizesToHack,
|
||||||
) -> ProofTreeBuilder<'tcx> {
|
) -> ProofTreeBuilder<'tcx> {
|
||||||
if self.0.is_none() {
|
if self.0.is_none() {
|
||||||
return ProofTreeBuilder(None);
|
return ProofTreeBuilder(None);
|
||||||
|
@ -150,7 +154,9 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
||||||
uncanonicalized_goal: goal,
|
uncanonicalized_goal: goal,
|
||||||
canonicalized_goal: None,
|
canonicalized_goal: None,
|
||||||
evaluation_steps: vec![],
|
evaluation_steps: vec![],
|
||||||
|
is_normalizes_to_hack,
|
||||||
cache_hit: None,
|
cache_hit: None,
|
||||||
|
returned_goals: vec![],
|
||||||
result: None,
|
result: None,
|
||||||
}))))
|
}))))
|
||||||
}
|
}
|
||||||
|
@ -181,6 +187,20 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
pub fn returned_goals(&mut self, goals: &[Goal<'tcx, ty::Predicate<'tcx>>]) {
|
||||||
|
let this = match self.0.as_mut() {
|
||||||
|
None => return,
|
||||||
|
Some(this) => &mut **this,
|
||||||
|
};
|
||||||
|
|
||||||
|
match this {
|
||||||
|
DebugSolver::GoalEvaluation(evaluation) => {
|
||||||
|
assert!(evaluation.returned_goals.is_empty());
|
||||||
|
evaluation.returned_goals.extend(goals);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) {
|
pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<'tcx>) {
|
||||||
let this = match self.0.as_mut() {
|
let this = match self.0.as_mut() {
|
||||||
None => return,
|
None => return,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue