Record impl args in the InsepctCandiate rather than rematching during select

This commit is contained in:
Michael Goulet
2024-05-06 11:24:40 -04:00
parent fc47cf38e5
commit 207b4b8e88
7 changed files with 99 additions and 65 deletions

View File

@@ -93,6 +93,7 @@ pub struct InspectCandidate<'a, 'tcx> {
kind: inspect::ProbeKind<'tcx>,
nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>,
final_state: inspect::CanonicalState<'tcx, ()>,
impl_args: Option<inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>>>,
result: QueryResult<'tcx>,
shallow_certainty: Certainty,
}
@@ -135,7 +136,20 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
/// Instantiate the nested goals for the candidate without rolling back their
/// inference constraints. This function modifies the state of the `infcx`.
///
/// See [`Self::instantiate_nested_goals_and_opt_impl_args`] if you need the impl args too.
pub fn instantiate_nested_goals(&self, span: Span) -> Vec<InspectGoal<'a, 'tcx>> {
self.instantiate_nested_goals_and_opt_impl_args(span).0
}
/// Instantiate the nested goals for the candidate without rolling back their
/// inference constraints, and optionally the args of an impl if this candidate
/// came from a `CandidateSource::Impl`. This function modifies the state of the
/// `infcx`.
pub fn instantiate_nested_goals_and_opt_impl_args(
&self,
span: Span,
) -> (Vec<InspectGoal<'a, 'tcx>>, Option<ty::GenericArgsRef<'tcx>>) {
let infcx = self.goal.infcx;
let param_env = self.goal.goal.param_env;
let mut orig_values = self.goal.orig_values.to_vec();
@@ -164,6 +178,17 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
self.final_state,
);
let impl_args = self.impl_args.map(|impl_args| {
canonical::instantiate_canonical_state(
infcx,
span,
param_env,
&mut orig_values,
impl_args,
)
.fold_with(&mut EagerResolver::new(infcx))
});
if let Some(term_hack) = self.goal.normalizes_to_term_hack {
// FIXME: We ignore the expected term of `NormalizesTo` goals
// when computing the result of its candidates. This is
@@ -171,7 +196,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
let _ = term_hack.constrain(infcx, span, param_env);
}
instantiated_goals
let goals = instantiated_goals
.into_iter()
.map(|(source, goal)| match goal.predicate.kind().no_bound_vars() {
Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
@@ -208,7 +233,9 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
source,
),
})
.collect()
.collect();
(goals, impl_args)
}
/// Visit all nested goals of this candidate, rolling back
@@ -245,9 +272,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
probe: &inspect::Probe<'tcx>,
) {
let mut shallow_certainty = None;
let mut impl_args = None;
for step in &probe.steps {
match step {
&inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
match *step {
inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
inspect::ProbeStep::NestedProbe(ref probe) => {
// Nested probes have to prove goals added in their parent
// but do not leak them, so we truncate the added goals
@@ -257,7 +285,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
nested_goals.truncate(num_goals);
}
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_eq!(shallow_certainty.replace(*c), None);
assert_eq!(shallow_certainty.replace(c), None);
}
inspect::ProbeStep::RecordImplArgs { impl_args: i } => {
assert_eq!(impl_args.replace(i), None);
}
inspect::ProbeStep::EvaluateGoals(_) => (),
}
@@ -284,6 +315,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
final_state: probe.final_state,
result,
shallow_certainty,
impl_args,
});
}
}

View File

@@ -242,6 +242,7 @@ enum WipProbeStep<'tcx> {
EvaluateGoals(WipAddedGoalsEvaluation<'tcx>),
NestedProbe(WipProbe<'tcx>),
MakeCanonicalResponse { shallow_certainty: Certainty },
RecordImplArgs { impl_args: inspect::CanonicalState<'tcx, ty::GenericArgsRef<'tcx>> },
}
impl<'tcx> WipProbeStep<'tcx> {
@@ -250,6 +251,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::RecordImplArgs { impl_args } => {
inspect::ProbeStep::RecordImplArgs { impl_args }
}
WipProbeStep::MakeCanonicalResponse { shallow_certainty } => {
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty }
}
@@ -534,6 +538,30 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
}
}
pub(crate) fn record_impl_args(
&mut self,
infcx: &InferCtxt<'tcx>,
max_input_universe: ty::UniverseIndex,
impl_args: ty::GenericArgsRef<'tcx>,
) {
match self.as_mut() {
Some(DebugSolver::GoalEvaluationStep(state)) => {
let impl_args = canonical::make_canonical_state(
infcx,
&state.var_values,
max_input_universe,
impl_args,
);
state
.current_evaluation_scope()
.steps
.push(WipProbeStep::RecordImplArgs { impl_args });
}
None => {}
_ => bug!(),
}
}
pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) {
match self.as_mut() {
Some(DebugSolver::GoalEvaluationStep(state)) => {
@@ -543,7 +571,7 @@ impl<'tcx> ProofTreeBuilder<'tcx> {
.push(WipProbeStep::MakeCanonicalResponse { shallow_certainty });
}
None => {}
_ => {}
_ => bug!(),
}
}