1
Fork 0

Pull out logic from #111131, plus some new logic in EvalCtxt::normalize_opaque_type

Co-authored-by: lcnr <rust@lcnr.de>
This commit is contained in:
Michael Goulet 2023-05-09 18:56:43 +00:00
parent 7664dfe433
commit 4d80b8090c
13 changed files with 122 additions and 43 deletions

View file

@ -133,12 +133,14 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(_, _, _)
| ty::PredicateKind::ConstEvaluatable(_)
| ty::PredicateKind::TypeWellFormedFromEnv(_)
| ty::PredicateKind::Ambiguous => {
FulfillmentErrorCode::CodeSelectionError(
SelectionError::Unimplemented,
)
}
ty::PredicateKind::TypeWellFormedFromEnv(_) => {
bug!("unexpected goal: {goal:?}")
}
},
root_obligation: obligation,
});

View file

@ -24,6 +24,7 @@ mod assembly;
mod canonicalize;
mod eval_ctxt;
mod fulfill;
mod opaques;
mod project_goals;
mod search_graph;
mod trait_goals;
@ -212,7 +213,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
);
}
match (lhs.to_projection_term(tcx), rhs.to_projection_term(tcx)) {
match (lhs.to_alias_ty(tcx), rhs.to_alias_ty(tcx)) {
(None, None) => bug!("`AliasRelate` goal without an alias on either lhs or rhs"),
// RHS is not a projection, only way this is true is if LHS normalizes-to RHS

View file

@ -0,0 +1,44 @@
use rustc_infer::infer::InferOk;
use rustc_middle::traits::solve::{Certainty, Goal, QueryResult};
use rustc_middle::traits::{ObligationCause, Reveal};
use rustc_middle::ty::ProjectionPredicate;
use super::{EvalCtxt, SolverMode};
impl<'tcx> EvalCtxt<'_, 'tcx> {
pub(super) fn normalize_opaque_type(
&mut self,
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
) -> QueryResult<'tcx> {
let tcx = self.tcx();
let opaque_ty = goal.predicate.projection_ty;
let expected = goal.predicate.term.ty().expect("no such thing as an opaque const");
match goal.param_env.reveal() {
Reveal::UserFacing => match self.solver_mode() {
SolverMode::Normal => self.probe(|ecx| {
// FIXME: Check that the usage is "defining" (all free params), otherwise bail.
// FIXME: This should probably just check the anchor directly
let InferOk { value: (), obligations } = self.infcx.handle_opaque_type(
expected,
tcx.mk_opaque(opaque_ty.def_id, opaque_ty.substs),
true,
&ObligationCause::dummy(),
goal.param_env,
)?;
// FIXME: Need to fold these to replace the opaque ty with the expected ty.
ecx.add_goals(obligations.into_iter().map(Into::into));
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}),
SolverMode::Coherence => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
}
},
Reveal::All => self.probe(|ecx| {
let actual = tcx.type_of(opaque_ty.def_id).subst(tcx, opaque_ty.substs);
ecx.eq(goal.param_env, expected, actual)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}),
}
}
}

View file

@ -30,8 +30,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// `U` and equate it with `u32`. This means that we don't need a separate
// projection cache in the solver.
if self.term_is_fully_unconstrained(goal) {
let candidates = self.assemble_and_evaluate_candidates(goal);
self.merge_candidates(candidates)
match goal.predicate.projection_ty.kind(self.tcx()) {
ty::AliasKind::Projection => {
let candidates = self.assemble_and_evaluate_candidates(goal);
self.merge_candidates(candidates)
}
ty::AliasKind::Opaque => self.normalize_opaque_type(goal),
}
} else {
self.set_normalizes_to_hack_goal(goal);
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)

View file

@ -834,8 +834,10 @@ impl<'tcx> AutoTraitFinder<'tcx> {
| ty::PredicateKind::Subtype(..)
// FIXME(generic_const_exprs): you can absolutely add this as a where clauses
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
| ty::PredicateKind::Coerce(..) => {}
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("predicate should only exist in the environment: {bound_predicate:?}")
}
ty::PredicateKind::Ambiguous => return false,
};
}