about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-10 20:54:01 +0000
committerbors <bors@rust-lang.org>2022-09-10 20:54:01 +0000
commit2287107588d92889d282e6cd3c1ca5df34cd34a5 (patch)
treeefd90ebe87db4b8b9c5642b56e62728829badf29
parent4a6ac3c225d6322caaf0ef86623cddc74e5260c6 (diff)
parent1e54fcc1adeb3932ea7844ec1f86389a680ab86d (diff)
downloadrust-2287107588d92889d282e6cd3c1ca5df34cd34a5.tar.gz
rust-2287107588d92889d282e6cd3c1ca5df34cd34a5.zip
Auto merge of #98559 - jackh726:remove-reempty, r=oli-obk
Remove ReEmpty

r? rust-lang/types
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs38
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs7
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs19
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs7
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs11
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs23
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs1
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs297
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs29
-rw-r--r--compiler/rustc_middle/src/ty/context.rs9
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs10
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs4
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs8
-rw-r--r--compiler/rustc_type_ir/src/sty.rs33
-rw-r--r--compiler/rustc_typeck/src/check/dropck.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs1
-rw-r--r--compiler/rustc_typeck/src/collect.rs3
-rw-r--r--compiler/rustc_typeck/src/outlives/utils.rs6
-rw-r--r--compiler/rustc_typeck/src/variance/constraints.rs6
-rw-r--r--src/librustdoc/clean/mod.rs9
-rw-r--r--src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir27
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir23
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir23
-rw-r--r--src/test/mir-opt/storage_ranges.main.nll.0.mir11
-rw-r--r--src/test/ui/closures/print/closure-print-generic-verbose-1.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
32 files changed, 336 insertions, 298 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 0707ff5ed02..6c1eaa809c9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -357,11 +357,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 ty::BoundRegionKind::BrAnon(_) => None,
             },
 
-            ty::ReLateBound(..)
-            | ty::ReVar(..)
-            | ty::RePlaceholder(..)
-            | ty::ReEmpty(_)
-            | ty::ReErased => None,
+            ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
         }
     }
 
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 0392367288c..9d088642f77 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -109,7 +109,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         .iter()
                         .find(|ur_vid| self.eval_equal(vid, **ur_vid))
                         .and_then(|ur_vid| self.definitions[*ur_vid].external_name)
-                        .unwrap_or(infcx.tcx.lifetimes.re_root_empty),
+                        .unwrap_or(infcx.tcx.lifetimes.re_erased),
                     _ => region,
                 });
 
@@ -433,7 +433,7 @@ struct ReverseMapper<'tcx> {
 
     key: ty::OpaqueTypeKey<'tcx>,
     map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
-    map_missing_regions_to_empty: bool,
+    do_not_error: bool,
 
     /// initially `Some`, set to `None` once error has been reported
     hidden_ty: Option<Ty<'tcx>>,
@@ -450,29 +450,19 @@ impl<'tcx> ReverseMapper<'tcx> {
         hidden_ty: Ty<'tcx>,
         span: Span,
     ) -> Self {
-        Self {
-            tcx,
-            key,
-            map,
-            map_missing_regions_to_empty: false,
-            hidden_ty: Some(hidden_ty),
-            span,
-        }
+        Self { tcx, key, map, do_not_error: false, hidden_ty: Some(hidden_ty), span }
     }
 
-    fn fold_kind_mapping_missing_regions_to_empty(
-        &mut self,
-        kind: GenericArg<'tcx>,
-    ) -> GenericArg<'tcx> {
-        assert!(!self.map_missing_regions_to_empty);
-        self.map_missing_regions_to_empty = true;
+    fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
+        assert!(!self.do_not_error);
+        self.do_not_error = true;
         let kind = kind.fold_with(self);
-        self.map_missing_regions_to_empty = false;
+        self.do_not_error = false;
         kind
     }
 
     fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
-        assert!(!self.map_missing_regions_to_empty);
+        assert!(!self.do_not_error);
         kind.fold_with(self)
     }
 }
@@ -496,9 +486,9 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
             ty::ReErased => return r,
 
             // The regions that we expect from borrow checking.
-            ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
+            ty::ReEarlyBound(_) | ty::ReFree(_) => {}
 
-            ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
+            ty::RePlaceholder(_) | ty::ReVar(_) => {
                 // All of the regions in the type should either have been
                 // erased by writeback, or mapped back to named regions by
                 // borrow checking.
@@ -510,7 +500,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
         match self.map.get(&r.into()).map(|k| k.unpack()) {
             Some(GenericArgKind::Lifetime(r1)) => r1,
             Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
-            None if self.map_missing_regions_to_empty => self.tcx.lifetimes.re_root_empty,
+            None if self.do_not_error => self.tcx.lifetimes.re_static,
             None if generics.parent.is_some() => {
                 if let Some(hidden_ty) = self.hidden_ty.take() {
                     unexpected_hidden_region_diagnostic(
@@ -522,7 +512,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
                     )
                     .emit();
                 }
-                self.tcx.lifetimes.re_root_empty
+                self.tcx.lifetimes.re_static
             }
             None => {
                 self.tcx
@@ -574,7 +564,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
                 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
                     if index < generics.parent_count {
                         // Accommodate missing regions in the parent kinds...
-                        self.fold_kind_mapping_missing_regions_to_empty(kind)
+                        self.fold_kind_no_missing_regions_error(kind)
                     } else {
                         // ...but not elsewhere.
                         self.fold_kind_normally(kind)
@@ -589,7 +579,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
                 let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
                     if index < generics.parent_count {
                         // Accommodate missing regions in the parent kinds...
-                        self.fold_kind_mapping_missing_regions_to_empty(kind)
+                        self.fold_kind_no_missing_regions_error(kind)
                     } else {
                         // ...but not elsewhere.
                         self.fold_kind_normally(kind)
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 7c10047e9dc..f1b1c33a105 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -347,13 +347,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
 
             match outlives_bound {
                 OutlivesBound::RegionSubRegion(r1, r2) => {
-                    // `where Type:` is lowered to `where Type: 'empty` so that
-                    // we check `Type` is well formed, but there's no use for
-                    // this bound here.
-                    if r1.is_empty() {
-                        return;
-                    }
-
                     // The bound says that `r1 <= r2`; we store `r2: r1`.
                     let r1 = self.universal_regions.to_region_vid(r1);
                     let r2 = self.universal_regions.to_region_vid(r2);
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index b9b181681ec..8cf9ed53d39 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -54,13 +54,6 @@ pub struct UniversalRegions<'tcx> {
     /// The total number of universal region variables instantiated.
     num_universals: usize,
 
-    /// A special region variable created for the `'empty(U0)` region.
-    /// Note that this is **not** a "universal" region, as it doesn't
-    /// represent a universally bound placeholder or any such thing.
-    /// But we do create it here in this type because it's a useful region
-    /// to have around in a few limited cases.
-    pub root_empty: RegionVid,
-
     /// The "defining" type for this function, with all universal
     /// regions instantiated. For a closure or generator, this is the
     /// closure type, but for a top-level function it's the `FnDef`.
@@ -323,11 +316,7 @@ impl<'tcx> UniversalRegions<'tcx> {
 
     /// See `UniversalRegionIndices::to_region_vid`.
     pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
-        if let ty::ReEmpty(ty::UniverseIndex::ROOT) = *r {
-            self.root_empty
-        } else {
-            self.indices.to_region_vid(r)
-        }
+        self.indices.to_region_vid(r)
     }
 
     /// As part of the NLL unit tests, you can annotate a function with
@@ -501,16 +490,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             _ => None,
         };
 
-        let root_empty = self
-            .infcx
-            .next_nll_region_var(NllRegionVariableOrigin::Existential { from_forall: true })
-            .to_region_vid();
-
         UniversalRegions {
             indices,
             fr_static,
             fr_fn_body,
-            root_empty,
             first_extern_index,
             first_local_index,
             num_universals,
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 6f1f9522c86..7e051835b4b 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -27,13 +27,6 @@ impl<'a> DescriptionCtx<'a> {
                 me.kind = "restatic";
             }
 
-            ty::ReEmpty(ty::UniverseIndex::ROOT) => me.kind = "reempty",
-
-            ty::ReEmpty(ui) => {
-                me.kind = "reemptyuni";
-                me.arg = format!("{:?}", ui);
-            }
-
             ty::RePlaceholder(_) => return None,
 
             // FIXME(#13998) RePlaceholder should probably print like
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 46f8c0e8d8b..9488d0a6cbb 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -180,11 +180,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
         match *r {
-            ty::ReFree(_)
-            | ty::ReErased
-            | ty::ReStatic
-            | ty::ReEmpty(ty::UniverseIndex::ROOT)
-            | ty::ReEarlyBound(..) => r,
+            ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r,
 
             ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
                 CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) },
@@ -199,10 +195,6 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
                 )
             }
 
-            ty::ReEmpty(ui) => {
-                bug!("canonicalizing 'empty in universe {:?}", ui) // FIXME
-            }
-
             _ => {
                 // Other than `'static` or `'empty`, the query
                 // response should be executing in a fully
@@ -381,7 +373,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
             ty::ReStatic
             | ty::ReEarlyBound(..)
             | ty::ReFree(_)
-            | ty::ReEmpty(_)
             | ty::RePlaceholder(..)
             | ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r),
         }
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index c1fb59009d3..524383e381f 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -688,7 +688,6 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
 
             ty::RePlaceholder(..)
             | ty::ReVar(..)
-            | ty::ReEmpty(_)
             | ty::ReStatic
             | ty::ReEarlyBound(..)
             | ty::ReFree(..) => {
@@ -900,7 +899,6 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
 
             ty::RePlaceholder(..)
             | ty::ReVar(..)
-            | ty::ReEmpty(_)
             | ty::ReStatic
             | ty::ReEarlyBound(..)
             | ty::ReFree(..) => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 08460463998..9d5a128f8de 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -97,11 +97,6 @@ pub(super) fn note_and_explain_region<'tcx>(
             msg_span_from_free_region(tcx, region, alt_span)
         }
 
-        ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), alt_span),
-
-        // uh oh, hope no user ever sees THIS
-        ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), alt_span),
-
         ty::RePlaceholder(_) => return,
 
         // FIXME(#13998) RePlaceholder should probably print like
@@ -140,8 +135,6 @@ fn msg_span_from_free_region<'tcx>(
             (msg, Some(span))
         }
         ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
-        ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), alt_span),
-        ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), alt_span),
         _ => bug!("{:?}", region),
     }
 }
@@ -251,17 +244,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
 
     // Explain the region we are capturing.
     match *hidden_region {
-        ty::ReEmpty(ty::UniverseIndex::ROOT) => {
-            // All lifetimes shorter than the function body are `empty` in
-            // lexical region resolution. The default explanation of "an empty
-            // lifetime" isn't really accurate here.
-            let message = format!(
-                "hidden type `{}` captures lifetime smaller than the function body",
-                hidden_ty
-            );
-            err.span_note(span, &message);
-        }
-        ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) => {
+        ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
             // Assuming regionck succeeded (*), we ought to always be
             // capturing *some* region from the fn header, and hence it
             // ought to be free. So under normal circumstances, we will go
@@ -387,7 +370,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     RegionResolutionError::UpperBoundUniverseConflict(
                         _,
                         _,
-                        var_universe,
+                        _,
                         sup_origin,
                         sup_r,
                     ) => {
@@ -398,7 +381,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         // placeholder. In practice, we expect more
                         // tailored errors that don't really use this
                         // value.
-                        let sub_r = self.tcx.mk_region(ty::ReEmpty(var_universe));
+                        let sub_r = self.tcx.lifetimes.re_erased;
 
                         self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
                     }
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index 84004d2b21f..fee15afc7b3 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -126,7 +126,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
             | ty::ReFree(_)
             | ty::ReVar(_)
             | ty::RePlaceholder(..)
-            | ty::ReEmpty(_)
             | ty::ReErased => {
                 // replace all free regions with 'erased
                 self.tcx().lifetimes.re_erased
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 13b7e8eb964..5f13b2b3deb 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -15,8 +15,9 @@ use rustc_data_structures::graph::implementation::{
 use rustc_data_structures::intern::Interned;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::ty::fold::TypeFoldable;
+use rustc_middle::ty::PlaceholderRegion;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
+use rustc_middle::ty::{ReEarlyBound, ReErased, ReFree, ReStatic};
 use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
 use rustc_middle::ty::{Region, RegionVid};
 use rustc_span::Span;
@@ -51,6 +52,13 @@ pub struct LexicalRegionResolutions<'tcx> {
 
 #[derive(Copy, Clone, Debug)]
 pub(crate) enum VarValue<'tcx> {
+    /// Empty lifetime is for data that is never accessed.  We tag the
+    /// empty lifetime with a universe -- the idea is that we don't
+    /// want `exists<'a> { forall<'b> { 'b: 'a } }` to be satisfiable.
+    /// Therefore, the `'empty` in a universe `U` is less than all
+    /// regions visible from `U`, but not less than regions not visible
+    /// from `U`.
+    Empty(ty::UniverseIndex),
     Value(Region<'tcx>),
     ErrorValue,
 }
@@ -117,7 +125,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         &mut self,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
     ) -> LexicalRegionResolutions<'tcx> {
-        let mut var_data = self.construct_var_data(self.tcx());
+        let mut var_data = self.construct_var_data();
 
         if cfg!(debug_assertions) {
             self.dump_constraints();
@@ -137,13 +145,12 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
     /// Initially, the value for all variables is set to `'empty`, the
     /// empty region. The `expansion` phase will grow this larger.
-    fn construct_var_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> {
+    fn construct_var_data(&self) -> LexicalRegionResolutions<'tcx> {
         LexicalRegionResolutions {
             values: IndexVec::from_fn_n(
                 |vid| {
                     let vid_universe = self.var_infos[vid].universe;
-                    let re_empty = tcx.mk_region(ty::ReEmpty(vid_universe));
-                    VarValue::Value(re_empty)
+                    VarValue::Empty(vid_universe)
                 },
                 self.num_vars(),
             ),
@@ -189,20 +196,131 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
+    /// Gets the LUb of a given region and the empty region
+    fn lub_empty(&self, a_region: Region<'tcx>) -> Result<Region<'tcx>, PlaceholderRegion> {
+        match *a_region {
+            ReLateBound(..) | ReErased => {
+                bug!("cannot relate region: {:?}", a_region);
+            }
+
+            ReVar(v_id) => {
+                span_bug!(
+                    self.var_infos[v_id].origin.span(),
+                    "lub invoked with non-concrete regions: {:?}",
+                    a_region,
+                );
+            }
+
+            ReStatic => {
+                // nothing lives longer than `'static`
+                Ok(self.tcx().lifetimes.re_static)
+            }
+
+            ReEarlyBound(_) | ReFree(_) => {
+                // All empty regions are less than early-bound, free,
+                // and scope regions.
+                Ok(a_region)
+            }
+
+            RePlaceholder(placeholder) => Err(placeholder),
+        }
+    }
+
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
+        // In the first pass, we expand region vids according to constraints we
+        // have previously found. In the second pass, we loop through the region
+        // vids we expanded and expand *across* region vids (effectively
+        // "expanding" new `RegSubVar` constraints).
+
+        // Tracks the `VarSubVar` constraints generated for each region vid. We
+        // later use this to expand across vids.
         let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
+        // Tracks the changed region vids.
         let mut changes = Vec::new();
         for constraint in self.data.constraints.keys() {
-            let (a_vid, a_region, b_vid, b_data) = match *constraint {
+            match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
                     let b_data = var_values.value_mut(b_vid);
-                    (None, a_region, b_vid, b_data)
+
+                    if self.expand_node(a_region, b_vid, b_data) {
+                        changes.push(b_vid);
+                    }
                 }
                 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
                     VarValue::ErrorValue => continue,
+                    VarValue::Empty(a_universe) => {
+                        let b_data = var_values.value_mut(b_vid);
+
+                        let changed = (|| match *b_data {
+                            VarValue::Empty(b_universe) => {
+                                // Empty regions are ordered according to the universe
+                                // they are associated with.
+                                let ui = a_universe.min(b_universe);
+
+                                debug!(
+                                    "Expanding value of {:?} \
+                                    from empty lifetime with universe {:?} \
+                                    to empty lifetime with universe {:?}",
+                                    b_vid, b_universe, ui
+                                );
+
+                                *b_data = VarValue::Empty(ui);
+                                true
+                            }
+                            VarValue::Value(cur_region) => {
+                                let lub = match self.lub_empty(cur_region) {
+                                    Ok(r) => r,
+                                    // If the empty and placeholder regions are in the same universe,
+                                    // then the LUB is the Placeholder region (which is the cur_region).
+                                    // If they are not in the same universe, the LUB is the Static lifetime.
+                                    Err(placeholder) if a_universe == placeholder.universe => {
+                                        cur_region
+                                    }
+                                    Err(_) => self.tcx().lifetimes.re_static,
+                                };
+
+                                if lub == cur_region {
+                                    return false;
+                                }
+
+                                debug!(
+                                    "Expanding value of {:?} from {:?} to {:?}",
+                                    b_vid, cur_region, lub
+                                );
+
+                                *b_data = VarValue::Value(lub);
+                                true
+                            }
+
+                            VarValue::ErrorValue => false,
+                        })();
+
+                        if changed {
+                            changes.push(b_vid);
+                        }
+                        match b_data {
+                            VarValue::Value(Region(Interned(ReStatic, _)))
+                            | VarValue::ErrorValue => (),
+                            _ => {
+                                constraints[a_vid].push((a_vid, b_vid));
+                                constraints[b_vid].push((a_vid, b_vid));
+                            }
+                        }
+                    }
                     VarValue::Value(a_region) => {
                         let b_data = var_values.value_mut(b_vid);
-                        (Some(a_vid), a_region, b_vid, b_data)
+
+                        if self.expand_node(a_region, b_vid, b_data) {
+                            changes.push(b_vid);
+                        }
+                        match b_data {
+                            VarValue::Value(Region(Interned(ReStatic, _)))
+                            | VarValue::ErrorValue => (),
+                            _ => {
+                                constraints[a_vid].push((a_vid, b_vid));
+                                constraints[b_vid].push((a_vid, b_vid));
+                            }
+                        }
                     }
                 },
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
@@ -210,18 +328,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                     // is done, in `collect_errors`.
                     continue;
                 }
-            };
-            if self.expand_node(a_region, b_vid, b_data) {
-                changes.push(b_vid);
-            }
-            if let Some(a_vid) = a_vid {
-                match b_data {
-                    VarValue::Value(Region(Interned(ReStatic, _))) | VarValue::ErrorValue => (),
-                    _ => {
-                        constraints[a_vid].push((a_vid, b_vid));
-                        constraints[b_vid].push((a_vid, b_vid));
-                    }
-                }
             }
         }
 
@@ -242,6 +348,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
+    /// Expands the value of the region represented with `b_vid` with current
+    /// value `b_data` to the lub of `b_data` and `a_region`. The corresponds
+    /// with the constraint `'?b: 'a` (`'a <: '?b`), where `'a` is some known
+    /// region and `'?b` is some region variable.
     fn expand_node(
         &self,
         a_region: Region<'tcx>,
@@ -263,14 +373,28 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
 
         match *b_data {
+            VarValue::Empty(empty_ui) => {
+                let lub = match self.lub_empty(a_region) {
+                    Ok(r) => r,
+                    // If this empty region is from a universe that can
+                    // name the placeholder, then the placeholder is
+                    // larger; otherwise, the only ancestor is `'static`.
+                    Err(placeholder) if empty_ui.can_name(placeholder.universe) => {
+                        self.tcx().mk_region(RePlaceholder(placeholder))
+                    }
+                    Err(_) => self.tcx().lifetimes.re_static,
+                };
+
+                debug!("Expanding value of {:?} from empty lifetime to {:?}", b_vid, lub);
+
+                *b_data = VarValue::Value(lub);
+                true
+            }
             VarValue::Value(cur_region) => {
                 // This is a specialized version of the `lub_concrete_regions`
                 // check below for a common case, here purely as an
                 // optimization.
                 let b_universe = self.var_infos[b_vid].universe;
-                if let ReEmpty(a_universe) = *a_region && a_universe == b_universe {
-                    return false;
-                }
 
                 let mut lub = self.lub_concrete_regions(a_region, cur_region);
                 if lub == cur_region {
@@ -300,6 +424,78 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         }
     }
 
+    /// True if `a <= b`.
+    fn sub_region_values(&self, a: VarValue<'tcx>, b: VarValue<'tcx>) -> bool {
+        match (a, b) {
+            // Error region is `'static`
+            (VarValue::ErrorValue, _) | (_, VarValue::ErrorValue) => return true,
+            (VarValue::Empty(a_ui), VarValue::Empty(b_ui)) => {
+                // Empty regions are ordered according to the universe
+                // they are associated with.
+                a_ui.min(b_ui) == b_ui
+            }
+            (VarValue::Value(a), VarValue::Empty(_)) => {
+                match *a {
+                    ReLateBound(..) | ReErased => {
+                        bug!("cannot relate region: {:?}", a);
+                    }
+
+                    ReVar(v_id) => {
+                        span_bug!(
+                            self.var_infos[v_id].origin.span(),
+                            "lub_concrete_regions invoked with non-concrete region: {:?}",
+                            a
+                        );
+                    }
+
+                    ReStatic | ReEarlyBound(_) | ReFree(_) => {
+                        // nothing lives longer than `'static`
+
+                        // All empty regions are less than early-bound, free,
+                        // and scope regions.
+
+                        false
+                    }
+
+                    RePlaceholder(_) => {
+                        // The LUB is either `a` or `'static`
+                        false
+                    }
+                }
+            }
+            (VarValue::Empty(a_ui), VarValue::Value(b)) => {
+                match *b {
+                    ReLateBound(..) | ReErased => {
+                        bug!("cannot relate region: {:?}", b);
+                    }
+
+                    ReVar(v_id) => {
+                        span_bug!(
+                            self.var_infos[v_id].origin.span(),
+                            "lub_concrete_regions invoked with non-concrete regions: {:?}",
+                            b
+                        );
+                    }
+
+                    ReStatic | ReEarlyBound(_) | ReFree(_) => {
+                        // nothing lives longer than `'static`
+                        // All empty regions are less than early-bound, free,
+                        // and scope regions.
+                        true
+                    }
+
+                    RePlaceholder(placeholder) => {
+                        // If this empty region is from a universe that can
+                        // name the placeholder, then the placeholder is
+                        // larger; otherwise, the only ancestor is `'static`.
+                        if a_ui.can_name(placeholder.universe) { true } else { false }
+                    }
+                }
+            }
+            (VarValue::Value(a), VarValue::Value(b)) => self.sub_concrete_regions(a, b),
+        }
+    }
+
     /// True if `a <= b`, but not defined over inference variables.
     #[instrument(level = "trace", skip(self))]
     fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool {
@@ -355,37 +551,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
                 self.tcx().lifetimes.re_static
             }
 
-            (ReEmpty(_), ReEarlyBound(_) | ReFree(_)) => {
-                // All empty regions are less than early-bound, free,
-                // and scope regions.
-                b
-            }
-
-            (ReEarlyBound(_) | ReFree(_), ReEmpty(_)) => {
-                // All empty regions are less than early-bound, free,
-                // and scope regions.
-                a
-            }
-
-            (ReEmpty(a_ui), ReEmpty(b_ui)) => {
-                // Empty regions are ordered according to the universe
-                // they are associated with.
-                let ui = a_ui.min(b_ui);
-                self.tcx().mk_region(ReEmpty(ui))
-            }
-
-            (ReEmpty(empty_ui), RePlaceholder(placeholder))
-            | (RePlaceholder(placeholder), ReEmpty(empty_ui)) => {
-                // If this empty region is from a universe that can
-                // name the placeholder, then the placeholder is
-                // larger; otherwise, the only ancestor is `'static`.
-                if empty_ui.can_name(placeholder.universe) {
-                    self.tcx().mk_region(RePlaceholder(placeholder))
-                } else {
-                    self.tcx().lifetimes.re_static
-                }
-            }
-
             (ReEarlyBound(_) | ReFree(_), ReEarlyBound(_) | ReFree(_)) => {
                 self.region_rels.lub_free_regions(a, b)
             }
@@ -508,7 +673,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
 
         for (node_vid, value) in var_data.values.iter_enumerated() {
             match *value {
-                VarValue::Value(_) => { /* Inference successful */ }
+                VarValue::Empty(_) | VarValue::Value(_) => { /* Inference successful */ }
                 VarValue::ErrorValue => {
                     // Inference impossible: this value contains
                     // inconsistent constraints.
@@ -829,12 +994,25 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             }
 
             VerifyBound::OutlivedBy(r) => {
-                self.sub_concrete_regions(min, var_values.normalize(self.tcx(), *r))
+                let a = match *min {
+                    ty::ReVar(rid) => var_values.values[rid],
+                    _ => VarValue::Value(min),
+                };
+                let b = match **r {
+                    ty::ReVar(rid) => var_values.values[rid],
+                    _ => VarValue::Value(*r),
+                };
+                self.sub_region_values(a, b)
             }
 
-            VerifyBound::IsEmpty => {
-                matches!(*min, ty::ReEmpty(_))
-            }
+            VerifyBound::IsEmpty => match *min {
+                ty::ReVar(rid) => match var_values.values[rid] {
+                    VarValue::ErrorValue => false,
+                    VarValue::Empty(_) => true,
+                    VarValue::Value(_) => false,
+                },
+                _ => false,
+            },
 
             VerifyBound::AnyBound(bs) => {
                 bs.iter().any(|b| self.bound_is_met(b, var_values, generic_ty, min))
@@ -876,6 +1054,7 @@ impl<'tcx> LexicalRegionResolutions<'tcx> {
     ) -> ty::Region<'tcx> {
         let result = match *r {
             ty::ReVar(rid) => match self.values[rid] {
+                VarValue::Empty(_) => r,
                 VarValue::Value(r) => r,
                 VarValue::ErrorValue => tcx.lifetimes.re_static,
             },
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 780e6ead10e..e43d28ee56e 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -426,21 +426,21 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         data
     }
 
-    pub fn data(&self) -> &RegionConstraintData<'tcx> {
+    pub(super) fn data(&self) -> &RegionConstraintData<'tcx> {
         &self.data
     }
 
-    pub fn start_snapshot(&mut self) -> RegionSnapshot {
+    pub(super) fn start_snapshot(&mut self) -> RegionSnapshot {
         debug!("RegionConstraintCollector: start_snapshot");
         RegionSnapshot { any_unifications: self.any_unifications }
     }
 
-    pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
+    pub(super) fn rollback_to(&mut self, snapshot: RegionSnapshot) {
         debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
         self.any_unifications = snapshot.any_unifications;
     }
 
-    pub fn new_region_var(
+    pub(super) fn new_region_var(
         &mut self,
         universe: ty::UniverseIndex,
         origin: RegionVariableOrigin,
@@ -455,12 +455,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     }
 
     /// Returns the universe for the given variable.
-    pub fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
+    pub(super) fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex {
         self.var_infos[vid].universe
     }
 
     /// Returns the origin for the given variable.
-    pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
+    pub(super) fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
         self.var_infos[vid].origin
     }
 
@@ -492,7 +492,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         self.undo_log.push(AddVerify(index));
     }
 
-    pub fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
+    pub(super) fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
         // cannot add givens once regions are resolved
         if self.data.givens.insert((sub, sup)) {
             debug!("add_given({:?} <= {:?})", sub, sup);
@@ -501,7 +501,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         }
     }
 
-    pub fn make_eqregion(
+    pub(super) fn make_eqregion(
         &mut self,
         origin: SubregionOrigin<'tcx>,
         sub: Region<'tcx>,
@@ -530,7 +530,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         }
     }
 
-    pub fn member_constraint(
+    pub(super) fn member_constraint(
         &mut self,
         key: ty::OpaqueTypeKey<'tcx>,
         definition_span: Span,
@@ -554,7 +554,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     }
 
     #[instrument(skip(self, origin), level = "debug")]
-    pub fn make_subregion(
+    pub(super) fn make_subregion(
         &mut self,
         origin: SubregionOrigin<'tcx>,
         sub: Region<'tcx>,
@@ -585,7 +585,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         }
     }
 
-    pub fn verify_generic_bound(
+    pub(super) fn verify_generic_bound(
         &mut self,
         origin: SubregionOrigin<'tcx>,
         kind: GenericKind<'tcx>,
@@ -595,7 +595,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         self.add_verify(Verify { kind, origin, region: sub, bound });
     }
 
-    pub fn lub_regions(
+    pub(super) fn lub_regions(
         &mut self,
         tcx: TyCtxt<'tcx>,
         origin: SubregionOrigin<'tcx>,
@@ -613,7 +613,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         }
     }
 
-    pub fn glb_regions(
+    pub(super) fn glb_regions(
         &mut self,
         tcx: TyCtxt<'tcx>,
         origin: SubregionOrigin<'tcx>,
@@ -634,7 +634,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
     }
 
     /// Resolves the passed RegionVid to the root RegionVid in the unification table
-    pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
+    pub(super) fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
         self.unification_table().find(rid).vid
     }
 
@@ -699,7 +699,6 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
             ty::ReStatic | ty::ReErased | ty::ReFree(..) | ty::ReEarlyBound(..) => {
                 ty::UniverseIndex::ROOT
             }
-            ty::ReEmpty(ui) => ui,
             ty::RePlaceholder(placeholder) => placeholder.universe,
             ty::ReVar(vid) => self.var_universe(vid),
             ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 53e91e48c24..afb2d5b2ba5 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -276,9 +276,6 @@ pub struct CommonTypes<'tcx> {
 }
 
 pub struct CommonLifetimes<'tcx> {
-    /// `ReEmpty` in the root universe.
-    pub re_root_empty: Region<'tcx>,
-
     /// `ReStatic`
     pub re_static: Region<'tcx>,
 
@@ -987,11 +984,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
             ))
         };
 
-        CommonLifetimes {
-            re_root_empty: mk(ty::ReEmpty(ty::UniverseIndex::ROOT)),
-            re_static: mk(ty::ReStatic),
-            re_erased: mk(ty::ReErased),
-        }
+        CommonLifetimes { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased) }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 5166372878f..301d1f5052e 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1986,7 +1986,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
 
             ty::ReVar(_) | ty::ReErased => false,
 
-            ty::ReStatic | ty::ReEmpty(_) => true,
+            ty::ReStatic => true,
         }
     }
 
@@ -2070,14 +2070,6 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                 p!("'static");
                 return Ok(self);
             }
-            ty::ReEmpty(ty::UniverseIndex::ROOT) => {
-                p!("'<empty>");
-                return Ok(self);
-            }
-            ty::ReEmpty(ui) => {
-                p!(write("'<empty:{:?}>", ui));
-                return Ok(self);
-            }
         }
 
         p!("'_");
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index c5c5d347341..702c2d27187 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1514,7 +1514,6 @@ impl<'tcx> Region<'tcx> {
             ty::ReStatic => true,
             ty::ReVar(..) => false,
             ty::RePlaceholder(placeholder) => placeholder.name.is_named(),
-            ty::ReEmpty(_) => false,
             ty::ReErased => false,
         }
     }
@@ -1540,11 +1539,6 @@ impl<'tcx> Region<'tcx> {
     }
 
     #[inline]
-    pub fn is_empty(self) -> bool {
-        matches!(*self, ty::ReEmpty(..))
-    }
-
-    #[inline]
     pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool {
         match *self {
             ty::ReLateBound(debruijn, _) => debruijn >= index,
@@ -1575,7 +1569,7 @@ impl<'tcx> Region<'tcx> {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
                 flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
             }
-            ty::ReEmpty(_) | ty::ReStatic => {
+            ty::ReStatic => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
             }
             ty::ReLateBound(..) => {
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index b1de979e8f8..bd8126f6177 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -305,8 +305,7 @@ fn encode_region<'tcx>(
         | RegionKind::ReFree(..)
         | RegionKind::ReStatic
         | RegionKind::ReVar(..)
-        | RegionKind::RePlaceholder(..)
-        | RegionKind::ReEmpty(..) => {
+        | RegionKind::RePlaceholder(..) => {
             bug!("encode_region: unexpected `{:?}`", region.kind());
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 9a571837e9f..9d3a1a4a031 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -101,6 +101,7 @@ pub fn trait_obligations<'a, 'tcx>(
     wf.normalize(infcx)
 }
 
+#[instrument(skip(infcx), ret)]
 pub fn predicate_obligations<'a, 'tcx>(
     infcx: &InferCtxt<'a, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -440,6 +441,7 @@ impl<'tcx> WfPredicates<'tcx> {
         let param_env = self.param_env;
         let depth = self.recursion_depth;
         while let Some(arg) = walker.next() {
+            debug!(?arg, ?self.out);
             let ty = match arg.unpack() {
                 GenericArgKind::Type(ty) => ty,
 
@@ -689,6 +691,8 @@ impl<'tcx> WfPredicates<'tcx> {
                     ));
                 }
             }
+
+            debug!(?self.out);
         }
     }
 
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index a166371fed1..a6a098ce73f 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -485,10 +485,6 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
                 })
                 .intern(interner)
             }
-            ty::ReEmpty(ui) => {
-                chalk_ir::LifetimeData::Empty(chalk_ir::UniverseIndex { counter: ui.index() })
-                    .intern(interner)
-            }
             ty::ReErased => chalk_ir::LifetimeData::Erased.intern(interner),
         }
     }
@@ -510,8 +506,8 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
                 name: ty::BoundRegionKind::BrAnon(p.idx as u32),
             }),
             chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
-            chalk_ir::LifetimeData::Empty(ui) => {
-                ty::ReEmpty(ty::UniverseIndex::from_usize(ui.counter))
+            chalk_ir::LifetimeData::Empty(_) => {
+                bug!("Chalk should not have been passed an empty lifetime.")
             }
             chalk_ir::LifetimeData::Erased => return interner.tcx.lifetimes.re_erased,
             chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 26e48d2d214..e164aaed6b4 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -3,14 +3,14 @@
 use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
 use std::{fmt, hash};
 
+use crate::DebruijnIndex;
 use crate::FloatTy;
+use crate::HashStableContext;
 use crate::IntTy;
 use crate::Interner;
 use crate::TyDecoder;
 use crate::TyEncoder;
 use crate::UintTy;
-use crate::UniverseIndex;
-use crate::{DebruijnIndex, HashStableContext};
 
 use self::RegionKind::*;
 use self::TyKind::*;
@@ -1023,14 +1023,6 @@ pub enum RegionKind<I: Interner> {
     /// Should not exist outside of type inference.
     RePlaceholder(I::PlaceholderRegion),
 
-    /// Empty lifetime is for data that is never accessed.  We tag the
-    /// empty lifetime with a universe -- the idea is that we don't
-    /// want `exists<'a> { forall<'b> { 'b: 'a } }` to be satisfiable.
-    /// Therefore, the `'empty` in a universe `U` is less than all
-    /// regions visible from `U`, but not less than regions not visible
-    /// from `U`.
-    ReEmpty(UniverseIndex),
-
     /// Erased region, used by trait selection, in MIR and during codegen.
     ReErased,
 }
@@ -1046,8 +1038,7 @@ const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
         ReStatic => 3,
         ReVar(_) => 4,
         RePlaceholder(_) => 5,
-        ReEmpty(_) => 6,
-        ReErased => 7,
+        ReErased => 6,
     }
 }
 
@@ -1072,7 +1063,6 @@ impl<I: Interner> Clone for RegionKind<I> {
             ReStatic => ReStatic,
             ReVar(a) => ReVar(a.clone()),
             RePlaceholder(a) => RePlaceholder(a.clone()),
-            ReEmpty(a) => ReEmpty(a.clone()),
             ReErased => ReErased,
         }
     }
@@ -1099,7 +1089,6 @@ impl<I: Interner> PartialEq for RegionKind<I> {
                 (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
                     __self_0 == __arg_1_0
                 }
-                (&ReEmpty(ref __self_0), &ReEmpty(ref __arg_1_0)) => __self_0 == __arg_1_0,
                 (&ReErased, &ReErased) => true,
                 _ => true,
             }
@@ -1144,7 +1133,6 @@ impl<I: Interner> Ord for RegionKind<I> {
                 (&RePlaceholder(ref __self_0), &RePlaceholder(ref __arg_1_0)) => {
                     Ord::cmp(__self_0, __arg_1_0)
                 }
-                (&ReEmpty(ref __self_0), &ReEmpty(ref __arg_1_0)) => Ord::cmp(__self_0, __arg_1_0),
                 (&ReErased, &ReErased) => Ordering::Equal,
                 _ => Ordering::Equal,
             }
@@ -1182,10 +1170,6 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
                 hash::Hash::hash(&regionkind_discriminant(self), state);
                 hash::Hash::hash(__self_0, state)
             }
-            (&ReEmpty(ref __self_0),) => {
-                hash::Hash::hash(&regionkind_discriminant(self), state);
-                hash::Hash::hash(__self_0, state)
-            }
             (&ReErased,) => {
                 hash::Hash::hash(&regionkind_discriminant(self), state);
             }
@@ -1211,8 +1195,6 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
 
             RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder),
 
-            ReEmpty(ui) => write!(f, "ReEmpty({:?})", ui),
-
             ReErased => write!(f, "ReErased"),
         }
     }
@@ -1247,9 +1229,6 @@ where
             RePlaceholder(a) => e.emit_enum_variant(disc, |e| {
                 a.encode(e);
             }),
-            ReEmpty(a) => e.emit_enum_variant(disc, |e| {
-                a.encode(e);
-            }),
             ReErased => e.emit_enum_variant(disc, |_| {}),
         }
     }
@@ -1272,8 +1251,7 @@ where
             3 => ReStatic,
             4 => ReVar(Decodable::decode(d)),
             5 => RePlaceholder(Decodable::decode(d)),
-            6 => ReEmpty(Decodable::decode(d)),
-            7 => ReErased,
+            6 => ReErased,
             _ => panic!(
                 "{}",
                 format!(
@@ -1305,9 +1283,6 @@ where
             ReErased | ReStatic => {
                 // No variant fields to hash for these ...
             }
-            ReEmpty(universe) => {
-                universe.hash_stable(hcx, hasher);
-            }
             ReLateBound(db, br) => {
                 db.hash_stable(hcx, hasher);
                 br.hash_stable(hcx, hasher);
diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs
index 321064ec0fc..ab143c05982 100644
--- a/compiler/rustc_typeck/src/check/dropck.rs
+++ b/compiler/rustc_typeck/src/check/dropck.rs
@@ -144,6 +144,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
     let assumptions_in_impl_context = assumptions_in_impl_context.predicates;
 
+    debug!(?assumptions_in_impl_context, ?dtor_predicates.predicates);
+
     let self_param_env = tcx.param_env(self_type_did);
 
     // An earlier version of this code attempted to do this checking
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 5c6c8aca173..b0ce0de1469 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1816,6 +1816,7 @@ fn report_bivariance(
 impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
     /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that
     /// aren't true.
+    #[instrument(level = "debug", skip(self))]
     fn check_false_global_bounds(&mut self) {
         let tcx = self.ocx.infcx.tcx;
         let mut span = self.span;
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index f9c7c008fa4..3e7a6c3c548 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1816,6 +1816,7 @@ pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir
     None
 }
 
+#[instrument(level = "debug", skip(tcx))]
 fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
     use rustc_hir::Node::*;
     use rustc_hir::*;
@@ -2046,8 +2047,8 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
 /// Returns a list of type predicates for the definition with ID `def_id`, including inferred
 /// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus
 /// inferred constraints concerning which regions outlive other regions.
+#[instrument(level = "debug", skip(tcx))]
 fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
-    debug!("predicates_defined_on({:?})", def_id);
     let mut result = tcx.explicit_predicates_of(def_id);
     debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,);
     let inferred_outlives = tcx.inferred_outlives_of(def_id);
diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_typeck/src/outlives/utils.rs
index b718ca94213..3e8d023fb55 100644
--- a/compiler/rustc_typeck/src/outlives/utils.rs
+++ b/compiler/rustc_typeck/src/outlives/utils.rs
@@ -161,12 +161,6 @@ fn is_free_region(region: Region<'_>) -> bool {
         // ignore it.  We can't put it on the struct header anyway.
         ty::ReLateBound(..) => false,
 
-        // This can appear in `where Self: ` bounds (#64855):
-        //
-        //     struct Bar<T>(<Self as Foo>::Type) where Self: ;
-        //     struct Baz<'a>(&'a Self) where Self: ;
-        ty::ReEmpty(_) => false,
-
         // These regions don't appear in types from type declarations:
         ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReFree(..) => {
             bug!("unexpected region in outlives inference: {:?}", region);
diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs
index 4fe213ffeea..840f0c97848 100644
--- a/compiler/rustc_typeck/src/variance/constraints.rs
+++ b/compiler/rustc_typeck/src/variance/constraints.rs
@@ -411,11 +411,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 // way early-bound regions do, so we skip them here.
             }
 
-            ty::ReFree(..)
-            | ty::ReVar(..)
-            | ty::RePlaceholder(..)
-            | ty::ReEmpty(_)
-            | ty::ReErased => {
+            ty::ReFree(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => {
                 // We don't expect to see anything but 'static or bound
                 // regions when visiting member types or method types.
                 bug!(
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index bca3f4db4a8..9f0b7018af5 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -250,7 +250,6 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life
         | ty::ReFree(..)
         | ty::ReVar(..)
         | ty::RePlaceholder(..)
-        | ty::ReEmpty(_)
         | ty::ReErased => {
             debug!("cannot clean region {:?}", region);
             None
@@ -347,10 +346,6 @@ fn clean_region_outlives_predicate<'tcx>(
 ) -> Option<WherePredicate> {
     let ty::OutlivesPredicate(a, b) = pred;
 
-    if a.is_empty() && b.is_empty() {
-        return None;
-    }
-
     Some(WherePredicate::RegionPredicate {
         lifetime: clean_middle_region(a).expect("failed to clean lifetime"),
         bounds: vec![GenericBound::Outlives(
@@ -365,10 +360,6 @@ fn clean_type_outlives_predicate<'tcx>(
 ) -> Option<WherePredicate> {
     let ty::OutlivesPredicate(ty, lt) = pred;
 
-    if lt.is_empty() {
-        return None;
-    }
-
     Some(WherePredicate::BoundPredicate {
         ty: clean_middle_ty(ty, cx, None),
         bounds: vec![GenericBound::Outlives(
diff --git a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir
index cbfdf8c5d56..0ab9d712d9f 100644
--- a/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir
+++ b/src/test/mir-opt/nll/named_lifetimes_basic.use_x.nll.0.mir
@@ -13,11 +13,10 @@
 | '_#2r | U0 | {bb0[0..=1], '_#2r}
 | '_#3r | U0 | {bb0[0..=1], '_#3r}
 | '_#4r | U0 | {bb0[0..=1], '_#4r}
-| '_#5r | U0 | {}
-| '_#6r | U0 | {bb0[0..=1], '_#1r}
-| '_#7r | U0 | {bb0[0..=1], '_#2r}
-| '_#8r | U0 | {bb0[0..=1], '_#1r}
-| '_#9r | U0 | {bb0[0..=1], '_#3r}
+| '_#5r | U0 | {bb0[0..=1], '_#1r}
+| '_#6r | U0 | {bb0[0..=1], '_#2r}
+| '_#7r | U0 | {bb0[0..=1], '_#1r}
+| '_#8r | U0 | {bb0[0..=1], '_#3r}
 |
 | Inference Constraints
 | '_#0r live at {bb0[0..=1]}
@@ -25,16 +24,16 @@
 | '_#2r live at {bb0[0..=1]}
 | '_#3r live at {bb0[0..=1]}
 | '_#4r live at {bb0[0..=1]}
-| '_#1r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
-| '_#1r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
-| '_#2r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
-| '_#3r: '_#9r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
-| '_#6r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
-| '_#7r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
-| '_#8r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
-| '_#9r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
+| '_#1r: '_#5r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
+| '_#1r: '_#7r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
+| '_#2r: '_#6r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
+| '_#3r: '_#8r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
+| '_#5r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:26: 12:27) ($DIR/named-lifetimes-basic.rs:12:26: 12:27 (#0)
+| '_#6r: '_#2r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:42: 12:43) ($DIR/named-lifetimes-basic.rs:12:42: 12:43 (#0)
+| '_#7r: '_#1r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:54: 12:55) ($DIR/named-lifetimes-basic.rs:12:54: 12:55 (#0)
+| '_#8r: '_#3r due to BoringNoLocation at All($DIR/named-lifetimes-basic.rs:12:66: 12:67) ($DIR/named-lifetimes-basic.rs:12:66: 12:67 (#0)
 |
-fn use_x(_1: &'_#6r mut i32, _2: &'_#7r u32, _3: &'_#8r u32, _4: &'_#9r u32) -> bool {
+fn use_x(_1: &'_#5r mut i32, _2: &'_#6r u32, _3: &'_#7r u32, _4: &'_#8r u32) -> bool {
     debug w => _1;                       // in scope 0 at $DIR/named-lifetimes-basic.rs:+0:26: +0:27
     debug x => _2;                       // in scope 0 at $DIR/named-lifetimes-basic.rs:+0:42: +0:43
     debug y => _3;                       // in scope 0 at $DIR/named-lifetimes-basic.rs:+0:54: +0:55
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 55e7faf9ee4..36705d18e01 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -7,19 +7,18 @@
 | Inferred Region Values
 | '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
 | '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
-| '_#2r | U0 | {}
-| '_#3r | U0 | {bb1[0..=7], bb2[0..=2]}
-| '_#4r | U0 | {bb1[1..=7], bb2[0..=2]}
-| '_#5r | U0 | {bb1[4..=7], bb2[0..=2]}
+| '_#2r | U0 | {bb1[0..=7], bb2[0..=2]}
+| '_#3r | U0 | {bb1[1..=7], bb2[0..=2]}
+| '_#4r | U0 | {bb1[4..=7], bb2[0..=2]}
 |
 | Inference Constraints
 | '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
 | '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
-| '_#3r live at {bb1[0]}
-| '_#4r live at {bb1[1..=3]}
-| '_#5r live at {bb1[4..=7], bb2[0..=2]}
-| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
-| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
+| '_#2r live at {bb1[0]}
+| '_#3r live at {bb1[1..=3]}
+| '_#4r live at {bb1[4..=7], bb2[0..=2]}
+| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
+| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region-subtyping-basic.rs:+0:11: +0:11
@@ -33,10 +32,10 @@ fn main() -> () {
     let _10: bool;                       // in scope 0 at $DIR/region-subtyping-basic.rs:+7:9: +7:18
     scope 1 {
         debug v => _1;                   // in scope 1 at $DIR/region-subtyping-basic.rs:+1:9: +1:14
-        let _2: &'_#4r usize;            // in scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
+        let _2: &'_#3r usize;            // in scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
         scope 2 {
             debug p => _2;               // in scope 2 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
-            let _6: &'_#5r usize;        // in scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
+            let _6: &'_#4r usize;        // in scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
             scope 3 {
                 debug q => _6;           // in scope 3 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
             }
@@ -56,7 +55,7 @@ fn main() -> () {
     }
 
     bb1: {
-        _2 = &'_#3r _1[_3];              // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:+2:13: +2:18
+        _2 = &'_#2r _1[_3];              // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:+2:13: +2:18
         FakeRead(ForLet(None), _2);      // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
         StorageLive(_6);                 // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
         _6 = _2;                         // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:+3:13: +3:14
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 2647c94335f..4f6256a67f4 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -7,19 +7,18 @@
 | Inferred Region Values
 | '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
 | '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
-| '_#2r | U0 | {}
-| '_#3r | U0 | {bb1[0..=7], bb2[0..=2]}
-| '_#4r | U0 | {bb1[1..=7], bb2[0..=2]}
-| '_#5r | U0 | {bb1[4..=7], bb2[0..=2]}
+| '_#2r | U0 | {bb1[0..=7], bb2[0..=2]}
+| '_#3r | U0 | {bb1[1..=7], bb2[0..=2]}
+| '_#4r | U0 | {bb1[4..=7], bb2[0..=2]}
 |
 | Inference Constraints
 | '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
 | '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
-| '_#3r live at {bb1[0]}
-| '_#4r live at {bb1[1..=3]}
-| '_#5r live at {bb1[4..=7], bb2[0..=2]}
-| '_#3r: '_#4r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
-| '_#4r: '_#5r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
+| '_#2r live at {bb1[0]}
+| '_#3r live at {bb1[1..=3]}
+| '_#4r live at {bb1[4..=7], bb2[0..=2]}
+| '_#2r: '_#3r due to Assignment at Single(bb1[0]) ($DIR/region-subtyping-basic.rs:18:13: 18:18 (#0)
+| '_#3r: '_#4r due to Assignment at Single(bb1[3]) ($DIR/region-subtyping-basic.rs:19:13: 19:14 (#0)
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region-subtyping-basic.rs:+0:11: +0:11
@@ -33,10 +32,10 @@ fn main() -> () {
     let _10: bool;                       // in scope 0 at $DIR/region-subtyping-basic.rs:+7:9: +7:18
     scope 1 {
         debug v => _1;                   // in scope 1 at $DIR/region-subtyping-basic.rs:+1:9: +1:14
-        let _2: &'_#4r usize;            // in scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
+        let _2: &'_#3r usize;            // in scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
         scope 2 {
             debug p => _2;               // in scope 2 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
-            let _6: &'_#5r usize;        // in scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
+            let _6: &'_#4r usize;        // in scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
             scope 3 {
                 debug q => _6;           // in scope 3 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
             }
@@ -56,7 +55,7 @@ fn main() -> () {
     }
 
     bb1: {
-        _2 = &'_#3r _1[_3];              // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:+2:13: +2:18
+        _2 = &'_#2r _1[_3];              // bb1[0]: scope 1 at $DIR/region-subtyping-basic.rs:+2:13: +2:18
         FakeRead(ForLet(None), _2);      // bb1[1]: scope 1 at $DIR/region-subtyping-basic.rs:+2:9: +2:10
         StorageLive(_6);                 // bb1[2]: scope 2 at $DIR/region-subtyping-basic.rs:+3:9: +3:10
         _6 = _2;                         // bb1[3]: scope 2 at $DIR/region-subtyping-basic.rs:+3:13: +3:14
diff --git a/src/test/mir-opt/storage_ranges.main.nll.0.mir b/src/test/mir-opt/storage_ranges.main.nll.0.mir
index 812eb3b82a6..8e10e70f192 100644
--- a/src/test/mir-opt/storage_ranges.main.nll.0.mir
+++ b/src/test/mir-opt/storage_ranges.main.nll.0.mir
@@ -7,16 +7,15 @@
 | Inferred Region Values
 | '_#0r | U0 | {bb0[0..=22], '_#0r, '_#1r}
 | '_#1r | U0 | {bb0[0..=22], '_#1r}
-| '_#2r | U0 | {}
-| '_#3r | U0 | {bb0[10..=11]}
-| '_#4r | U0 | {bb0[11]}
+| '_#2r | U0 | {bb0[10..=11]}
+| '_#3r | U0 | {bb0[11]}
 |
 | Inference Constraints
 | '_#0r live at {bb0[0..=22]}
 | '_#1r live at {bb0[0..=22]}
-| '_#3r live at {bb0[10]}
-| '_#4r live at {bb0[11]}
-| '_#3r: '_#4r due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:6:17: 6:25 (#0)
+| '_#2r live at {bb0[10]}
+| '_#3r live at {bb0[11]}
+| '_#2r: '_#3r due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:6:17: 6:25 (#0)
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/storage_ranges.rs:+0:11: +0:11
diff --git a/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr b/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr
index fdaf353fe3d..3ab7c66d11f 100644
--- a/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr
+++ b/src/test/ui/closures/print/closure-print-generic-verbose-1.stderr
@@ -2,7 +2,7 @@ error[E0382]: use of moved value: `c`
   --> $DIR/closure-print-generic-verbose-1.rs:17:5
    |
 LL |     let c = to_fn_once(move|| {
-   |         - move occurs because `c` has type `[f<T>::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'_#10r str>, T)]`, which does not implement the `Copy` trait
+   |         - move occurs because `c` has type `[f<T>::{closure#0} closure_kind_ty=i32 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=(Foo<&'_#9r str>, T)]`, which does not implement the `Copy` trait
 ...
 LL |     c();
    |     --- `c` moved due to this call
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index c3c7eb1bd9e..296131111e8 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -46,7 +46,7 @@ LL | |     });
    | |______`cell_a` escapes the function body here
    |        argument requires that `'a` must outlive `'static`
    |
-   = note: requirement occurs because of the type `Cell<&'_#10r u32>`, which makes the generic argument `&'_#10r u32` invariant
+   = note: requirement occurs because of the type `Cell<&'_#9r u32>`, which makes the generic argument `&'_#9r u32` invariant
    = note: the struct `Cell<T>` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 846e5aedb3e..96a1bd1f07b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -46,7 +46,7 @@ LL | |     });
    | |______`cell_a` escapes the function body here
    |        argument requires that `'a` must outlive `'static`
    |
-   = note: requirement occurs because of the type `Cell<&'_#11r u32>`, which makes the generic argument `&'_#11r u32` invariant
+   = note: requirement occurs because of the type `Cell<&'_#10r u32>`, which makes the generic argument `&'_#10r u32` invariant
    = note: the struct `Cell<T>` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 6d17c7a7346..060037ed496 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -173,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                 (
                     preds.iter().any(|t| cx.tcx.is_diagnostic_item(sym::Borrow, t.def_id())),
                     !preds.is_empty() && {
-                        let ty_empty_region = cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_root_empty, ty);
+                        let ty_empty_region = cx.tcx.mk_imm_ref(cx.tcx.lifetimes.re_erased, ty);
                         preds.iter().all(|t| {
                             let ty_params = t.trait_ref.substs.iter().skip(1).collect::<Vec<_>>();
                             implements_trait(cx, ty_empty_region, t.def_id(), &ty_params)