diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index 66542431149fc..0f3ace2d55d38 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -150,6 +150,6 @@ pub enum ProbeKind<'tcx> { /// 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. UpcastProjectionCompatibility, - /// Try to unify an opaque type with an existing - OpaqueTypeStorageLookup, + /// Try to unify an opaque type with an existing key in the storage. + OpaqueTypeStorageLookup { result: QueryResult<'tcx> }, } diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 91f0880fd2085..2d73be387fdcd 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -112,8 +112,8 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProbeKind::UpcastProjectionCompatibility => { write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") } - ProbeKind::OpaqueTypeStorageLookup => { - write!(self.f, "PROBING FOR AN EXISTING OPAQUE:") + ProbeKind::OpaqueTypeStorageLookup { result } => { + write!(self.f, "PROBING FOR AN EXISTING OPAQUE: {result:?}") } ProbeKind::TraitCandidate { source, result } => { write!(self.f, "CANDIDATE {source:?}: {result:?}") diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 225479fcff347..d8fd5c0591141 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -998,8 +998,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { if candidate_key.def_id != key.def_id { continue; } - values.extend(self.probe(|_| inspect::ProbeKind::OpaqueTypeStorageLookup).enter( - |ecx| { + values.extend( + self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { + result: *result, + }) + .enter(|ecx| { for (a, b) in std::iter::zip(candidate_key.args, key.args) { ecx.eq(param_env, a, b)?; } @@ -1011,8 +1014,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidate_ty, ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }, - )); + }), + ); } values } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 7daf99cb7e563..2d58111e80385 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -45,7 +45,7 @@ pub struct InspectCandidate<'a, 'tcx> { nested_goals: Vec>>>, final_state: inspect::CanonicalState<'tcx, ()>, result: QueryResult<'tcx>, - candidate_certainty: Option, + shallow_certainty: Certainty, } 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`. /// - /// 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 - /// `Some(Maybe)`, which suggests we forced ambiguity instead, or if it is `None`, - /// which suggests we may have not assembled any candidates at all. + /// `Maybe(..)`, which suggests we forced ambiguity instead. /// - /// This is *not* the certainty of the candidate's nested evaluation, which can be - /// accessed with [`Self::result`] instead. - pub fn candidate_certainty(&self) -> Option { - self.candidate_certainty + /// This is *not* the certainty of the candidate's full nested evaluation, which + /// can be accessed with [`Self::result`] instead. + pub fn shallow_certainty(&self) -> Certainty { + self.shallow_certainty } /// Visit all nested goals of this candidate without rolling @@ -174,9 +173,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { nested_goals: &mut Vec>>>, probe: &inspect::Probe<'tcx>, ) { - let mut candidate_certainty = None; - let num_candidates = candidates.len(); - + let mut shallow_certainty = None; for step in &probe.steps { match step { &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); nested_goals.truncate(num_goals); } - inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty } => { - assert_eq!(candidate_certainty.replace(*shallow_certainty), None); + inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { + assert_eq!(shallow_certainty.replace(*c), None); } inspect::ProbeStep::EvaluateGoals(_) => (), } @@ -198,37 +195,27 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { match probe.kind { inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly - | inspect::ProbeKind::UpcastProjectionCompatibility - | inspect::ProbeKind::OpaqueTypeStorageLookup => (), - // We add a candidate for the root evaluation if there + | inspect::ProbeKind::UpcastProjectionCompatibility => (), + + // We add a candidate even for the root evaluation if there // 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::TryNormalizeNonRigid { result } => { - if candidates.len() == num_candidates { + | inspect::ProbeKind::TryNormalizeNonRigid { result } + | 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 { goal: self, kind: probe.kind, nested_goals: nested_goals.clone(), final_state: probe.final_state, 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, - }); - } } }