about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2023-06-09 16:41:11 +0200
committerlcnr <rust@lcnr.de>2023-06-09 16:41:11 +0200
commitb62e20d2fd5fd186a662c5621a41b717fcc313e0 (patch)
treed9a2feb6226bb035cc3ffc5a051043b298f93b08
parent669d609dfda2f61f2b358c9e9061f76ebd852e7e (diff)
downloadrust-b62e20d2fd5fd186a662c5621a41b717fcc313e0.tar.gz
rust-b62e20d2fd5fd186a662c5621a41b717fcc313e0.zip
split opaque type handling in new solver
be more explicit in where we only add new hidden types
and where we also have to deal with item bounds.
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs28
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs83
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs69
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs9
-rw-r--r--compiler/rustc_trait_selection/src/solve/opaques.rs3
5 files changed, 114 insertions, 78 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 63a2a24fd43..6697e1aff7d 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -27,6 +27,7 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::*;
 use rustc_middle::traits::query::NoSolution;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
@@ -1051,15 +1052,28 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             ConstraintCategory::OpaqueType,
             CustomTypeOp::new(
                 |ocx| {
-                    for (key, hidden_ty) in renumbered_opaques {
-                        ocx.register_infer_ok_obligations(
-                            ocx.infcx.register_hidden_type_in_new_solver(
-                                key,
-                                param_env,
-                                hidden_ty.ty,
-                            )?,
+                    let mut obligations = Vec::new();
+                    for (opaque_type_key, hidden_ty) in renumbered_opaques {
+                        let cause = ObligationCause::dummy();
+                        ocx.infcx.insert_hidden_type(
+                            opaque_type_key,
+                            &cause,
+                            param_env,
+                            hidden_ty.ty,
+                            true,
+                            &mut obligations,
+                        )?;
+
+                        ocx.infcx.add_item_bounds_for_hidden_type(
+                            opaque_type_key,
+                            cause,
+                            param_env,
+                            hidden_ty.ty,
+                            &mut obligations,
                         );
                     }
+
+                    ocx.register_obligations(obligations);
                     Ok(())
                 },
                 "register pre-defined opaques",
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 44efd334a16..6b8293f90f1 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -524,22 +524,60 @@ impl<'tcx> InferCtxt<'tcx> {
         hidden_ty: Ty<'tcx>,
         a_is_expected: bool,
     ) -> InferResult<'tcx, ()> {
+        let mut obligations = Vec::new();
+
+        self.insert_hidden_type(
+            opaque_type_key,
+            &cause,
+            param_env,
+            hidden_ty,
+            a_is_expected,
+            &mut obligations,
+        )?;
+
+        self.add_item_bounds_for_hidden_type(
+            opaque_type_key,
+            cause,
+            param_env,
+            hidden_ty,
+            &mut obligations,
+        );
+
+        Ok(InferOk { value: (), obligations })
+    }
+
+    /// Insert a hidden type into the opaque type storage, equating it
+    /// with any previous entries if necessary.
+    ///
+    /// This **does not** add the item bounds of the opaque as nested
+    /// obligations. That is only necessary when normalizing the opaque
+    /// itself, not when getting the opaque type constraints from
+    /// somewhere else.
+    pub fn insert_hidden_type(
+        &self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        hidden_ty: Ty<'tcx>,
+        a_is_expected: bool,
+        obligations: &mut Vec<PredicateObligation<'tcx>>,
+    ) -> Result<(), TypeError<'tcx>> {
         // Ideally, we'd get the span where *this specific `ty` came
         // from*, but right now we just use the span from the overall
         // value being folded. In simple cases like `-> impl Foo`,
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
         let span = cause.span;
-        let mut obligations = if self.intercrate {
+        if self.intercrate {
             // During intercrate we do not define opaque types but instead always
             // force ambiguity unless the hidden type is known to not implement
             // our trait.
-            vec![traits::Obligation::new(
+            obligations.push(traits::Obligation::new(
                 self.tcx,
                 cause.clone(),
                 param_env,
                 ty::PredicateKind::Ambiguous,
-            )]
+            ))
         } else {
             let prev = self
                 .inner
@@ -547,42 +585,15 @@ impl<'tcx> InferCtxt<'tcx> {
                 .opaque_types()
                 .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span });
             if let Some(prev) = prev {
-                self.at(&cause, param_env)
-                    .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
-                    .obligations
-            } else {
-                Vec::new()
+                obligations.extend(
+                    self.at(&cause, param_env)
+                        .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
+                        .obligations,
+                );
             }
         };
 
-        self.add_item_bounds_for_hidden_type(
-            opaque_type_key,
-            cause,
-            param_env,
-            hidden_ty,
-            &mut obligations,
-        );
-
-        Ok(InferOk { value: (), obligations })
-    }
-
-    /// Registers an opaque's hidden type -- only should be used when the opaque
-    /// can be defined. For something more fallible -- checks the anchors, tries
-    /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`.
-    pub fn register_hidden_type_in_new_solver(
-        &self,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        hidden_ty: Ty<'tcx>,
-    ) -> InferResult<'tcx, ()> {
-        assert!(self.next_trait_solver());
-        self.register_hidden_type(
-            opaque_type_key,
-            ObligationCause::dummy(),
-            param_env,
-            hidden_ty,
-            true,
-        )
+        Ok(())
     }
 
     pub fn add_item_bounds_for_hidden_type(
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 3001d9f1b1f..e01187bcd3c 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -15,8 +15,8 @@ use rustc_middle::traits::solve::{
 };
 use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::{
-    self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
-    TypeVisitor,
+    self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable,
+    TypeVisitableExt, TypeVisitor,
 };
 use rustc_span::DUMMY_SP;
 use std::ops::ControlFlow;
@@ -191,16 +191,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 .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
-                    .register_hidden_type_in_new_solver(a, input.goal.param_env, b)
-                    .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,
@@ -211,6 +201,15 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
                 tainted: Ok(()),
             };
 
+            for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
+                ecx.insert_hidden_type(key, input.goal.param_env, ty)
+                    .expect("failed to prepopulate opaque types");
+            }
+
+            if !ecx.nested_goals.is_empty() {
+                panic!("prepopulating opaque types shouldn't add goals: {:?}", ecx.nested_goals);
+            }
+
             let result = ecx.compute_goal(input.goal);
 
             // When creating a query response we clone the opaque type constraints
@@ -729,18 +728,42 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         self.infcx.opaque_type_origin(def_id).is_some()
     }
 
-    pub(super) fn register_opaque_ty(
+    pub(super) fn insert_hidden_type(
         &mut self,
-        a: ty::OpaqueTypeKey<'tcx>,
-        b: Ty<'tcx>,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
+        hidden_ty: Ty<'tcx>,
     ) -> Result<(), NoSolution> {
-        let InferOk { value: (), obligations } =
-            self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
-        self.add_goals(obligations.into_iter().map(|obligation| obligation.into()));
+        let mut obligations = Vec::new();
+        self.infcx.insert_hidden_type(
+            opaque_type_key,
+            &ObligationCause::dummy(),
+            param_env,
+            hidden_ty,
+            true,
+            &mut obligations,
+        )?;
+        self.add_goals(obligations.into_iter().map(|o| o.into()));
         Ok(())
     }
 
+    pub(super) fn add_item_bounds_for_hidden_type(
+        &mut self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        hidden_ty: Ty<'tcx>,
+    ) {
+        let mut obligations = Vec::new();
+        self.infcx.add_item_bounds_for_hidden_type(
+            opaque_type_key,
+            ObligationCause::dummy(),
+            param_env,
+            hidden_ty,
+            &mut obligations,
+        );
+        self.add_goals(obligations.into_iter().map(|o| o.into()));
+    }
+
     // Do something for each opaque/hidden pair defined with `def_id` in the
     // current inference context.
     pub(super) fn unify_existing_opaque_tys(
@@ -762,15 +785,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     ecx.eq(param_env, a, b)?;
                 }
                 ecx.eq(param_env, candidate_ty, ty)?;
-                let mut obl = vec![];
-                ecx.infcx.add_item_bounds_for_hidden_type(
-                    candidate_key,
-                    ObligationCause::dummy(),
-                    param_env,
-                    candidate_ty,
-                    &mut obl,
-                );
-                ecx.add_goals(obl.into_iter().map(Into::into));
+                ecx.add_item_bounds_for_hidden_type(candidate_key, param_env, candidate_ty);
                 ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }));
         }
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index bca2343e424..db673410008 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -15,7 +15,6 @@ use rustc_index::IndexVec;
 use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
 use rustc_infer::infer::canonical::CanonicalVarValues;
 use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
-use rustc_infer::infer::InferOk;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::{
     ExternalConstraints, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
@@ -317,12 +316,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         opaque_types: &[(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)],
     ) -> Result<(), NoSolution> {
-        for &(a, b) in opaque_types {
-            let InferOk { value: (), obligations } =
-                self.infcx.register_hidden_type_in_new_solver(a, param_env, b)?;
-            // It's sound to drop these obligations, since the normalizes-to goal
-            // is responsible for proving these obligations.
-            let _ = obligations;
+        for &(key, ty) in opaque_types {
+            self.insert_hidden_type(key, param_env, ty)?;
         }
         Ok(())
     }
diff --git a/compiler/rustc_trait_selection/src/solve/opaques.rs b/compiler/rustc_trait_selection/src/solve/opaques.rs
index a5de4ddee82..538c16c8ce2 100644
--- a/compiler/rustc_trait_selection/src/solve/opaques.rs
+++ b/compiler/rustc_trait_selection/src/solve/opaques.rs
@@ -50,7 +50,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                     }
                 }
                 // Otherwise, define a new opaque type
-                self.register_opaque_ty(opaque_ty, expected, goal.param_env)?;
+                self.insert_hidden_type(opaque_ty, goal.param_env, expected)?;
+                self.add_item_bounds_for_hidden_type(opaque_ty, goal.param_env, expected);
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
             (Reveal::UserFacing, SolverMode::Coherence) => {