1
Fork 0

Canonicalize trait solver response inside probe

This commit is contained in:
Michael Goulet 2023-01-17 19:29:52 +00:00
parent 1f72129ffe
commit b84b1da2db
4 changed files with 25 additions and 24 deletions

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 super::infcx_ext::InferCtxtExt; use super::infcx_ext::InferCtxtExt;
use super::{CanonicalResponse, Certainty, EvalCtxt, Goal}; use super::{CanonicalResponse, EvalCtxt, Goal, QueryResult};
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::ty::TypeFoldable; use rustc_middle::ty::TypeFoldable;
@ -89,18 +89,18 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
ecx: &mut EvalCtxt<'_, 'tcx>, ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>, goal: Goal<'tcx, Self>,
impl_def_id: DefId, impl_def_id: DefId,
) -> Result<Certainty, NoSolution>; ) -> QueryResult<'tcx>;
fn consider_builtin_sized_candidate( fn consider_builtin_sized_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>, ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>, goal: Goal<'tcx, Self>,
) -> Result<Certainty, NoSolution>; ) -> QueryResult<'tcx>;
fn consider_assumption( fn consider_assumption(
ecx: &mut EvalCtxt<'_, 'tcx>, ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>, goal: Goal<'tcx, Self>,
assumption: ty::Predicate<'tcx>, assumption: ty::Predicate<'tcx>,
) -> Result<Certainty, NoSolution>; ) -> QueryResult<'tcx>;
} }
impl<'tcx> EvalCtxt<'_, 'tcx> { impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>( pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<'tcx>>(
@ -180,9 +180,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
tcx.for_each_relevant_impl( tcx.for_each_relevant_impl(
goal.predicate.trait_def_id(tcx), goal.predicate.trait_def_id(tcx),
goal.predicate.self_ty(), goal.predicate.self_ty(),
|impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) |impl_def_id| match G::consider_impl_candidate(self, goal, impl_def_id) {
.and_then(|certainty| self.make_canonical_response(certainty))
{
Ok(result) => candidates Ok(result) => candidates
.push(Candidate { source: CandidateSource::Impl(impl_def_id), result }), .push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
Err(NoSolution) => (), Err(NoSolution) => (),
@ -203,7 +201,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
Err(NoSolution) Err(NoSolution)
}; };
match result.and_then(|certainty| self.make_canonical_response(certainty)) { match result {
Ok(result) => { Ok(result) => {
candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result })
} }
@ -217,9 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
candidates: &mut Vec<Candidate<'tcx>>, candidates: &mut Vec<Candidate<'tcx>>,
) { ) {
for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() {
match G::consider_assumption(self, goal, assumption) match G::consider_assumption(self, goal, assumption) {
.and_then(|certainty| self.make_canonical_response(certainty))
{
Ok(result) => { Ok(result) => {
candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result })
} }
@ -268,9 +264,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
.subst_iter_copied(self.tcx(), alias_ty.substs) .subst_iter_copied(self.tcx(), alias_ty.substs)
.enumerate() .enumerate()
{ {
match G::consider_assumption(self, goal, assumption) match G::consider_assumption(self, goal, assumption) {
.and_then(|certainty| self.make_canonical_response(certainty))
{
Ok(result) => { Ok(result) => {
candidates.push(Candidate { source: CandidateSource::AliasBound(i), result }) candidates.push(Candidate { source: CandidateSource::AliasBound(i), result })
} }

View file

@ -313,6 +313,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
} }
}) })
} }
fn evaluate_all_and_make_canonical_response(
&mut self,
goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
) -> QueryResult<'tcx> {
self.evaluate_all(goals).and_then(|certainty| self.make_canonical_response(certainty))
}
} }
#[instrument(level = "debug", skip(infcx), ret)] #[instrument(level = "debug", skip(infcx), ret)]

View file

@ -191,7 +191,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
ecx: &mut EvalCtxt<'_, 'tcx>, ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>, goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
impl_def_id: DefId, impl_def_id: DefId,
) -> Result<Certainty, NoSolution> { ) -> QueryResult<'tcx> {
let tcx = ecx.tcx(); let tcx = ecx.tcx();
let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx); let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);
@ -229,7 +229,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
impl_def_id impl_def_id
)? else { )? else {
let certainty = Certainty::Maybe(MaybeCause::Ambiguity); let certainty = Certainty::Maybe(MaybeCause::Ambiguity);
return Ok(trait_ref_certainty.unify_and(certainty)); return ecx.make_canonical_response(trait_ref_certainty.unify_and(certainty));
}; };
if !assoc_def.item.defaultness(tcx).has_value() { if !assoc_def.item.defaultness(tcx).has_value() {
@ -286,14 +286,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
let rhs_certainty = let rhs_certainty =
ecx.evaluate_all(nested_goals).expect("failed to unify with unconstrained term"); ecx.evaluate_all(nested_goals).expect("failed to unify with unconstrained term");
Ok(trait_ref_certainty.unify_and(rhs_certainty)) ecx.make_canonical_response(trait_ref_certainty.unify_and(rhs_certainty))
}) })
} }
fn consider_builtin_sized_candidate( fn consider_builtin_sized_candidate(
_ecx: &mut EvalCtxt<'_, 'tcx>, _ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>, goal: Goal<'tcx, Self>,
) -> Result<Certainty, NoSolution> { ) -> QueryResult<'tcx> {
bug!("`Sized` does not have an associated type: {:?}", goal); bug!("`Sized` does not have an associated type: {:?}", goal);
} }
@ -301,7 +301,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
_ecx: &mut EvalCtxt<'_, 'tcx>, _ecx: &mut EvalCtxt<'_, 'tcx>,
_goal: Goal<'tcx, Self>, _goal: Goal<'tcx, Self>,
assumption: ty::Predicate<'tcx>, assumption: ty::Predicate<'tcx>,
) -> Result<Certainty, NoSolution> { ) -> QueryResult<'tcx> {
if let Some(_poly_projection_pred) = assumption.to_opt_poly_projection_pred() { if let Some(_poly_projection_pred) = assumption.to_opt_poly_projection_pred() {
unimplemented!() unimplemented!()
} else { } else {

View file

@ -4,7 +4,7 @@ use std::iter;
use super::assembly::{self, Candidate, CandidateSource}; use super::assembly::{self, Candidate, CandidateSource};
use super::infcx_ext::InferCtxtExt; use super::infcx_ext::InferCtxtExt;
use super::{Certainty, EvalCtxt, Goal, QueryResult}; use super::{EvalCtxt, Goal, QueryResult};
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::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@ -29,7 +29,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
ecx: &mut EvalCtxt<'_, 'tcx>, ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, TraitPredicate<'tcx>>, goal: Goal<'tcx, TraitPredicate<'tcx>>,
impl_def_id: DefId, impl_def_id: DefId,
) -> Result<Certainty, NoSolution> { ) -> QueryResult<'tcx> {
let tcx = ecx.tcx(); let tcx = ecx.tcx();
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
@ -53,14 +53,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
.into_iter() .into_iter()
.map(|pred| goal.with(tcx, pred)); .map(|pred| goal.with(tcx, pred));
nested_goals.extend(where_clause_bounds); nested_goals.extend(where_clause_bounds);
ecx.evaluate_all(nested_goals) ecx.evaluate_all_and_make_canonical_response(nested_goals)
}) })
} }
fn consider_builtin_sized_candidate( fn consider_builtin_sized_candidate(
_ecx: &mut EvalCtxt<'_, 'tcx>, _ecx: &mut EvalCtxt<'_, 'tcx>,
_goal: Goal<'tcx, Self>, _goal: Goal<'tcx, Self>,
) -> Result<Certainty, NoSolution> { ) -> QueryResult<'tcx> {
unimplemented!(); unimplemented!();
} }
@ -68,7 +68,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
_ecx: &mut EvalCtxt<'_, 'tcx>, _ecx: &mut EvalCtxt<'_, 'tcx>,
_goal: Goal<'tcx, Self>, _goal: Goal<'tcx, Self>,
assumption: ty::Predicate<'tcx>, assumption: ty::Predicate<'tcx>,
) -> Result<Certainty, NoSolution> { ) -> QueryResult<'tcx> {
if let Some(_poly_trait_pred) = assumption.to_opt_poly_trait_pred() { if let Some(_poly_trait_pred) = assumption.to_opt_poly_trait_pred() {
unimplemented!() unimplemented!()
} else { } else {