diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index bb574954587ea..bd52957d162f2 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -57,6 +57,14 @@ 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, a probe needs to be introduced somewhere in the + // evaluation code. + tainted: Result<(), NoSolution>, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -121,6 +129,7 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { max_input_universe: ty::UniverseIndex::ROOT, var_values: CanonicalVarValues::dummy(), nested_goals: NestedGoals::new(), + tainted: Ok(()), }; let result = ecx.evaluate_goal(IsNormalizesToHack::No, goal); @@ -172,6 +181,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { max_input_universe: canonical_goal.max_universe, search_graph, nested_goals: NestedGoals::new(), + tainted: Ok(()), }; ecx.compute_goal(goal) }) @@ -391,6 +401,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { }, ); + if response.is_err() { + self.tainted = Err(NoSolution); + } + self.nested_goals = goals; response } @@ -404,6 +418,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..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,6 +51,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { certainty: Certainty, ) -> QueryResult<'tcx> { let goals_certainty = self.try_evaluate_added_goals()?; + assert_eq!( + self.tainted, + Ok(()), + "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()?;