Use a proper probe for shadowing impl

This commit is contained in:
Michael Goulet 2024-05-07 11:09:21 -04:00
parent 9105c57b7f
commit dbd2ca6478
5 changed files with 39 additions and 22 deletions

View File

@ -153,6 +153,8 @@ 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,
/// Looking for param-env candidates that satisfy the trait ref for a projection.
ShadowedEnvProbing,
/// Try to unify an opaque type with an existing key in the storage. /// Try to unify an opaque type with an existing key in the storage.
OpaqueTypeStorageLookup { result: QueryResult<'tcx> }, OpaqueTypeStorageLookup { result: QueryResult<'tcx> },
} }

View File

@ -118,6 +118,9 @@ pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result {
ProbeKind::TraitCandidate { source, result } => { ProbeKind::TraitCandidate { source, result } => {
write!(self.f, "CANDIDATE {source:?}: {result:?}") write!(self.f, "CANDIDATE {source:?}: {result:?}")
} }
ProbeKind::ShadowedEnvProbing => {
write!(self.f, "PROBING FOR IMPLS SHADOWED BY PARAM-ENV CANDIDATE:")
}
}?; }?;
self.nested(|this| { self.nested(|this| {

View File

@ -1,7 +1,7 @@
//! Code shared by trait and projection goals for candidate assembly. //! Code shared by trait and projection goals for candidate assembly.
use crate::solve::GoalSource; use crate::solve::GoalSource;
use crate::solve::{inspect, EvalCtxt, SolverMode}; use crate::solve::{EvalCtxt, SolverMode};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::query::NoSolution;
use rustc_middle::bug; use rustc_middle::bug;
@ -16,7 +16,6 @@
use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, DUMMY_SP}; use rustc_span::{ErrorGuaranteed, DUMMY_SP};
use std::fmt::Debug; use std::fmt::Debug;
use std::mem;
pub(super) mod structural_traits; pub(super) mod structural_traits;
@ -792,17 +791,16 @@ fn discard_impls_shadowed_by_env<G: GoalKind<'tcx>>(
goal: Goal<'tcx, G>, goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>, candidates: &mut Vec<Candidate<'tcx>>,
) { ) {
// HACK: We temporarily remove the `ProofTreeBuilder` to
// avoid adding `Trait` candidates to the candidates used
// to prove the current goal.
let inspect = mem::replace(&mut self.inspect, inspect::ProofTreeBuilder::new_noop());
let tcx = self.tcx(); let tcx = self.tcx();
let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> =
goal.with(tcx, goal.predicate.trait_ref(tcx)); goal.with(tcx, goal.predicate.trait_ref(tcx));
let mut trait_candidates_from_env = Vec::new();
self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); let mut trait_candidates_from_env = vec![];
self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| {
ecx.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env);
ecx.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env);
});
if !trait_candidates_from_env.is_empty() { if !trait_candidates_from_env.is_empty() {
let trait_env_result = self.merge_candidates(trait_candidates_from_env); let trait_env_result = self.merge_candidates(trait_candidates_from_env);
match trait_env_result.unwrap().value.certainty { match trait_env_result.unwrap().value.certainty {
@ -831,7 +829,6 @@ fn discard_impls_shadowed_by_env<G: GoalKind<'tcx>>(
} }
} }
} }
self.inspect = inspect;
} }
/// If there are multiple ways to prove a trait or projection goal, we have /// If there are multiple ways to prove a trait or projection goal, we have

View File

@ -176,7 +176,8 @@ fn to_selection<'tcx>(
| ProbeKind::UnsizeAssembly | ProbeKind::UnsizeAssembly
| ProbeKind::UpcastProjectionCompatibility | ProbeKind::UpcastProjectionCompatibility
| ProbeKind::OpaqueTypeStorageLookup { result: _ } | ProbeKind::OpaqueTypeStorageLookup { result: _ }
| ProbeKind::Root { result: _ } => { | ProbeKind::Root { result: _ }
| ProbeKind::ShadowedEnvProbing => {
span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind()) span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind())
} }
}) })

View File

@ -18,8 +18,8 @@
use rustc_middle::traits::solve::{inspect, QueryResult}; use rustc_middle::traits::solve::{inspect, QueryResult};
use rustc_middle::traits::solve::{Certainty, Goal}; use rustc_middle::traits::solve::{Certainty, Goal};
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::ty;
use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::TypeFoldable;
use rustc_middle::{bug, ty};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use crate::solve::eval_ctxt::canonical; use crate::solve::eval_ctxt::canonical;
@ -290,6 +290,17 @@ fn candidates_recur(
match *step { match *step {
inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)), inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
inspect::ProbeStep::NestedProbe(ref probe) => { inspect::ProbeStep::NestedProbe(ref probe) => {
match probe.kind {
// These never assemble candidates for the goal we're trying to solve.
inspect::ProbeKind::UpcastProjectionCompatibility
| inspect::ProbeKind::ShadowedEnvProbing => continue,
inspect::ProbeKind::NormalizedSelfTyAssembly
| inspect::ProbeKind::UnsizeAssembly
| inspect::ProbeKind::Root { .. }
| inspect::ProbeKind::TryNormalizeNonRigid { .. }
| inspect::ProbeKind::TraitCandidate { .. }
| inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => {
// Nested probes have to prove goals added in their parent // Nested probes have to prove goals added in their parent
// but do not leak them, so we truncate the added goals // but do not leak them, so we truncate the added goals
// afterwards. // afterwards.
@ -297,6 +308,8 @@ fn candidates_recur(
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: c } => { inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => {
assert_eq!(shallow_certainty.replace(c), None); assert_eq!(shallow_certainty.replace(c), None);
} }
@ -308,9 +321,10 @@ fn candidates_recur(
} }
match probe.kind { match probe.kind {
inspect::ProbeKind::NormalizedSelfTyAssembly inspect::ProbeKind::UpcastProjectionCompatibility
| inspect::ProbeKind::UnsizeAssembly | inspect::ProbeKind::ShadowedEnvProbing => bug!(),
| inspect::ProbeKind::UpcastProjectionCompatibility => (),
inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {}
// We add a candidate even 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`.