allow caller to force proof tree generation
This commit is contained in:
parent
51090b962f
commit
bb743f8635
2 changed files with 89 additions and 72 deletions
|
@ -9,7 +9,7 @@ use rustc_infer::infer::{
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::ObligationCause;
|
||||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||||
use rustc_middle::traits::solve::inspect::CandidateKind;
|
use rustc_middle::traits::solve::inspect::{self, CandidateKind};
|
||||||
use rustc_middle::traits::solve::{
|
use rustc_middle::traits::solve::{
|
||||||
CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
|
CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
|
||||||
PredefinedOpaquesData, QueryResult,
|
PredefinedOpaquesData, QueryResult,
|
||||||
|
@ -108,6 +108,12 @@ impl NestedGoals<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)]
|
||||||
|
pub enum GenerateProofTree {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait InferCtxtEvalExt<'tcx> {
|
pub trait InferCtxtEvalExt<'tcx> {
|
||||||
/// Evaluates a goal from **outside** of the trait solver.
|
/// Evaluates a goal from **outside** of the trait solver.
|
||||||
///
|
///
|
||||||
|
@ -116,7 +122,11 @@ pub trait InferCtxtEvalExt<'tcx> {
|
||||||
fn evaluate_root_goal(
|
fn evaluate_root_goal(
|
||||||
&self,
|
&self,
|
||||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||||
) -> Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution>;
|
generate_proof_tree: GenerateProofTree,
|
||||||
|
) -> (
|
||||||
|
Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution>,
|
||||||
|
Option<inspect::GoalEvaluation<'tcx>>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
|
impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
|
||||||
|
@ -124,7 +134,11 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
|
||||||
fn evaluate_root_goal(
|
fn evaluate_root_goal(
|
||||||
&self,
|
&self,
|
||||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||||
) -> Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> {
|
generate_proof_tree: GenerateProofTree,
|
||||||
|
) -> (
|
||||||
|
Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution>,
|
||||||
|
Option<inspect::GoalEvaluation<'tcx>>,
|
||||||
|
) {
|
||||||
let mode = if self.intercrate { SolverMode::Coherence } else { SolverMode::Normal };
|
let mode = if self.intercrate { SolverMode::Coherence } else { SolverMode::Normal };
|
||||||
let mut search_graph = search_graph::SearchGraph::new(self.tcx, mode);
|
let mut search_graph = search_graph::SearchGraph::new(self.tcx, mode);
|
||||||
|
|
||||||
|
@ -141,19 +155,16 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
|
||||||
var_values: CanonicalVarValues::dummy(),
|
var_values: CanonicalVarValues::dummy(),
|
||||||
nested_goals: NestedGoals::new(),
|
nested_goals: NestedGoals::new(),
|
||||||
tainted: Ok(()),
|
tainted: Ok(()),
|
||||||
inspect: self
|
inspect: (self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree
|
||||||
.tcx
|
|| matches!(generate_proof_tree, GenerateProofTree::Yes))
|
||||||
.sess
|
|
||||||
.opts
|
|
||||||
.unstable_opts
|
|
||||||
.dump_solver_proof_tree
|
|
||||||
.then(ProofTreeBuilder::new_root)
|
.then(ProofTreeBuilder::new_root)
|
||||||
.unwrap_or_else(ProofTreeBuilder::new_noop),
|
.unwrap_or_else(ProofTreeBuilder::new_noop),
|
||||||
};
|
};
|
||||||
let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal);
|
let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal);
|
||||||
|
|
||||||
if let Some(tree) = ecx.inspect.finalize() {
|
let tree = ecx.inspect.finalize();
|
||||||
println!("{:?}", tree);
|
if let Some(tree) = &tree {
|
||||||
|
debug!(?tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -162,7 +173,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(search_graph.is_empty());
|
assert!(search_graph.is_empty());
|
||||||
result
|
(result, tree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use rustc_infer::traits::{
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
|
|
||||||
|
use super::eval_ctxt::GenerateProofTree;
|
||||||
use super::{Certainty, InferCtxtEvalExt};
|
use super::{Certainty, InferCtxtEvalExt};
|
||||||
|
|
||||||
/// A trait engine using the new trait solver.
|
/// A trait engine using the new trait solver.
|
||||||
|
@ -46,8 +47,11 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
||||||
self.obligations
|
self.obligations
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|obligation| {
|
.map(|obligation| {
|
||||||
let code =
|
let code = infcx.probe(|_| {
|
||||||
infcx.probe(|_| match infcx.evaluate_root_goal(obligation.clone().into()) {
|
match infcx
|
||||||
|
.evaluate_root_goal(obligation.clone().into(), GenerateProofTree::No)
|
||||||
|
.0
|
||||||
|
{
|
||||||
Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
|
Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
|
||||||
FulfillmentErrorCode::CodeAmbiguity { overflow: false }
|
FulfillmentErrorCode::CodeAmbiguity { overflow: false }
|
||||||
}
|
}
|
||||||
|
@ -60,6 +64,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
bug!("did not expect selection error when collecting ambiguity errors")
|
bug!("did not expect selection error when collecting ambiguity errors")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
FulfillmentError {
|
FulfillmentError {
|
||||||
|
@ -81,7 +86,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
||||||
let mut has_changed = false;
|
let mut has_changed = false;
|
||||||
for obligation in mem::take(&mut self.obligations) {
|
for obligation in mem::take(&mut self.obligations) {
|
||||||
let goal = obligation.clone().into();
|
let goal = obligation.clone().into();
|
||||||
let (changed, certainty, nested_goals) = match infcx.evaluate_root_goal(goal) {
|
let (changed, certainty, nested_goals) =
|
||||||
|
match infcx.evaluate_root_goal(goal, GenerateProofTree::No).0 {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(NoSolution) => {
|
Err(NoSolution) => {
|
||||||
errors.push(FulfillmentError {
|
errors.push(FulfillmentError {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue