about summary refs log tree commit diff
path: root/compiler/rustc_borrowck
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-02-14 16:10:22 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-03-28 16:27:14 +0000
commit264cd05b16198c2838ec6cd585bd122491e3f7a9 (patch)
tree133ca794d093e515a783cd92db831ff51e197820 /compiler/rustc_borrowck
parent0e4524e5b4a9c5656fef69f532f96eb9959a1803 (diff)
downloadrust-264cd05b16198c2838ec6cd585bd122491e3f7a9.tar.gz
rust-264cd05b16198c2838ec6cd585bd122491e3f7a9.zip
Revert "Auto merge of #93893 - oli-obk:sad_revert, r=oli-obk"
This reverts commit 6499c5e7fc173a3f55b7a3bd1e6a50e9edef782d, reversing
changes made to 78450d2d602b06d9b94349aaf8cece1a4acaf3a8.
Diffstat (limited to 'compiler/rustc_borrowck')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs112
-rw-r--r--compiler/rustc_borrowck/src/lib.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs58
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs9
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs271
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs37
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs14
10 files changed, 261 insertions, 260 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 7507ea76ed0..8601fbe27f3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -2,9 +2,13 @@ use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
 use rustc_infer::infer::region_constraints::Constraint;
+use rustc_infer::infer::region_constraints::RegionConstraintData;
+use rustc_infer::infer::RegionVariableOrigin;
 use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
 use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
 use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::RegionVid;
+use rustc_middle::ty::UniverseIndex;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op;
@@ -76,6 +80,15 @@ crate trait ToUniverseInfo<'tcx> {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx>;
 }
 
+impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
+    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
+        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType {
+            base_universe: Some(base_universe),
+            ..self
+        })))
+    }
+}
+
 impl<'tcx> ToUniverseInfo<'tcx>
     for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>>
 {
@@ -116,6 +129,12 @@ impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::Custo
     }
 }
 
+impl<'tcx> ToUniverseInfo<'tcx> for ! {
+    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
+        self
+    }
+}
+
 #[allow(unused_lifetimes)]
 trait TypeOpInfo<'tcx> {
     /// Returns an error to be reported if rerunning the type op fails to
@@ -130,7 +149,7 @@ trait TypeOpInfo<'tcx> {
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
@@ -175,7 +194,7 @@ trait TypeOpInfo<'tcx> {
         debug!(?placeholder_region);
 
         let span = cause.span;
-        let nice_error = self.nice_error(tcx, cause, placeholder_region, error_region);
+        let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
 
         if let Some(nice_error) = nice_error {
             mbcx.buffer_error(nice_error);
@@ -208,16 +227,16 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        tcx.infer_ctxt().enter_with_canonical(
+        mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
             cause.span,
             &self.canonical_query,
             |ref infcx, key, _| {
-                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
+                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
                 type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
                 try_extract_error_from_fulfill_cx(
                     fulfill_cx,
@@ -255,16 +274,16 @@ where
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        tcx.infer_ctxt().enter_with_canonical(
+        mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
             cause.span,
             &self.canonical_query,
             |ref infcx, key, _| {
-                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
+                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
 
                 let mut selcx = SelectionContext::new(infcx);
 
@@ -316,16 +335,16 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
 
     fn nice_error(
         &self,
-        tcx: TyCtxt<'tcx>,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
         cause: ObligationCause<'tcx>,
         placeholder_region: ty::Region<'tcx>,
         error_region: Option<ty::Region<'tcx>>,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        tcx.infer_ctxt().enter_with_canonical(
+        mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
             cause.span,
             &self.canonical_query,
             |ref infcx, key, _| {
-                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
+                let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
                 type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span))
                     .ok()?;
                 try_extract_error_from_fulfill_cx(
@@ -339,6 +358,43 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
     }
 }
 
+impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
+    fn fallback_error(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
+        // and is only the fallback when the nice error fails. Consider improving this some more.
+        tcx.sess.struct_span_err(span, "higher-ranked lifetime error for opaque type!")
+    }
+
+    fn base_universe(&self) -> ty::UniverseIndex {
+        self.base_universe.unwrap()
+    }
+
+    fn nice_error(
+        &self,
+        mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
+        _cause: ObligationCause<'tcx>,
+        placeholder_region: ty::Region<'tcx>,
+        error_region: Option<ty::Region<'tcx>>,
+    ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+        try_extract_error_from_region_constraints(
+            mbcx.infcx,
+            placeholder_region,
+            error_region,
+            self.region_constraints.as_ref().unwrap(),
+            // We're using the original `InferCtxt` that we
+            // started MIR borrowchecking with, so the region
+            // constraints have already been taken. Use the data from
+            // our `mbcx` instead.
+            |vid| mbcx.regioncx.var_infos[vid].origin,
+            |vid| mbcx.regioncx.var_infos[vid].universe,
+        )
+    }
+}
+
 #[instrument(skip(fulfill_cx, infcx), level = "debug")]
 fn try_extract_error_from_fulfill_cx<'tcx>(
     mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
@@ -346,15 +402,30 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
     placeholder_region: ty::Region<'tcx>,
     error_region: Option<ty::Region<'tcx>>,
 ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-    let tcx = infcx.tcx;
-
     // We generally shouldn't have errors here because the query was
     // already run, but there's no point using `delay_span_bug`
     // when we're going to emit an error here anyway.
     let _errors = fulfill_cx.select_all_or_error(infcx);
+    let region_constraints = infcx.with_region_constraints(|r| r.clone());
+    try_extract_error_from_region_constraints(
+        infcx,
+        placeholder_region,
+        error_region,
+        &region_constraints,
+        |vid| infcx.region_var_origin(vid),
+        |vid| infcx.universe_of_region(infcx.tcx.mk_region(ty::ReVar(vid))),
+    )
+}
 
-    let (sub_region, cause) = infcx.with_region_constraints(|region_constraints| {
-        debug!("{:#?}", region_constraints);
+fn try_extract_error_from_region_constraints<'tcx>(
+    infcx: &InferCtxt<'_, 'tcx>,
+    placeholder_region: ty::Region<'tcx>,
+    error_region: Option<ty::Region<'tcx>>,
+    region_constraints: &RegionConstraintData<'tcx>,
+    mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
+    mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
+) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
+    let (sub_region, cause) =
         region_constraints.constraints.iter().find_map(|(constraint, cause)| {
             match *constraint {
                 Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
@@ -362,12 +433,11 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
                 }
                 // FIXME: Should this check the universe of the var?
                 Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
-                    Some((tcx.mk_region(ty::ReVar(vid)), cause.clone()))
+                    Some((infcx.tcx.mk_region(ty::ReVar(vid)), cause.clone()))
                 }
                 _ => None,
             }
-        })
-    })?;
+        })?;
 
     debug!(?sub_region, "cause = {:#?}", cause);
     let nice_error = match (error_region, *sub_region) {
@@ -375,7 +445,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
             infcx,
             RegionResolutionError::SubSupConflict(
                 vid,
-                infcx.region_var_origin(vid),
+                region_var_origin(vid),
                 cause.clone(),
                 error_region,
                 cause.clone(),
@@ -392,8 +462,8 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
             infcx,
             RegionResolutionError::UpperBoundUniverseConflict(
                 vid,
-                infcx.region_var_origin(vid),
-                infcx.universe_of_region(sub_region),
+                region_var_origin(vid),
+                universe_of_region(vid),
                 cause.clone(),
                 placeholder_region,
             ),
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 6f78c816093..58b246ec873 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -7,6 +7,7 @@
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(min_specialization)]
+#![feature(never_type)]
 #![feature(stmt_expr_attributes)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
@@ -125,8 +126,9 @@ fn mir_borrowck<'tcx>(
 ) -> &'tcx BorrowCheckResult<'tcx> {
     let (input_body, promoted) = tcx.mir_promoted(def);
     debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
+    let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
 
-    let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(def.did).enter(|infcx| {
+    let opt_closure_req = tcx.infer_ctxt().with_opaque_type_inference(hir_owner).enter(|infcx| {
         let input_body: &Body<'_> = &input_body.borrow();
         let promoted: &IndexVec<_, _> = &promoted.borrow();
         do_mir_borrowck(&infcx, input_body, promoted, false).0
@@ -141,7 +143,7 @@ fn mir_borrowck<'tcx>(
 /// If `return_body_with_facts` is true, then return the body with non-erased
 /// region ids on which the borrow checking was performed together with Polonius
 /// facts.
-#[instrument(skip(infcx, input_body, input_promoted), level = "debug")]
+#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
 fn do_mir_borrowck<'a, 'tcx>(
     infcx: &InferCtxt<'a, 'tcx>,
     input_body: &Body<'tcx>,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 20f54d04777..1f81f7dda13 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -45,6 +45,7 @@ mod reverse_sccs;
 pub mod values;
 
 pub struct RegionInferenceContext<'tcx> {
+    pub var_infos: VarInfos,
     /// Contains the definition for every region variable. Region
     /// variables are identified by their index (`RegionVid`). The
     /// definition contains information about where the region came
@@ -267,7 +268,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ) -> Self {
         // Create a RegionDefinition for each inference variable.
         let definitions: IndexVec<_, _> = var_infos
-            .into_iter()
+            .iter()
             .map(|info| RegionDefinition::new(info.universe, info.origin))
             .collect();
 
@@ -292,6 +293,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             Rc::new(member_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
 
         let mut result = Self {
+            var_infos,
             definitions,
             liveness_constraints,
             constraints,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 60c48d8a764..a2378802802 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,7 +1,6 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir::OpaqueTyOrigin;
-use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
@@ -54,27 +53,44 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
-        opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
+        opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (Ty<'tcx>, Span, OpaqueTyOrigin)>,
         span: Span,
     ) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
         opaque_ty_decls
             .into_iter()
-            .filter_map(|(opaque_type_key, decl)| {
+            .map(|(opaque_type_key, (concrete_type, decl_span, origin))| {
                 let substs = opaque_type_key.substs;
-                let concrete_type = decl.concrete_ty;
+                // FIXME: why are the spans in decl_span often DUMMY_SP?
+                let span = decl_span.substitute_dummy(span);
                 debug!(?concrete_type, ?substs);
 
                 let mut subst_regions = vec![self.universal_regions.fr_static];
                 let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
-                    let vid = self.universal_regions.to_region_vid(region);
-                    subst_regions.push(vid);
-                    self.definitions[vid].external_name.unwrap_or_else(|| {
-                        infcx
-                            .tcx
-                            .sess
-                            .delay_span_bug(span, "opaque type with non-universal region substs");
-                        infcx.tcx.lifetimes.re_static
-                    })
+                    if let ty::RePlaceholder(..) = region.kind() {
+                        // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
+                        return region;
+                    }
+                    let vid = self.to_region_vid(region);
+                    trace!(?vid);
+                    let scc = self.constraint_sccs.scc(vid);
+                    trace!(?scc);
+                    match self.scc_values.universal_regions_outlived_by(scc).find_map(|lb| {
+                        self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?)
+                    }) {
+                        Some(region) => {
+                            let vid = self.universal_regions.to_region_vid(region);
+                            subst_regions.push(vid);
+                            region
+                        }
+                        None => {
+                            subst_regions.push(vid);
+                            infcx.tcx.sess.delay_span_bug(
+                                span,
+                                "opaque type with non-universal region substs",
+                            );
+                            infcx.tcx.lifetimes.re_static
+                        }
+                    }
                 });
 
                 subst_regions.sort();
@@ -100,12 +116,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     span,
                 );
 
-                check_opaque_type_parameter_valid(
-                    infcx.tcx,
+                (
                     opaque_type_key,
-                    OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
+                    if check_opaque_type_parameter_valid(infcx.tcx, opaque_type_key, origin, span) {
+                        remapped_type
+                    } else {
+                        infcx.tcx.ty_error()
+                    },
                 )
-                .then_some((opaque_type_key, remapped_type))
             })
             .collect()
     }
@@ -149,9 +167,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 fn check_opaque_type_parameter_valid(
     tcx: TyCtxt<'_>,
     opaque_type_key: OpaqueTypeKey<'_>,
-    decl: OpaqueTypeDecl<'_>,
+    origin: OpaqueTyOrigin,
+    span: Span,
 ) -> bool {
-    match decl.origin {
+    match origin {
         // No need to check return position impl trait (RPIT)
         // because for type and const parameters they are correct
         // by construction: we convert
@@ -177,7 +196,6 @@ fn check_opaque_type_parameter_valid(
         // Check these
         OpaqueTyOrigin::TyAlias => {}
     }
-    let span = decl.definition_span;
     let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
     let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
     for (i, arg) in opaque_type_key.substs.iter().enumerate() {
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 0fa72ed8241..3856b7f4a4b 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -33,12 +33,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     ) -> Fallible<R>
     where
         Op: type_op::TypeOp<'tcx, Output = R>,
-        Canonical<'tcx, Op>: ToUniverseInfo<'tcx>,
+        Op::ErrorInfo: ToUniverseInfo<'tcx>,
     {
         let old_universe = self.infcx.universe();
 
-        let TypeOpOutput { output, constraints, canonicalized_query } =
-            op.fully_perform(self.infcx)?;
+        let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
 
         if let Some(data) = &constraints {
             self.push_region_constraints(locations, category, data);
@@ -47,8 +46,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let universe = self.infcx.universe();
 
         if old_universe != universe {
-            let universe_info = match canonicalized_query {
-                Some(canonicalized_query) => canonicalized_query.to_universe_info(old_universe),
+            let universe_info = match error_info {
+                Some(error_info) => error_info.to_universe_info(old_universe),
                 None => UniverseInfo::other(),
             };
             for u in old_universe..universe {
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 2e7798beb64..0b9d0a0e922 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -267,7 +267,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                         TypeOpOutput {
                             output: self.infcx.tcx.ty_error(),
                             constraints: None,
-                            canonicalized_query: None,
+                            error_info: None,
                         }
                     });
                 // Note: we need this in examples like
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index bc740de5150..83c8ecba1f1 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -147,9 +147,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // Return types are a bit more complex. They may contain opaque `impl Trait` types.
         let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
         let output_span = body.local_decls[RETURN_PLACE].source_info.span;
-        if let Err(terr) = self.eq_opaque_type_and_type(
-            mir_output_ty,
+        if let Err(terr) = self.eq_types(
             normalized_output_ty,
+            mir_output_ty,
             Locations::All(output_span),
             ConstraintCategory::BoringNoLocation,
         ) {
@@ -169,9 +169,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             let user_provided_output_ty = user_provided_sig.output();
             let user_provided_output_ty =
                 self.normalize(user_provided_output_ty, Locations::All(output_span));
-            if let Err(err) = self.eq_opaque_type_and_type(
-                mir_output_ty,
+            if let Err(err) = self.eq_types(
                 user_provided_output_ty,
+                mir_output_ty,
                 Locations::All(output_span),
                 ConstraintCategory::BoringNoLocation,
             ) {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index a7cf25d43d2..2d4bb272df5 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -5,6 +5,7 @@ use std::{fmt, iter, mem};
 
 use either::Either;
 
+use hir::OpaqueTyOrigin;
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::vec_map::VecMap;
@@ -15,8 +16,8 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
-use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
+use rustc_infer::infer::region_constraints::RegionConstraintData;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{
     InferCtxt, InferOk, LateBoundRegionConversionTime, NllRegionVariableOrigin,
@@ -39,9 +40,11 @@ use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::type_op;
+use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
+use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
 use rustc_trait_selection::traits::query::Fallible;
-use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
+use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
 
 use rustc_const_eval::transform::{
     check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
@@ -75,7 +78,7 @@ macro_rules! span_mirbug {
             $context.last_span,
             &format!(
                 "broken MIR in {:?} ({:?}): {}",
-                $context.body.source.def_id(),
+                $context.body().source.def_id(),
                 $elem,
                 format_args!($($message)*),
             ),
@@ -199,59 +202,44 @@ pub(crate) fn type_check<'mir, 'tcx>(
             );
 
             translate_outlives_facts(&mut cx);
-            let opaque_type_values = mem::take(&mut infcx.inner.borrow_mut().opaque_types);
+            let opaque_type_values =
+                infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
 
             opaque_type_values
                 .into_iter()
-                .filter_map(|(opaque_type_key, mut decl)| {
-                    decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
+                .map(|(opaque_type_key, decl)| {
+                    cx.fully_perform_op(
+                        Locations::All(body.span),
+                        ConstraintCategory::OpaqueType,
+                        CustomTypeOp::new(
+                            |infcx| {
+                                infcx.register_member_constraints(
+                                    param_env,
+                                    opaque_type_key,
+                                    decl.hidden_type.ty,
+                                    decl.hidden_type.span,
+                                );
+                                Ok(InferOk { value: (), obligations: vec![] })
+                            },
+                            || "opaque_type_map".to_string(),
+                        ),
+                    )
+                    .unwrap();
+                    let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type.ty);
                     trace!(
                         "finalized opaque type {:?} to {:#?}",
                         opaque_type_key,
-                        decl.concrete_ty.kind()
+                        hidden_type.kind()
                     );
-                    if decl.concrete_ty.has_infer_types_or_consts() {
+                    if hidden_type.has_infer_types_or_consts() {
                         infcx.tcx.sess.delay_span_bug(
-                            body.span,
-                            &format!("could not resolve {:#?}", decl.concrete_ty.kind()),
+                            decl.hidden_type.span,
+                            &format!("could not resolve {:#?}", hidden_type.kind()),
                         );
-                        decl.concrete_ty = infcx.tcx.ty_error();
+                        hidden_type = infcx.tcx.ty_error();
                     }
-                    let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind()
-                    {
-                        *def_id == opaque_type_key.def_id
-                    } else {
-                        false
-                    };
 
-                    if concrete_is_opaque {
-                        // We're using an opaque `impl Trait` type without
-                        // 'revealing' it. For example, code like this:
-                        //
-                        // type Foo = impl Debug;
-                        // fn foo1() -> Foo { ... }
-                        // fn foo2() -> Foo { foo1() }
-                        //
-                        // In `foo2`, we're not revealing the type of `Foo` - we're
-                        // just treating it as the opaque type.
-                        //
-                        // When this occurs, we do *not* want to try to equate
-                        // the concrete type with the underlying defining type
-                        // of the opaque type - this will always fail, since
-                        // the defining type of an opaque type is always
-                        // some other type (e.g. not itself)
-                        // Essentially, none of the normal obligations apply here -
-                        // we're just passing around some unknown opaque type,
-                        // without actually looking at the underlying type it
-                        // gets 'revealed' into
-                        debug!(
-                            "eq_opaque_type_and_type: non-defining use of {:?}",
-                            opaque_type_key.def_id,
-                        );
-                        None
-                    } else {
-                        Some((opaque_type_key, decl))
-                    }
+                    (opaque_type_key, (hidden_type, decl.hidden_type.span, decl.origin))
                 })
                 .collect()
         },
@@ -283,7 +271,7 @@ fn type_check_internal<'a, 'tcx, R>(
         borrowck_context,
     );
     let errors_reported = {
-        let mut verifier = TypeVerifier::new(&mut checker, body, promoted);
+        let mut verifier = TypeVerifier::new(&mut checker, promoted);
         verifier.visit_body(&body);
         verifier.errors_reported
     };
@@ -340,7 +328,6 @@ enum FieldAccessError {
 /// is a problem.
 struct TypeVerifier<'a, 'b, 'tcx> {
     cx: &'a mut TypeChecker<'b, 'tcx>,
-    body: &'b Body<'tcx>,
     promoted: &'b IndexVec<Promoted, Body<'tcx>>,
     last_span: Span,
     errors_reported: bool,
@@ -476,7 +463,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
-        let rval_ty = rvalue.ty(self.body, self.tcx());
+        let rval_ty = rvalue.ty(self.body(), self.tcx());
         self.sanitize_type(rvalue, rval_ty);
     }
 
@@ -535,10 +522,13 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
     fn new(
         cx: &'a mut TypeChecker<'b, 'tcx>,
-        body: &'b Body<'tcx>,
         promoted: &'b IndexVec<Promoted, Body<'tcx>>,
     ) -> Self {
-        TypeVerifier { body, promoted, cx, last_span: body.span, errors_reported: false }
+        TypeVerifier { promoted, last_span: cx.body.span, cx, errors_reported: false }
+    }
+
+    fn body(&self) -> &Body<'tcx> {
+        self.cx.body
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -563,7 +553,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
     ) -> PlaceTy<'tcx> {
         debug!("sanitize_place: {:?}", place);
 
-        let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty);
+        let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
 
         for elem in place.projection.iter() {
             if place_ty.variant_index.is_none() {
@@ -608,7 +598,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // checker on the promoted MIR, then transfer the constraints back to
         // the main MIR, changing the locations to the provided location.
 
-        let parent_body = mem::replace(&mut self.body, promoted_body);
+        let parent_body = mem::replace(&mut self.cx.body, promoted_body);
 
         // Use new sets of constraints and closure bounds so that we can
         // modify their locations.
@@ -644,7 +634,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             self.cx.typeck_mir(promoted_body);
         }
 
-        self.body = parent_body;
+        self.cx.body = parent_body;
         // Merge the outlives constraints back in, at the given location.
         swap_constraints(self);
 
@@ -706,7 +696,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 }))
             }
             ProjectionElem::Index(i) => {
-                let index_ty = Place::from(i).ty(self.body, tcx).ty;
+                let index_ty = Place::from(i).ty(self.body(), tcx).ty;
                 if index_ty != tcx.types.usize {
                     PlaceTy::from_ty(span_mirbug_and_err!(self, i, "index by non-usize {:?}", i))
                 } else {
@@ -915,7 +905,7 @@ struct BorrowCheckContext<'a, 'tcx> {
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
     crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
+    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, (Ty<'tcx>, Span, OpaqueTyOrigin)>,
 }
 
 /// A collection of region constraints that must be satisfied for the
@@ -1065,17 +1055,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         checker
     }
 
+    fn body(&self) -> &Body<'tcx> {
+        self.body
+    }
+
     fn unsized_feature_enabled(&self) -> bool {
         let features = self.tcx().features();
         features.unsized_locals || features.unsized_fn_params
     }
 
     /// Equate the inferred type and the annotated type for user type annotations
+    #[instrument(skip(self), level = "debug")]
     fn check_user_type_annotations(&mut self) {
-        debug!(
-            "check_user_type_annotations: user_type_annotations={:?}",
-            self.user_type_annotations
-        );
+        debug!(?self.user_type_annotations);
         for user_annotation in self.user_type_annotations {
             let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
             let inferred_ty = self.normalize(inferred_ty, Locations::All(span));
@@ -1216,131 +1208,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         Ok(())
     }
 
-    /// Equates a type `anon_ty` that may contain opaque types whose
-    /// values are to be inferred by the MIR.
-    ///
-    /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
-    /// hidden types for impl traits revealed.
-    ///
-    /// # Example
-    ///
-    /// Consider a piece of code like
-    ///
-    /// ```rust
-    /// type Foo<U> = impl Debug;
-    ///
-    /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
-    ///      Box::new((t, 22_u32))
-    /// }
-    /// ```
-    ///
-    /// Here, the function signature would be something like
-    /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
-    /// the type with the opaque type revealed, so `Box<(T, u32)>`.
-    ///
-    /// In terms of our function parameters:
-    ///
-    /// * `anon_ty` would be `Box<Foo<T>>` where `Foo<T>` is an opaque type
-    ///   scoped to this function (note that it is parameterized by the
-    ///   generics of `foo`). Note that `anon_ty` is not just the opaque type,
-    ///   but the entire return type (which may contain opaque types within it).
-    /// * `revealed_ty` would be `Box<(T, u32)>`
-    #[instrument(skip(self), level = "debug")]
-    fn eq_opaque_type_and_type(
-        &mut self,
-        revealed_ty: Ty<'tcx>,
-        anon_ty: Ty<'tcx>,
-        locations: Locations,
-        category: ConstraintCategory,
-    ) -> Fallible<()> {
-        // Fast path for the common case.
-        if !anon_ty.has_opaque_types() {
-            if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) {
-                span_mirbug!(
-                    self,
-                    locations,
-                    "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`",
-                    revealed_ty,
-                    anon_ty,
-                    terr
-                );
-            }
-            return Ok(());
-        }
-
-        let param_env = self.param_env;
-        let body = self.body;
-        let mir_def_id = body.source.def_id().expect_local();
-
-        debug!(?mir_def_id);
-        self.fully_perform_op(
-            locations,
-            category,
-            CustomTypeOp::new(
-                |infcx| {
-                    let mut obligations = ObligationAccumulator::default();
-
-                    let dummy_body_id = hir::CRATE_HIR_ID;
-
-                    // Replace the opaque types defined by this function with
-                    // inference variables, creating a map. In our example above,
-                    // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
-                    // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
-                    // (Note that the key of the map is both the def-id of `Foo` along with
-                    // any generic parameters.)
-                    let output_ty = obligations.add(infcx.instantiate_opaque_types(
-                        dummy_body_id,
-                        param_env,
-                        anon_ty,
-                        locations.span(body),
-                    ));
-                    debug!(?output_ty, ?revealed_ty);
-
-                    // Make sure that the inferred types are well-formed. I'm
-                    // not entirely sure this is needed (the HIR type check
-                    // didn't do this) but it seems sensible to prevent opaque
-                    // types hiding ill-formed types.
-                    obligations.obligations.push(traits::Obligation::new(
-                        ObligationCause::dummy(),
-                        param_env,
-                        ty::Binder::dummy(ty::PredicateKind::WellFormed(revealed_ty.into()))
-                            .to_predicate(infcx.tcx),
-                    ));
-                    obligations.add(
-                        infcx
-                            .at(&ObligationCause::dummy(), param_env)
-                            .eq(output_ty, revealed_ty)?,
-                    );
-
-                    debug!("equated");
-
-                    Ok(InferOk { value: (), obligations: obligations.into_vec() })
-                },
-                || "input_output".to_string(),
-            ),
-        )?;
-
-        // Finally, if we instantiated the anon types successfully, we
-        // have to solve any bounds (e.g., `-> impl Iterator` needs to
-        // prove that `T: Iterator` where `T` is the type we
-        // instantiated it with).
-        let opaque_type_map = self.infcx.inner.borrow().opaque_types.clone();
-        for (opaque_type_key, opaque_decl) in opaque_type_map {
-            self.fully_perform_op(
-                locations,
-                ConstraintCategory::OpaqueType,
-                CustomTypeOp::new(
-                    |infcx| {
-                        infcx.constrain_opaque_type(opaque_type_key, &opaque_decl);
-                        Ok(InferOk { value: (), obligations: vec![] })
-                    },
-                    || "opaque_type_map".to_string(),
-                ),
-            )?;
-        }
-        Ok(())
-    }
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
@@ -2772,19 +2639,31 @@ impl NormalizeLocation for Location {
     }
 }
 
-#[derive(Debug, Default)]
-struct ObligationAccumulator<'tcx> {
-    obligations: PredicateObligations<'tcx>,
+/// Runs `infcx.instantiate_opaque_types`. Unlike other `TypeOp`s,
+/// this is not canonicalized - it directly affects the main `InferCtxt`
+/// that we use during MIR borrowchecking.
+#[derive(Debug)]
+pub(super) struct InstantiateOpaqueType<'tcx> {
+    pub base_universe: Option<ty::UniverseIndex>,
+    pub region_constraints: Option<RegionConstraintData<'tcx>>,
+    pub obligation: PredicateObligation<'tcx>,
 }
 
-impl<'tcx> ObligationAccumulator<'tcx> {
-    fn add<T>(&mut self, value: InferOk<'tcx, T>) -> T {
-        let InferOk { value, obligations } = value;
-        self.obligations.extend(obligations);
-        value
-    }
-
-    fn into_vec(self) -> PredicateObligations<'tcx> {
-        self.obligations
+impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
+    type Output = ();
+    /// We use this type itself to store the information used
+    /// when reporting errors. Since this is not a query, we don't
+    /// re-run anything during error reporting - we just use the information
+    /// we saved to help extract an error from the already-existing region
+    /// constraints in our `InferCtxt`
+    type ErrorInfo = InstantiateOpaqueType<'tcx>;
+
+    fn fully_perform(mut self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+        let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
+            Ok(InferOk { value: (), obligations: vec![self.obligation.clone()] })
+        })?;
+        self.region_constraints = Some(region_constraints);
+        output.error_info = Some(self);
+        Ok(output)
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 590a7a91641..a032095bf98 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,13 +1,15 @@
 use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
 use rustc_infer::infer::NllRegionVariableOrigin;
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Const, Ty};
+use rustc_span::Span;
 use rustc_trait_selection::traits::query::Fallible;
 
 use crate::constraints::OutlivesConstraint;
 use crate::diagnostics::UniverseInfo;
-use crate::type_check::{Locations, TypeChecker};
+use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker};
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
@@ -63,6 +65,10 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
 }
 
 impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
+    fn span(&self) -> Span {
+        self.locations.span(self.type_checker.body)
+    }
+
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.type_checker.param_env
     }
@@ -117,6 +123,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
 
     // We don't have to worry about the equality of consts during borrow checking
     // as consts always have a static lifetime.
+    // FIXME(oli-obk): is this really true? We can at least have HKL and with
+    // inline consts we may have further lifetimes that may be unsound to treat as
+    // 'static.
     fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {}
 
     fn normalization() -> NormalizationStrategy {
@@ -126,4 +135,30 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
     fn forbid_inference_vars() -> bool {
         true
     }
+
+    fn register_opaque_type(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected: bool) {
+        let param_env = self.param_env();
+        let span = self.span();
+        let def_id = self.type_checker.body.source.def_id().expect_local();
+        let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id);
+        let cause = ObligationCause::misc(span, body_id);
+        self.type_checker
+            .fully_perform_op(
+                self.locations,
+                self.category,
+                InstantiateOpaqueType {
+                    obligation: self.type_checker.infcx.opaque_ty_obligation(
+                        a,
+                        b,
+                        a_is_expected,
+                        param_env,
+                        cause,
+                    ),
+                    // These fields are filled in during exectuion of the operation
+                    base_universe: None,
+                    region_constraints: None,
+                },
+            )
+            .unwrap();
+    }
 }
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 478dbe31fba..e9c64049817 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -725,6 +725,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
         self.tcx.fold_regions(value, &mut false, |_region, _depth| self.next_nll_region_var(origin))
     }
 
+    #[instrument(level = "debug", skip(self, indices))]
     fn replace_bound_regions_with_nll_infer_vars<T>(
         &self,
         origin: NllRegionVariableOrigin,
@@ -735,22 +736,15 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        debug!(
-            "replace_bound_regions_with_nll_infer_vars(value={:?}, all_outlive_scope={:?})",
-            value, all_outlive_scope,
-        );
         let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
-            debug!("replace_bound_regions_with_nll_infer_vars: br={:?}", br);
+            debug!(?br);
             let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
                 scope: all_outlive_scope.to_def_id(),
                 bound_region: br.kind,
             }));
             let region_vid = self.next_nll_region_var(origin);
             indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
-            debug!(
-                "replace_bound_regions_with_nll_infer_vars: liberated_region={:?} => {:?}",
-                liberated_region, region_vid
-            );
+            debug!(?liberated_region, ?region_vid);
             region_vid
         });
         value
@@ -765,6 +759,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
     /// entries for them and store them in the indices map. This code iterates over the complete
     /// set of late-bound regions and checks for any that we have not yet seen, adding them to the
     /// inputs vector.
+    #[instrument(skip(self, indices))]
     fn replace_late_bound_regions_with_nll_infer_vars(
         &self,
         mir_def_id: LocalDefId,
@@ -776,6 +771,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
             debug!("replace_late_bound_regions_with_nll_infer_vars: r={:?}", r);
             if !indices.indices.contains_key(&r) {
                 let region_vid = self.next_nll_region_var(FR);
+                debug!(?region_vid);
                 indices.insert_late_bound_region(r, region_vid.to_region_vid());
             }
         });