about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs39
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs122
2 files changed, 89 insertions, 72 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 9ac37de71d3..a8c569cd38b 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -9,7 +9,7 @@ use rustc_infer::infer::{
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::ObligationCause;
 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::{
     CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
     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> {
     /// Evaluates a goal from **outside** of the trait solver.
     ///
@@ -116,7 +122,11 @@ pub trait InferCtxtEvalExt<'tcx> {
     fn evaluate_root_goal(
         &self,
         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> {
@@ -124,7 +134,11 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
     fn evaluate_root_goal(
         &self,
         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 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(),
             nested_goals: NestedGoals::new(),
             tainted: Ok(()),
-            inspect: self
-                .tcx
-                .sess
-                .opts
-                .unstable_opts
-                .dump_solver_proof_tree
-                .then(ProofTreeBuilder::new_root)
-                .unwrap_or_else(ProofTreeBuilder::new_noop),
+            inspect: (self.tcx.sess.opts.unstable_opts.dump_solver_proof_tree
+                || matches!(generate_proof_tree, GenerateProofTree::Yes))
+            .then(ProofTreeBuilder::new_root)
+            .unwrap_or_else(ProofTreeBuilder::new_noop),
         };
         let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal);
 
-        if let Some(tree) = ecx.inspect.finalize() {
-            println!("{:?}", tree);
+        let tree = ecx.inspect.finalize();
+        if let Some(tree) = &tree {
+            debug!(?tree);
         }
 
         assert!(
@@ -162,7 +173,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
         );
 
         assert!(search_graph.is_empty());
-        result
+        (result, tree)
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 65c8d9c8f69..0e671144a29 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -10,6 +10,7 @@ use rustc_infer::traits::{
 use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 
+use super::eval_ctxt::GenerateProofTree;
 use super::{Certainty, InferCtxtEvalExt};
 
 /// A trait engine using the new trait solver.
@@ -46,8 +47,11 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
         self.obligations
             .drain(..)
             .map(|obligation| {
-                let code =
-                    infcx.probe(|_| match infcx.evaluate_root_goal(obligation.clone().into()) {
+                let code = infcx.probe(|_| {
+                    match infcx
+                        .evaluate_root_goal(obligation.clone().into(), GenerateProofTree::No)
+                        .0
+                    {
                         Ok((_, Certainty::Maybe(MaybeCause::Ambiguity), _)) => {
                             FulfillmentErrorCode::CodeAmbiguity { overflow: false }
                         }
@@ -60,7 +64,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
                         Err(_) => {
                             bug!("did not expect selection error when collecting ambiguity errors")
                         }
-                    });
+                    }
+                });
 
                 FulfillmentError {
                     obligation: obligation.clone(),
@@ -81,61 +86,62 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             let mut has_changed = false;
             for obligation in mem::take(&mut self.obligations) {
                 let goal = obligation.clone().into();
-                let (changed, certainty, nested_goals) = match infcx.evaluate_root_goal(goal) {
-                    Ok(result) => result,
-                    Err(NoSolution) => {
-                        errors.push(FulfillmentError {
-                            obligation: obligation.clone(),
-                            code: match goal.predicate.kind().skip_binder() {
-                                ty::PredicateKind::Clause(ty::Clause::Projection(_)) => {
-                                    FulfillmentErrorCode::CodeProjectionError(
-                                        // FIXME: This could be a `Sorts` if the term is a type
-                                        MismatchedProjectionTypes { err: TypeError::Mismatch },
-                                    )
-                                }
-                                ty::PredicateKind::AliasRelate(_, _, _) => {
-                                    FulfillmentErrorCode::CodeProjectionError(
-                                        MismatchedProjectionTypes { err: TypeError::Mismatch },
-                                    )
-                                }
-                                ty::PredicateKind::Subtype(pred) => {
-                                    let (a, b) = infcx.instantiate_binder_with_placeholders(
-                                        goal.predicate.kind().rebind((pred.a, pred.b)),
-                                    );
-                                    let expected_found = ExpectedFound::new(true, a, b);
-                                    FulfillmentErrorCode::CodeSubtypeError(
-                                        expected_found,
-                                        TypeError::Sorts(expected_found),
-                                    )
-                                }
-                                ty::PredicateKind::Coerce(pred) => {
-                                    let (a, b) = infcx.instantiate_binder_with_placeholders(
-                                        goal.predicate.kind().rebind((pred.a, pred.b)),
-                                    );
-                                    let expected_found = ExpectedFound::new(false, a, b);
-                                    FulfillmentErrorCode::CodeSubtypeError(
-                                        expected_found,
-                                        TypeError::Sorts(expected_found),
-                                    )
-                                }
-                                ty::PredicateKind::Clause(_)
-                                | ty::PredicateKind::ObjectSafe(_)
-                                | ty::PredicateKind::ClosureKind(_, _, _)
-                                | ty::PredicateKind::Ambiguous => {
-                                    FulfillmentErrorCode::CodeSelectionError(
-                                        SelectionError::Unimplemented,
-                                    )
-                                }
-                                ty::PredicateKind::ConstEquate(..)
-                                | ty::PredicateKind::TypeWellFormedFromEnv(_) => {
-                                    bug!("unexpected goal: {goal:?}")
-                                }
-                            },
-                            root_obligation: obligation,
-                        });
-                        continue;
-                    }
-                };
+                let (changed, certainty, nested_goals) =
+                    match infcx.evaluate_root_goal(goal, GenerateProofTree::No).0 {
+                        Ok(result) => result,
+                        Err(NoSolution) => {
+                            errors.push(FulfillmentError {
+                                obligation: obligation.clone(),
+                                code: match goal.predicate.kind().skip_binder() {
+                                    ty::PredicateKind::Clause(ty::Clause::Projection(_)) => {
+                                        FulfillmentErrorCode::CodeProjectionError(
+                                            // FIXME: This could be a `Sorts` if the term is a type
+                                            MismatchedProjectionTypes { err: TypeError::Mismatch },
+                                        )
+                                    }
+                                    ty::PredicateKind::AliasRelate(_, _, _) => {
+                                        FulfillmentErrorCode::CodeProjectionError(
+                                            MismatchedProjectionTypes { err: TypeError::Mismatch },
+                                        )
+                                    }
+                                    ty::PredicateKind::Subtype(pred) => {
+                                        let (a, b) = infcx.instantiate_binder_with_placeholders(
+                                            goal.predicate.kind().rebind((pred.a, pred.b)),
+                                        );
+                                        let expected_found = ExpectedFound::new(true, a, b);
+                                        FulfillmentErrorCode::CodeSubtypeError(
+                                            expected_found,
+                                            TypeError::Sorts(expected_found),
+                                        )
+                                    }
+                                    ty::PredicateKind::Coerce(pred) => {
+                                        let (a, b) = infcx.instantiate_binder_with_placeholders(
+                                            goal.predicate.kind().rebind((pred.a, pred.b)),
+                                        );
+                                        let expected_found = ExpectedFound::new(false, a, b);
+                                        FulfillmentErrorCode::CodeSubtypeError(
+                                            expected_found,
+                                            TypeError::Sorts(expected_found),
+                                        )
+                                    }
+                                    ty::PredicateKind::Clause(_)
+                                    | ty::PredicateKind::ObjectSafe(_)
+                                    | ty::PredicateKind::ClosureKind(_, _, _)
+                                    | ty::PredicateKind::Ambiguous => {
+                                        FulfillmentErrorCode::CodeSelectionError(
+                                            SelectionError::Unimplemented,
+                                        )
+                                    }
+                                    ty::PredicateKind::ConstEquate(..)
+                                    | ty::PredicateKind::TypeWellFormedFromEnv(_) => {
+                                        bug!("unexpected goal: {goal:?}")
+                                    }
+                                },
+                                root_obligation: obligation,
+                            });
+                            continue;
+                        }
+                    };
                 // Push any nested goals that we get from unifying our canonical response
                 // with our obligation onto the fulfillment context.
                 self.obligations.extend(nested_goals.into_iter().map(|goal| {