From c2de8fe29443d8c9c70da66dee2c99d4c8d04930 Mon Sep 17 00:00:00 2001
From: "Chai T. Rex" <ChaiTRex@users.noreply.github.com>
Date: Sun, 18 Oct 2020 15:45:09 -0400
Subject: [PATCH 01/13] Stabilize or_insert_with_key

---
 compiler/rustc_data_structures/src/sso/map.rs    | 2 +-
 library/alloc/src/collections/btree/map/entry.rs | 3 +--
 library/std/src/collections/hash/map.rs          | 3 +--
 3 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs
index fa510e58314af..7aca6fd93f2ae 100644
--- a/compiler/rustc_data_structures/src/sso/map.rs
+++ b/compiler/rustc_data_structures/src/sso/map.rs
@@ -40,7 +40,7 @@ const SSO_ARRAY_SIZE: usize = 8;
 //   into_keys/into_values (unstable)
 //   all raw_entry-related
 //   PartialEq/Eq (requires sorting the array)
-//   Entry::or_insert_with_key (unstable)
+//   Entry::or_insert_with_key
 //   Vacant/Occupied entries and related
 //
 // FIXME: In HashMap most methods accepting key reference
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 73a0ca21f6733..3ff648fe24cff 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -116,7 +116,6 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
         }
     }
 
-    #[unstable(feature = "or_insert_with_key", issue = "71024")]
     /// Ensures a value is in the entry by inserting, if empty, the result of the default function,
     /// which takes the key as its argument, and returns a mutable reference to the value in the
     /// entry.
@@ -124,7 +123,6 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(or_insert_with_key)]
     /// use std::collections::BTreeMap;
     ///
     /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
@@ -134,6 +132,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
     /// assert_eq!(map["poneyland"], 9);
     /// ```
     #[inline]
+    #[stable(feature = "or_insert_with_key", since = "1.49.0")]
     pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 114707b639bce..3d130c1628e04 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2229,7 +2229,6 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(or_insert_with_key)]
     /// use std::collections::HashMap;
     ///
     /// let mut map: HashMap<&str, usize> = HashMap::new();
@@ -2239,7 +2238,7 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// assert_eq!(map["poneyland"], 9);
     /// ```
     #[inline]
-    #[unstable(feature = "or_insert_with_key", issue = "71024")]
+    #[stable(feature = "or_insert_with_key", since = "1.49.0")]
     pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),

From 75eb72cc9c23d31f10bd7b4ec6331dd8383cf829 Mon Sep 17 00:00:00 2001
From: David Wood <david@davidtw.co>
Date: Sun, 15 Nov 2020 13:03:30 +0000
Subject: [PATCH 02/13] passes: prohibit attrs on generic params

This commit modifies the `check_attr` pass so that attribute placement
on generic parameters is checked for validity.

Signed-off-by: David Wood <david@davidtw.co>
---
 compiler/rustc_hir/src/target.rs              | 23 +++++++
 compiler/rustc_passes/src/check_attr.rs       | 12 ++++
 src/test/ui/issues/issue-78957.rs             | 30 ++++++++
 src/test/ui/issues/issue-78957.stderr         | 69 +++++++++++++++++++
 .../ui/proc-macro/ambiguous-builtin-attrs.rs  |  4 +-
 .../proc-macro/ambiguous-builtin-attrs.stderr | 14 ++--
 6 files changed, 147 insertions(+), 5 deletions(-)
 create mode 100644 src/test/ui/issues/issue-78957.rs
 create mode 100644 src/test/ui/issues/issue-78957.stderr

diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index b870e4c6ead83..2774cc9c08e16 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -9,6 +9,13 @@ use crate::{Item, ItemKind, TraitItem, TraitItemKind};
 
 use std::fmt::{self, Display};
 
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum GenericParamKind {
+    Type,
+    Lifetime,
+    Const,
+}
+
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum MethodKind {
     Trait { body: bool },
@@ -43,6 +50,7 @@ pub enum Target {
     ForeignFn,
     ForeignStatic,
     ForeignTy,
+    GenericParam(GenericParamKind),
 }
 
 impl Display for Target {
@@ -77,6 +85,11 @@ impl Display for Target {
                 Target::ForeignFn => "foreign function",
                 Target::ForeignStatic => "foreign static item",
                 Target::ForeignTy => "foreign type",
+                Target::GenericParam(kind) => match kind {
+                    GenericParamKind::Type => "type parameter",
+                    GenericParamKind::Lifetime => "lifetime parameter",
+                    GenericParamKind::Const => "const parameter",
+                },
             }
         )
     }
@@ -124,4 +137,14 @@ impl Target {
             hir::ForeignItemKind::Type => Target::ForeignTy,
         }
     }
+
+    pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target {
+        match generic_param.kind {
+            hir::GenericParamKind::Type { .. } => Target::GenericParam(GenericParamKind::Type),
+            hir::GenericParamKind::Lifetime { .. } => {
+                Target::GenericParam(GenericParamKind::Lifetime)
+            }
+            hir::GenericParamKind::Const { .. } => Target::GenericParam(GenericParamKind::Const),
+        }
+    }
 }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 9c0234953bba9..e0babd1885be9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -814,6 +814,18 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
         intravisit::walk_item(self, item)
     }
 
+    fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
+        let target = Target::from_generic_param(generic_param);
+        self.check_attributes(
+            generic_param.hir_id,
+            generic_param.attrs,
+            &generic_param.span,
+            target,
+            None,
+        );
+        intravisit::walk_generic_param(self, generic_param)
+    }
+
     fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) {
         let target = Target::from_trait_item(trait_item);
         self.check_attributes(trait_item.hir_id, &trait_item.attrs, &trait_item.span, target, None);
diff --git a/src/test/ui/issues/issue-78957.rs b/src/test/ui/issues/issue-78957.rs
new file mode 100644
index 0000000000000..263c69bbc0b62
--- /dev/null
+++ b/src/test/ui/issues/issue-78957.rs
@@ -0,0 +1,30 @@
+#![deny(unused_attributes)]
+#![feature(min_const_generics)]
+
+use std::marker::PhantomData;
+
+pub struct Foo<#[inline] const N: usize>;
+//~^ ERROR attribute should be applied to function or closure
+pub struct Bar<#[cold] const N: usize>;
+//~^ ERROR attribute should be applied to a function
+//~| WARN this was previously accepted
+pub struct Baz<#[repr(C)] const N: usize>;
+//~^ ERROR attribute should be applied to a struct, enum, or union
+//
+pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
+//~^ ERROR attribute should be applied to function or closure
+pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
+//~^ ERROR attribute should be applied to a function
+//~| WARN this was previously accepted
+pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
+//~^ ERROR attribute should be applied to a struct, enum, or union
+//
+pub struct Foo3<#[inline] T>(PhantomData<T>);
+//~^ ERROR attribute should be applied to function or closure
+pub struct Bar3<#[cold] T>(PhantomData<T>);
+//~^ ERROR attribute should be applied to a function
+//~| WARN this was previously accepted
+pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
+//~^ ERROR attribute should be applied to a struct, enum, or union
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-78957.stderr b/src/test/ui/issues/issue-78957.stderr
new file mode 100644
index 0000000000000..26437ee4befde
--- /dev/null
+++ b/src/test/ui/issues/issue-78957.stderr
@@ -0,0 +1,69 @@
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-78957.rs:6:16
+   |
+LL | pub struct Foo<#[inline] const N: usize>;
+   |                ^^^^^^^^^       - not a function or closure
+
+error: attribute should be applied to a function
+  --> $DIR/issue-78957.rs:8:16
+   |
+LL | pub struct Bar<#[cold] const N: usize>;
+   |                ^^^^^^^       - not a function
+   |
+note: the lint level is defined here
+  --> $DIR/issue-78957.rs:1:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-78957.rs:11:23
+   |
+LL | pub struct Baz<#[repr(C)] const N: usize>;
+   |                       ^         - not a struct, enum, or union
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-78957.rs:14:17
+   |
+LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>);
+   |                 ^^^^^^^^^ -- not a function or closure
+
+error: attribute should be applied to a function
+  --> $DIR/issue-78957.rs:16:17
+   |
+LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>);
+   |                 ^^^^^^^ -- not a function
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-78957.rs:19:24
+   |
+LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>);
+   |                        ^   -- not a struct, enum, or union
+
+error[E0518]: attribute should be applied to function or closure
+  --> $DIR/issue-78957.rs:22:17
+   |
+LL | pub struct Foo3<#[inline] T>(PhantomData<T>);
+   |                 ^^^^^^^^^ - not a function or closure
+
+error: attribute should be applied to a function
+  --> $DIR/issue-78957.rs:24:17
+   |
+LL | pub struct Bar3<#[cold] T>(PhantomData<T>);
+   |                 ^^^^^^^ - not a function
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-78957.rs:27:24
+   |
+LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>);
+   |                        ^   - not a struct, enum, or union
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0517, E0518.
+For more information about an error, try `rustc --explain E0517`.
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
index 9f4f0abf32486..142efb3c6cdcf 100644
--- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.rs
@@ -17,7 +17,9 @@ fn test() {}
 #[bench] // OK, shadowed
 fn bench() {}
 
-fn non_macro_expanded_location<#[repr(C)] T>() { //~ ERROR `repr` is ambiguous
+fn non_macro_expanded_location<#[repr(C)] T>() {
+    //~^ ERROR `repr` is ambiguous
+    //~| ERROR attribute should be applied to a struct, enum, or union
     match 0u8 {
         #[repr(C)] //~ ERROR `repr` is ambiguous
         _ => {}
diff --git a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
index 23310f6c6f528..276ee1cfd3562 100644
--- a/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
+++ b/src/test/ui/proc-macro/ambiguous-builtin-attrs.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `NonExistent` in this scope
-  --> $DIR/ambiguous-builtin-attrs.rs:30:5
+  --> $DIR/ambiguous-builtin-attrs.rs:32:5
    |
 LL |     NonExistent;
    |     ^^^^^^^^^^^ not found in this scope
@@ -47,7 +47,7 @@ LL | use builtin_attrs::*;
    = help: use `crate::repr` to refer to this attribute macro unambiguously
 
 error[E0659]: `repr` is ambiguous (built-in attribute vs any other name)
-  --> $DIR/ambiguous-builtin-attrs.rs:22:11
+  --> $DIR/ambiguous-builtin-attrs.rs:24:11
    |
 LL |         #[repr(C)]
    |           ^^^^ ambiguous name
@@ -74,7 +74,13 @@ LL | use builtin_attrs::*;
    |     ^^^^^^^^^^^^^^^^
    = help: use `crate::feature` to refer to this attribute macro unambiguously
 
-error: aborting due to 6 previous errors
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/ambiguous-builtin-attrs.rs:20:39
+   |
+LL | fn non_macro_expanded_location<#[repr(C)] T>() {
+   |                                       ^   - not a struct, enum, or union
+
+error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0425, E0659.
+Some errors have detailed explanations: E0425, E0517, E0659.
 For more information about an error, try `rustc --explain E0425`.

From 866ef87d3f1f368687095b263829ef1182b2727a Mon Sep 17 00:00:00 2001
From: "Chai T. Rex" <ChaiTRex@users.noreply.github.com>
Date: Tue, 1 Dec 2020 01:06:40 -0500
Subject: [PATCH 03/13] Update rustc version that or_insert_with_key landed

---
 library/alloc/src/collections/btree/map/entry.rs | 2 +-
 library/std/src/collections/hash/map.rs          | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 3ff648fe24cff..77c285ef595b0 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -132,7 +132,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
     /// assert_eq!(map["poneyland"], 9);
     /// ```
     #[inline]
-    #[stable(feature = "or_insert_with_key", since = "1.49.0")]
+    #[stable(feature = "or_insert_with_key", since = "1.50.0")]
     pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 3d130c1628e04..323ea5d8244b6 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2238,7 +2238,7 @@ impl<'a, K, V> Entry<'a, K, V> {
     /// assert_eq!(map["poneyland"], 9);
     /// ```
     #[inline]
-    #[stable(feature = "or_insert_with_key", since = "1.49.0")]
+    #[stable(feature = "or_insert_with_key", since = "1.50.0")]
     pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),

From f1b930d57cd9014a4e97c2b0ac366c8fa51f38c7 Mon Sep 17 00:00:00 2001
From: "Chai T. Rex" <ChaiTRex@users.noreply.github.com>
Date: Mon, 7 Dec 2020 21:36:01 -0500
Subject: [PATCH 04/13] Improved documentation for HashMap/BTreeMap Entry's
 .or_insert_with_key method

---
 library/alloc/src/collections/btree/map/entry.rs | 9 ++++++---
 library/std/src/collections/hash/map.rs          | 9 ++++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 77c285ef595b0..9dd68e27914bf 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -116,9 +116,12 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
         }
     }
 
-    /// Ensures a value is in the entry by inserting, if empty, the result of the default function,
-    /// which takes the key as its argument, and returns a mutable reference to the value in the
-    /// entry.
+    /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
+    /// This method allows for generating key-derived values for insertion by providing the default
+    /// function a reference to the key that was moved during the `.entry(key)` method call.<br />
+    ///
+    /// The reference to the moved key is provided so that cloning or copying the key is
+    /// unnecessary, unlike with `.or_insert_with(|| ... )`.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 323ea5d8244b6..ae48d7fe7ee10 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -2222,9 +2222,12 @@ impl<'a, K, V> Entry<'a, K, V> {
         }
     }
 
-    /// Ensures a value is in the entry by inserting, if empty, the result of the default function,
-    /// which takes the key as its argument, and returns a mutable reference to the value in the
-    /// entry.
+    /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
+    /// This method allows for generating key-derived values for insertion by providing the default
+    /// function a reference to the key that was moved during the `.entry(key)` method call.
+    ///
+    /// The reference to the moved key is provided so that cloning or copying the key is
+    /// unnecessary, unlike with `.or_insert_with(|| ... )`.
     ///
     /// # Examples
     ///

From f115be93abd2634f3d71d91bf1341e9860a87056 Mon Sep 17 00:00:00 2001
From: "Chai T. Rex" <ChaiTRex@users.noreply.github.com>
Date: Mon, 7 Dec 2020 21:59:52 -0500
Subject: [PATCH 05/13] Removed spurious linebreak from new documentation

---
 library/alloc/src/collections/btree/map/entry.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index 9dd68e27914bf..6626124a34e4e 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -118,7 +118,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
 
     /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
     /// This method allows for generating key-derived values for insertion by providing the default
-    /// function a reference to the key that was moved during the `.entry(key)` method call.<br />
+    /// function a reference to the key that was moved during the `.entry(key)` method call.
     ///
     /// The reference to the moved key is provided so that cloning or copying the key is
     /// unnecessary, unlike with `.or_insert_with(|| ... )`.

From 8fb553c7daf3b82721f53336c607c16559cf1570 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Tue, 15 Dec 2020 20:22:12 -0500
Subject: [PATCH 06/13] Add `&mut` as an alias for 'reference' primitive

---
 library/std/src/primitive_docs.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 55171ef2292d7..25736cc3b50e1 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -920,6 +920,7 @@ mod prim_usize {}
 
 #[doc(primitive = "reference")]
 #[doc(alias = "&")]
+#[doc(alias = "&mut")]
 //
 /// References, both shared and mutable.
 ///

From 30c9307bfc9e57d9901cbd0efe792f321ad2b48b Mon Sep 17 00:00:00 2001
From: pierwill <19642016+pierwill@users.noreply.github.com>
Date: Thu, 17 Dec 2020 11:55:49 -0800
Subject: [PATCH 07/13] docs: Edit rustc_ast::token::Token

Add missing punctuation.
---
 compiler/rustc_ast/src/token.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index f583825fbb3c5..a74464937c8b4 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -434,7 +434,7 @@ impl Token {
             || self == &OpenDelim(Paren)
     }
 
-    /// Returns `true` if the token is any literal
+    /// Returns `true` if the token is any literal.
     pub fn is_lit(&self) -> bool {
         match self.kind {
             Literal(..) => true,

From dea13632a8e8f90febe3de17c740498285397936 Mon Sep 17 00:00:00 2001
From: Aaron Hill <aa1ronham@gmail.com>
Date: Thu, 17 Dec 2020 15:25:55 -0500
Subject: [PATCH 08/13] Suppress `CONST_ITEM_MUTATION` lint if a dereference
 occurs anywhere

Fixes #79971
---
 .../src/transform/check_const_item_mutation.rs   |  8 +++++---
 src/test/ui/lint/lint-const-item-mutation.rs     |  8 ++++++++
 src/test/ui/lint/lint-const-item-mutation.stderr | 16 ++++++++--------
 3 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs
index a84570432786e..e2d50ba034ad3 100644
--- a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs
+++ b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs
@@ -66,12 +66,14 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
         location: Location,
         decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b>) -> DiagnosticBuilder<'b>,
     ) {
-        // Don't lint on borrowing/assigning to a dereference
-        // e.g:
+        // Don't lint on borrowing/assigning when a dereference is involved.
+        // If we 'leave' the temporary via a dereference, we must
+        // be modifying something else
         //
         // `unsafe { *FOO = 0; *BAR.field = 1; }`
         // `unsafe { &mut *FOO }`
-        if !matches!(place.projection.last(), Some(PlaceElem::Deref)) {
+        // `unsafe { (*ARRAY)[0] = val; }
+        if !place.projection.iter().any(|p| matches!(p, PlaceElem::Deref)) {
             let source_info = self.body.source_info(location);
             let lint_root = self.body.source_scopes[source_info.scope]
                 .local_data
diff --git a/src/test/ui/lint/lint-const-item-mutation.rs b/src/test/ui/lint/lint-const-item-mutation.rs
index ef55f31593b63..4bf5e0a9e212a 100644
--- a/src/test/ui/lint/lint-const-item-mutation.rs
+++ b/src/test/ui/lint/lint-const-item-mutation.rs
@@ -30,6 +30,8 @@ const MUTABLE: Mutable = Mutable { msg: "" };
 const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() };
 const VEC: Vec<i32> = Vec::new();
 const PTR: *mut () = 1 as *mut _;
+const PTR_TO_ARRAY: *mut [u32; 4] = 0x12345678 as _;
+const ARRAY_OF_PTR: [*mut u32; 1] = [1 as *mut _];
 
 fn main() {
     ARRAY[0] = 5; //~ WARN attempting to modify
@@ -55,4 +57,10 @@ fn main() {
     // Test that we don't warn when converting a raw pointer
     // into a mutable reference
     unsafe { &mut *PTR };
+
+    // Test that we don't warn when there's a dereference involved.
+    // If we ever 'leave' the const via a deference, we're going
+    // to end up modifying something other than the temporary
+    unsafe { (*PTR_TO_ARRAY)[0] = 1 };
+    unsafe { *ARRAY_OF_PTR[0] = 25; }
 }
diff --git a/src/test/ui/lint/lint-const-item-mutation.stderr b/src/test/ui/lint/lint-const-item-mutation.stderr
index ae95abc72f39a..74505eeb987c6 100644
--- a/src/test/ui/lint/lint-const-item-mutation.stderr
+++ b/src/test/ui/lint/lint-const-item-mutation.stderr
@@ -1,5 +1,5 @@
 warning: attempting to modify a `const` item
-  --> $DIR/lint-const-item-mutation.rs:35:5
+  --> $DIR/lint-const-item-mutation.rs:37:5
    |
 LL |     ARRAY[0] = 5;
    |     ^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL | const ARRAY: [u8; 1] = [25];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: attempting to modify a `const` item
-  --> $DIR/lint-const-item-mutation.rs:36:5
+  --> $DIR/lint-const-item-mutation.rs:38:5
    |
 LL |     MY_STRUCT.field = false;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: attempting to modify a `const` item
-  --> $DIR/lint-const-item-mutation.rs:37:5
+  --> $DIR/lint-const-item-mutation.rs:39:5
    |
 LL |     MY_STRUCT.inner_array[0] = 'b';
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -39,7 +39,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/lint-const-item-mutation.rs:38:5
+  --> $DIR/lint-const-item-mutation.rs:40:5
    |
 LL |     MY_STRUCT.use_mut();
    |     ^^^^^^^^^^^^^^^^^^^
@@ -58,7 +58,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/lint-const-item-mutation.rs:39:5
+  --> $DIR/lint-const-item-mutation.rs:41:5
    |
 LL |     &mut MY_STRUCT;
    |     ^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/lint-const-item-mutation.rs:40:5
+  --> $DIR/lint-const-item-mutation.rs:42:5
    |
 LL |     (&mut MY_STRUCT).use_mut();
    |     ^^^^^^^^^^^^^^^^
@@ -86,7 +86,7 @@ LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: attempting to modify a `const` item
-  --> $DIR/lint-const-item-mutation.rs:52:5
+  --> $DIR/lint-const-item-mutation.rs:54:5
    |
 LL |     MUTABLE2.msg = "wow";
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -99,7 +99,7 @@ LL | const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/lint-const-item-mutation.rs:53:5
+  --> $DIR/lint-const-item-mutation.rs:55:5
    |
 LL |     VEC.push(0);
    |     ^^^^^^^^^^^

From 56530a2f25b621b4589c4f0c7aa147ec811a040e Mon Sep 17 00:00:00 2001
From: Hirochika Matsumoto <matsujika@gmail.com>
Date: Fri, 18 Dec 2020 22:13:25 +0900
Subject: [PATCH 09/13] Fix typo

---
 compiler/rustc_lexer/src/unescape.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index 697d25fdb585b..b4dd0fc2449ec 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -201,7 +201,7 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result<ch
                 return Err(EscapeError::NoBraceInUnicodeEscape);
             }
 
-            // First characrer must be a hexadecimal digit.
+            // First character must be a hexadecimal digit.
             let mut n_digits = 1;
             let mut value: u32 = match chars.next().ok_or(EscapeError::UnclosedUnicodeEscape)? {
                 '_' => return Err(EscapeError::LeadingUnderscoreUnicodeEscape),

From 48d5874914083e920a8500e860d01d1757701283 Mon Sep 17 00:00:00 2001
From: Yoshua Wuyts <yoshuawuyts@gmail.com>
Date: Thu, 19 Nov 2020 21:22:32 +0100
Subject: [PATCH 10/13] Add the "promise" aliases to the `async` lang feature

---
 library/std/src/keyword_docs.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index b990b78570393..54f4eb22d6a1c 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -2175,6 +2175,7 @@ mod where_keyword {}
 
 // 2018 Edition keywords
 
+#[doc(alias = "promise")]
 #[doc(keyword = "async")]
 //
 /// Return a [`Future`] instead of blocking the current thread.

From fd4ae3ae12a78ed77e113bf81ba6f3e127650897 Mon Sep 17 00:00:00 2001
From: mark <markm@cs.wisc.edu>
Date: Tue, 10 Nov 2020 18:00:53 -0600
Subject: [PATCH 11/13] implement edition-specific :pat behavior for 2015/18

---
 compiler/rustc_expand/src/mbe/macro_parser.rs | 33 ++++++++++---
 compiler/rustc_parse/src/parser/expr.rs       |  8 ++--
 compiler/rustc_parse/src/parser/mod.rs        |  1 +
 .../rustc_parse/src/parser/nonterminal.rs     | 23 +++++++--
 compiler/rustc_parse/src/parser/pat.rs        | 17 +++++--
 compiler/rustc_parse/src/parser/stmt.rs       |  4 +-
 src/test/ui/macros/macro-pat-follow-2018.rs   | 15 ++++++
 src/test/ui/macros/macro-pat-follow.rs        | 16 ++-----
 .../or-patterns-syntactic-fail-2018.rs        | 15 ++++++
 .../or-patterns-syntactic-fail-2018.stderr    | 20 ++++++++
 .../or-patterns/or-patterns-syntactic-fail.rs | 10 ----
 .../or-patterns-syntactic-fail.stderr         | 48 ++++++-------------
 .../or-patterns-syntactic-pass-2021.rs        | 14 ++++++
 src/test/ui/pattern/or-pattern-macro-pat.rs   | 44 +++++++++++++++++
 14 files changed, 193 insertions(+), 75 deletions(-)
 create mode 100644 src/test/ui/macros/macro-pat-follow-2018.rs
 create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.rs
 create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr
 create mode 100644 src/test/ui/or-patterns/or-patterns-syntactic-pass-2021.rs
 create mode 100644 src/test/ui/pattern/or-pattern-macro-pat.rs

diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 92a8f23112679..84af934fdac65 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -77,9 +77,9 @@ use TokenTreeOrTokenTreeSlice::*;
 use crate::mbe::{self, TokenTree};
 
 use rustc_ast::token::{self, DocComment, Nonterminal, Token};
-use rustc_parse::parser::Parser;
+use rustc_parse::parser::{OrPatNonterminalMode, Parser};
 use rustc_session::parse::ParseSess;
-use rustc_span::symbol::MacroRulesNormalizedIdent;
+use rustc_span::{edition::Edition, symbol::MacroRulesNormalizedIdent};
 
 use smallvec::{smallvec, SmallVec};
 
@@ -414,6 +414,18 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
     }
 }
 
+/// In edition 2015/18, `:pat` can only match `pat<no_top_alt>` because otherwise, we have
+/// breakage. As of edition 2021, `:pat` matches `top_pat`.
+///
+/// See <https://github.com/rust-lang/rust/issues/54883> for more info.
+fn or_pat_mode(edition: Edition) -> OrPatNonterminalMode {
+    match edition {
+        Edition::Edition2015 | Edition::Edition2018 => OrPatNonterminalMode::NoTopAlt,
+        // FIXME(mark-i-m): uncomment this when edition 2021 machinery is added.
+        // Edition::Edition2021 =>  OrPatNonterminalMode::TopPat,
+    }
+}
+
 /// Process the matcher positions of `cur_items` until it is empty. In the process, this will
 /// produce more items in `next_items`, `eof_items`, and `bb_items`.
 ///
@@ -556,10 +568,14 @@ fn inner_parse_loop<'root, 'tt>(
 
                 // We need to match a metavar with a valid ident... call out to the black-box
                 // parser by adding an item to `bb_items`.
-                TokenTree::MetaVarDecl(_, _, kind) => {
-                    // Built-in nonterminals never start with these tokens,
-                    // so we can eliminate them from consideration.
-                    if Parser::nonterminal_may_begin_with(kind, token) {
+                TokenTree::MetaVarDecl(span, _, kind) => {
+                    // Built-in nonterminals never start with these tokens, so we can eliminate
+                    // them from consideration.
+                    //
+                    // We use the span of the metavariable declaration to determine any
+                    // edition-specific matching behavior for non-terminals.
+                    if Parser::nonterminal_may_begin_with(kind, token, or_pat_mode(span.edition()))
+                    {
                         bb_items.push(item);
                     }
                 }
@@ -720,7 +736,10 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
             let mut item = bb_items.pop().unwrap();
             if let TokenTree::MetaVarDecl(span, _, kind) = item.top_elts.get_tt(item.idx) {
                 let match_cur = item.match_cur;
-                let nt = match parser.to_mut().parse_nonterminal(kind) {
+                // We use the span of the metavariable declaration to determine any
+                // edition-specific matching behavior for non-terminals.
+                let nt = match parser.to_mut().parse_nonterminal(kind, or_pat_mode(span.edition()))
+                {
                     Err(mut err) => {
                         err.span_label(
                             span,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 93be478fc8c2c..bd1f828bf7766 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,4 +1,4 @@
-use super::pat::{GateOr, PARAM_EXPECTED};
+use super::pat::{GateOr, RecoverComma, PARAM_EXPECTED};
 use super::ty::{AllowPlus, RecoverQPath};
 use super::{BlockMode, Parser, PathStyle, Restrictions, TokenType};
 use super::{SemiColonMode, SeqSep, TokenExpectType};
@@ -1728,7 +1728,7 @@ impl<'a> Parser<'a> {
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let lo = self.prev_token.span;
-        let pat = self.parse_top_pat(GateOr::No)?;
+        let pat = self.parse_top_pat(GateOr::No, RecoverComma::Yes)?;
         self.expect(&token::Eq)?;
         let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
             this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
@@ -1791,7 +1791,7 @@ impl<'a> Parser<'a> {
             _ => None,
         };
 
-        let pat = self.parse_top_pat(GateOr::Yes)?;
+        let pat = self.parse_top_pat(GateOr::Yes, RecoverComma::Yes)?;
         if !self.eat_keyword(kw::In) {
             self.error_missing_in_for_loop();
         }
@@ -1901,7 +1901,7 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
-        let pat = self.parse_top_pat(GateOr::No)?;
+        let pat = self.parse_top_pat(GateOr::No, RecoverComma::Yes)?;
         let guard = if self.eat_keyword(kw::If) {
             let if_span = self.prev_token.span;
             let cond = self.parse_expr()?;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index d51a0fcbf09e4..e19ebb8fd2fbc 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -12,6 +12,7 @@ mod ty;
 use crate::lexer::UnmatchedBrace;
 pub use diagnostics::AttemptLocalParseRecovery;
 use diagnostics::Error;
+pub use pat::OrPatNonterminalMode;
 pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index c007f96a79800..606ff5a673df4 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -4,6 +4,7 @@ use rustc_ast_pretty::pprust;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
 
+use crate::parser::pat::{GateOr, OrPatNonterminalMode, RecoverComma};
 use crate::parser::{FollowedByType, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
@@ -11,7 +12,11 @@ impl<'a> Parser<'a> {
     ///
     /// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
     /// token. Be conservative (return true) if not sure.
-    pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
+    pub fn nonterminal_may_begin_with(
+        kind: NonterminalKind,
+        token: &Token,
+        or_pat_mode: OrPatNonterminalMode,
+    ) -> bool {
         /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
         fn may_be_ident(nt: &token::Nonterminal) -> bool {
             match *nt {
@@ -68,6 +73,8 @@ impl<'a> Parser<'a> {
                 token::ModSep |                     // path
                 token::Lt |                         // path (UFCS constant)
                 token::BinOp(token::Shl) => true,   // path (double UFCS)
+                // leading vert `|` or-pattern
+                token::BinOp(token::Or) =>  matches!(or_pat_mode, OrPatNonterminalMode::TopPat),
                 token::Interpolated(ref nt) => may_be_ident(nt),
                 _ => false,
             },
@@ -84,7 +91,12 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonterminal> {
+    /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`).
+    pub fn parse_nonterminal(
+        &mut self,
+        kind: NonterminalKind,
+        or_pat_mode: OrPatNonterminalMode,
+    ) -> PResult<'a, Nonterminal> {
         // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
         // needs to have them force-captured here.
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
@@ -128,7 +140,12 @@ impl<'a> Parser<'a> {
                 }
             }
             NonterminalKind::Pat => {
-                let (mut pat, tokens) = self.collect_tokens(|this| this.parse_pat(None))?;
+                let (mut pat, tokens) = self.collect_tokens(|this| match or_pat_mode {
+                    OrPatNonterminalMode::TopPat => {
+                        this.parse_top_pat(GateOr::Yes, RecoverComma::No)
+                    }
+                    OrPatNonterminalMode::NoTopAlt => this.parse_pat(None),
+                })?;
                 // We have have eaten an NtPat, which could already have tokens
                 if pat.tokens.is_none() {
                     pat.tokens = tokens;
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index b62c737380087..1da371e0b7294 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -26,11 +26,18 @@ pub(super) enum GateOr {
 
 /// Whether or not to recover a `,` when parsing or-patterns.
 #[derive(PartialEq, Copy, Clone)]
-enum RecoverComma {
+pub(super) enum RecoverComma {
     Yes,
     No,
 }
 
+/// Used when parsing a non-terminal (see `parse_nonterminal`) to determine if `:pat` should match
+/// `top_pat` or `pat<no_top_alt>`. See issue <https://github.com/rust-lang/rust/pull/78935>.
+pub enum OrPatNonterminalMode {
+    TopPat,
+    NoTopAlt,
+}
+
 impl<'a> Parser<'a> {
     /// Parses a pattern.
     ///
@@ -43,13 +50,17 @@ impl<'a> Parser<'a> {
 
     /// Entry point to the main pattern parser.
     /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
-    pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P<Pat>> {
+    pub(super) fn parse_top_pat(
+        &mut self,
+        gate_or: GateOr,
+        rc: RecoverComma,
+    ) -> PResult<'a, P<Pat>> {
         // Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
         let gated_leading_vert = self.eat_or_separator(None) && gate_or == GateOr::Yes;
         let leading_vert_span = self.prev_token.span;
 
         // Parse the possibly-or-pattern.
-        let pat = self.parse_pat_with_or(None, gate_or, RecoverComma::Yes)?;
+        let pat = self.parse_pat_with_or(None, gate_or, rc)?;
 
         // If we parsed a leading `|` which should be gated,
         // and no other gated or-pattern has been parsed thus far,
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index e974556f43a49..2942747991a1d 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -1,7 +1,7 @@
 use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
 use super::diagnostics::{AttemptLocalParseRecovery, Error};
 use super::expr::LhsExpr;
-use super::pat::GateOr;
+use super::pat::{GateOr, RecoverComma};
 use super::path::PathStyle;
 use super::{BlockMode, Parser, Restrictions, SemiColonMode};
 use crate::maybe_whole;
@@ -185,7 +185,7 @@ impl<'a> Parser<'a> {
     /// Parses a local variable declaration.
     fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
         let lo = self.prev_token.span;
-        let pat = self.parse_top_pat(GateOr::Yes)?;
+        let pat = self.parse_top_pat(GateOr::Yes, RecoverComma::Yes)?;
 
         let (err, ty) = if self.eat(&token::Colon) {
             // Save the state of the parser before parsing type normally, in case there is a `:`
diff --git a/src/test/ui/macros/macro-pat-follow-2018.rs b/src/test/ui/macros/macro-pat-follow-2018.rs
new file mode 100644
index 0000000000000..ce2911de986dc
--- /dev/null
+++ b/src/test/ui/macros/macro-pat-follow-2018.rs
@@ -0,0 +1,15 @@
+// run-pass
+// edition:2018
+
+macro_rules! pat_bar {
+    ($p:pat | $p2:pat) => {{
+        match Some(1u8) {
+            $p | $p2 => {}
+            _ => {}
+        }
+    }};
+}
+
+fn main() {
+    pat_bar!(Some(1u8) | None);
+}
diff --git a/src/test/ui/macros/macro-pat-follow.rs b/src/test/ui/macros/macro-pat-follow.rs
index 8673cf7946787..8e02789fdd8da 100644
--- a/src/test/ui/macros/macro-pat-follow.rs
+++ b/src/test/ui/macros/macro-pat-follow.rs
@@ -3,29 +3,19 @@ macro_rules! pat_in {
     ($p:pat in $e:expr) => {{
         let mut iter = $e.into_iter();
         while let $p = iter.next() {}
-    }}
+    }};
 }
 
 macro_rules! pat_if {
     ($p:pat if $e:expr) => {{
         match Some(1u8) {
-            $p if $e => {},
+            $p if $e => {}
             _ => {}
         }
-    }}
-}
-
-macro_rules! pat_bar {
-    ($p:pat | $p2:pat) => {{
-        match Some(1u8) {
-            $p | $p2 => {},
-            _ => {}
-        }
-    }}
+    }};
 }
 
 fn main() {
     pat_in!(Some(_) in 0..10);
     pat_if!(Some(x) if x > 0);
-    pat_bar!(Some(1u8) | None);
 }
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.rs
new file mode 100644
index 0000000000000..9c3c5dd360e07
--- /dev/null
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.rs
@@ -0,0 +1,15 @@
+// Test that :pat doesn't accept top-level or-patterns in edition 2018.
+
+// edition:2018
+
+#![feature(or_patterns)]
+
+fn main() {}
+
+// Test the `pat` macro fragment parser:
+macro_rules! accept_pat {
+    ($p:pat) => {};
+}
+
+accept_pat!(p | q); //~ ERROR no rules expected the token `|`
+accept_pat!(|p| q); //~ ERROR no rules expected the token `|`
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr
new file mode 100644
index 0000000000000..7dbc308766347
--- /dev/null
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail-2018.stderr
@@ -0,0 +1,20 @@
+error: no rules expected the token `|`
+  --> $DIR/or-patterns-syntactic-fail-2018.rs:14:15
+   |
+LL | macro_rules! accept_pat {
+   | ----------------------- when calling this macro
+...
+LL | accept_pat!(p | q);
+   |               ^ no rules expected this token in macro call
+
+error: no rules expected the token `|`
+  --> $DIR/or-patterns-syntactic-fail-2018.rs:15:13
+   |
+LL | macro_rules! accept_pat {
+   | ----------------------- when calling this macro
+...
+LL | accept_pat!(|p| q);
+   |             ^ no rules expected this token in macro call
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs
index d23220056524b..efe90b3e3c60c 100644
--- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs
@@ -5,16 +5,6 @@
 
 fn main() {}
 
-// Test the `pat` macro fragment parser:
-macro_rules! accept_pat {
-    ($p:pat) => {}
-}
-
-accept_pat!(p | q); //~ ERROR no rules expected the token `|`
-accept_pat!(| p | q); //~ ERROR no rules expected the token `|`
-
-// Non-macro tests:
-
 enum E { A, B }
 use E::*;
 
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
index 861d274ab5c72..989aeb5200645 100644
--- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
@@ -1,53 +1,53 @@
 error: an or-pattern parameter must be wrapped in parenthesis
-  --> $DIR/or-patterns-syntactic-fail.rs:27:13
+  --> $DIR/or-patterns-syntactic-fail.rs:17:13
    |
 LL |     fn fun1(A | B: E) {}
    |             ^^^^^ help: wrap the pattern in parenthesis: `(A | B)`
 
 error: a leading `|` is not allowed in a parameter pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:29:13
+  --> $DIR/or-patterns-syntactic-fail.rs:19:13
    |
 LL |     fn fun2(| A | B: E) {}
    |             ^ help: remove the `|`
 
 error: an or-pattern parameter must be wrapped in parenthesis
-  --> $DIR/or-patterns-syntactic-fail.rs:29:15
+  --> $DIR/or-patterns-syntactic-fail.rs:19:15
    |
 LL |     fn fun2(| A | B: E) {}
    |               ^^^^^ help: wrap the pattern in parenthesis: `(A | B)`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:40:11
+  --> $DIR/or-patterns-syntactic-fail.rs:30:11
    |
 LL |     let ( | A | B) = E::A;
    |           ^ help: remove the `|`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:41:11
+  --> $DIR/or-patterns-syntactic-fail.rs:31:11
    |
 LL |     let ( | A | B,) = (E::B,);
    |           ^ help: remove the `|`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:42:11
+  --> $DIR/or-patterns-syntactic-fail.rs:32:11
    |
 LL |     let [ | A | B ] = [E::A];
    |           ^ help: remove the `|`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:43:13
+  --> $DIR/or-patterns-syntactic-fail.rs:33:13
    |
 LL |     let TS( | A | B );
    |             ^ help: remove the `|`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:44:17
+  --> $DIR/or-patterns-syntactic-fail.rs:34:17
    |
 LL |     let NS { f: | A | B };
    |                 ^ help: remove the `|`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:46:11
+  --> $DIR/or-patterns-syntactic-fail.rs:36:11
    |
 LL |     let ( || A | B) = E::A;
    |           ^^ help: remove the `||`
@@ -55,7 +55,7 @@ LL |     let ( || A | B) = E::A;
    = note: alternatives in or-patterns are separated with `|`, not `||`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:47:11
+  --> $DIR/or-patterns-syntactic-fail.rs:37:11
    |
 LL |     let [ || A | B ] = [E::A];
    |           ^^ help: remove the `||`
@@ -63,7 +63,7 @@ LL |     let [ || A | B ] = [E::A];
    = note: alternatives in or-patterns are separated with `|`, not `||`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:48:13
+  --> $DIR/or-patterns-syntactic-fail.rs:38:13
    |
 LL |     let TS( || A | B );
    |             ^^ help: remove the `||`
@@ -71,33 +71,15 @@ LL |     let TS( || A | B );
    = note: alternatives in or-patterns are separated with `|`, not `||`
 
 error: a leading `|` is only allowed in a top-level pattern
-  --> $DIR/or-patterns-syntactic-fail.rs:49:17
+  --> $DIR/or-patterns-syntactic-fail.rs:39:17
    |
 LL |     let NS { f: || A | B };
    |                 ^^ help: remove the `||`
    |
    = note: alternatives in or-patterns are separated with `|`, not `||`
 
-error: no rules expected the token `|`
-  --> $DIR/or-patterns-syntactic-fail.rs:13:15
-   |
-LL | macro_rules! accept_pat {
-   | ----------------------- when calling this macro
-...
-LL | accept_pat!(p | q);
-   |               ^ no rules expected this token in macro call
-
-error: no rules expected the token `|`
-  --> $DIR/or-patterns-syntactic-fail.rs:14:13
-   |
-LL | macro_rules! accept_pat {
-   | ----------------------- when calling this macro
-...
-LL | accept_pat!(| p | q);
-   |             ^ no rules expected this token in macro call
-
 error[E0369]: no implementation for `E | ()`
-  --> $DIR/or-patterns-syntactic-fail.rs:23:22
+  --> $DIR/or-patterns-syntactic-fail.rs:13:22
    |
 LL |     let _ = |A | B: E| ();
    |                  ----^ -- ()
@@ -107,7 +89,7 @@ LL |     let _ = |A | B: E| ();
    = note: an implementation of `std::ops::BitOr` might be missing for `E`
 
 error[E0308]: mismatched types
-  --> $DIR/or-patterns-syntactic-fail.rs:51:36
+  --> $DIR/or-patterns-syntactic-fail.rs:41:36
    |
 LL |     let recovery_witness: String = 0;
    |                           ------   ^
@@ -116,7 +98,7 @@ LL |     let recovery_witness: String = 0;
    |                           |        help: try using a conversion method: `0.to_string()`
    |                           expected due to this
 
-error: aborting due to 16 previous errors
+error: aborting due to 14 previous errors
 
 Some errors have detailed explanations: E0308, E0369.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass-2021.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass-2021.rs
new file mode 100644
index 0000000000000..f0ce7597aeed1
--- /dev/null
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass-2021.rs
@@ -0,0 +1,14 @@
+// Tests that :pat in macros in edition 2021 allows top-level or-patterns.
+
+// run-pass
+// ignore-test
+// edition:2021
+// FIXME(mark-i-m): unignore when 2021 machinery is in place.
+
+macro_rules! accept_pat {
+    ($p:pat) => {};
+}
+
+accept_pat!(p | q);
+
+fn main() {}
diff --git a/src/test/ui/pattern/or-pattern-macro-pat.rs b/src/test/ui/pattern/or-pattern-macro-pat.rs
new file mode 100644
index 0000000000000..8749407675b37
--- /dev/null
+++ b/src/test/ui/pattern/or-pattern-macro-pat.rs
@@ -0,0 +1,44 @@
+// run-pass
+// edition:2021
+// ignore-test
+// FIXME(mark-i-m): enable this test again when 2021 machinery is available
+
+#![feature(or_patterns)]
+
+use Foo::*;
+
+#[derive(Eq, PartialEq, Debug)]
+enum Foo {
+    A(u64),
+    B(u64),
+    C,
+    D,
+}
+
+macro_rules! foo {
+    ($orpat:pat, $val:expr) => {
+        match $val {
+            x @ ($orpat) => x, // leading vert would not be allowed in $orpat
+            _ => B(0xDEADBEEFu64),
+        }
+    };
+}
+
+macro_rules! bar {
+    ($orpat:pat, $val:expr) => {
+        match $val {
+            $orpat => 42, // leading vert allowed here
+            _ => 0xDEADBEEFu64,
+        }
+    };
+}
+
+fn main() {
+    // Test or-pattern.
+    let y = foo!(A(_)|B(_), A(32));
+    assert_eq!(y, A(32));
+
+    // Leading vert in or-pattern.
+    let y = bar!(|C| D, C);
+    assert_eq!(y, 42u64);
+}

From 35f16c60e7d3fd1b42c90a0fc084689c817345cb Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Tue, 1 Dec 2020 17:41:09 -0500
Subject: [PATCH 12/13] Switch compiler/ to intra-doc links

rustc_lint and rustc_lint_defs weren't switched because they're included
in the compiler book and so can't use intra-doc links.
---
 compiler/rustc_data_structures/src/graph/iterate/mod.rs    | 2 --
 compiler/rustc_data_structures/src/sorted_map/index_map.rs | 3 +--
 compiler/rustc_errors/src/diagnostic.rs                    | 2 --
 compiler/rustc_index/src/bit_set.rs                        | 1 -
 compiler/rustc_mir/src/dataflow/impls/liveness.rs          | 2 +-
 5 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
index 1634c5863163b..09b91083a6347 100644
--- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
@@ -149,8 +149,6 @@ struct Event<N> {
 /// those successors), we will pop off that node's `Settled` event.
 ///
 /// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms
-/// [`NodeStatus`]: ./enum.NodeStatus.html
-/// [`TriColorVisitor::node_examined`]: ./trait.TriColorVisitor.html#method.node_examined
 pub struct TriColorDepthFirstSearch<'graph, G>
 where
     G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index 2bb421a47efa6..01cd1cec92455 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -24,8 +24,7 @@ use rustc_index::vec::{Idx, IndexVec};
 /// to insert into the middle of the sorted array. Users should avoid mutating this data structure
 /// in-place.
 ///
-/// [`IndexVec`]: ../../rustc_index/vec/struct.IndexVec.html
-/// [`SortedMap`]: ../sorted_map/struct.SortedMap.html
+/// [`SortedMap`]: super::SortedMap
 #[derive(Clone, Debug)]
 pub struct SortedIndexMultiMap<I: Idx, K, V> {
     /// The elements of the map in insertion order.
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 538e1a59ab8d9..e61476bf23e1e 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -138,8 +138,6 @@ impl Diagnostic {
     ///
     /// This span is *not* considered a ["primary span"][`MultiSpan`]; only
     /// the `Span` supplied when creating the diagnostic is primary.
-    ///
-    /// [`MultiSpan`]: ../rustc_span/struct.MultiSpan.html
     pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
         self.span.push_span_label(span, label.into());
         self
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 8e00e54650df0..0b501da7cd975 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -27,7 +27,6 @@ pub const WORD_BITS: usize = WORD_BYTES * 8;
 /// to or greater than the domain size. All operations that involve two bitsets
 /// will panic if the bitsets have differing domain sizes.
 ///
-/// [`GrowableBitSet`]: struct.GrowableBitSet.html
 #[derive(Eq, PartialEq, Decodable, Encodable)]
 pub struct BitSet<T> {
     domain_size: usize,
diff --git a/compiler/rustc_mir/src/dataflow/impls/liveness.rs b/compiler/rustc_mir/src/dataflow/impls/liveness.rs
index a2b0713cd7d0b..85aaff5ab7293 100644
--- a/compiler/rustc_mir/src/dataflow/impls/liveness.rs
+++ b/compiler/rustc_mir/src/dataflow/impls/liveness.rs
@@ -11,7 +11,7 @@ use crate::dataflow::{AnalysisDomain, Backward, GenKill, GenKillAnalysis};
 /// exist. See [this `mir-dataflow` test][flow-test] for an example. You almost never want to use
 /// this analysis without also looking at the results of [`MaybeBorrowedLocals`].
 ///
-/// [`MaybeBorrowedLocals`]: ../struct.MaybeBorrowedLocals.html
+/// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals
 /// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs
 /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
 pub struct MaybeLiveLocals;

From 328fcee4af7aed31343244206abb7dff25106d04 Mon Sep 17 00:00:00 2001
From: Jack Huey <jack.huey@umassmed.edu>
Date: Fri, 18 Dec 2020 13:24:55 -0500
Subject: [PATCH 13/13] Make BoundRegion have a kind of BoungRegionKind

---
 .../rustc_codegen_cranelift/src/abi/mod.rs    |  2 +-
 .../src/infer/canonical/canonicalizer.rs      |  3 +-
 .../src/infer/canonical/substitute.rs         |  2 +-
 .../src/infer/error_reporting/mod.rs          |  6 +-
 .../nice_region_error/find_anon_type.rs       |  8 +--
 .../error_reporting/nice_region_error/util.rs |  8 +--
 .../src/infer/higher_ranked/mod.rs            |  4 +-
 compiler/rustc_infer/src/infer/mod.rs         |  5 +-
 .../rustc_infer/src/infer/nll_relate/mod.rs   |  2 +-
 compiler/rustc_middle/src/ich/impls_ty.rs     |  6 +-
 compiler/rustc_middle/src/infer/canonical.rs  |  7 +-
 compiler/rustc_middle/src/ty/context.rs       |  6 +-
 compiler/rustc_middle/src/ty/error.rs         |  8 +--
 compiler/rustc_middle/src/ty/fold.rs          | 57 +++++++---------
 compiler/rustc_middle/src/ty/layout.rs        |  3 +-
 compiler/rustc_middle/src/ty/mod.rs           |  6 +-
 compiler/rustc_middle/src/ty/print/pretty.rs  | 18 ++---
 .../rustc_middle/src/ty/structural_impls.rs   |  8 +--
 compiler/rustc_middle/src/ty/sty.rs           | 32 +++++----
 compiler/rustc_middle/src/ty/util.rs          |  3 +-
 .../src/borrow_check/diagnostics/mod.rs       |  4 +-
 .../borrow_check/diagnostics/region_errors.rs |  2 +-
 .../borrow_check/diagnostics/region_name.rs   |  6 +-
 .../src/borrow_check/universal_regions.rs     |  4 +-
 compiler/rustc_symbol_mangling/src/v0.rs      |  2 +-
 compiler/rustc_traits/src/chalk/db.rs         | 12 ++--
 compiler/rustc_traits/src/chalk/lowering.rs   | 66 ++++++++-----------
 compiler/rustc_traits/src/chalk/mod.rs        |  2 +-
 compiler/rustc_typeck/src/astconv/mod.rs      | 10 +--
 .../src/check/generator_interior.rs           |  3 +-
 compiler/rustc_typeck/src/check/intrinsic.rs  | 19 +++---
 compiler/rustc_typeck/src/collect.rs          |  2 +-
 src/librustdoc/clean/mod.rs                   |  4 +-
 src/librustdoc/clean/utils.rs                 |  4 +-
 .../escape-argument-callee.stderr             |  2 +-
 .../escape-argument.stderr                    |  2 +-
 ...pagate-approximated-fail-no-postdom.stderr |  2 +-
 .../propagate-approximated-ref.stderr         |  2 +-
 ...er-to-static-comparing-against-free.stderr |  4 +-
 ...oximated-shorter-to-static-no-bound.stderr |  2 +-
 ...mated-shorter-to-static-wrong-bound.stderr |  2 +-
 .../propagate-approximated-val.stderr         |  2 +-
 .../propagate-despite-same-free-region.stderr |  2 +-
 ...ail-to-approximate-longer-no-bounds.stderr |  2 +-
 ...-to-approximate-longer-wrong-bounds.stderr |  2 +-
 .../return-wrong-bound-region.stderr          |  2 +-
 ...ram-closure-approximate-lower-bound.stderr |  4 +-
 47 files changed, 183 insertions(+), 181 deletions(-)

diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index aee274ab4a823..76e1987459f87 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -64,7 +64,7 @@ pub(crate) fn fn_sig_for_fn_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx
         ty::Generator(_, substs, _) => {
             let sig = substs.as_generator().poly_sig();
 
-            let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
+            let env_region = ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv });
             let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
 
             let pin_did = tcx.require_lang_item(rustc_hir::LangItem::Pin, None);
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 8a60b196e5e6e..9002d251f1237 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -625,7 +625,8 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
-        let region = ty::ReLateBound(self.binder_index, ty::BoundRegion::BrAnon(var.as_u32()));
+        let br = ty::BoundRegion { kind: ty::BrAnon(var.as_u32()) };
+        let region = ty::ReLateBound(self.binder_index, br);
         self.tcx().mk_region(region)
     }
 
diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs
index cd4f1fa3bc30a..387f480814ae7 100644
--- a/compiler/rustc_infer/src/infer/canonical/substitute.rs
+++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs
@@ -87,6 +87,6 @@ where
             c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
         };
 
-        tcx.replace_escaping_bound_vars(value, fld_r, fld_t, fld_c).0
+        tcx.replace_escaping_bound_vars(value, fld_r, fld_t, fld_c)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 18e1465c0e6ed..6b7edde9a67af 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -165,7 +165,9 @@ fn msg_span_from_early_bound_and_free_regions(
             }
             (format!("the lifetime `{}` as defined on", br.name), sp)
         }
-        ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => {
+        ty::ReFree(ty::FreeRegion {
+            bound_region: ty::BoundRegionKind::BrNamed(_, name), ..
+        }) => {
             let mut sp = sm.guess_head_span(tcx.hir().span(node));
             if let Some(param) =
                 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
@@ -2279,7 +2281,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         &self,
         var_origin: RegionVariableOrigin,
     ) -> DiagnosticBuilder<'tcx> {
-        let br_string = |br: ty::BoundRegion| {
+        let br_string = |br: ty::BoundRegionKind| {
             let mut s = match br {
                 ty::BrNamed(_, name) => name.to_string(),
                 _ => String::new(),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
index eb1521f056576..b014b9832e783 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs
@@ -25,7 +25,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     pub(super) fn find_anon_type(
         &self,
         region: Region<'tcx>,
-        br: &ty::BoundRegion,
+        br: &ty::BoundRegionKind,
     ) -> Option<(&hir::Ty<'tcx>, &hir::FnDecl<'tcx>)> {
         if let Some(anon_reg) = self.tcx().is_suitable_region(region) {
             let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
@@ -56,7 +56,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     fn find_component_for_bound_region(
         &self,
         arg: &'tcx hir::Ty<'tcx>,
-        br: &ty::BoundRegion,
+        br: &ty::BoundRegionKind,
     ) -> Option<&'tcx hir::Ty<'tcx>> {
         let mut nested_visitor = FindNestedTypeVisitor {
             tcx: self.tcx(),
@@ -80,7 +80,7 @@ struct FindNestedTypeVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     // The bound_region corresponding to the Refree(freeregion)
     // associated with the anonymous region we are looking for.
-    bound_region: ty::BoundRegion,
+    bound_region: ty::BoundRegionKind,
     // The type where the anonymous lifetime appears
     // for e.g., Vec<`&u8`> and <`&u8`>
     found_type: Option<&'tcx hir::Ty<'tcx>>,
@@ -207,7 +207,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
 struct TyPathVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     found_it: bool,
-    bound_region: ty::BoundRegion,
+    bound_region: ty::BoundRegionKind,
     current_index: ty::DebruijnIndex,
 }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index 61fad8863e7c4..17a56046a5cc8 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -14,8 +14,8 @@ pub(super) struct AnonymousParamInfo<'tcx> {
     pub param: &'tcx hir::Param<'tcx>,
     /// The type corresponding to the anonymous region parameter.
     pub param_ty: Ty<'tcx>,
-    /// The ty::BoundRegion corresponding to the anonymous region.
-    pub bound_region: ty::BoundRegion,
+    /// The ty::BoundRegionKind corresponding to the anonymous region.
+    pub bound_region: ty::BoundRegionKind,
     /// The `Span` of the parameter type.
     pub param_ty_span: Span,
     /// Signals that the argument is the first parameter in the declaration.
@@ -43,7 +43,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
             ty::ReEarlyBound(ebr) => (
                 self.tcx().parent(ebr.def_id).unwrap(),
-                ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
+                ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
             ),
             _ => return None, // not a free region
         };
@@ -145,7 +145,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     pub(super) fn is_return_type_anon(
         &self,
         scope_def_id: LocalDefId,
-        br: ty::BoundRegion,
+        br: ty::BoundRegionKind,
         decl: &hir::FnDecl<'_>,
     ) -> Option<Span> {
         let ret_ty = self.tcx().type_of(scope_def_id);
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index 39043980dc4f1..e794903fca3aa 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -77,10 +77,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         // (i.e., if there are no placeholders).
         let next_universe = self.universe().next_universe();
 
-        let fld_r = |br| {
+        let fld_r = |br: ty::BoundRegion| {
             self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
                 universe: next_universe,
-                name: br,
+                name: br.kind,
             }))
         };
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 6affe0e5463df..069f708856ea4 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -450,7 +450,7 @@ pub enum RegionVariableOrigin {
 
     /// Region variables created for bound regions
     /// in a function or method that is called
-    LateBoundRegion(Span, ty::BoundRegion, LateBoundRegionConversionTime),
+    LateBoundRegion(Span, ty::BoundRegionKind, LateBoundRegionConversionTime),
 
     UpvarRegion(ty::UpvarId, Span),
 
@@ -1421,7 +1421,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        let fld_r = |br| self.next_region_var(LateBoundRegion(span, br, lbrct));
+        let fld_r =
+            |br: ty::BoundRegion| self.next_region_var(LateBoundRegion(span, br.kind, lbrct));
         let fld_t = |_| {
             self.next_ty_var(TypeVariableOrigin {
                 kind: TypeVariableOriginKind::MiscVariable,
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 0b2847658f71e..971e0e1863bdf 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -176,7 +176,7 @@ where
                         universe
                     });
 
-                    let placeholder = ty::PlaceholderRegion { universe, name: br };
+                    let placeholder = ty::PlaceholderRegion { universe, name: br.kind };
                     delegate.next_placeholder_region(placeholder)
                 } else {
                     delegate.next_existential_region_var(true)
diff --git a/compiler/rustc_middle/src/ich/impls_ty.rs b/compiler/rustc_middle/src/ich/impls_ty.rs
index 69bb4e23c4c0d..573b514e8445f 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 6e5f95c452745..e106db38b2c9a 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 adf02412b96d3..ed91c4ffd88d7 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -889,7 +889,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,
 }
@@ -1411,7 +1411,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) => {
@@ -1419,7 +1419,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 97af927dfcba2..fc02e78b2fadf 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 13c8d6b2bccb8..382f3708c3d4b 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 d6b3afb3be3df..b545b92c9252a 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 7428f34153c87..27a5aacb67492 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};
@@ -1597,7 +1597,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 09ef69e9690ab..9b178d9d2bd00 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 8af5792b3fb68..7a1ca6a6c2bfc 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 62d1dda37d675..81ee05d4b23ca 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 25787f005aa23..a64580336ad62 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 {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
index 41f3edaa41380..81571fd73003f 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
@@ -496,7 +496,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         // lifetimes without names with the value `'0`.
         match ty.kind() {
             ty::Ref(
-                ty::RegionKind::ReLateBound(_, br)
+                ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br })
                 | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                 _,
                 _,
@@ -517,7 +517,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let region = match ty.kind() {
             ty::Ref(region, _, _) => {
                 match region {
-                    ty::RegionKind::ReLateBound(_, br)
+                    ty::RegionKind::ReLateBound(_, ty::BoundRegion { kind: br })
                     | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
                         printer.region_highlight_mode.highlighting_bound_region(*br, counter)
                     }
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
index e22dab0151703..78da43c31c0fb 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
@@ -138,7 +138,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// Returns `true` if a closure is inferred to be an `FnMut` closure.
     fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
         if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
-            if let ty::BoundRegion::BrEnv = free_region.bound_region {
+            if let ty::BoundRegionKind::BrEnv = free_region.bound_region {
                 if let DefiningTy::Closure(_, substs) =
                     self.regioncx.universal_regions().defining_ty
                 {
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
index 6211cf8a9da85..cbca012824f82 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
@@ -281,7 +281,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
             }
 
             ty::ReFree(free_region) => match free_region.bound_region {
-                ty::BoundRegion::BrNamed(region_def_id, name) => {
+                ty::BoundRegionKind::BrNamed(region_def_id, name) => {
                     // Get the span to point to, even if we don't use the name.
                     let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
                     debug!(
@@ -307,7 +307,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     }
                 }
 
-                ty::BoundRegion::BrEnv => {
+                ty::BoundRegionKind::BrEnv => {
                     let def_ty = self.regioncx.universal_regions().defining_ty;
 
                     if let DefiningTy::Closure(_, substs) = def_ty {
@@ -349,7 +349,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     }
                 }
 
-                ty::BoundRegion::BrAnon(_) => None,
+                ty::BoundRegionKind::BrAnon(_) => None,
             },
 
             ty::ReLateBound(..)
diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
index 7ad38a1f82cd4..c1a0d9856b7ea 100644
--- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs
+++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs
@@ -700,7 +700,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
             debug!("replace_bound_regions_with_nll_infer_vars: br={:?}", br);
             let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion {
                 scope: all_outlive_scope.to_def_id(),
-                bound_region: br,
+                bound_region: br.kind,
             }));
             let region_vid = self.next_nll_region_var(origin);
             indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
@@ -795,7 +795,7 @@ fn for_each_late_bound_region_defined_on<'tcx>(
             let region_def_id = tcx.hir().local_def_id(hir_id);
             let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
                 scope: fn_def_id,
-                bound_region: ty::BoundRegion::BrNamed(region_def_id.to_def_id(), name),
+                bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),
             }));
             f(liberated_region);
         }
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 0294fb23c568c..7b6e6ad0696a1 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -319,7 +319,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
 
             // Late-bound lifetimes use indices starting at 1,
             // see `BinderLevel` for more details.
-            ty::ReLateBound(debruijn, ty::BrAnon(i)) => {
+            ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i) }) => {
                 let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
                 let depth = binder.lifetime_depths.start + i;
 
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index b1b9ef343d5a1..1893d74335ab8 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -648,7 +648,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
 
 /// Creates a `InternalSubsts` that maps each generic parameter to a higher-ranked
 /// var bound at index `0`. For types, we use a `BoundVar` index equal to
-/// the type parameter index. For regions, we use the `BoundRegion::BrNamed`
+/// the type parameter index. For regions, we use the `BoundRegionKind::BrNamed`
 /// variant (which has a `DefId`).
 fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
     InternalSubsts::for_item(tcx, def_id, |param, substs| match param.kind {
@@ -662,12 +662,10 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> {
             ))
             .into(),
 
-        ty::GenericParamDefKind::Lifetime => tcx
-            .mk_region(ty::RegionKind::ReLateBound(
-                ty::INNERMOST,
-                ty::BoundRegion::BrAnon(substs.len() as u32),
-            ))
-            .into(),
+        ty::GenericParamDefKind::Lifetime => {
+            let br = ty::BoundRegion { kind: ty::BrAnon(substs.len() as u32) };
+            tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into()
+        }
 
         ty::GenericParamDefKind::Const => tcx
             .mk_const(ty::Const {
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 3a747b09cd4c4..8aa68e533a2e1 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -35,9 +35,7 @@ use rustc_ast::ast;
 use rustc_middle::traits::{ChalkEnvironmentAndGoal, ChalkRustInterner as RustInterner};
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_middle::ty::{
-    self, Binder, BoundRegion, Region, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor,
-};
+use rustc_middle::ty::{self, Binder, Region, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 use rustc_span::def_id::DefId;
 
 use chalk_ir::{FnSig, ForeignDefId};
@@ -444,15 +442,15 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
             ReEarlyBound(_) => {
                 panic!("Should have already been substituted.");
             }
-            ReLateBound(db, br) => match br {
-                ty::BoundRegion::BrAnon(var) => {
+            ReLateBound(db, br) => match br.kind {
+                ty::BoundRegionKind::BrAnon(var) => {
                     chalk_ir::LifetimeData::BoundVar(chalk_ir::BoundVar::new(
                         chalk_ir::DebruijnIndex::new(db.as_u32()),
-                        *var as usize,
+                        var as usize,
                     ))
                     .intern(interner)
                 }
-                ty::BoundRegion::BrNamed(_def_id, _name) => unimplemented!(),
+                ty::BoundRegionKind::BrNamed(_def_id, _name) => unimplemented!(),
                 ty::BrEnv => unimplemented!(),
             },
             ReFree(_) => unimplemented!(),
@@ -477,13 +475,13 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
         let kind = match self.data(interner) {
             chalk_ir::LifetimeData::BoundVar(var) => ty::RegionKind::ReLateBound(
                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
-                ty::BoundRegion::BrAnon(var.index as u32),
+                ty::BoundRegion { kind: ty::BrAnon(var.index as u32) },
             ),
             chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
             chalk_ir::LifetimeData::Placeholder(p) => {
                 ty::RegionKind::RePlaceholder(ty::Placeholder {
                     universe: ty::UniverseIndex::from_usize(p.ui.counter),
-                    name: ty::BoundRegion::BrAnon(p.idx as u32),
+                    name: ty::BoundRegionKind::BrAnon(p.idx as u32),
                 })
             }
             chalk_ir::LifetimeData::Static => ty::RegionKind::ReStatic,
@@ -805,7 +803,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound<RustInterner<'tcx>
 }
 
 /// To collect bound vars, we have to do two passes. In the first pass, we
-/// collect all `BoundRegion`s and `ty::Bound`s. In the second pass, we then
+/// collect all `BoundRegionKind`s and `ty::Bound`s. In the second pass, we then
 /// replace `BrNamed` into `BrAnon`. The two separate passes are important,
 /// since we can only replace `BrNamed` with `BrAnon`s with indices *after* all
 /// "real" `BrAnon`s.
@@ -893,14 +891,14 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
 
     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         match r {
-            ty::ReLateBound(index, br) if *index == self.binder_index => match br {
-                ty::BoundRegion::BrNamed(def_id, _name) => {
-                    if self.named_parameters.iter().find(|d| *d == def_id).is_none() {
-                        self.named_parameters.push(*def_id);
+            ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
+                ty::BoundRegionKind::BrNamed(def_id, _name) => {
+                    if self.named_parameters.iter().find(|d| **d == def_id).is_none() {
+                        self.named_parameters.push(def_id);
                     }
                 }
 
-                ty::BoundRegion::BrAnon(var) => match self.parameters.entry(*var) {
+                ty::BoundRegionKind::BrAnon(var) => match self.parameters.entry(var) {
                     Entry::Vacant(entry) => {
                         entry.insert(chalk_ir::VariableKind::Lifetime);
                     }
@@ -926,7 +924,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
     }
 }
 
-/// This is used to replace `BoundRegion::BrNamed` with `BoundRegion::BrAnon`.
+/// This is used to replace `BoundRegionKind::BrNamed` with `BoundRegionKind::BrAnon`.
 /// Note: we assume that we will always have room for more bound vars. (i.e. we
 /// won't ever hit the `u32` limit in `BrAnon`s).
 struct NamedBoundVarSubstitutor<'a, 'tcx> {
@@ -955,20 +953,16 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
 
     fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
         match r {
-            ty::ReLateBound(index, br) if *index == self.binder_index => match br {
-                ty::BoundRegion::BrNamed(def_id, _name) => {
-                    match self.named_parameters.get(def_id) {
-                        Some(idx) => {
-                            return self.tcx.mk_region(RegionKind::ReLateBound(
-                                *index,
-                                BoundRegion::BrAnon(*idx),
-                            ));
-                        }
-                        None => panic!("Missing `BrNamed`."),
+            ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind {
+                ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
+                    Some(idx) => {
+                        let new_br = ty::BoundRegion { kind: ty::BrAnon(*idx) };
+                        return self.tcx.mk_region(RegionKind::ReLateBound(*index, new_br));
                     }
-                }
+                    None => panic!("Missing `BrNamed`."),
+                },
                 ty::BrEnv => unimplemented!(),
-                ty::BoundRegion::BrAnon(_) => {}
+                ty::BrAnon(_) => {}
             },
             _ => (),
         };
@@ -1044,17 +1038,15 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
             // FIXME(chalk) - jackh726 - this currently isn't hit in any tests.
             // This covers any region variables in a goal, right?
             ty::ReEarlyBound(_re) => match self.named_regions.get(&_re.def_id) {
-                Some(idx) => self.tcx.mk_region(RegionKind::ReLateBound(
-                    self.binder_index,
-                    BoundRegion::BrAnon(*idx),
-                )),
+                Some(idx) => {
+                    let br = ty::BoundRegion { kind: ty::BrAnon(*idx) };
+                    self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
+                }
                 None => {
                     let idx = self.named_regions.len() as u32;
+                    let br = ty::BoundRegion { kind: ty::BrAnon(idx) };
                     self.named_regions.insert(_re.def_id, idx);
-                    self.tcx.mk_region(RegionKind::ReLateBound(
-                        self.binder_index,
-                        BoundRegion::BrAnon(idx),
-                    ))
+                    self.tcx.mk_region(RegionKind::ReLateBound(self.binder_index, br))
                 }
             },
 
@@ -1096,7 +1088,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         match r {
             ty::RePlaceholder(p) if p.universe == self.universe_index => {
-                if let ty::BoundRegion::BrAnon(anon) = p.name {
+                if let ty::BoundRegionKind::BrAnon(anon) = p.name {
                     self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
                 }
             }
diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs
index b117e28875e76..f3a55fec9e462 100644
--- a/compiler/rustc_traits/src/chalk/mod.rs
+++ b/compiler/rustc_traits/src/chalk/mod.rs
@@ -44,7 +44,7 @@ crate fn evaluate_goal<'tcx>(
 
     let reempty_placeholder = tcx.mk_region(ty::RegionKind::RePlaceholder(ty::Placeholder {
         universe: ty::UniverseIndex::ROOT,
-        name: ty::BoundRegion::BrAnon(placeholders_collector.next_anon_region_placeholder + 1),
+        name: ty::BoundRegionKind::BrAnon(placeholders_collector.next_anon_region_placeholder + 1),
     }));
 
     let mut params_substitutor =
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 693cd236299a8..1648c629186bc 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -196,11 +196,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
             Some(rl::Region::LateBound(debruijn, id, _)) => {
                 let name = lifetime_name(id.expect_local());
-                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrNamed(id, name)))
+                let br = ty::BoundRegion { kind: ty::BrNamed(id, name) };
+                tcx.mk_region(ty::ReLateBound(debruijn, br))
             }
 
             Some(rl::Region::LateBoundAnon(debruijn, index)) => {
-                tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index)))
+                let br = ty::BoundRegion { kind: ty::BrAnon(index) };
+                tcx.mk_region(ty::ReLateBound(debruijn, br))
             }
 
             Some(rl::Region::EarlyBound(index, id, _)) => {
@@ -2295,8 +2297,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
     fn validate_late_bound_regions(
         &self,
-        constrained_regions: FxHashSet<ty::BoundRegion>,
-        referenced_regions: FxHashSet<ty::BoundRegion>,
+        constrained_regions: FxHashSet<ty::BoundRegionKind>,
+        referenced_regions: FxHashSet<ty::BoundRegionKind>,
         generate_err: impl Fn(&str) -> rustc_errors::DiagnosticBuilder<'tcx>,
     ) {
         for br in referenced_regions.difference(&constrained_regions) {
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index 5bc40d617d044..b324e6b7f8e41 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -186,7 +186,8 @@ pub fn resolve_interior<'a, 'tcx>(
                 // which means that none of the regions inside relate to any other, even if
                 // typeck had previously found constraints that would cause them to be related.
                 let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| {
-                    let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, ty::BrAnon(counter)));
+                    let br = ty::BoundRegion { kind: ty::BrAnon(counter) };
+                    let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
                     counter += 1;
                     r
                 });
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index e2712a3033995..6bc598693183b 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -116,13 +116,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
 
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
-            let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0)));
-            let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
+            let region = tcx
+                .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrAnon(0) }));
+            let env_region =
+                tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv }));
             let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
-            (
-                tcx.mk_ref(tcx.mk_region(env_region), ty::TypeAndMut { ty: va_list_ty, mutbl }),
-                va_list_ty,
-            )
+            (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
         })
     };
 
@@ -320,12 +319,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                     tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
                 let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id;
 
+                let br = ty::BoundRegion { kind: ty::BrAnon(0) };
                 (
                     1,
-                    vec![tcx.mk_imm_ref(
-                        tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0))),
-                        param(0),
-                    )],
+                    vec![
+                        tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)), param(0)),
+                    ],
                     tcx.mk_projection(discriminant_def_id, tcx.mk_substs([param(0).into()].iter())),
                 )
             }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index c70554cc62725..731a4da244f23 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -461,7 +461,7 @@ fn get_new_lifetime_name<'tcx>(
         .collect_referenced_late_bound_regions(&poly_trait_ref)
         .into_iter()
         .filter_map(|lt| {
-            if let ty::BoundRegion::BrNamed(_, name) = lt {
+            if let ty::BoundRegionKind::BrNamed(_, name) = lt {
                 Some(name.as_str().to_string())
             } else {
                 None
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2809e85761d41..9f0d111cc3763 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -431,7 +431,9 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
     fn clean(&self, _cx: &DocContext<'_>) -> Option<Lifetime> {
         match *self {
             ty::ReStatic => Some(Lifetime::statik()),
-            ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name)),
+            ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) => {
+                Some(Lifetime(name))
+            }
             ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
 
             ty::ReLateBound(..)
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 1ae2e5de82c45..4d525d62c52cc 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -104,7 +104,9 @@ fn external_generic_args(
         .iter()
         .filter_map(|kind| match kind.unpack() {
             GenericArgKind::Lifetime(lt) => match lt {
-                ty::ReLateBound(_, ty::BrAnon(_)) => Some(GenericArg::Lifetime(Lifetime::elided())),
+                ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrAnon(_) }) => {
+                    Some(GenericArg::Lifetime(Lifetime::elided()))
+                }
                 _ => lt.clean(cx).map(GenericArg::Lifetime),
             },
             GenericArgKind::Type(_) if skip_self => {
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 799ed89dcce3c..4e122d930fc4e 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) i32)),
+               for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) i32)),
                (),
            ]
 
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index a094fc45178f7..44d1d2327fcdb 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) mut &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)),
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)),
                (),
            ]
 
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index c4f4facae1fb5..fa9f994c4fae3 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -10,7 +10,7 @@ LL | |         },
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#4r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index c1450564c45d3..0555f79bcb03b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index e7b8dff4e7ecb..0115f5412f21d 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -10,7 +10,7 @@ LL | |     })
    |
    = note: defining type: case1::{closure#0} with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)),
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)),
                (),
            ]
 
@@ -49,7 +49,7 @@ LL | |     })
    |
    = note: defining type: case2::{closure#0} with closure substs [
                i32,
-               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>)),
+               for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>)),
                (),
            ]
    = note: number of external vids: 2
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 c7e68d02dcf1b..e55d033d2c763 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
@@ -12,7 +12,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t1)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t2)) u32>)),
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
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 abbc76eaf4ddf..ac4a4579c9cd2 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
@@ -12,7 +12,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index c91b514a796ce..60dca1baa40e7 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index 4ddf6f8323f63..cbb10eb187ed8 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -10,7 +10,7 @@ LL | |         },
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
+               for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index 6dc6f4568058b..f9f1d8bb6fffa 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>)),
+               for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 6bcada5c26c83..1587c28e1bef3 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -11,7 +11,7 @@ LL | |     });
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('s)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed('t3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed('t1)) u32>)),
+               for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('t1) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 1da6c6d2c6857..44f743310b483 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -6,7 +6,7 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed('r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed('s)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed('r)) i32,
+               for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) i32,
                (),
            ]
 
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index 7c0d63c368be5..dbf76cd1329cb 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -6,7 +6,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic::<T>::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)),
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)),
                (),
            ]
    = note: number of external vids: 2
@@ -31,7 +31,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic_fail::<T>::{closure#0} with closure substs [
                i16,
-               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed('r)) ()>>, &ReLateBound(DebruijnIndex(0), BrNamed('s)) T)),
+               for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { kind: BrNamed('s) }) T)),
                (),
            ]
    = note: late-bound region is '_#2r