about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBoxy <supbscripter@gmail.com>2023-06-08 23:58:34 +0100
committerBoxy <supbscripter@gmail.com>2023-06-19 09:06:16 +0100
commit51090b962f10a178f9e15ef445692f6732c9c7ce (patch)
tree3c64667dbd599d95f538ae5867e74b223a69c995
parente367c04dc6b23cc09d3bed448450a6c5d19dd254 (diff)
downloadrust-51090b962f10a178f9e15ef445692f6732c9c7ce.tar.gz
rust-51090b962f10a178f9e15ef445692f6732c9c7ce.zip
show normalizes-to hack and response instantiation goals
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs6
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs24
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs31
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect.rs28
4 files changed, 71 insertions, 18 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index f0380204970..73959038582 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -991,3 +991,9 @@ pub enum DefiningAnchor {
     /// Used to catch type mismatch errors when handling opaque types.
     Error,
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
+pub enum IsNormalizesToHack {
+    Yes,
+    No,
+}
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index 0379833d503..d0091d1c30f 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -1,5 +1,5 @@
 use super::{CanonicalInput, Certainty, Goal, NoSolution, QueryInput, QueryResult};
-use crate::ty;
+use crate::{traits::IsNormalizesToHack, ty};
 use std::fmt::{Debug, Write};
 
 #[derive(Eq, PartialEq, Debug, Hash, HashStable)]
@@ -14,6 +14,8 @@ pub struct GoalEvaluation<'tcx> {
     pub canonicalized_goal: CanonicalInput<'tcx>,
 
     pub kind: GoalEvaluationKind<'tcx>,
+    pub is_normalizes_to_hack: IsNormalizesToHack,
+    pub returned_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
 
     pub result: QueryResult<'tcx>,
 }
@@ -99,7 +101,13 @@ impl ProofTreeFormatter<'_, '_> {
 
     fn format_goal_evaluation(&mut self, goal: &GoalEvaluation<'_>) -> std::fmt::Result {
         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)?;
 
         match &goal.kind {
@@ -120,7 +128,19 @@ impl ProofTreeFormatter<'_, '_> {
                 let f = &mut *self.f;
                 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(
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index c9d531f27ab..9ac37de71d3 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -14,7 +14,7 @@ use rustc_middle::traits::solve::{
     CanonicalInput, CanonicalResponse, Certainty, MaybeCause, PredefinedOpaques,
     PredefinedOpaquesData, QueryResult,
 };
-use rustc_middle::traits::DefiningAnchor;
+use rustc_middle::traits::{DefiningAnchor, IsNormalizesToHack};
 use rustc_middle::ty::{
     self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
     TypeVisitableExt, TypeVisitor,
@@ -79,12 +79,6 @@ pub struct EvalCtxt<'a, 'tcx> {
     inspect: ProofTreeBuilder<'tcx>,
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)]
-pub(super) enum IsNormalizesToHack {
-    Yes,
-    No,
-}
-
 #[derive(Debug, Clone)]
 pub(super) struct NestedGoals<'tcx> {
     /// 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>>,
     ) -> Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution> {
         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(
             self.tcx(),
             self.search_graph,
@@ -270,16 +264,29 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             &mut goal_evaluation,
         );
         goal_evaluation.query_result(canonical_response);
-        self.inspect.goal_evaluation(goal_evaluation);
-        let canonical_response = canonical_response?;
+        let canonical_response = match 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()
             || !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,
             orig_values,
             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() {
             bug!("an unchanged goal shouldn't have any side-effects on instantiation");
diff --git a/compiler/rustc_trait_selection/src/solve/inspect.rs b/compiler/rustc_trait_selection/src/solve/inspect.rs
index 00c4e631b88..3cba141d9a1 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect.rs
@@ -5,6 +5,7 @@ use rustc_middle::{
             inspect::{self, CacheHit, CandidateKind},
             CanonicalInput, Certainty, Goal, QueryInput, QueryResult,
         },
+        IsNormalizesToHack,
     },
     ty,
 };
@@ -17,6 +18,8 @@ pub struct WipGoalEvaluation<'tcx> {
     pub evaluation_steps: Vec<WipGoalEvaluationStep<'tcx>>,
 
     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>>,
 }
@@ -35,6 +38,8 @@ impl<'tcx> WipGoalEvaluation<'tcx> {
                         .collect(),
                 },
             },
+            is_normalizes_to_hack: self.is_normalizes_to_hack,
+            returned_goals: self.returned_goals,
             result: self.result.unwrap(),
         }
     }
@@ -116,13 +121,11 @@ pub enum DebugSolver<'tcx> {
 pub struct ProofTreeBuilder<'tcx>(Option<Box<DebugSolver<'tcx>>>);
 impl<'tcx> ProofTreeBuilder<'tcx> {
     pub fn finalize(self) -> Option<inspect::GoalEvaluation<'tcx>> {
-        let wip_tree = *(self.0?);
-
-        match wip_tree {
+        match *(self.0?) {
             DebugSolver::GoalEvaluation(wip_goal_evaluation) => {
                 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(
         &mut self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
+        is_normalizes_to_hack: IsNormalizesToHack,
     ) -> ProofTreeBuilder<'tcx> {
         if self.0.is_none() {
             return ProofTreeBuilder(None);
@@ -150,7 +154,9 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
             uncanonicalized_goal: goal,
             canonicalized_goal: None,
             evaluation_steps: vec![],
+            is_normalizes_to_hack,
             cache_hit: None,
+            returned_goals: vec![],
             result: None,
         }))))
     }
@@ -181,6 +187,20 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
             _ => 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>) {
         let this = match self.0.as_mut() {
             None => return,