diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve')
4 files changed, 56 insertions, 4 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 32bd10f0beb..4a403196c7e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -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, }); diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index d94679fef28..1427268f829 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -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 diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs new file mode 100644 index 00000000000..1a770459338 --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/opaques.rs @@ -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) + }), + } + } +} diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index d3228074421..248b750b3bd 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -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) |
