Track if EvalCtxt has been tainted, make sure it can't be used to make query responses after

This commit is contained in:
Michael Goulet 2023-04-20 16:54:39 +00:00
parent b9fd498fa7
commit 4fd7739aac
2 changed files with 20 additions and 0 deletions

View File

@ -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))
}

View File

@ -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()?;