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:
parent
7664dfe433
commit
4d80b8090c
13 changed files with 122 additions and 43 deletions
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
44
compiler/rustc_trait_selection/src/solve/opaques.rs
Normal file
44
compiler/rustc_trait_selection/src/solve/opaques.rs
Normal 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)
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue