about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-04-27 12:55:28 -0400
committerMichael Goulet <michael@errs.io>2024-04-27 17:46:29 -0400
commit17728a9bb2d40537f57c5e7d40e6293529e85a89 (patch)
treed2370c3dab1095b76fe919f743d317dfa48a2bf3
parent61a1dbd751ab7f3c973be17d7ff3948ffda07c6e (diff)
downloadrust-17728a9bb2d40537f57c5e7d40e6293529e85a89.tar.gz
rust-17728a9bb2d40537f57c5e7d40e6293529e85a89.zip
Record certainty of evaluate_added_goals_and_make_canonical_response call in candidate
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs6
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs21
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/build.rs17
5 files changed, 49 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index f2283e71dc8..1b2e2781bfe 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -122,6 +122,12 @@ pub enum ProbeStep<'tcx> {
     /// used whenever there are multiple candidates to prove the
     /// current goalby .
     NestedProbe(Probe<'tcx>),
+    /// A call to `EvalCtxt::evaluate_added_goals_make_canonical_response` with
+    /// `Certainty` was made. This is the certainty passed in, so it's not unified
+    /// with the certainty of the `try_evaluate_added_goals` that is done within;
+    /// if it's `Certainty::Yes`, then we can trust that the candidate is "finished"
+    /// and we didn't force ambiguity for some reason.
+    MakeCanonicalResponse { shallow_certainty: Certainty },
 }
 
 /// What kind of probe we're in. In case the probe represents a candidate, or
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 98f01fe8772..2e2d1df8d19 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -132,6 +132,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
                     }
                     ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?,
                     ProbeStep::NestedProbe(probe) => this.format_probe(probe)?,
+                    ProbeStep::MakeCanonicalResponse { shallow_certainty } => {
+                        writeln!(this.f, "EVALUATE GOALS AND MAKE RESPONSE: {shallow_certainty:?}")?
+                    }
                 }
             }
             Ok(())
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 9edeb0fa71b..6722abd709c 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -98,6 +98,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             previous call to `try_evaluate_added_goals!`"
         );
 
+        self.inspect.make_canonical_response(certainty);
+
         // When normalizing, we've replaced the expected term with an unconstrained
         // inference variable. This means that we dropped information which could
         // have been important. We handle this by instead returning the nested goals
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index f137780c536..e918f20577c 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -45,6 +45,7 @@ pub struct InspectCandidate<'a, 'tcx> {
     nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
     final_state: inspect::CanonicalState<'tcx, ()>,
     result: QueryResult<'tcx>,
+    candidate_certainty: Option<Certainty>,
 }
 
 impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
@@ -56,6 +57,19 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
         self.result.map(|c| c.value.certainty)
     }
 
+    /// Certainty passed into `evaluate_added_goals_and_make_canonical_response`.
+    ///
+    /// If this certainty is `Some(Yes)`, then we must be confident that the candidate
+    /// must hold iff it's nested goals hold. This is not true if the certainty is
+    /// `Some(Maybe)`, which suggests we forced ambiguity instead, or if it is `None`,
+    /// which suggests we may have not assembled any candidates at all.
+    ///
+    /// This is *not* the certainty of the candidate's nested evaluation, which can be
+    /// accessed with [`Self::result`] instead.
+    pub fn candidate_certainty(&self) -> Option<Certainty> {
+        self.candidate_certainty
+    }
+
     /// Visit all nested goals of this candidate without rolling
     /// back their inference constraints. This function modifies
     /// the state of the `infcx`.
@@ -160,7 +174,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
         probe: &inspect::Probe<'tcx>,
     ) {
+        let mut candidate_certainty = None;
         let num_candidates = candidates.len();
+
         for step in &probe.steps {
             match step {
                 &inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal),
@@ -172,6 +188,9 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
                     self.candidates_recur(candidates, nested_goals, probe);
                     nested_goals.truncate(num_goals);
                 }
+                inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty } => {
+                    assert_eq!(candidate_certainty.replace(*shallow_certainty), None);
+                }
                 inspect::ProbeStep::EvaluateGoals(_) => (),
             }
         }
@@ -195,6 +214,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
                         nested_goals: nested_goals.clone(),
                         final_state: probe.final_state,
                         result,
+                        candidate_certainty,
                     })
                 }
             }
@@ -206,6 +226,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
                     nested_goals: nested_goals.clone(),
                     final_state: probe.final_state,
                     result,
+                    candidate_certainty,
                 });
             }
         }
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
index c3651517d49..466d0d80060 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
@@ -241,6 +241,7 @@ enum WipProbeStep<'tcx> {
     AddGoal(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>),
     EvaluateGoals(WipAddedGoalsEvaluation<'tcx>),
     NestedProbe(WipProbe<'tcx>),
+    MakeCanonicalResponse { shallow_certainty: Certainty },
 }
 
 impl<'tcx> WipProbeStep<'tcx> {
@@ -249,6 +250,9 @@ impl<'tcx> WipProbeStep<'tcx> {
             WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal),
             WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()),
             WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()),
+            WipProbeStep::MakeCanonicalResponse { shallow_certainty } => {
+                inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty }
+            }
         }
     }
 }
@@ -530,6 +534,19 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
         }
     }
 
+    pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
+        match self.as_mut() {
+            Some(DebugSolver::GoalEvaluationStep(state)) => {
+                state
+                    .current_evaluation_scope()
+                    .steps
+                    .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty });
+            }
+            None => {}
+            _ => {}
+        }
+    }
+
     pub fn finish_probe(mut self) -> ProofTreeBuilder<'tcx> {
         match self.as_mut() {
             None => {}