about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-11 03:42:14 +0000
committerbors <bors@rust-lang.org>2023-06-11 03:42:14 +0000
commit34d64ab7a21f704adb496ee2749242fc3511f0f8 (patch)
treeb3b18faa5de609c681a53429bd1e4091f72362fb
parent970058e16b307e1cff01e2ddb084d2e8d14ea8be (diff)
parentb62e20d2fd5fd186a662c5621a41b717fcc313e0 (diff)
downloadrust-34d64ab7a21f704adb496ee2749242fc3511f0f8.tar.gz
rust-34d64ab7a21f704adb496ee2749242fc3511f0f8.zip
Auto merge of #112466 - lcnr:opaque-type-cleanup, r=compiler-errors
opaque type cleanup

the commits are pretty self-contained.

r? `@compiler-errors` cc `@oli-obk`
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs150
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs34
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs110
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/table.rs4
-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
7 files changed, 204 insertions, 175 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index a561496b026..b5d5071dc05 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -61,7 +61,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'tcx>,
-        opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
+        opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
     ) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
         let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
 
@@ -72,7 +72,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             .collect();
         debug!(?member_constraints);
 
-        for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
+        for (opaque_type_key, concrete_type) in opaque_ty_decls {
             let substs = opaque_type_key.substs;
             debug!(?concrete_type, ?substs);
 
@@ -143,7 +143,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             let ty = infcx.infer_opaque_definition_from_instantiation(
                 opaque_type_key,
                 universal_concrete_type,
-                origin,
             );
             // Sometimes two opaque types are the same only after we remap the generic parameters
             // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
@@ -215,7 +214,6 @@ pub trait InferCtxtExt<'tcx> {
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
         instantiated_ty: OpaqueHiddenType<'tcx>,
-        origin: OpaqueTyOrigin,
     ) -> Ty<'tcx>;
 }
 
@@ -248,109 +246,115 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
         instantiated_ty: OpaqueHiddenType<'tcx>,
-        origin: OpaqueTyOrigin,
     ) -> Ty<'tcx> {
         if let Some(e) = self.tainted_by_errors() {
             return self.tcx.ty_error(e);
         }
 
+        if let Err(guar) =
+            check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
+        {
+            return self.tcx.ty_error(guar);
+        }
+
         let definition_ty = instantiated_ty
             .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
             .ty;
 
-        if let Err(guar) = check_opaque_type_parameter_valid(
+        // `definition_ty` does not live in of the current inference context,
+        // so lets make sure that we don't accidentally misuse our current `infcx`.
+        match check_opaque_type_well_formed(
             self.tcx,
-            opaque_type_key,
-            origin,
+            self.next_trait_solver(),
+            opaque_type_key.def_id,
             instantiated_ty.span,
+            definition_ty,
         ) {
-            return self.tcx.ty_error(guar);
+            Ok(hidden_ty) => hidden_ty,
+            Err(guar) => self.tcx.ty_error(guar),
         }
+    }
+}
 
-        // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
-        // on stable and we'd break that.
-        let OpaqueTyOrigin::TyAlias { .. } = origin else {
-            return definition_ty;
-        };
-        let def_id = opaque_type_key.def_id;
-        // This logic duplicates most of `check_opaque_meets_bounds`.
-        // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
-        let param_env = self.tcx.param_env(def_id);
-        // HACK This bubble is required for this tests to pass:
-        // nested-return-type2-tait2.rs
-        // nested-return-type2-tait3.rs
-        // FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
-        // and prepopulate this `InferCtxt` with known opaque values, rather than
-        // using the `Bind` anchor here. For now it's fine.
-        let infcx = self
-            .tcx
-            .infer_ctxt()
-            .with_opaque_type_inference(if self.next_trait_solver() {
-                DefiningAnchor::Bind(def_id)
-            } else {
-                DefiningAnchor::Bubble
-            })
-            .build();
-        let ocx = ObligationCtxt::new(&infcx);
-        // Require the hidden type to be well-formed with only the generics of the opaque type.
-        // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
-        // hidden type is well formed even without those bounds.
-        let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
-
-        let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
+/// This logic duplicates most of `check_opaque_meets_bounds`.
+/// FIXME(oli-obk): Also do region checks here and then consider removing
+/// `check_opaque_meets_bounds` entirely.
+fn check_opaque_type_well_formed<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    next_trait_solver: bool,
+    def_id: LocalDefId,
+    definition_span: Span,
+    definition_ty: Ty<'tcx>,
+) -> Result<Ty<'tcx>, ErrorGuaranteed> {
+    // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
+    // on stable and we'd break that.
+    let opaque_ty_hir = tcx.hir().expect_item(def_id);
+    let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.expect_opaque_ty().origin else {
+        return Ok(definition_ty);
+    };
+    let param_env = tcx.param_env(def_id);
+    // HACK This bubble is required for this tests to pass:
+    // nested-return-type2-tait2.rs
+    // nested-return-type2-tait3.rs
+    // FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
+    // and prepopulate this `InferCtxt` with known opaque values, rather than
+    // using the `Bind` anchor here. For now it's fine.
+    let infcx = tcx
+        .infer_ctxt()
+        .with_next_trait_solver(next_trait_solver)
+        .with_opaque_type_inference(if next_trait_solver {
+            DefiningAnchor::Bind(def_id)
+        } else {
+            DefiningAnchor::Bubble
+        })
+        .build();
+    let ocx = ObligationCtxt::new(&infcx);
+    let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
 
-        // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
-        // the bounds that the function supplies.
-        let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
-        if let Err(err) = ocx.eq(
-            &ObligationCause::misc(instantiated_ty.span, def_id),
-            param_env,
-            opaque_ty,
-            definition_ty,
-        ) {
+    // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
+    // the bounds that the function supplies.
+    let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), identity_substs);
+    ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
+        .map_err(|err| {
             infcx
                 .err_ctxt()
                 .report_mismatched_types(
-                    &ObligationCause::misc(instantiated_ty.span, def_id),
+                    &ObligationCause::misc(definition_span, def_id),
                     opaque_ty,
                     definition_ty,
                     err,
                 )
-                .emit();
-        }
+                .emit()
+        })?;
 
-        ocx.register_obligation(Obligation::misc(
-            infcx.tcx,
-            instantiated_ty.span,
-            def_id,
-            param_env,
-            predicate,
-        ));
+    // Require the hidden type to be well-formed with only the generics of the opaque type.
+    // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
+    // hidden type is well formed even without those bounds.
+    let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
+    ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate));
 
-        // Check that all obligations are satisfied by the implementation's
-        // version.
-        let errors = ocx.select_all_or_error();
+    // Check that all obligations are satisfied by the implementation's
+    // version.
+    let errors = ocx.select_all_or_error();
 
-        // This is still required for many(half of the tests in ui/type-alias-impl-trait)
-        // tests to pass
-        let _ = infcx.take_opaque_types();
+    // This is still required for many(half of the tests in ui/type-alias-impl-trait)
+    // tests to pass
+    let _ = infcx.take_opaque_types();
 
-        if errors.is_empty() {
-            definition_ty
-        } else {
-            let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
-            self.tcx.ty_error(reported)
-        }
+    if errors.is_empty() {
+        Ok(definition_ty)
+    } else {
+        Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
     }
 }
 
 fn check_opaque_type_parameter_valid(
     tcx: TyCtxt<'_>,
     opaque_type_key: OpaqueTypeKey<'_>,
-    origin: OpaqueTyOrigin,
     span: Span,
 ) -> Result<(), ErrorGuaranteed> {
-    match origin {
+    let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
+    match opaque_ty_hir.expect_opaque_ty().origin {
         // No need to check return position impl trait (RPIT)
         // because for type and const parameters they are correct
         // by construction: we convert
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 00fd3762fa7..6697e1aff7d 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -7,7 +7,6 @@ use std::{fmt, iter, mem};
 
 use either::Either;
 
-use hir::OpaqueTyOrigin;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::ErrorGuaranteed;
@@ -28,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};
@@ -241,7 +241,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
                 hidden_type.ty = infcx.tcx.ty_error(reported);
             }
 
-            (opaque_type_key, (hidden_type, decl.origin))
+            (opaque_type_key, hidden_type)
         })
         .collect();
 
@@ -878,8 +878,7 @@ struct BorrowCheckContext<'a, 'tcx> {
 pub(crate) struct MirTypeckResults<'tcx> {
     pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
     pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-    pub(crate) opaque_type_values:
-        FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
+    pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
 }
 
 /// A collection of region constraints that must be satisfied for the
@@ -1053,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 a9ead429f4c..6b8293f90f1 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -33,9 +33,6 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// There can be multiple, but they are all `lub`ed together at the end
     /// to obtain the canonical hidden type.
     pub hidden_type: OpaqueHiddenType<'tcx>,
-
-    /// The origin of the opaque type.
-    pub origin: hir::OpaqueTyOrigin,
 }
 
 impl<'tcx> InferCtxt<'tcx> {
@@ -108,7 +105,7 @@ impl<'tcx> InferCtxt<'tcx> {
         let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => {
                 let def_id = def_id.expect_local();
-                let origin = match self.defining_use_anchor {
+                match self.defining_use_anchor {
                     DefiningAnchor::Bind(_) => {
                         // Check that this is `impl Trait` type is
                         // declared by `parent_def_id` -- i.e., one whose
@@ -144,9 +141,11 @@ impl<'tcx> InferCtxt<'tcx> {
                         //     let x = || foo(); // returns the Opaque assoc with `foo`
                         // }
                         // ```
-                        self.opaque_type_origin(def_id)?
+                        if self.opaque_type_origin(def_id).is_none() {
+                            return None;
+                        }
                     }
-                    DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id),
+                    DefiningAnchor::Bubble => {}
                     DefiningAnchor::Error => return None,
                 };
                 if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
@@ -170,7 +169,6 @@ impl<'tcx> InferCtxt<'tcx> {
                     cause.clone(),
                     param_env,
                     b,
-                    origin,
                     a_is_expected,
                 ))
             }
@@ -524,72 +522,78 @@ impl<'tcx> InferCtxt<'tcx> {
         cause: ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         hidden_ty: Ty<'tcx>,
-        origin: hir::OpaqueTyOrigin,
         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.borrow_mut().opaque_types().register(
-                opaque_type_key,
-                OpaqueHiddenType { ty: hidden_ty, span },
-                origin,
-            );
+            let prev = self
+                .inner
+                .borrow_mut()
+                .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());
-        let origin = self
-            .opaque_type_origin(opaque_type_key.def_id)
-            .expect("should be called for defining usages only");
-        self.register_hidden_type(
-            opaque_type_key,
-            ObligationCause::dummy(),
-            param_env,
-            hidden_ty,
-            origin,
-            true,
-        )
+        Ok(())
     }
 
     pub fn add_item_bounds_for_hidden_type(
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index a0f6d7ecab7..a737761ba22 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -1,5 +1,4 @@
 use rustc_data_structures::undo_log::UndoLogs;
-use rustc_hir::OpaqueTyOrigin;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
 use rustc_span::DUMMY_SP;
 
@@ -60,14 +59,13 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
         &mut self,
         key: OpaqueTypeKey<'tcx>,
         hidden_type: OpaqueHiddenType<'tcx>,
-        origin: OpaqueTyOrigin,
     ) -> Option<Ty<'tcx>> {
         if let Some(decl) = self.storage.opaque_types.get_mut(&key) {
             let prev = std::mem::replace(&mut decl.hidden_type, hidden_type);
             self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev)));
             return Some(prev.ty);
         }
-        let decl = OpaqueTypeDecl { hidden_type, origin };
+        let decl = OpaqueTypeDecl { hidden_type };
         self.storage.opaque_types.insert(key, decl);
         self.undo_log.push(UndoLog::OpaqueTypes(key, None));
         None
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 72b3c3d0180..851edf1fa1c 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -16,7 +16,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,
@@ -321,12 +320,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) => {