1
Fork 0

Only register candidate if it is associated w a shallow certainty

This commit is contained in:
Michael Goulet 2024-04-28 15:35:35 -04:00
parent 7cf1c547c2
commit 2eb7c8196b
4 changed files with 32 additions and 42 deletions

View file

@ -150,6 +150,6 @@ pub enum ProbeKind<'tcx> {
/// do a probe to find out what projection type(s) may be used to prove that /// do a probe to find out what projection type(s) may be used to prove that
/// the source type upholds all of the target type's object bounds. /// the source type upholds all of the target type's object bounds.
UpcastProjectionCompatibility, UpcastProjectionCompatibility,
/// Try to unify an opaque type with an existing /// Try to unify an opaque type with an existing key in the storage.
OpaqueTypeStorageLookup, OpaqueTypeStorageLookup { result: QueryResult<'tcx> },
} }

View file

@ -112,8 +112,8 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
ProbeKind::UpcastProjectionCompatibility => { ProbeKind::UpcastProjectionCompatibility => {
write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
} }
ProbeKind::OpaqueTypeStorageLookup => { ProbeKind::OpaqueTypeStorageLookup { result } => {
write!(self.f, "PROBING FOR AN EXISTING OPAQUE:") write!(self.f, "PROBING FOR AN EXISTING OPAQUE: {result:?}")
} }
ProbeKind::TraitCandidate { source, result } => { ProbeKind::TraitCandidate { source, result } => {
write!(self.f, "CANDIDATE {source:?}: {result:?}") write!(self.f, "CANDIDATE {source:?}: {result:?}")

View file

@ -998,8 +998,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if candidate_key.def_id != key.def_id { if candidate_key.def_id != key.def_id {
continue; continue;
} }
values.extend(self.probe(|_| inspect::ProbeKind::OpaqueTypeStorageLookup).enter( values.extend(
|ecx| { self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
result: *result,
})
.enter(|ecx| {
for (a, b) in std::iter::zip(candidate_key.args, key.args) { for (a, b) in std::iter::zip(candidate_key.args, key.args) {
ecx.eq(param_env, a, b)?; ecx.eq(param_env, a, b)?;
} }
@ -1011,8 +1014,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
candidate_ty, candidate_ty,
); );
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}, }),
)); );
} }
values values
} }

View file

@ -45,7 +45,7 @@ pub struct InspectCandidate<'a, 'tcx> {
nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>, nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
final_state: inspect::CanonicalState<'tcx, ()>, final_state: inspect::CanonicalState<'tcx, ()>,
result: QueryResult<'tcx>, result: QueryResult<'tcx>,
candidate_certainty: Option<Certainty>, shallow_certainty: Certainty,
} }
impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
@ -59,15 +59,14 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
/// Certainty passed into `evaluate_added_goals_and_make_canonical_response`. /// Certainty passed into `evaluate_added_goals_and_make_canonical_response`.
/// ///
/// If this certainty is `Some(Yes)`, then we must be confident that the candidate /// If this certainty is `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 /// 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`, /// `Maybe(..)`, which suggests we forced ambiguity instead.
/// 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 /// This is *not* the certainty of the candidate's full nested evaluation, which
/// accessed with [`Self::result`] instead. /// can be accessed with [`Self::result`] instead.
pub fn candidate_certainty(&self) -> Option<Certainty> { pub fn shallow_certainty(&self) -> Certainty {
self.candidate_certainty self.shallow_certainty
} }
/// Visit all nested goals of this candidate without rolling /// Visit all nested goals of this candidate without rolling
@ -174,9 +173,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>, nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
probe: &inspect::Probe<'tcx>, probe: &inspect::Probe<'tcx>,
) { ) {
let mut candidate_certainty = None; let mut shallow_certainty = None;
let num_candidates = candidates.len();
for step in &probe.steps { for step in &probe.steps {
match step { match step {
&inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal), &inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal),
@ -188,8 +185,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
self.candidates_recur(candidates, nested_goals, probe); self.candidates_recur(candidates, nested_goals, probe);
nested_goals.truncate(num_goals); nested_goals.truncate(num_goals);
} }
inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty } => { inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_eq!(candidate_certainty.replace(*shallow_certainty), None); assert_eq!(shallow_certainty.replace(*c), None);
} }
inspect::ProbeStep::EvaluateGoals(_) => (), inspect::ProbeStep::EvaluateGoals(_) => (),
} }
@ -198,37 +195,27 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
match probe.kind { match probe.kind {
inspect::ProbeKind::NormalizedSelfTyAssembly inspect::ProbeKind::NormalizedSelfTyAssembly
| inspect::ProbeKind::UnsizeAssembly | inspect::ProbeKind::UnsizeAssembly
| inspect::ProbeKind::UpcastProjectionCompatibility | inspect::ProbeKind::UpcastProjectionCompatibility => (),
| inspect::ProbeKind::OpaqueTypeStorageLookup => (),
// We add a candidate for the root evaluation if there // We add a candidate even for the root evaluation if there
// is only one way to prove a given goal, e.g. for `WellFormed`. // is only one way to prove a given goal, e.g. for `WellFormed`.
//
// FIXME: This is currently wrong if we don't even try any
// candidates, e.g. for a trait goal, as in this case `candidates` is
// actually supposed to be empty.
inspect::ProbeKind::Root { result } inspect::ProbeKind::Root { result }
| inspect::ProbeKind::TryNormalizeNonRigid { result } => { | inspect::ProbeKind::TryNormalizeNonRigid { result }
if candidates.len() == num_candidates { | inspect::ProbeKind::TraitCandidate { source: _, result }
| inspect::ProbeKind::OpaqueTypeStorageLookup { result } => {
// We only add a candidate if `shallow_certainty` was set, which means
// that we ended up calling `evaluate_added_goals_and_make_canonical_response`.
if let Some(shallow_certainty) = shallow_certainty {
candidates.push(InspectCandidate { candidates.push(InspectCandidate {
goal: self, goal: self,
kind: probe.kind, kind: probe.kind,
nested_goals: nested_goals.clone(), nested_goals: nested_goals.clone(),
final_state: probe.final_state, final_state: probe.final_state,
result, result,
candidate_certainty, shallow_certainty,
}) });
} }
} }
inspect::ProbeKind::TraitCandidate { source: _, result } => {
candidates.push(InspectCandidate {
goal: self,
kind: probe.kind,
nested_goals: nested_goals.clone(),
final_state: probe.final_state,
result,
candidate_certainty,
});
}
} }
} }