From 4fd7739aac547f99b5f0378ee1b6752258d234f7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Apr 2023 16:54:39 +0000 Subject: [PATCH 1/2] Track if EvalCtxt has been tainted, make sure it can't be used to make query responses after --- .../rustc_trait_selection/src/solve/eval_ctxt.rs | 14 ++++++++++++++ .../src/solve/eval_ctxt/canonical.rs | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index bb574954587ea..4c79445d345e4 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -57,6 +57,13 @@ pub struct EvalCtxt<'a, 'tcx> { pub(super) search_graph: &'a mut SearchGraph<'tcx>, pub(super) nested_goals: NestedGoals<'tcx>, + + // Has this `EvalCtxt` errored out with `NoSolution` in `try_evaluate_added_goals`? + // + // If so, then it can no longer be used to make a canonical query response, + // since subsequent calls to `try_evaluate_added_goals` have possibly dropped + // ambiguous goals. Instead, use a probe. + tainted: bool, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -121,6 +128,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { max_input_universe: ty::UniverseIndex::ROOT, var_values: CanonicalVarValues::dummy(), nested_goals: NestedGoals::new(), + tainted: false, }; let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal); @@ -172,6 +180,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { max_input_universe: canonical_goal.max_universe, search_graph, nested_goals: NestedGoals::new(), + tainted: false, }; ecx.compute_goal(goal) }) @@ -391,6 +400,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { }, ); + if response.is_err() { + self.tainted = true; + } + self.nested_goals = goals; response } @@ -404,6 +417,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { max_input_universe: self.max_input_universe, search_graph: self.search_graph, nested_goals: self.nested_goals.clone(), + tainted: self.tainted, }; self.infcx.probe(|_| f(&mut ecx)) } 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 23cf0f0c724ba..e7a6282cb3de1 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -51,6 +51,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { certainty: Certainty, ) -> QueryResult<'tcx> { let goals_certainty = self.try_evaluate_added_goals()?; + assert!( + !self.tainted, + "EvalCtxt is tainted -- nested goals may have been dropped in a \ + previous call to `try_evaluate_added_goals!`" + ); + let certainty = certainty.unify_with(goals_certainty); let external_constraints = self.compute_external_query_constraints()?; From 3206100ed9273c1adcc661d30db460c2402d568c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Apr 2023 18:40:34 +0000 Subject: [PATCH 2/2] Result is just bool but special --- compiler/rustc_trait_selection/src/solve/eval_ctxt.rs | 11 ++++++----- .../src/solve/eval_ctxt/canonical.rs | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 4c79445d345e4..bd52957d162f2 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -62,8 +62,9 @@ pub struct EvalCtxt<'a, 'tcx> { // // If so, then it can no longer be used to make a canonical query response, // since subsequent calls to `try_evaluate_added_goals` have possibly dropped - // ambiguous goals. Instead, use a probe. - tainted: bool, + // ambiguous goals. Instead, a probe needs to be introduced somewhere in the + // evaluation code. + tainted: Result<(), NoSolution>, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -128,7 +129,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { max_input_universe: ty::UniverseIndex::ROOT, var_values: CanonicalVarValues::dummy(), nested_goals: NestedGoals::new(), - tainted: false, + tainted: Ok(()), }; let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal); @@ -180,7 +181,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { max_input_universe: canonical_goal.max_universe, search_graph, nested_goals: NestedGoals::new(), - tainted: false, + tainted: Ok(()), }; ecx.compute_goal(goal) }) @@ -401,7 +402,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { ); if response.is_err() { - self.tainted = true; + self.tainted = Err(NoSolution); } self.nested_goals = goals; 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 e7a6282cb3de1..2dea36811d80b 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -51,8 +51,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { certainty: Certainty, ) -> QueryResult<'tcx> { let goals_certainty = self.try_evaluate_added_goals()?; - assert!( - !self.tainted, + assert_eq!( + self.tainted, + Ok(()), "EvalCtxt is tainted -- nested goals may have been dropped in a \ previous call to `try_evaluate_added_goals!`" );