about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/solve
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve')
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/opaques.rs44
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs9
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)