about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-12-20 07:01:00 +0000
committerbors <bors@rust-lang.org>2020-12-20 07:01:00 +0000
commitb1964e60b72c2d10e9fd4e801990f8af3f306ac0 (patch)
tree5c922d403f94a6393c5492d9cefa3245a3930567 /compiler/rustc_middle/src
parent29e32120c33d30ff526fc7f4d94ec9fce0dc10c9 (diff)
parent328fcee4af7aed31343244206abb7dff25106d04 (diff)
Auto merge of #80163 - jackh726:binder-refactor-part-3, r=lcnr
Make BoundRegion have a kind of BoungRegionKind

Split from #76814

Also includes making `replace_escaping_bound_vars` only return `T`

Going to r? `@lcnr`
Feel free to reassign
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/ich/impls_ty.rs6
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs7
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_middle/src/ty/error.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs57
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs3
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs18
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs8
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs32
-rw-r--r--compiler/rustc_middle/src/ty/util.rs3
11 files changed, 78 insertions, 76 deletions
diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs
index 69bb4e23c4c..573b514e844 100644
--- a/compiler/rustc_middle/src/ich/impls_ty.rs
+++ b/compiler/rustc_middle/src/ich/impls_ty.rs
@@ -70,16 +70,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
             ty::ReEmpty(universe) => {
                 universe.hash_stable(hcx, hasher);
             }
-            ty::ReLateBound(db, ty::BrAnon(i)) => {
+            ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrAnon(i) }) => {
                 db.hash_stable(hcx, hasher);
                 i.hash_stable(hcx, hasher);
             }
-            ty::ReLateBound(db, ty::BrNamed(def_id, name)) => {
+            ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrNamed(def_id, name) }) => {
                 db.hash_stable(hcx, hasher);
                 def_id.hash_stable(hcx, hasher);
                 name.hash_stable(hcx, hasher);
             }
-            ty::ReLateBound(db, ty::BrEnv) => {
+            ty::ReLateBound(db, ty::BoundRegion { kind: ty::BrEnv }) => {
                 db.hash_stable(hcx, hasher);
             }
             ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 6e5f95c4527..e106db38b2c 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -323,9 +323,10 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                     GenericArgKind::Type(..) => {
                         tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into()
                     }
-                    GenericArgKind::Lifetime(..) => tcx
-                        .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(i)))
-                        .into(),
+                    GenericArgKind::Lifetime(..) => {
+                        let br = ty::BoundRegion { kind: ty::BrAnon(i) };
+                        tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
+                    }
                     GenericArgKind::Const(ct) => tcx
                         .mk_const(ty::Const {
                             ty: ct.ty,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 615972ae45c..4205e2ca5aa 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -890,7 +890,7 @@ pub struct FreeRegionInfo {
     // `LocalDefId` corresponding to FreeRegion
     pub def_id: LocalDefId,
     // the bound region corresponding to FreeRegion
-    pub boundregion: ty::BoundRegion,
+    pub boundregion: ty::BoundRegionKind,
     // checks if bound region is in Impl Item
     pub is_impl_item: bool,
 }
@@ -1412,7 +1412,7 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    // Returns the `DefId` and the `BoundRegion` corresponding to the given region.
+    // Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
     pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
         let (suitable_region_binding_scope, bound_region) = match *region {
             ty::ReFree(ref free_region) => {
@@ -1420,7 +1420,7 @@ impl<'tcx> TyCtxt<'tcx> {
             }
             ty::ReEarlyBound(ref ebr) => (
                 self.parent(ebr.def_id).unwrap().expect_local(),
-                ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
+                ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
             ),
             _ => return None, // not a free region
         };
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 97af927dfcb..fc02e78b2fa 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -1,6 +1,6 @@
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::diagnostics::suggest_constraining_type_param;
-use crate::ty::{self, BoundRegion, Region, Ty, TyCtxt};
+use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
 use rustc_ast as ast;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, DiagnosticBuilder};
@@ -42,8 +42,8 @@ pub enum TypeError<'tcx> {
     ArgCount,
 
     RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
-    RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>),
-    RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>),
+    RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
+    RegionsOverlyPolymorphic(BoundRegionKind, Region<'tcx>),
     RegionsPlaceholderMismatch,
 
     Sorts(ExpectedFound<Ty<'tcx>>),
@@ -94,7 +94,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
             }
         }
 
-        let br_string = |br: ty::BoundRegion| match br {
+        let br_string = |br: ty::BoundRegionKind| match br {
             ty::BrNamed(_, name) => format!(" {}", name),
             _ => String::new(),
         };
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 13c8d6b2bcc..382f3708c3d 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -534,8 +534,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// results returned by the closure; the closure is expected to
     /// return a free region (relative to this binder), and hence the
     /// binder is removed in the return type. The closure is invoked
-    /// once for each unique `BoundRegion`; multiple references to the
-    /// same `BoundRegion` will reuse the previous result. A map is
+    /// once for each unique `BoundRegionKind`; multiple references to the
+    /// same `BoundRegionKind` will reuse the previous result. A map is
     /// returned at the end with each bound region and the free region
     /// that replaced it.
     ///
@@ -544,7 +544,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn replace_late_bound_regions<T, F>(
         self,
         value: Binder<T>,
-        fld_r: F,
+        mut fld_r: F,
     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
     where
         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
@@ -555,7 +555,10 @@ impl<'tcx> TyCtxt<'tcx> {
         let fld_c = |bound_ct, ty| {
             self.mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, bound_ct), ty })
         };
-        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c)
+        let mut region_map = BTreeMap::new();
+        let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
+        let value = self.replace_escaping_bound_vars(value.skip_binder(), real_fld_r, fld_t, fld_c);
+        (value, region_map)
     }
 
     /// Replaces all escaping bound vars. The `fld_r` closure replaces escaping
@@ -567,34 +570,18 @@ impl<'tcx> TyCtxt<'tcx> {
         mut fld_r: F,
         mut fld_t: G,
         mut fld_c: H,
-    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
+    ) -> T
     where
         F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
         G: FnMut(ty::BoundTy) -> Ty<'tcx>,
         H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>,
         T: TypeFoldable<'tcx>,
     {
-        use rustc_data_structures::fx::FxHashMap;
-
-        let mut region_map = BTreeMap::new();
-        let mut type_map = FxHashMap::default();
-        let mut const_map = FxHashMap::default();
-
         if !value.has_escaping_bound_vars() {
-            (value, region_map)
+            value
         } else {
-            let mut real_fld_r = |br| *region_map.entry(br).or_insert_with(|| fld_r(br));
-
-            let mut real_fld_t =
-                |bound_ty| *type_map.entry(bound_ty).or_insert_with(|| fld_t(bound_ty));
-
-            let mut real_fld_c =
-                |bound_ct, ty| *const_map.entry(bound_ct).or_insert_with(|| fld_c(bound_ct, ty));
-
-            let mut replacer =
-                BoundVarReplacer::new(self, &mut real_fld_r, &mut real_fld_t, &mut real_fld_c);
-            let result = value.fold_with(&mut replacer);
-            (result, region_map)
+            let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t, &mut fld_c);
+            value.fold_with(&mut replacer)
         }
     }
 
@@ -604,7 +591,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn replace_bound_vars<T, F, G, H>(
         self,
         value: Binder<T>,
-        fld_r: F,
+        mut fld_r: F,
         fld_t: G,
         fld_c: H,
     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
@@ -614,7 +601,10 @@ impl<'tcx> TyCtxt<'tcx> {
         H: FnMut(ty::BoundVar, Ty<'tcx>) -> &'tcx ty::Const<'tcx>,
         T: TypeFoldable<'tcx>,
     {
-        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t, fld_c)
+        let mut region_map = BTreeMap::new();
+        let real_fld_r = |br: ty::BoundRegion| *region_map.entry(br).or_insert_with(|| fld_r(br));
+        let value = self.replace_escaping_bound_vars(value.skip_binder(), real_fld_r, fld_t, fld_c);
+        (value, region_map)
     }
 
     /// Replaces any late-bound regions bound in `value` with
@@ -626,7 +616,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self.replace_late_bound_regions(value, |br| {
             self.mk_region(ty::ReFree(ty::FreeRegion {
                 scope: all_outlive_scope,
-                bound_region: br,
+                bound_region: br.kind,
             }))
         })
         .0
@@ -639,7 +629,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn collect_constrained_late_bound_regions<T>(
         self,
         value: &Binder<T>,
-    ) -> FxHashSet<ty::BoundRegion>
+    ) -> FxHashSet<ty::BoundRegionKind>
     where
         T: TypeFoldable<'tcx>,
     {
@@ -650,7 +640,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn collect_referenced_late_bound_regions<T>(
         self,
         value: &Binder<T>,
-    ) -> FxHashSet<ty::BoundRegion>
+    ) -> FxHashSet<ty::BoundRegionKind>
     where
         T: TypeFoldable<'tcx>,
     {
@@ -661,7 +651,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         value: &Binder<T>,
         just_constraint: bool,
-    ) -> FxHashSet<ty::BoundRegion>
+    ) -> FxHashSet<ty::BoundRegionKind>
     where
         T: TypeFoldable<'tcx>,
     {
@@ -695,7 +685,8 @@ impl<'tcx> TyCtxt<'tcx> {
         let mut counter = 0;
         Binder::bind(
             self.replace_late_bound_regions(sig, |_| {
-                let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(counter)));
+                let br = ty::BoundRegion { kind: ty::BrAnon(counter) };
+                let r = self.mk_region(ty::ReLateBound(ty::INNERMOST, br));
                 counter += 1;
                 r
             })
@@ -955,7 +946,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
 /// into a hash set.
 struct LateBoundRegionsCollector {
     current_index: ty::DebruijnIndex,
-    regions: FxHashSet<ty::BoundRegion>,
+    regions: FxHashSet<ty::BoundRegionKind>,
 
     /// `true` if we only want regions that are known to be
     /// "constrained" when you equate this type with another type. In
@@ -1014,7 +1005,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         if let ty::ReLateBound(debruijn, br) = *r {
             if debruijn == self.current_index {
-                self.regions.insert(br);
+                self.regions.insert(br.kind);
             }
         }
         ControlFlow::CONTINUE
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index d6b3afb3be3..b545b92c925 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2455,7 +2455,8 @@ impl<'tcx> ty::Instance<'tcx> {
             ty::Generator(_, substs, _) => {
                 let sig = substs.as_generator().poly_sig();
 
-                let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
+                let br = ty::BoundRegion { kind: ty::BrEnv };
+                let env_region = ty::ReLateBound(ty::INNERMOST, br);
                 let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
 
                 let pin_did = tcx.require_lang_item(LangItem::Pin, None);
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 98602d6a459..c163a37c5a1 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -51,13 +51,13 @@ use std::ops::{ControlFlow, Range};
 use std::ptr;
 use std::str;
 
-pub use self::sty::BoundRegion::*;
+pub use self::sty::BoundRegionKind::*;
 pub use self::sty::InferTy::*;
 pub use self::sty::RegionKind;
 pub use self::sty::RegionKind::*;
 pub use self::sty::TyKind::*;
 pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar};
-pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
+pub use self::sty::{BoundRegion, BoundRegionKind, EarlyBoundRegion, FreeRegion, Region};
 pub use self::sty::{CanonicalPolyFnSig, FnSig, GenSig, PolyFnSig, PolyGenSig};
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, TypeAndMut, UpvarSubsts};
 pub use self::sty::{ClosureSubstsParts, GeneratorSubstsParts};
@@ -1607,7 +1607,7 @@ where
     }
 }
 
-pub type PlaceholderRegion = Placeholder<BoundRegion>;
+pub type PlaceholderRegion = Placeholder<BoundRegionKind>;
 
 pub type PlaceholderType = Placeholder<BoundVar>;
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 09ef69e9690..9b178d9d2bd 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -125,13 +125,13 @@ pub struct RegionHighlightMode {
     highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
 
     /// If enabled, when printing a "free region" that originated from
-    /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
+    /// the given `ty::BoundRegionKind`, print it as "`'1`". Free regions that would ordinarily
     /// have names print as normal.
     ///
     /// This is used when you have a signature like `fn foo(x: &u32,
     /// y: &'a u32)` and we want to give a name to the region of the
     /// reference `x`.
-    highlight_bound_region: Option<(ty::BoundRegion, usize)>,
+    highlight_bound_region: Option<(ty::BoundRegionKind, usize)>,
 }
 
 impl RegionHighlightMode {
@@ -175,7 +175,7 @@ impl RegionHighlightMode {
     /// Highlight the given bound region.
     /// We can only highlight one bound region at a time. See
     /// the field `highlight_bound_region` for more detailed notes.
-    pub fn highlighting_bound_region(&mut self, br: ty::BoundRegion, number: usize) {
+    pub fn highlighting_bound_region(&mut self, br: ty::BoundRegionKind, number: usize) {
         assert!(self.highlight_bound_region.is_none());
         self.highlight_bound_region = Some((br, number));
     }
@@ -1611,7 +1611,7 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
                 data.name != kw::Invalid && data.name != kw::UnderscoreLifetime
             }
 
-            ty::ReLateBound(_, br)
+            ty::ReLateBound(_, ty::BoundRegion { kind: br })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
             | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
@@ -1690,7 +1690,7 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
                     return Ok(self);
                 }
             }
-            ty::ReLateBound(_, br)
+            ty::ReLateBound(_, ty::BoundRegion { kind: br })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
             | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
@@ -1779,10 +1779,10 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
         let mut region_index = self.region_index;
         let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| {
             let _ = start_or_continue(&mut self, "for<", ", ");
-            let br = match br {
+            let kind = match br.kind {
                 ty::BrNamed(_, name) => {
                     let _ = write!(self, "{}", name);
-                    br
+                    br.kind
                 }
                 ty::BrAnon(_) | ty::BrEnv => {
                     let name = loop {
@@ -1796,7 +1796,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
                     ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
                 }
             };
-            self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
+            self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind }))
         });
         start_or_continue(&mut self, "", "> ")?;
 
@@ -1840,7 +1840,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
         struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet<Symbol>);
         impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> {
             fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-                if let ty::ReLateBound(_, ty::BrNamed(_, name)) = *r {
+                if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) = *r {
                     self.0.insert(name);
                 }
                 r.super_visit_with(self)
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 8af5792b3fb..7a1ca6a6c2b 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -65,7 +65,7 @@ impl fmt::Debug for ty::adjustment::Adjustment<'tcx> {
     }
 }
 
-impl fmt::Debug for ty::BoundRegion {
+impl fmt::Debug for ty::BoundRegionKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
@@ -308,13 +308,13 @@ TrivialTypeFoldableAndLiftImpls! {
     crate::traits::Reveal,
     crate::ty::adjustment::AutoBorrowMutability,
     crate::ty::AdtKind,
-    // Including `BoundRegion` is a *bit* dubious, but direct
+    // Including `BoundRegionKind` is a *bit* dubious, but direct
     // references to bound region appear in `ty::Error`, and aren't
     // really meant to be folded. In general, we can only fold a fully
     // general `Region`.
-    crate::ty::BoundRegion,
+    crate::ty::BoundRegionKind,
     crate::ty::AssocItem,
-    crate::ty::Placeholder<crate::ty::BoundRegion>,
+    crate::ty::Placeholder<crate::ty::BoundRegionKind>,
     crate::ty::ClosureKind,
     crate::ty::FreeRegion,
     crate::ty::InferTy,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 62d1dda37d6..81ee05d4b23 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -40,12 +40,12 @@ pub struct TypeAndMut<'tcx> {
 /// at least as big as the scope `fr.scope`".
 pub struct FreeRegion {
     pub scope: DefId,
-    pub bound_region: BoundRegion,
+    pub bound_region: BoundRegionKind,
 }
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
 #[derive(HashStable)]
-pub enum BoundRegion {
+pub enum BoundRegionKind {
     /// An anonymous region parameter for a given fn (&T)
     BrAnon(u32),
 
@@ -60,26 +60,34 @@ pub enum BoundRegion {
     BrEnv,
 }
 
-impl BoundRegion {
-    pub fn is_named(&self) -> bool {
-        match *self {
-            BoundRegion::BrNamed(_, name) => name != kw::UnderscoreLifetime,
-            _ => false,
-        }
-    }
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)]
+#[derive(HashStable)]
+pub struct BoundRegion {
+    pub kind: BoundRegionKind,
+}
 
+impl BoundRegion {
     /// When canonicalizing, we replace unbound inference variables and free
     /// regions with anonymous late bound regions. This method asserts that
     /// we have an anonymous late bound region, which hence may refer to
     /// a canonical variable.
     pub fn assert_bound_var(&self) -> BoundVar {
-        match *self {
-            BoundRegion::BrAnon(var) => BoundVar::from_u32(var),
+        match self.kind {
+            BoundRegionKind::BrAnon(var) => BoundVar::from_u32(var),
             _ => bug!("bound region is not anonymous"),
         }
     }
 }
 
+impl BoundRegionKind {
+    pub fn is_named(&self) -> bool {
+        match *self {
+            BoundRegionKind::BrNamed(_, name) => name != kw::UnderscoreLifetime,
+            _ => false,
+        }
+    }
+}
+
 /// N.B., if you change this, you'll probably want to change the corresponding
 /// AST structure in `librustc_ast/ast.rs` as well.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)]
@@ -1551,7 +1559,7 @@ impl RegionKind {
     pub fn has_name(&self) -> bool {
         match *self {
             RegionKind::ReEarlyBound(ebr) => ebr.has_name(),
-            RegionKind::ReLateBound(_, br) => br.is_named(),
+            RegionKind::ReLateBound(_, br) => br.kind.is_named(),
             RegionKind::ReFree(fr) => fr.bound_region.is_named(),
             RegionKind::ReStatic => true,
             RegionKind::ReVar(..) => false,
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 25787f005aa..a64580336ad 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -503,7 +503,8 @@ impl<'tcx> TyCtxt<'tcx> {
         closure_substs: SubstsRef<'tcx>,
     ) -> Option<ty::Binder<Ty<'tcx>>> {
         let closure_ty = self.mk_closure(closure_def_id, closure_substs);
-        let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
+        let br = ty::BoundRegion { kind: ty::BrEnv };
+        let env_region = ty::ReLateBound(ty::INNERMOST, br);
         let closure_kind_ty = closure_substs.as_closure().kind_ty();
         let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
         let env_ty = match closure_kind {