about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/solve/eval_ctxt.rs')
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs71
1 files changed, 63 insertions, 8 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 63a73f8d50d..bd83666eb1e 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -9,7 +9,10 @@ use rustc_infer::infer::{
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
+use rustc_middle::traits::solve::{
+    CanonicalInput, Certainty, MaybeCause, PredefinedOpaques, PredefinedOpaquesData, QueryResult,
+};
+use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{
     self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
     TypeVisitor,
@@ -44,6 +47,9 @@ pub struct EvalCtxt<'a, 'tcx> {
     infcx: &'a InferCtxt<'tcx>,
 
     pub(super) var_values: CanonicalVarValues<'tcx>,
+
+    predefined_opaques_in_body: PredefinedOpaques<'tcx>,
+
     /// The highest universe index nameable by the caller.
     ///
     /// When we enter a new binder inside of the query we create new universes
@@ -126,6 +132,11 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
         let mut ecx = EvalCtxt {
             search_graph: &mut search_graph,
             infcx: self,
+            // Only relevant when canonicalizing the response,
+            // which we don't do within this evaluation context.
+            predefined_opaques_in_body: self
+                .tcx
+                .mk_predefined_opaques_in_body(PredefinedOpaquesData::default()),
             // Only relevant when canonicalizing the response.
             max_input_universe: ty::UniverseIndex::ROOT,
             var_values: CanonicalVarValues::dummy(),
@@ -162,29 +173,59 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
     fn evaluate_canonical_goal(
         tcx: TyCtxt<'tcx>,
         search_graph: &'a mut search_graph::SearchGraph<'tcx>,
-        canonical_goal: CanonicalGoal<'tcx>,
+        canonical_input: CanonicalInput<'tcx>,
     ) -> QueryResult<'tcx> {
         // Deal with overflow, caching, and coinduction.
         //
         // The actual solver logic happens in `ecx.compute_goal`.
-        search_graph.with_new_goal(tcx, canonical_goal, |search_graph| {
+        search_graph.with_new_goal(tcx, canonical_input, |search_graph| {
             let intercrate = match search_graph.solver_mode() {
                 SolverMode::Normal => false,
                 SolverMode::Coherence => true,
             };
-            let (ref infcx, goal, var_values) = tcx
+            let (ref infcx, input, var_values) = tcx
                 .infer_ctxt()
                 .intercrate(intercrate)
-                .build_with_canonical(DUMMY_SP, &canonical_goal);
+                .with_opaque_type_inference(canonical_input.value.anchor)
+                .build_with_canonical(DUMMY_SP, &canonical_input);
+
+            for &(a, b) in &input.predefined_opaques_in_body.opaque_types {
+                let InferOk { value: (), obligations } = infcx
+                    .handle_opaque_type(
+                        tcx.mk_opaque(a.def_id.to_def_id(), a.substs),
+                        b,
+                        true,
+                        &ObligationCause::dummy(),
+                        input.goal.param_env,
+                    )
+                    .expect("expected opaque type instantiation to succeed");
+                // We're only registering opaques already defined by the caller,
+                // so we're not responsible for proving that they satisfy their
+                // item bounds, unless we use them in a normalizes-to goal,
+                // which is handled in `EvalCtxt::unify_existing_opaque_tys`.
+                let _ = obligations;
+            }
             let mut ecx = EvalCtxt {
                 infcx,
                 var_values,
-                max_input_universe: canonical_goal.max_universe,
+                predefined_opaques_in_body: input.predefined_opaques_in_body,
+                max_input_universe: canonical_input.max_universe,
                 search_graph,
                 nested_goals: NestedGoals::new(),
                 tainted: Ok(()),
             };
-            ecx.compute_goal(goal)
+
+            let result = ecx.compute_goal(input.goal);
+
+            // When creating a query response we clone the opaque type constraints
+            // instead of taking them. This would cause an ICE here, since we have
+            // assertions against dropping an `InferCtxt` without taking opaques.
+            // FIXME: Once we remove support for the old impl we can remove this.
+            if input.anchor != DefiningAnchor::Error {
+                let _ = infcx.take_opaque_types();
+            }
+
+            result
         })
     }
 
@@ -199,7 +240,8 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         let canonical_response =
             EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
 
-        let has_changed = !canonical_response.value.var_values.is_identity();
+        let has_changed = !canonical_response.value.var_values.is_identity()
+            || !canonical_response.value.external_constraints.opaque_types.is_empty();
         let (certainty, nested_goals) = self.instantiate_and_apply_query_response(
             goal.param_env,
             orig_values,
@@ -418,6 +460,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let mut ecx = EvalCtxt {
             infcx: self.infcx,
             var_values: self.var_values,
+            predefined_opaques_in_body: self.predefined_opaques_in_body,
             max_input_universe: self.max_input_universe,
             search_graph: self.search_graph,
             nested_goals: self.nested_goals.clone(),
@@ -682,4 +725,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | rustc_transmute::Answer::IfAny(_) => Err(NoSolution),
         }
     }
+
+    pub(super) fn handle_opaque_ty(
+        &mut self,
+        a: Ty<'tcx>,
+        b: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> Result<(), NoSolution> {
+        let InferOk { value: (), obligations } =
+            self.infcx.handle_opaque_type(a, b, true, &ObligationCause::dummy(), param_env)?;
+        self.add_goals(obligations.into_iter().map(|obligation| obligation.into()));
+        Ok(())
+    }
 }