From e467f435ae1194f4617005b6e07a98cec04ee5ed Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 20:41:37 +0000
Subject: [PATCH 01/38] Move `ty::Visibility` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs        | 63 ++--------------------
 compiler/rustc_middle/src/ty/visibility.rs | 61 +++++++++++++++++++++
 2 files changed, 64 insertions(+), 60 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/visibility.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 88b084bbccbdc..925680fcb869c 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -148,7 +148,9 @@ mod structural_impls;
 mod sty;
 mod typeck_results;
 
-// Data types
+mod visibility;
+
+pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
     pub global_ctxt: ResolverGlobalCtxt,
@@ -278,14 +280,6 @@ impl fmt::Display for ImplPolarity {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)]
-pub enum Visibility<Id = LocalDefId> {
-    /// Visible everywhere (including in other crates).
-    Public,
-    /// Visible only in the given crate-local module.
-    Restricted(Id),
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
 pub enum BoundConstness {
     /// `T: Trait`
@@ -369,57 +363,6 @@ impl TyCtxt<'_> {
         true
     }
 }
-
-impl<Id> Visibility<Id> {
-    pub fn is_public(self) -> bool {
-        matches!(self, Visibility::Public)
-    }
-
-    pub fn map_id<OutId>(self, f: impl FnOnce(Id) -> OutId) -> Visibility<OutId> {
-        match self {
-            Visibility::Public => Visibility::Public,
-            Visibility::Restricted(id) => Visibility::Restricted(f(id)),
-        }
-    }
-}
-
-impl<Id: Into<DefId>> Visibility<Id> {
-    pub fn to_def_id(self) -> Visibility<DefId> {
-        self.map_id(Into::into)
-    }
-
-    /// Returns `true` if an item with this visibility is accessible from the given module.
-    pub fn is_accessible_from(self, module: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool {
-        match self {
-            // Public items are visible everywhere.
-            Visibility::Public => true,
-            Visibility::Restricted(id) => tcx.is_descendant_of(module.into(), id.into()),
-        }
-    }
-
-    /// Returns `true` if this visibility is at least as accessible as the given visibility
-    pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tcx: TyCtxt<'_>) -> bool {
-        match vis {
-            Visibility::Public => self.is_public(),
-            Visibility::Restricted(id) => self.is_accessible_from(id, tcx),
-        }
-    }
-}
-
-impl Visibility<DefId> {
-    pub fn expect_local(self) -> Visibility {
-        self.map_id(|id| id.expect_local())
-    }
-
-    /// Returns `true` if this item is visible anywhere in the local crate.
-    pub fn is_visible_locally(self) -> bool {
-        match self {
-            Visibility::Public => true,
-            Visibility::Restricted(def_id) => def_id.is_local(),
-        }
-    }
-}
-
 /// The crate variances map is computed during typeck and contains the
 /// variance of every item in the local crate. You should not use it
 /// directly, because to do so will make your pass dependent on the
diff --git a/compiler/rustc_middle/src/ty/visibility.rs b/compiler/rustc_middle/src/ty/visibility.rs
new file mode 100644
index 0000000000000..c6778d0c5e9bd
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/visibility.rs
@@ -0,0 +1,61 @@
+use rustc_hir::def_id::{DefId, LocalDefId};
+
+use crate::ty::TyCtxt;
+
+#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, Encodable, Decodable, HashStable)]
+pub enum Visibility<Id = LocalDefId> {
+    /// Visible everywhere (including in other crates).
+    Public,
+    /// Visible only in the given crate-local module.
+    Restricted(Id),
+}
+
+impl<Id> Visibility<Id> {
+    pub fn is_public(self) -> bool {
+        matches!(self, Visibility::Public)
+    }
+
+    pub fn map_id<OutId>(self, f: impl FnOnce(Id) -> OutId) -> Visibility<OutId> {
+        match self {
+            Visibility::Public => Visibility::Public,
+            Visibility::Restricted(id) => Visibility::Restricted(f(id)),
+        }
+    }
+}
+
+impl<Id: Into<DefId>> Visibility<Id> {
+    pub fn to_def_id(self) -> Visibility<DefId> {
+        self.map_id(Into::into)
+    }
+
+    /// Returns `true` if an item with this visibility is accessible from the given module.
+    pub fn is_accessible_from(self, module: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool {
+        match self {
+            // Public items are visible everywhere.
+            Visibility::Public => true,
+            Visibility::Restricted(id) => tcx.is_descendant_of(module.into(), id.into()),
+        }
+    }
+
+    /// Returns `true` if this visibility is at least as accessible as the given visibility
+    pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tcx: TyCtxt<'_>) -> bool {
+        match vis {
+            Visibility::Public => self.is_public(),
+            Visibility::Restricted(id) => self.is_accessible_from(id, tcx),
+        }
+    }
+}
+
+impl Visibility<DefId> {
+    pub fn expect_local(self) -> Visibility {
+        self.map_id(|id| id.expect_local())
+    }
+
+    /// Returns `true` if this item is visible anywhere in the local crate.
+    pub fn is_visible_locally(self) -> bool {
+        match self {
+            Visibility::Public => true,
+            Visibility::Restricted(def_id) => def_id.is_local(),
+        }
+    }
+}

From 5854e46a1c06207a8b44c4fa9bc832ab27899500 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 20:53:15 +0000
Subject: [PATCH 02/38] Move `ty::ImplPolarity` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/impl_polarity.rs | 36 ++++++++++++++++++
 compiler/rustc_middle/src/ty/mod.rs           | 37 +------------------
 2 files changed, 38 insertions(+), 35 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/impl_polarity.rs

diff --git a/compiler/rustc_middle/src/ty/impl_polarity.rs b/compiler/rustc_middle/src/ty/impl_polarity.rs
new file mode 100644
index 0000000000000..a55f4d395261d
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/impl_polarity.rs
@@ -0,0 +1,36 @@
+use std::fmt;
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub enum ImplPolarity {
+    /// `impl Trait for Type`
+    Positive,
+    /// `impl !Trait for Type`
+    Negative,
+    /// `#[rustc_reservation_impl] impl Trait for Type`
+    ///
+    /// This is a "stability hack", not a real Rust feature.
+    /// See #64631 for details.
+    Reservation,
+}
+
+impl ImplPolarity {
+    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
+    pub fn flip(&self) -> Option<ImplPolarity> {
+        match self {
+            ImplPolarity::Positive => Some(ImplPolarity::Negative),
+            ImplPolarity::Negative => Some(ImplPolarity::Positive),
+            ImplPolarity::Reservation => None,
+        }
+    }
+}
+
+impl fmt::Display for ImplPolarity {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Positive => f.write_str("positive"),
+            Self::Negative => f.write_str("negative"),
+            Self::Reservation => f.write_str("reservation"),
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 925680fcb869c..b9b00bf372eef 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -148,8 +148,10 @@ mod structural_impls;
 mod sty;
 mod typeck_results;
 
+mod impl_polarity;
 mod visibility;
 
+pub use impl_polarity::ImplPolarity;
 pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
@@ -245,41 +247,6 @@ pub enum ImplSubject<'tcx> {
     Inherent(Ty<'tcx>),
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub enum ImplPolarity {
-    /// `impl Trait for Type`
-    Positive,
-    /// `impl !Trait for Type`
-    Negative,
-    /// `#[rustc_reservation_impl] impl Trait for Type`
-    ///
-    /// This is a "stability hack", not a real Rust feature.
-    /// See #64631 for details.
-    Reservation,
-}
-
-impl ImplPolarity {
-    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
-    pub fn flip(&self) -> Option<ImplPolarity> {
-        match self {
-            ImplPolarity::Positive => Some(ImplPolarity::Negative),
-            ImplPolarity::Negative => Some(ImplPolarity::Positive),
-            ImplPolarity::Reservation => None,
-        }
-    }
-}
-
-impl fmt::Display for ImplPolarity {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Positive => f.write_str("positive"),
-            Self::Negative => f.write_str("negative"),
-            Self::Reservation => f.write_str("reservation"),
-        }
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
 pub enum BoundConstness {
     /// `T: Trait`

From 9990165182012e71eb119deb4dcba918c979b7a5 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 20:57:16 +0000
Subject: [PATCH 03/38] Move `ty::BoundConstness` to its own little module
 (cute)

---
 .../rustc_middle/src/ty/bound_constness.rs    | 34 +++++++++++++++++++
 compiler/rustc_middle/src/ty/mod.rs           | 34 ++-----------------
 2 files changed, 36 insertions(+), 32 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/bound_constness.rs

diff --git a/compiler/rustc_middle/src/ty/bound_constness.rs b/compiler/rustc_middle/src/ty/bound_constness.rs
new file mode 100644
index 0000000000000..2f771fc711676
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/bound_constness.rs
@@ -0,0 +1,34 @@
+use rustc_hir as hir;
+use std::fmt;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
+pub enum BoundConstness {
+    /// `T: Trait`
+    NotConst,
+    /// `T: ~const Trait`
+    ///
+    /// Requires resolving to const only when we are in a const context.
+    ConstIfConst,
+}
+
+impl BoundConstness {
+    /// Reduce `self` and `constness` to two possible combined states instead of four.
+    pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
+        match (constness, self) {
+            (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
+            (_, this) => {
+                *this = BoundConstness::NotConst;
+                hir::Constness::NotConst
+            }
+        }
+    }
+}
+
+impl fmt::Display for BoundConstness {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::NotConst => f.write_str("normal"),
+            Self::ConstIfConst => f.write_str("`~const`"),
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b9b00bf372eef..267b7dc695e96 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -148,9 +148,11 @@ mod structural_impls;
 mod sty;
 mod typeck_results;
 
+mod bound_constness;
 mod impl_polarity;
 mod visibility;
 
+pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
 pub use visibility::Visibility;
 
@@ -247,38 +249,6 @@ pub enum ImplSubject<'tcx> {
     Inherent(Ty<'tcx>),
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
-pub enum BoundConstness {
-    /// `T: Trait`
-    NotConst,
-    /// `T: ~const Trait`
-    ///
-    /// Requires resolving to const only when we are in a const context.
-    ConstIfConst,
-}
-
-impl BoundConstness {
-    /// Reduce `self` and `constness` to two possible combined states instead of four.
-    pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
-        match (constness, self) {
-            (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
-            (_, this) => {
-                *this = BoundConstness::NotConst;
-                hir::Constness::NotConst
-            }
-        }
-    }
-}
-
-impl fmt::Display for BoundConstness {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::NotConst => f.write_str("normal"),
-            Self::ConstIfConst => f.write_str("`~const`"),
-        }
-    }
-}
-
 #[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct ClosureSizeProfileData<'tcx> {

From 05c87281150f1761f8863bfc3f1fd7426e097169 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:16:05 +0000
Subject: [PATCH 04/38] Move `ty::{Predicate, PredicateKind}` to their own
 little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs       | 328 +--------------------
 compiler/rustc_middle/src/ty/predicate.rs | 334 ++++++++++++++++++++++
 2 files changed, 336 insertions(+), 326 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 267b7dc695e96..14e272f3228ed 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -150,10 +150,12 @@ mod typeck_results;
 
 mod bound_constness;
 mod impl_polarity;
+mod predicate;
 mod visibility;
 
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
+pub use predicate::{Predicate, PredicateKind};
 pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
@@ -336,111 +338,6 @@ impl ty::EarlyBoundRegion {
     }
 }
 
-/// Use this rather than `PredicateKind`, whenever possible.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
-#[rustc_pass_by_value]
-pub struct Predicate<'tcx>(
-    Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
-);
-
-impl<'tcx> Predicate<'tcx> {
-    /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
-    #[inline]
-    pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
-        self.0.internee
-    }
-
-    #[inline(always)]
-    pub fn flags(self) -> TypeFlags {
-        self.0.flags
-    }
-
-    #[inline(always)]
-    pub fn outer_exclusive_binder(self) -> DebruijnIndex {
-        self.0.outer_exclusive_binder
-    }
-
-    /// Flips the polarity of a Predicate.
-    ///
-    /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
-    pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
-        let kind = self
-            .kind()
-            .map_bound(|kind| match kind {
-                PredicateKind::Clause(Clause::Trait(TraitPredicate {
-                    trait_ref,
-                    constness,
-                    polarity,
-                })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate {
-                    trait_ref,
-                    constness,
-                    polarity: polarity.flip()?,
-                }))),
-
-                _ => None,
-            })
-            .transpose()?;
-
-        Some(tcx.mk_predicate(kind))
-    }
-
-    pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
-        if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
-            && constness != BoundConstness::NotConst
-        {
-            self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate {
-                trait_ref,
-                constness: BoundConstness::NotConst,
-                polarity,
-            }))));
-        }
-        self
-    }
-
-    #[instrument(level = "debug", skip(tcx), ret)]
-    pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
-        match self.kind().skip_binder() {
-            ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
-                tcx.trait_is_coinductive(data.def_id())
-            }
-            ty::PredicateKind::WellFormed(_) => true,
-            _ => false,
-        }
-    }
-
-    /// Whether this projection can be soundly normalized.
-    ///
-    /// Wf predicates must not be normalized, as normalization
-    /// can remove required bounds which would cause us to
-    /// unsoundly accept some programs. See #91068.
-    #[inline]
-    pub fn allow_normalization(self) -> bool {
-        match self.kind().skip_binder() {
-            PredicateKind::WellFormed(_) => false,
-            PredicateKind::Clause(Clause::Trait(_))
-            | PredicateKind::Clause(Clause::RegionOutlives(_))
-            | PredicateKind::Clause(Clause::TypeOutlives(_))
-            | PredicateKind::Clause(Clause::Projection(_))
-            | PredicateKind::Clause(Clause::ConstArgHasType(..))
-            | PredicateKind::AliasRelate(..)
-            | PredicateKind::ObjectSafe(_)
-            | PredicateKind::ClosureKind(_, _, _)
-            | PredicateKind::Subtype(_)
-            | PredicateKind::Coerce(_)
-            | PredicateKind::ConstEvaluatable(_)
-            | PredicateKind::ConstEquate(_, _)
-            | PredicateKind::Ambiguous
-            | PredicateKind::TypeWellFormedFromEnv(_) => true,
-        }
-    }
-}
-
-impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
-        rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
-    }
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 /// A clause is something that can appear in where bounds or be inferred
@@ -466,62 +363,6 @@ pub enum Clause<'tcx> {
     ConstArgHasType(Const<'tcx>, Ty<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum PredicateKind<'tcx> {
-    /// Prove a clause
-    Clause(Clause<'tcx>),
-
-    /// No syntax: `T` well-formed.
-    WellFormed(GenericArg<'tcx>),
-
-    /// Trait must be object-safe.
-    ObjectSafe(DefId),
-
-    /// No direct syntax. May be thought of as `where T: FnFoo<...>`
-    /// for some substitutions `...` and `T` being a closure type.
-    /// Satisfied (or refuted) once we know the closure's kind.
-    ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind),
-
-    /// `T1 <: T2`
-    ///
-    /// This obligation is created most often when we have two
-    /// unresolved type variables and hence don't have enough
-    /// information to process the subtyping obligation yet.
-    Subtype(SubtypePredicate<'tcx>),
-
-    /// `T1` coerced to `T2`
-    ///
-    /// Like a subtyping obligation, this is created most often
-    /// when we have two unresolved type variables and hence
-    /// don't have enough information to process the coercion
-    /// obligation yet. At the moment, we actually process coercions
-    /// very much like subtyping and don't handle the full coercion
-    /// logic.
-    Coerce(CoercePredicate<'tcx>),
-
-    /// Constant initializer must evaluate successfully.
-    ConstEvaluatable(ty::Const<'tcx>),
-
-    /// Constants must be equal. The first component is the const that is expected.
-    ConstEquate(Const<'tcx>, Const<'tcx>),
-
-    /// Represents a type found in the environment that we can use for implied bounds.
-    ///
-    /// Only used for Chalk.
-    TypeWellFormedFromEnv(Ty<'tcx>),
-
-    /// A marker predicate that is always ambiguous.
-    /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
-    Ambiguous,
-
-    /// Separate from `Clause::Projection` which is used for normalization in new solver.
-    /// This predicate requires two terms to be equal to eachother.
-    ///
-    /// Only used for new solver
-    AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, Debug)]
 pub enum AliasRelationDirection {
@@ -552,106 +393,6 @@ pub struct CratePredicatesMap<'tcx> {
     pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
 
-impl<'tcx> Predicate<'tcx> {
-    /// Performs a substitution suitable for going from a
-    /// poly-trait-ref to supertraits that must hold if that
-    /// poly-trait-ref holds. This is slightly different from a normal
-    /// substitution in terms of what happens with bound regions. See
-    /// lengthy comment below for details.
-    pub fn subst_supertrait(
-        self,
-        tcx: TyCtxt<'tcx>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) -> Predicate<'tcx> {
-        // The interaction between HRTB and supertraits is not entirely
-        // obvious. Let me walk you (and myself) through an example.
-        //
-        // Let's start with an easy case. Consider two traits:
-        //
-        //     trait Foo<'a>: Bar<'a,'a> { }
-        //     trait Bar<'b,'c> { }
-        //
-        // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then
-        // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we
-        // knew that `Foo<'x>` (for any 'x) then we also know that
-        // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
-        // normal substitution.
-        //
-        // In terms of why this is sound, the idea is that whenever there
-        // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
-        // holds. So if there is an impl of `T:Foo<'a>` that applies to
-        // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
-        // `'a`.
-        //
-        // Another example to be careful of is this:
-        //
-        //     trait Foo1<'a>: for<'b> Bar1<'a,'b> { }
-        //     trait Bar1<'b,'c> { }
-        //
-        // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know?
-        // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The
-        // reason is similar to the previous example: any impl of
-        // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So
-        // basically we would want to collapse the bound lifetimes from
-        // the input (`trait_ref`) and the supertraits.
-        //
-        // To achieve this in practice is fairly straightforward. Let's
-        // consider the more complicated scenario:
-        //
-        // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x`
-        //   has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`,
-        //   where both `'x` and `'b` would have a DB index of 1.
-        //   The substitution from the input trait-ref is therefore going to be
-        //   `'a => 'x` (where `'x` has a DB index of 1).
-        // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
-        //   early-bound parameter and `'b` is a late-bound parameter with a
-        //   DB index of 1.
-        // - If we replace `'a` with `'x` from the input, it too will have
-        //   a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
-        //   just as we wanted.
-        //
-        // There is only one catch. If we just apply the substitution `'a
-        // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
-        // adjust the DB index because we substituting into a binder (it
-        // tries to be so smart...) resulting in `for<'x> for<'b>
-        // Bar1<'x,'b>` (we have no syntax for this, so use your
-        // imagination). Basically the 'x will have DB index of 2 and 'b
-        // will have DB index of 1. Not quite what we want. So we apply
-        // the substitution to the *contents* of the trait reference,
-        // rather than the trait reference itself (put another way, the
-        // substitution code expects equal binding levels in the values
-        // from the substitution and the value being substituted into, and
-        // this trick achieves that).
-
-        // Working through the second example:
-        // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0]
-        // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0]
-        // We want to end up with:
-        //     for<'x, 'b> T: Bar1<'^0.0, '^0.1>
-        // To do this:
-        // 1) We must shift all bound vars in predicate by the length
-        //    of trait ref's bound vars. So, we would end up with predicate like
-        //    Self: Bar1<'a, '^0.1>
-        // 2) We can then apply the trait substs to this, ending up with
-        //    T: Bar1<'^0.0, '^0.1>
-        // 3) Finally, to create the final bound vars, we concatenate the bound
-        //    vars of the trait ref with those of the predicate:
-        //    ['x, 'b]
-        let bound_pred = self.kind();
-        let pred_bound_vars = bound_pred.bound_vars();
-        let trait_bound_vars = trait_ref.bound_vars();
-        // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
-        let shifted_pred =
-            tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
-        // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
-        let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
-        // 3) ['x] + ['b] -> ['x, 'b]
-        let bound_vars =
-            tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
-        tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
-    }
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct TraitPredicate<'tcx> {
@@ -1132,71 +873,6 @@ impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
     }
 }
 
-impl<'tcx> Predicate<'tcx> {
-    pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
-        let predicate = self.kind();
-        match predicate.skip_binder() {
-            PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
-            PredicateKind::Clause(Clause::Projection(..))
-            | PredicateKind::Clause(Clause::ConstArgHasType(..))
-            | PredicateKind::AliasRelate(..)
-            | PredicateKind::Subtype(..)
-            | PredicateKind::Coerce(..)
-            | PredicateKind::Clause(Clause::RegionOutlives(..))
-            | PredicateKind::WellFormed(..)
-            | PredicateKind::ObjectSafe(..)
-            | PredicateKind::ClosureKind(..)
-            | PredicateKind::Clause(Clause::TypeOutlives(..))
-            | PredicateKind::ConstEvaluatable(..)
-            | PredicateKind::ConstEquate(..)
-            | PredicateKind::Ambiguous
-            | PredicateKind::TypeWellFormedFromEnv(..) => None,
-        }
-    }
-
-    pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> {
-        let predicate = self.kind();
-        match predicate.skip_binder() {
-            PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
-            PredicateKind::Clause(Clause::Trait(..))
-            | PredicateKind::Clause(Clause::ConstArgHasType(..))
-            | PredicateKind::AliasRelate(..)
-            | PredicateKind::Subtype(..)
-            | PredicateKind::Coerce(..)
-            | PredicateKind::Clause(Clause::RegionOutlives(..))
-            | PredicateKind::WellFormed(..)
-            | PredicateKind::ObjectSafe(..)
-            | PredicateKind::ClosureKind(..)
-            | PredicateKind::Clause(Clause::TypeOutlives(..))
-            | PredicateKind::ConstEvaluatable(..)
-            | PredicateKind::ConstEquate(..)
-            | PredicateKind::Ambiguous
-            | PredicateKind::TypeWellFormedFromEnv(..) => None,
-        }
-    }
-
-    pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
-        let predicate = self.kind();
-        match predicate.skip_binder() {
-            PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
-            PredicateKind::Clause(Clause::Trait(..))
-            | PredicateKind::Clause(Clause::ConstArgHasType(..))
-            | PredicateKind::Clause(Clause::Projection(..))
-            | PredicateKind::AliasRelate(..)
-            | PredicateKind::Subtype(..)
-            | PredicateKind::Coerce(..)
-            | PredicateKind::Clause(Clause::RegionOutlives(..))
-            | PredicateKind::WellFormed(..)
-            | PredicateKind::ObjectSafe(..)
-            | PredicateKind::ClosureKind(..)
-            | PredicateKind::ConstEvaluatable(..)
-            | PredicateKind::ConstEquate(..)
-            | PredicateKind::Ambiguous
-            | PredicateKind::TypeWellFormedFromEnv(..) => None,
-        }
-    }
-}
-
 /// Represents the bounds declared on a particular set of type
 /// parameters. Should eventually be generalized into a flag list of
 /// where-clauses. You can obtain an `InstantiatedPredicates` list from a
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
new file mode 100644
index 0000000000000..f9afb09e120b0
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -0,0 +1,334 @@
+pub use crate::ty::context::{
+    tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
+};
+use rustc_data_structures::intern::Interned;
+use rustc_hir::def_id::DefId;
+use rustc_type_ir::WithCachedTypeInfo;
+
+use crate::ty::{
+    self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, CoercePredicate,
+    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, PolyTraitPredicate,
+    PolyTypeOutlivesPredicate, SubstsRef, SubtypePredicate, Term, TraitPredicate, Ty, TypeFlags,
+};
+
+/// Use this rather than `PredicateKind`, whenever possible.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
+#[rustc_pass_by_value]
+pub struct Predicate<'tcx>(
+    pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
+);
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum PredicateKind<'tcx> {
+    /// Prove a clause
+    Clause(Clause<'tcx>),
+
+    /// No syntax: `T` well-formed.
+    WellFormed(GenericArg<'tcx>),
+
+    /// Trait must be object-safe.
+    ObjectSafe(DefId),
+
+    /// No direct syntax. May be thought of as `where T: FnFoo<...>`
+    /// for some substitutions `...` and `T` being a closure type.
+    /// Satisfied (or refuted) once we know the closure's kind.
+    ClosureKind(DefId, SubstsRef<'tcx>, ClosureKind),
+
+    /// `T1 <: T2`
+    ///
+    /// This obligation is created most often when we have two
+    /// unresolved type variables and hence don't have enough
+    /// information to process the subtyping obligation yet.
+    Subtype(SubtypePredicate<'tcx>),
+
+    /// `T1` coerced to `T2`
+    ///
+    /// Like a subtyping obligation, this is created most often
+    /// when we have two unresolved type variables and hence
+    /// don't have enough information to process the coercion
+    /// obligation yet. At the moment, we actually process coercions
+    /// very much like subtyping and don't handle the full coercion
+    /// logic.
+    Coerce(CoercePredicate<'tcx>),
+
+    /// Constant initializer must evaluate successfully.
+    ConstEvaluatable(ty::Const<'tcx>),
+
+    /// Constants must be equal. The first component is the const that is expected.
+    ConstEquate(Const<'tcx>, Const<'tcx>),
+
+    /// Represents a type found in the environment that we can use for implied bounds.
+    ///
+    /// Only used for Chalk.
+    TypeWellFormedFromEnv(Ty<'tcx>),
+
+    /// A marker predicate that is always ambiguous.
+    /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
+    Ambiguous,
+
+    /// Separate from `Clause::Projection` which is used for normalization in new solver.
+    /// This predicate requires two terms to be equal to eachother.
+    ///
+    /// Only used for new solver
+    AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
+}
+
+impl<'tcx> Predicate<'tcx> {
+    /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
+    #[inline]
+    pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
+        self.0.internee
+    }
+
+    #[inline(always)]
+    pub fn flags(self) -> TypeFlags {
+        self.0.flags
+    }
+
+    #[inline(always)]
+    pub fn outer_exclusive_binder(self) -> DebruijnIndex {
+        self.0.outer_exclusive_binder
+    }
+
+    /// Flips the polarity of a Predicate.
+    ///
+    /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
+    pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
+        let kind = self
+            .kind()
+            .map_bound(|kind| match kind {
+                PredicateKind::Clause(Clause::Trait(TraitPredicate {
+                    trait_ref,
+                    constness,
+                    polarity,
+                })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate {
+                    trait_ref,
+                    constness,
+                    polarity: polarity.flip()?,
+                }))),
+
+                _ => None,
+            })
+            .transpose()?;
+
+        Some(tcx.mk_predicate(kind))
+    }
+
+    pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
+        if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
+            && constness != BoundConstness::NotConst
+        {
+            self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate {
+                trait_ref,
+                constness: BoundConstness::NotConst,
+                polarity,
+            }))));
+        }
+        self
+    }
+
+    #[instrument(level = "debug", skip(tcx), ret)]
+    pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
+        match self.kind().skip_binder() {
+            ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+                tcx.trait_is_coinductive(data.def_id())
+            }
+            ty::PredicateKind::WellFormed(_) => true,
+            _ => false,
+        }
+    }
+
+    /// Whether this projection can be soundly normalized.
+    ///
+    /// Wf predicates must not be normalized, as normalization
+    /// can remove required bounds which would cause us to
+    /// unsoundly accept some programs. See #91068.
+    #[inline]
+    pub fn allow_normalization(self) -> bool {
+        match self.kind().skip_binder() {
+            PredicateKind::WellFormed(_) => false,
+            PredicateKind::Clause(Clause::Trait(_))
+            | PredicateKind::Clause(Clause::RegionOutlives(_))
+            | PredicateKind::Clause(Clause::TypeOutlives(_))
+            | PredicateKind::Clause(Clause::Projection(_))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
+            | PredicateKind::AliasRelate(..)
+            | PredicateKind::ObjectSafe(_)
+            | PredicateKind::ClosureKind(_, _, _)
+            | PredicateKind::Subtype(_)
+            | PredicateKind::Coerce(_)
+            | PredicateKind::ConstEvaluatable(_)
+            | PredicateKind::ConstEquate(_, _)
+            | PredicateKind::Ambiguous
+            | PredicateKind::TypeWellFormedFromEnv(_) => true,
+        }
+    }
+
+    /// Performs a substitution suitable for going from a
+    /// poly-trait-ref to supertraits that must hold if that
+    /// poly-trait-ref holds. This is slightly different from a normal
+    /// substitution in terms of what happens with bound regions. See
+    /// lengthy comment below for details.
+    pub fn subst_supertrait(
+        self,
+        tcx: TyCtxt<'tcx>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) -> Predicate<'tcx> {
+        // The interaction between HRTB and supertraits is not entirely
+        // obvious. Let me walk you (and myself) through an example.
+        //
+        // Let's start with an easy case. Consider two traits:
+        //
+        //     trait Foo<'a>: Bar<'a,'a> { }
+        //     trait Bar<'b,'c> { }
+        //
+        // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then
+        // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we
+        // knew that `Foo<'x>` (for any 'x) then we also know that
+        // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
+        // normal substitution.
+        //
+        // In terms of why this is sound, the idea is that whenever there
+        // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
+        // holds. So if there is an impl of `T:Foo<'a>` that applies to
+        // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
+        // `'a`.
+        //
+        // Another example to be careful of is this:
+        //
+        //     trait Foo1<'a>: for<'b> Bar1<'a,'b> { }
+        //     trait Bar1<'b,'c> { }
+        //
+        // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know?
+        // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The
+        // reason is similar to the previous example: any impl of
+        // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So
+        // basically we would want to collapse the bound lifetimes from
+        // the input (`trait_ref`) and the supertraits.
+        //
+        // To achieve this in practice is fairly straightforward. Let's
+        // consider the more complicated scenario:
+        //
+        // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x`
+        //   has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`,
+        //   where both `'x` and `'b` would have a DB index of 1.
+        //   The substitution from the input trait-ref is therefore going to be
+        //   `'a => 'x` (where `'x` has a DB index of 1).
+        // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
+        //   early-bound parameter and `'b` is a late-bound parameter with a
+        //   DB index of 1.
+        // - If we replace `'a` with `'x` from the input, it too will have
+        //   a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
+        //   just as we wanted.
+        //
+        // There is only one catch. If we just apply the substitution `'a
+        // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
+        // adjust the DB index because we substituting into a binder (it
+        // tries to be so smart...) resulting in `for<'x> for<'b>
+        // Bar1<'x,'b>` (we have no syntax for this, so use your
+        // imagination). Basically the 'x will have DB index of 2 and 'b
+        // will have DB index of 1. Not quite what we want. So we apply
+        // the substitution to the *contents* of the trait reference,
+        // rather than the trait reference itself (put another way, the
+        // substitution code expects equal binding levels in the values
+        // from the substitution and the value being substituted into, and
+        // this trick achieves that).
+
+        // Working through the second example:
+        // trait_ref: for<'x> T: Foo1<'^0.0>; substs: [T, '^0.0]
+        // predicate: for<'b> Self: Bar1<'a, '^0.0>; substs: [Self, 'a, '^0.0]
+        // We want to end up with:
+        //     for<'x, 'b> T: Bar1<'^0.0, '^0.1>
+        // To do this:
+        // 1) We must shift all bound vars in predicate by the length
+        //    of trait ref's bound vars. So, we would end up with predicate like
+        //    Self: Bar1<'a, '^0.1>
+        // 2) We can then apply the trait substs to this, ending up with
+        //    T: Bar1<'^0.0, '^0.1>
+        // 3) Finally, to create the final bound vars, we concatenate the bound
+        //    vars of the trait ref with those of the predicate:
+        //    ['x, 'b]
+        let bound_pred = self.kind();
+        let pred_bound_vars = bound_pred.bound_vars();
+        let trait_bound_vars = trait_ref.bound_vars();
+        // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
+        let shifted_pred =
+            tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
+        // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
+        let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
+        // 3) ['x] + ['b] -> ['x, 'b]
+        let bound_vars =
+            tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
+        tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
+    }
+
+    pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
+        let predicate = self.kind();
+        match predicate.skip_binder() {
+            PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
+            PredicateKind::Clause(Clause::Projection(..))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
+            | PredicateKind::AliasRelate(..)
+            | PredicateKind::Subtype(..)
+            | PredicateKind::Coerce(..)
+            | PredicateKind::Clause(Clause::RegionOutlives(..))
+            | PredicateKind::WellFormed(..)
+            | PredicateKind::ObjectSafe(..)
+            | PredicateKind::ClosureKind(..)
+            | PredicateKind::Clause(Clause::TypeOutlives(..))
+            | PredicateKind::ConstEvaluatable(..)
+            | PredicateKind::ConstEquate(..)
+            | PredicateKind::Ambiguous
+            | PredicateKind::TypeWellFormedFromEnv(..) => None,
+        }
+    }
+
+    pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> {
+        let predicate = self.kind();
+        match predicate.skip_binder() {
+            PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
+            PredicateKind::Clause(Clause::Trait(..))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
+            | PredicateKind::AliasRelate(..)
+            | PredicateKind::Subtype(..)
+            | PredicateKind::Coerce(..)
+            | PredicateKind::Clause(Clause::RegionOutlives(..))
+            | PredicateKind::WellFormed(..)
+            | PredicateKind::ObjectSafe(..)
+            | PredicateKind::ClosureKind(..)
+            | PredicateKind::Clause(Clause::TypeOutlives(..))
+            | PredicateKind::ConstEvaluatable(..)
+            | PredicateKind::ConstEquate(..)
+            | PredicateKind::Ambiguous
+            | PredicateKind::TypeWellFormedFromEnv(..) => None,
+        }
+    }
+
+    pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
+        let predicate = self.kind();
+        match predicate.skip_binder() {
+            PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
+            PredicateKind::Clause(Clause::Trait(..))
+            | PredicateKind::Clause(Clause::ConstArgHasType(..))
+            | PredicateKind::Clause(Clause::Projection(..))
+            | PredicateKind::AliasRelate(..)
+            | PredicateKind::Subtype(..)
+            | PredicateKind::Coerce(..)
+            | PredicateKind::Clause(Clause::RegionOutlives(..))
+            | PredicateKind::WellFormed(..)
+            | PredicateKind::ObjectSafe(..)
+            | PredicateKind::ClosureKind(..)
+            | PredicateKind::ConstEvaluatable(..)
+            | PredicateKind::ConstEquate(..)
+            | PredicateKind::Ambiguous
+            | PredicateKind::TypeWellFormedFromEnv(..) => None,
+        }
+    }
+}
+
+impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
+    }
+}

From fb29d65ef3e378b823721eee6987cdb81a0e938e Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:22:30 +0000
Subject: [PATCH 05/38] Move `ty::InstantiatedPredicates` to its own little
 module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 67 +------------------
 compiler/rustc_middle/src/ty/predicate.rs     |  4 ++
 .../ty/predicate/instantiated_predicates.rs   | 67 +++++++++++++++++++
 3 files changed, 72 insertions(+), 66 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/instantiated_predicates.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 14e272f3228ed..5bb7cdaabc478 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -155,7 +155,7 @@ mod visibility;
 
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
-pub use predicate::{Predicate, PredicateKind};
+pub use predicate::{InstantiatedPredicates, Predicate, PredicateKind};
 pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
@@ -872,71 +872,6 @@ impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
         PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx)
     }
 }
-
-/// Represents the bounds declared on a particular set of type
-/// parameters. Should eventually be generalized into a flag list of
-/// where-clauses. You can obtain an `InstantiatedPredicates` list from a
-/// `GenericPredicates` by using the `instantiate` method. Note that this method
-/// reflects an important semantic invariant of `InstantiatedPredicates`: while
-/// the `GenericPredicates` are expressed in terms of the bound type
-/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance
-/// represented a set of bounds for some particular instantiation,
-/// meaning that the generic parameters have been substituted with
-/// their values.
-///
-/// Example:
-/// ```ignore (illustrative)
-/// struct Foo<T, U: Bar<T>> { ... }
-/// ```
-/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like
-/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
-/// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
-/// [usize:Bar<isize>]]`.
-#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
-pub struct InstantiatedPredicates<'tcx> {
-    pub predicates: Vec<Predicate<'tcx>>,
-    pub spans: Vec<Span>,
-}
-
-impl<'tcx> InstantiatedPredicates<'tcx> {
-    pub fn empty() -> InstantiatedPredicates<'tcx> {
-        InstantiatedPredicates { predicates: vec![], spans: vec![] }
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.predicates.is_empty()
-    }
-
-    pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
-        (&self).into_iter()
-    }
-}
-
-impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
-    type Item = (Predicate<'tcx>, Span);
-
-    type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>;
-
-    fn into_iter(self) -> Self::IntoIter {
-        debug_assert_eq!(self.predicates.len(), self.spans.len());
-        std::iter::zip(self.predicates, self.spans)
-    }
-}
-
-impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
-    type Item = (Predicate<'tcx>, Span);
-
-    type IntoIter = std::iter::Zip<
-        std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>,
-        std::iter::Copied<std::slice::Iter<'a, Span>>,
-    >;
-
-    fn into_iter(self) -> Self::IntoIter {
-        debug_assert_eq!(self.predicates.len(), self.spans.len());
-        std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied())
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct OpaqueTypeKey<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index f9afb09e120b0..72f07fe2c4b23 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -11,6 +11,10 @@ use crate::ty::{
     PolyTypeOutlivesPredicate, SubstsRef, SubtypePredicate, Term, TraitPredicate, Ty, TypeFlags,
 };
 
+mod instantiated_predicates;
+
+pub use instantiated_predicates::InstantiatedPredicates;
+
 /// Use this rather than `PredicateKind`, whenever possible.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
diff --git a/compiler/rustc_middle/src/ty/predicate/instantiated_predicates.rs b/compiler/rustc_middle/src/ty/predicate/instantiated_predicates.rs
new file mode 100644
index 0000000000000..d0153c44ab40b
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/instantiated_predicates.rs
@@ -0,0 +1,67 @@
+use rustc_span::Span;
+
+use crate::ty::Predicate;
+
+/// Represents the bounds declared on a particular set of type
+/// parameters. Should eventually be generalized into a flag list of
+/// where-clauses. You can obtain an `InstantiatedPredicates` list from a
+/// `GenericPredicates` by using the `instantiate` method. Note that this method
+/// reflects an important semantic invariant of `InstantiatedPredicates`: while
+/// the `GenericPredicates` are expressed in terms of the bound type
+/// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance
+/// represented a set of bounds for some particular instantiation,
+/// meaning that the generic parameters have been substituted with
+/// their values.
+///
+/// Example:
+/// ```ignore (illustrative)
+/// struct Foo<T, U: Bar<T>> { ... }
+/// ```
+/// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like
+/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
+/// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
+/// [usize:Bar<isize>]]`.
+#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
+pub struct InstantiatedPredicates<'tcx> {
+    pub predicates: Vec<Predicate<'tcx>>,
+    pub spans: Vec<Span>,
+}
+
+impl<'tcx> InstantiatedPredicates<'tcx> {
+    pub fn empty() -> InstantiatedPredicates<'tcx> {
+        InstantiatedPredicates { predicates: vec![], spans: vec![] }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.predicates.is_empty()
+    }
+
+    pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
+        (&self).into_iter()
+    }
+}
+
+impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
+    type Item = (Predicate<'tcx>, Span);
+
+    type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        debug_assert_eq!(self.predicates.len(), self.spans.len());
+        std::iter::zip(self.predicates, self.spans)
+    }
+}
+
+impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
+    type Item = (Predicate<'tcx>, Span);
+
+    type IntoIter = std::iter::Zip<
+        std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>,
+        std::iter::Copied<std::slice::Iter<'a, Span>>,
+    >;
+
+    fn into_iter(self) -> Self::IntoIter {
+        debug_assert_eq!(self.predicates.len(), self.spans.len());
+        std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied())
+    }
+}

From c19b3f12cdbc7d4b8f888ff32ca1e85cdfa7b4c7 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:28:33 +0000
Subject: [PATCH 06/38] Move `ty::{TraitPredicate, PolyTraitPredicate}` to
 their own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 98 +------------------
 compiler/rustc_middle/src/ty/predicate.rs     |  6 +-
 .../src/ty/predicate/trait_predicate.rs       | 98 +++++++++++++++++++
 3 files changed, 105 insertions(+), 97 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/trait_predicate.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5bb7cdaabc478..1ac9d45909c7f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -155,7 +155,9 @@ mod visibility;
 
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
-pub use predicate::{InstantiatedPredicates, Predicate, PredicateKind};
+pub use predicate::{
+    InstantiatedPredicates, PolyTraitPredicate, Predicate, PredicateKind, TraitPredicate,
+};
 pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
@@ -393,100 +395,6 @@ pub struct CratePredicatesMap<'tcx> {
     pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct TraitPredicate<'tcx> {
-    pub trait_ref: TraitRef<'tcx>,
-
-    pub constness: BoundConstness,
-
-    /// If polarity is Positive: we are proving that the trait is implemented.
-    ///
-    /// If polarity is Negative: we are proving that a negative impl of this trait
-    /// exists. (Note that coherence also checks whether negative impls of supertraits
-    /// exist via a series of predicates.)
-    ///
-    /// If polarity is Reserved: that's a bug.
-    pub polarity: ImplPolarity,
-}
-
-pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
-
-impl<'tcx> TraitPredicate<'tcx> {
-    pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) {
-        *param_env = param_env.with_constness(self.constness.and(param_env.constness()))
-    }
-
-    /// Remap the constness of this predicate before emitting it for diagnostics.
-    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
-        // this is different to `remap_constness` that callees want to print this predicate
-        // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the
-        // param_env is not const because it is always satisfied in non-const contexts.
-        if let hir::Constness::NotConst = param_env.constness() {
-            self.constness = ty::BoundConstness::NotConst;
-        }
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
-    }
-
-    pub fn def_id(self) -> DefId {
-        self.trait_ref.def_id
-    }
-
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.trait_ref.self_ty()
-    }
-
-    #[inline]
-    pub fn is_const_if_const(self) -> bool {
-        self.constness == BoundConstness::ConstIfConst
-    }
-
-    pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
-        match (self.constness, constness) {
-            (BoundConstness::NotConst, _)
-            | (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
-            (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
-        }
-    }
-
-    pub fn without_const(mut self) -> Self {
-        self.constness = BoundConstness::NotConst;
-        self
-    }
-}
-
-impl<'tcx> PolyTraitPredicate<'tcx> {
-    pub fn def_id(self) -> DefId {
-        // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().def_id()
-    }
-
-    pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
-        self.map_bound(|trait_ref| trait_ref.self_ty())
-    }
-
-    /// Remap the constness of this predicate before emitting it for diagnostics.
-    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
-        *self = self.map_bound(|mut p| {
-            p.remap_constness_diag(param_env);
-            p
-        });
-    }
-
-    #[inline]
-    pub fn is_const_if_const(self) -> bool {
-        self.skip_binder().is_const_if_const()
-    }
-
-    #[inline]
-    pub fn polarity(self) -> ImplPolarity {
-        self.skip_binder().polarity
-    }
-}
-
 /// `A: B`
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 72f07fe2c4b23..a5438ca10085f 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -7,13 +7,15 @@ use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
     self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, CoercePredicate,
-    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, PolyTraitPredicate,
-    PolyTypeOutlivesPredicate, SubstsRef, SubtypePredicate, Term, TraitPredicate, Ty, TypeFlags,
+    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate,
+    PolyTypeOutlivesPredicate, SubstsRef, SubtypePredicate, Term, Ty, TypeFlags,
 };
 
 mod instantiated_predicates;
+mod trait_predicate;
 
 pub use instantiated_predicates::InstantiatedPredicates;
+pub use trait_predicate::{PolyTraitPredicate, TraitPredicate};
 
 /// Use this rather than `PredicateKind`, whenever possible.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/predicate/trait_predicate.rs b/compiler/rustc_middle/src/ty/predicate/trait_predicate.rs
new file mode 100644
index 0000000000000..9dfb1152223a4
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/trait_predicate.rs
@@ -0,0 +1,98 @@
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+
+use crate::ty::{self, BoundConstness, ImplPolarity, ParamEnv, TraitRef, Ty, TyCtxt};
+
+pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct TraitPredicate<'tcx> {
+    pub trait_ref: TraitRef<'tcx>,
+
+    pub constness: BoundConstness,
+
+    /// If polarity is Positive: we are proving that the trait is implemented.
+    ///
+    /// If polarity is Negative: we are proving that a negative impl of this trait
+    /// exists. (Note that coherence also checks whether negative impls of supertraits
+    /// exist via a series of predicates.)
+    ///
+    /// If polarity is Reserved: that's a bug.
+    pub polarity: ImplPolarity,
+}
+
+impl<'tcx> TraitPredicate<'tcx> {
+    pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) {
+        *param_env = param_env.with_constness(self.constness.and(param_env.constness()))
+    }
+
+    /// Remap the constness of this predicate before emitting it for diagnostics.
+    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
+        // this is different to `remap_constness` that callees want to print this predicate
+        // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the
+        // param_env is not const because it is always satisfied in non-const contexts.
+        if let hir::Constness::NotConst = param_env.constness() {
+            self.constness = ty::BoundConstness::NotConst;
+        }
+    }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn def_id(self) -> DefId {
+        self.trait_ref.def_id
+    }
+
+    pub fn self_ty(self) -> Ty<'tcx> {
+        self.trait_ref.self_ty()
+    }
+
+    #[inline]
+    pub fn is_const_if_const(self) -> bool {
+        self.constness == BoundConstness::ConstIfConst
+    }
+
+    pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
+        match (self.constness, constness) {
+            (BoundConstness::NotConst, _)
+            | (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
+            (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
+        }
+    }
+
+    pub fn without_const(mut self) -> Self {
+        self.constness = BoundConstness::NotConst;
+        self
+    }
+}
+
+impl<'tcx> PolyTraitPredicate<'tcx> {
+    pub fn def_id(self) -> DefId {
+        // Ok to skip binder since trait `DefId` does not care about regions.
+        self.skip_binder().def_id()
+    }
+
+    pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
+        self.map_bound(|trait_ref| trait_ref.self_ty())
+    }
+
+    /// Remap the constness of this predicate before emitting it for diagnostics.
+    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
+        *self = self.map_bound(|mut p| {
+            p.remap_constness_diag(param_env);
+            p
+        });
+    }
+
+    #[inline]
+    pub fn is_const_if_const(self) -> bool {
+        self.skip_binder().is_const_if_const()
+    }
+
+    #[inline]
+    pub fn polarity(self) -> ImplPolarity {
+        self.skip_binder().polarity
+    }
+}

From 7ca97d18e152fc926ff334e73040ce5b5901dec9 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:34:19 +0000
Subject: [PATCH 07/38] Move `ty::{OutlivesPredicate,
 PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate,
 RegionOutlivesPredicate, TypeOutlivesPredicate}` to their own little module
 (cute)

---
 compiler/rustc_middle/src/ty/mod.rs                | 14 +++-----------
 compiler/rustc_middle/src/ty/predicate.rs          |  9 +++++++--
 .../src/ty/predicate/outlives_predicate.rs         | 11 +++++++++++
 3 files changed, 21 insertions(+), 13 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 1ac9d45909c7f..113b217602139 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -156,7 +156,9 @@ mod visibility;
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
 pub use predicate::{
-    InstantiatedPredicates, PolyTraitPredicate, Predicate, PredicateKind, TraitPredicate,
+    InstantiatedPredicates, OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTraitPredicate,
+    PolyTypeOutlivesPredicate, Predicate, PredicateKind, RegionOutlivesPredicate, TraitPredicate,
+    TypeOutlivesPredicate,
 };
 pub use visibility::Visibility;
 
@@ -394,16 +396,6 @@ pub struct CratePredicatesMap<'tcx> {
     /// bounds, it will have no entry.
     pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
-
-/// `A: B`
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct OutlivesPredicate<A, B>(pub A, pub B);
-pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
-pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
-pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
-pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
-
 /// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
 /// whether the `a` type is the type that we should label as "expected" when
 /// presenting user diagnostics.
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index a5438ca10085f..019393469a539 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -7,14 +7,19 @@ use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
     self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, CoercePredicate,
-    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate,
-    PolyTypeOutlivesPredicate, SubstsRef, SubtypePredicate, Term, Ty, TypeFlags,
+    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, SubstsRef,
+    SubtypePredicate, Term, Ty, TypeFlags,
 };
 
 mod instantiated_predicates;
+mod outlives_predicate;
 mod trait_predicate;
 
 pub use instantiated_predicates::InstantiatedPredicates;
+pub use outlives_predicate::{
+    OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate,
+    RegionOutlivesPredicate, TypeOutlivesPredicate,
+};
 pub use trait_predicate::{PolyTraitPredicate, TraitPredicate};
 
 /// Use this rather than `PredicateKind`, whenever possible.
diff --git a/compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs b/compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs
new file mode 100644
index 0000000000000..ecf44be6799db
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs
@@ -0,0 +1,11 @@
+use crate::ty::{self, Ty};
+
+pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
+pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
+pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
+pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
+
+/// `A: B`
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct OutlivesPredicate<A, B>(pub A, pub B);

From 81f69a351edd2958419c8ca697efb2b4d2467895 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:38:03 +0000
Subject: [PATCH 08/38] Move `ty::{PolyTraitPredicate, TraitPredicate}` to
 their own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs             | 17 +++--------------
 compiler/rustc_middle/src/ty/predicate.rs       |  6 ++++--
 .../src/ty/predicate/subtype_predicate.rs       | 14 ++++++++++++++
 3 files changed, 21 insertions(+), 16 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 113b217602139..095e69c72150a 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -156,9 +156,9 @@ mod visibility;
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
 pub use predicate::{
-    InstantiatedPredicates, OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTraitPredicate,
-    PolyTypeOutlivesPredicate, Predicate, PredicateKind, RegionOutlivesPredicate, TraitPredicate,
-    TypeOutlivesPredicate,
+    InstantiatedPredicates, OutlivesPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate,
+    PolyTraitPredicate, PolyTypeOutlivesPredicate, Predicate, PredicateKind,
+    RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TypeOutlivesPredicate,
 };
 pub use visibility::Visibility;
 
@@ -396,17 +396,6 @@ pub struct CratePredicatesMap<'tcx> {
     /// bounds, it will have no entry.
     pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
-/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
-/// whether the `a` type is the type that we should label as "expected" when
-/// presenting user diagnostics.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct SubtypePredicate<'tcx> {
-    pub a_is_expected: bool,
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
-pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
 
 /// Encodes that we have to coerce *from* the `a` type to the `b` type.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 019393469a539..89e36256a3f3a 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -7,12 +7,13 @@ use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
     self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, CoercePredicate,
-    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, SubstsRef,
-    SubtypePredicate, Term, Ty, TypeFlags,
+    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, SubstsRef, Term, Ty,
+    TypeFlags,
 };
 
 mod instantiated_predicates;
 mod outlives_predicate;
+mod subtype_predicate;
 mod trait_predicate;
 
 pub use instantiated_predicates::InstantiatedPredicates;
@@ -20,6 +21,7 @@ pub use outlives_predicate::{
     OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate,
     RegionOutlivesPredicate, TypeOutlivesPredicate,
 };
+pub use subtype_predicate::{PolySubtypePredicate, SubtypePredicate};
 pub use trait_predicate::{PolyTraitPredicate, TraitPredicate};
 
 /// Use this rather than `PredicateKind`, whenever possible.
diff --git a/compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs b/compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs
new file mode 100644
index 0000000000000..82b87635790b9
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs
@@ -0,0 +1,14 @@
+use crate::ty::{self, Ty};
+
+pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
+
+/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
+/// whether the `a` type is the type that we should label as "expected" when
+/// presenting user diagnostics.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct SubtypePredicate<'tcx> {
+    pub a_is_expected: bool,
+    pub a: Ty<'tcx>,
+    pub b: Ty<'tcx>,
+}

From 94d522e05fc75e28a13ad039a20a0794361a6abc Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:40:41 +0000
Subject: [PATCH 09/38] Move `ty::{CoercePredicate, PolyCoercePredicate}` to
 their own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs              | 16 ++++------------
 compiler/rustc_middle/src/ty/predicate.rs        |  6 ++++--
 .../src/ty/predicate/coerce_predicate.rs         | 11 +++++++++++
 3 files changed, 19 insertions(+), 14 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 095e69c72150a..086453f24df7f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -156,9 +156,10 @@ mod visibility;
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
 pub use predicate::{
-    InstantiatedPredicates, OutlivesPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate,
-    PolyTraitPredicate, PolyTypeOutlivesPredicate, Predicate, PredicateKind,
-    RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TypeOutlivesPredicate,
+    CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
+    PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
+    PolyTypeOutlivesPredicate, Predicate, PredicateKind, RegionOutlivesPredicate, SubtypePredicate,
+    TraitPredicate, TypeOutlivesPredicate,
 };
 pub use visibility::Visibility;
 
@@ -397,15 +398,6 @@ pub struct CratePredicatesMap<'tcx> {
     pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
 
-/// Encodes that we have to coerce *from* the `a` type to the `b` type.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct CoercePredicate<'tcx> {
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
-pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
-
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Term<'tcx> {
     ptr: NonZeroUsize,
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 89e36256a3f3a..455be0bdf6655 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -6,16 +6,18 @@ use rustc_hir::def_id::DefId;
 use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
-    self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, CoercePredicate,
-    Const, DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, SubstsRef, Term, Ty,
+    self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, Const,
+    DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, SubstsRef, Term, Ty,
     TypeFlags,
 };
 
+mod coerce_predicate;
 mod instantiated_predicates;
 mod outlives_predicate;
 mod subtype_predicate;
 mod trait_predicate;
 
+pub use coerce_predicate::{CoercePredicate, PolyCoercePredicate};
 pub use instantiated_predicates::InstantiatedPredicates;
 pub use outlives_predicate::{
     OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate,
diff --git a/compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs b/compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs
new file mode 100644
index 0000000000000..caf6c772e1b63
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs
@@ -0,0 +1,11 @@
+use crate::ty::{self, Ty};
+
+pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
+
+/// Encodes that we have to coerce *from* the `a` type to the `b` type.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct CoercePredicate<'tcx> {
+    pub a: Ty<'tcx>,
+    pub b: Ty<'tcx>,
+}

From 8a600a3bd8e4934956c759624e35ff68e38ee119 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:44:43 +0000
Subject: [PATCH 10/38] Move `ty::{PolyProjectionPredicate,
 ProjectionPredicate}` to their own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 80 +------------------
 compiler/rustc_middle/src/ty/predicate.rs     |  5 +-
 .../src/ty/predicate/projection_predicate.rs  | 75 +++++++++++++++++
 3 files changed, 81 insertions(+), 79 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/projection_predicate.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 086453f24df7f..a6c36fa19a1b2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -157,9 +157,9 @@ pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
 pub use predicate::{
     CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
-    PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
-    PolyTypeOutlivesPredicate, Predicate, PredicateKind, RegionOutlivesPredicate, SubtypePredicate,
-    TraitPredicate, TypeOutlivesPredicate,
+    PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
+    PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
+    RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TypeOutlivesPredicate,
 };
 pub use visibility::Visibility;
 
@@ -571,80 +571,6 @@ impl ParamTerm {
         }
     }
 }
-
-/// This kind of predicate has no *direct* correspondent in the
-/// syntax, but it roughly corresponds to the syntactic forms:
-///
-/// 1. `T: TraitRef<..., Item = Type>`
-/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
-///
-/// In particular, form #1 is "desugared" to the combination of a
-/// normal trait predicate (`T: TraitRef<...>`) and one of these
-/// predicates. Form #2 is a broader form in that it also permits
-/// equality between arbitrary types. Processing an instance of
-/// Form #2 eventually yields one of these `ProjectionPredicate`
-/// instances to normalize the LHS.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionPredicate<'tcx> {
-    pub projection_ty: AliasTy<'tcx>,
-    pub term: Term<'tcx>,
-}
-
-impl<'tcx> ProjectionPredicate<'tcx> {
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.projection_ty.self_ty()
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
-        Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
-    }
-
-    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.projection_ty.trait_def_id(tcx)
-    }
-
-    pub fn def_id(self) -> DefId {
-        self.projection_ty.def_id
-    }
-}
-
-pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
-
-impl<'tcx> PolyProjectionPredicate<'tcx> {
-    /// Returns the `DefId` of the trait of the associated item being projected.
-    #[inline]
-    pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.skip_binder().projection_ty.trait_def_id(tcx)
-    }
-
-    /// Get the [PolyTraitRef] required for this projection to be well formed.
-    /// Note that for generic associated types the predicates of the associated
-    /// type also need to be checked.
-    #[inline]
-    pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
-        // Note: unlike with `TraitRef::to_poly_trait_ref()`,
-        // `self.0.trait_ref` is permitted to have escaping regions.
-        // This is because here `self` has a `Binder` and so does our
-        // return value, so we are preserving the number of binding
-        // levels.
-        self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
-    }
-
-    pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
-        self.map_bound(|predicate| predicate.term)
-    }
-
-    /// The `DefId` of the `TraitItem` for the associated type.
-    ///
-    /// Note that this is not the `DefId` of the `TraitRef` containing this
-    /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
-    pub fn projection_def_id(&self) -> DefId {
-        // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().projection_ty.def_id
-    }
-}
-
 pub trait ToPolyTraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
 }
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 455be0bdf6655..cc18051e5684c 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -7,13 +7,13 @@ use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
     self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, Const,
-    DebruijnIndex, EarlyBinder, GenericArg, PolyProjectionPredicate, SubstsRef, Term, Ty,
-    TypeFlags,
+    DebruijnIndex, EarlyBinder, GenericArg, SubstsRef, Term, Ty, TypeFlags,
 };
 
 mod coerce_predicate;
 mod instantiated_predicates;
 mod outlives_predicate;
+mod projection_predicate;
 mod subtype_predicate;
 mod trait_predicate;
 
@@ -23,6 +23,7 @@ pub use outlives_predicate::{
     OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate,
     RegionOutlivesPredicate, TypeOutlivesPredicate,
 };
+pub use projection_predicate::{PolyProjectionPredicate, ProjectionPredicate};
 pub use subtype_predicate::{PolySubtypePredicate, SubtypePredicate};
 pub use trait_predicate::{PolyTraitPredicate, TraitPredicate};
 
diff --git a/compiler/rustc_middle/src/ty/predicate/projection_predicate.rs b/compiler/rustc_middle/src/ty/predicate/projection_predicate.rs
new file mode 100644
index 0000000000000..b79fefeed174b
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/projection_predicate.rs
@@ -0,0 +1,75 @@
+use crate::ty::{self, AliasTy, PolyTraitRef, Term, Ty, TyCtxt};
+use rustc_hir::def_id::DefId;
+
+pub type PolyProjectionPredicate<'tcx> = ty::Binder<'tcx, ProjectionPredicate<'tcx>>;
+
+/// This kind of predicate has no *direct* correspondent in the
+/// syntax, but it roughly corresponds to the syntactic forms:
+///
+/// 1. `T: TraitRef<..., Item = Type>`
+/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
+///
+/// In particular, form #1 is "desugared" to the combination of a
+/// normal trait predicate (`T: TraitRef<...>`) and one of these
+/// predicates. Form #2 is a broader form in that it also permits
+/// equality between arbitrary types. Processing an instance of
+/// Form #2 eventually yields one of these `ProjectionPredicate`
+/// instances to normalize the LHS.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct ProjectionPredicate<'tcx> {
+    pub projection_ty: AliasTy<'tcx>,
+    pub term: Term<'tcx>,
+}
+
+impl<'tcx> ProjectionPredicate<'tcx> {
+    pub fn self_ty(self) -> Ty<'tcx> {
+        self.projection_ty.self_ty()
+    }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
+        Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+        self.projection_ty.trait_def_id(tcx)
+    }
+
+    pub fn def_id(self) -> DefId {
+        self.projection_ty.def_id
+    }
+}
+
+impl<'tcx> PolyProjectionPredicate<'tcx> {
+    /// Returns the `DefId` of the trait of the associated item being projected.
+    #[inline]
+    pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
+        self.skip_binder().projection_ty.trait_def_id(tcx)
+    }
+
+    /// Get the [PolyTraitRef] required for this projection to be well formed.
+    /// Note that for generic associated types the predicates of the associated
+    /// type also need to be checked.
+    #[inline]
+    pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
+        // Note: unlike with `TraitRef::to_poly_trait_ref()`,
+        // `self.0.trait_ref` is permitted to have escaping regions.
+        // This is because here `self` has a `Binder` and so does our
+        // return value, so we are preserving the number of binding
+        // levels.
+        self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
+    }
+
+    pub fn term(&self) -> ty::Binder<'tcx, Term<'tcx>> {
+        self.map_bound(|predicate| predicate.term)
+    }
+
+    /// The `DefId` of the `TraitItem` for the associated type.
+    ///
+    /// Note that this is not the `DefId` of the `TraitRef` containing this
+    /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
+    pub fn projection_def_id(&self) -> DefId {
+        // Ok to skip binder since trait `DefId` does not care about regions.
+        self.skip_binder().projection_ty.def_id
+    }
+}

From 64c7cc25a220f221cf3e19657f7f5c7f75ed05b9 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 21:49:49 +0000
Subject: [PATCH 11/38] Move `ty::ToPredicate` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 100 +----------------
 compiler/rustc_middle/src/ty/predicate.rs     |   2 +
 .../src/ty/predicate/to_predicate.rs          | 103 ++++++++++++++++++
 3 files changed, 106 insertions(+), 99 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/to_predicate.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a6c36fa19a1b2..6dc97c6526554 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -159,7 +159,7 @@ pub use predicate::{
     CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
     PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
     PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
-    RegionOutlivesPredicate, SubtypePredicate, TraitPredicate, TypeOutlivesPredicate,
+    RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
 };
 pub use visibility::Visibility;
 
@@ -581,104 +581,6 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
     }
 }
 
-pub trait ToPredicate<'tcx, P = Predicate<'tcx>> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P;
-}
-
-impl<'tcx, T> ToPredicate<'tcx, T> for T {
-    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T {
-        self
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> {
-    #[inline(always)]
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        ty::Binder::dummy(self).to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
-    #[inline(always)]
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        tcx.mk_predicate(self)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
-    #[inline(always)]
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
-    #[inline(always)]
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        ty::Binder::dummy(self).to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
-    #[inline(always)]
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
-        pred.to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
-    #[inline(always)]
-    fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
-        self.map_bound(|trait_ref| TraitPredicate {
-            trait_ref,
-            constness: ty::BoundConstness::NotConst,
-            polarity: ty::ImplPolarity::Positive,
-        })
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitRef<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
-        ty::Binder::dummy(self).to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx> {
-    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
-        ty::Binder::dummy(self)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
-    }
-}
-
-impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
-    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
-        PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx)
-    }
-}
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct OpaqueTypeKey<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index cc18051e5684c..c4673a0aac005 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -15,6 +15,7 @@ mod instantiated_predicates;
 mod outlives_predicate;
 mod projection_predicate;
 mod subtype_predicate;
+mod to_predicate;
 mod trait_predicate;
 
 pub use coerce_predicate::{CoercePredicate, PolyCoercePredicate};
@@ -25,6 +26,7 @@ pub use outlives_predicate::{
 };
 pub use projection_predicate::{PolyProjectionPredicate, ProjectionPredicate};
 pub use subtype_predicate::{PolySubtypePredicate, SubtypePredicate};
+pub use to_predicate::ToPredicate;
 pub use trait_predicate::{PolyTraitPredicate, TraitPredicate};
 
 /// Use this rather than `PredicateKind`, whenever possible.
diff --git a/compiler/rustc_middle/src/ty/predicate/to_predicate.rs b/compiler/rustc_middle/src/ty/predicate/to_predicate.rs
new file mode 100644
index 0000000000000..7d2eb5270697a
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/to_predicate.rs
@@ -0,0 +1,103 @@
+use crate::ty::{
+    self, Clause, PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolyTraitPredicate,
+    PolyTypeOutlivesPredicate, Predicate, PredicateKind, TraitPredicate, TraitRef, TyCtxt,
+};
+
+pub trait ToPredicate<'tcx, P = Predicate<'tcx>> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P;
+}
+
+impl<'tcx, T> ToPredicate<'tcx, T> for T {
+    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T {
+        self
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> {
+    #[inline(always)]
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        ty::Binder::dummy(self).to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for ty::Binder<'tcx, PredicateKind<'tcx>> {
+    #[inline(always)]
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        tcx.mk_predicate(self)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
+    #[inline(always)]
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
+    #[inline(always)]
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        ty::Binder::dummy(self).to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for ty::Binder<'tcx, TraitRef<'tcx>> {
+    #[inline(always)]
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
+        pred.to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for ty::Binder<'tcx, TraitRef<'tcx>> {
+    #[inline(always)]
+    fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
+        self.map_bound(|trait_ref| TraitPredicate {
+            trait_ref,
+            constness: ty::BoundConstness::NotConst,
+            polarity: ty::ImplPolarity::Positive,
+        })
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitRef<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
+        ty::Binder::dummy(self).to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx> {
+    fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
+        ty::Binder::dummy(self)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
+    }
+}
+
+impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
+    fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+        PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx)
+    }
+}

From 528e9b5ea32878cc6c8bab88031b13e2d9d4c0cb Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 22:02:16 +0000
Subject: [PATCH 12/38] Move `ty::{ParamEnv, ParamEnvAnd}` to their own little
 module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs       | 223 +--------------------
 compiler/rustc_middle/src/ty/param_env.rs | 231 ++++++++++++++++++++++
 2 files changed, 233 insertions(+), 221 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/param_env.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6dc97c6526554..f77a93a906bb1 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -21,7 +21,6 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
 use crate::mir::{Body, GeneratorLayout};
-use crate::traits::{self, Reveal};
 use crate::ty;
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::util::Discr;
@@ -35,7 +34,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
-use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
@@ -150,11 +148,13 @@ mod typeck_results;
 
 mod bound_constness;
 mod impl_polarity;
+mod param_env;
 mod predicate;
 mod visibility;
 
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
+pub use param_env::{ParamEnv, ParamEnvAnd};
 pub use predicate::{
     CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
     PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
@@ -692,212 +692,6 @@ pub struct BoundConst<'tcx> {
 
 pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
 
-/// When type checking, we use the `ParamEnv` to track
-/// details about the set of where-clauses that are in scope at this
-/// particular point.
-#[derive(Copy, Clone, Hash, PartialEq, Eq)]
-pub struct ParamEnv<'tcx> {
-    /// This packs both caller bounds and the reveal enum into one pointer.
-    ///
-    /// Caller bounds are `Obligation`s that the caller must satisfy. This is
-    /// basically the set of bounds on the in-scope type parameters, translated
-    /// into `Obligation`s, and elaborated and normalized.
-    ///
-    /// Use the `caller_bounds()` method to access.
-    ///
-    /// Typically, this is `Reveal::UserFacing`, but during codegen we
-    /// want `Reveal::All`.
-    ///
-    /// Note: This is packed, use the reveal() method to access it.
-    packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>,
-}
-
-#[derive(Copy, Clone)]
-struct ParamTag {
-    reveal: traits::Reveal,
-    constness: hir::Constness,
-}
-
-impl_tag! {
-    impl Tag for ParamTag;
-    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
-    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::NotConst },
-    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const    },
-    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::Const    },
-}
-
-impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("ParamEnv")
-            .field("caller_bounds", &self.caller_bounds())
-            .field("reveal", &self.reveal())
-            .field("constness", &self.constness())
-            .finish()
-    }
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.caller_bounds().hash_stable(hcx, hasher);
-        self.reveal().hash_stable(hcx, hasher);
-        self.constness().hash_stable(hcx, hasher);
-    }
-}
-
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
-    fn try_fold_with<F: ty::fold::FallibleTypeFolder<TyCtxt<'tcx>>>(
-        self,
-        folder: &mut F,
-    ) -> Result<Self, F::Error> {
-        Ok(ParamEnv::new(
-            self.caller_bounds().try_fold_with(folder)?,
-            self.reveal().try_fold_with(folder)?,
-            self.constness(),
-        ))
-    }
-}
-
-impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.caller_bounds().visit_with(visitor)?;
-        self.reveal().visit_with(visitor)
-    }
-}
-
-impl<'tcx> ParamEnv<'tcx> {
-    /// Construct a trait environment suitable for contexts where
-    /// there are no where-clauses in scope. Hidden types (like `impl
-    /// Trait`) are left hidden, so this is suitable for ordinary
-    /// type-checking.
-    #[inline]
-    pub fn empty() -> Self {
-        Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst)
-    }
-
-    #[inline]
-    pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> {
-        self.packed.pointer()
-    }
-
-    #[inline]
-    pub fn reveal(self) -> traits::Reveal {
-        self.packed.tag().reveal
-    }
-
-    #[inline]
-    pub fn constness(self) -> hir::Constness {
-        self.packed.tag().constness
-    }
-
-    #[inline]
-    pub fn is_const(self) -> bool {
-        self.packed.tag().constness == hir::Constness::Const
-    }
-
-    /// Construct a trait environment with no where-clauses in scope
-    /// where the values of all `impl Trait` and other hidden types
-    /// are revealed. This is suitable for monomorphized, post-typeck
-    /// environments like codegen or doing optimizations.
-    ///
-    /// N.B., if you want to have predicates in scope, use `ParamEnv::new`,
-    /// or invoke `param_env.with_reveal_all()`.
-    #[inline]
-    pub fn reveal_all() -> Self {
-        Self::new(List::empty(), Reveal::All, hir::Constness::NotConst)
-    }
-
-    /// Construct a trait environment with the given set of predicates.
-    #[inline]
-    pub fn new(
-        caller_bounds: &'tcx List<Predicate<'tcx>>,
-        reveal: Reveal,
-        constness: hir::Constness,
-    ) -> Self {
-        ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) }
-    }
-
-    pub fn with_user_facing(mut self) -> Self {
-        self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() });
-        self
-    }
-
-    #[inline]
-    pub fn with_constness(mut self, constness: hir::Constness) -> Self {
-        self.packed.set_tag(ParamTag { constness, ..self.packed.tag() });
-        self
-    }
-
-    #[inline]
-    pub fn with_const(mut self) -> Self {
-        self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() });
-        self
-    }
-
-    #[inline]
-    pub fn without_const(mut self) -> Self {
-        self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() });
-        self
-    }
-
-    #[inline]
-    pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) {
-        *self = self.with_constness(constness.and(self.constness()))
-    }
-
-    /// Returns a new parameter environment with the same clauses, but
-    /// which "reveals" the true results of projections in all cases
-    /// (even for associated types that are specializable). This is
-    /// the desired behavior during codegen and certain other special
-    /// contexts; normally though we want to use `Reveal::UserFacing`,
-    /// which is the default.
-    /// All opaque types in the caller_bounds of the `ParamEnv`
-    /// will be normalized to their underlying types.
-    /// See PR #65989 and issue #65918 for more details
-    pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
-        if self.packed.tag().reveal == traits::Reveal::All {
-            return self;
-        }
-
-        ParamEnv::new(
-            tcx.reveal_opaque_types_in_bounds(self.caller_bounds()),
-            Reveal::All,
-            self.constness(),
-        )
-    }
-
-    /// Returns this same environment but with no caller bounds.
-    #[inline]
-    pub fn without_caller_bounds(self) -> Self {
-        Self::new(List::empty(), self.reveal(), self.constness())
-    }
-
-    /// Creates a suitable environment in which to perform trait
-    /// queries on the given value. When type-checking, this is simply
-    /// the pair of the environment plus value. But when reveal is set to
-    /// All, then if `value` does not reference any type parameters, we will
-    /// pair it with the empty environment. This improves caching and is generally
-    /// invisible.
-    ///
-    /// N.B., we preserve the environment when type-checking because it
-    /// is possible for the user to have wacky where-clauses like
-    /// `where Box<u32>: Copy`, which are clearly never
-    /// satisfiable. We generally want to behave as if they were true,
-    /// although the surrounding function is never reachable.
-    pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
-        match self.reveal() {
-            Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
-
-            Reveal::All => {
-                if value.is_global() {
-                    ParamEnvAnd { param_env: self.without_caller_bounds(), value }
-                } else {
-                    ParamEnvAnd { param_env: self, value }
-                }
-            }
-        }
-    }
-}
-
 // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
 // the constness of trait bounds is being propagated correctly.
 impl<'tcx> PolyTraitRef<'tcx> {
@@ -916,19 +710,6 @@ impl<'tcx> PolyTraitRef<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
-#[derive(HashStable, Lift)]
-pub struct ParamEnvAnd<'tcx, T> {
-    pub param_env: ParamEnv<'tcx>,
-    pub value: T,
-}
-
-impl<'tcx, T> ParamEnvAnd<'tcx, T> {
-    pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
-        (self.param_env, self.value)
-    }
-}
-
 #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
 pub struct Destructor {
     /// The `DefId` of the destructor method
diff --git a/compiler/rustc_middle/src/ty/param_env.rs b/compiler/rustc_middle/src/ty/param_env.rs
new file mode 100644
index 0000000000000..2a41105c7ecab
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/param_env.rs
@@ -0,0 +1,231 @@
+use std::fmt;
+use std::ops::ControlFlow;
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
+use rustc_hir as hir;
+use rustc_query_system::ich::StableHashingContext;
+
+use crate::traits;
+use crate::ty::{
+    self, list::List, Predicate, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+};
+
+/// When type checking, we use the `ParamEnv` to track
+/// details about the set of where-clauses that are in scope at this
+/// particular point.
+#[derive(Copy, Clone, Hash, PartialEq, Eq)]
+pub struct ParamEnv<'tcx> {
+    /// This packs both caller bounds and the reveal enum into one pointer.
+    ///
+    /// Caller bounds are `Obligation`s that the caller must satisfy. This is
+    /// basically the set of bounds on the in-scope type parameters, translated
+    /// into `Obligation`s, and elaborated and normalized.
+    ///
+    /// Use the `caller_bounds()` method to access.
+    ///
+    /// Typically, this is `Reveal::UserFacing`, but during codegen we
+    /// want `Reveal::All`.
+    ///
+    /// Note: This is packed, use the reveal() method to access it.
+    packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
+#[derive(HashStable, Lift)]
+pub struct ParamEnvAnd<'tcx, T> {
+    pub param_env: ParamEnv<'tcx>,
+    pub value: T,
+}
+
+#[derive(Copy, Clone)]
+struct ParamTag {
+    reveal: traits::Reveal,
+    constness: hir::Constness,
+}
+
+impl<'tcx> ParamEnv<'tcx> {
+    /// Construct a trait environment suitable for contexts where
+    /// there are no where-clauses in scope. Hidden types (like `impl
+    /// Trait`) are left hidden, so this is suitable for ordinary
+    /// type-checking.
+    #[inline]
+    pub fn empty() -> Self {
+        Self::new(List::empty(), traits::Reveal::UserFacing, hir::Constness::NotConst)
+    }
+
+    #[inline]
+    pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> {
+        self.packed.pointer()
+    }
+
+    #[inline]
+    pub fn reveal(self) -> traits::Reveal {
+        self.packed.tag().reveal
+    }
+
+    #[inline]
+    pub fn constness(self) -> hir::Constness {
+        self.packed.tag().constness
+    }
+
+    #[inline]
+    pub fn is_const(self) -> bool {
+        self.packed.tag().constness == hir::Constness::Const
+    }
+
+    /// Construct a trait environment with no where-clauses in scope
+    /// where the values of all `impl Trait` and other hidden types
+    /// are revealed. This is suitable for monomorphized, post-typeck
+    /// environments like codegen or doing optimizations.
+    ///
+    /// N.B., if you want to have predicates in scope, use `ParamEnv::new`,
+    /// or invoke `param_env.with_reveal_all()`.
+    #[inline]
+    pub fn reveal_all() -> Self {
+        Self::new(List::empty(), traits::Reveal::All, hir::Constness::NotConst)
+    }
+
+    /// Construct a trait environment with the given set of predicates.
+    #[inline]
+    pub fn new(
+        caller_bounds: &'tcx List<Predicate<'tcx>>,
+        reveal: traits::Reveal,
+        constness: hir::Constness,
+    ) -> Self {
+        ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) }
+    }
+
+    pub fn with_user_facing(mut self) -> Self {
+        self.packed.set_tag(ParamTag { reveal: traits::Reveal::UserFacing, ..self.packed.tag() });
+        self
+    }
+
+    #[inline]
+    pub fn with_constness(mut self, constness: hir::Constness) -> Self {
+        self.packed.set_tag(ParamTag { constness, ..self.packed.tag() });
+        self
+    }
+
+    #[inline]
+    pub fn with_const(mut self) -> Self {
+        self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() });
+        self
+    }
+
+    #[inline]
+    pub fn without_const(mut self) -> Self {
+        self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() });
+        self
+    }
+
+    #[inline]
+    pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) {
+        *self = self.with_constness(constness.and(self.constness()))
+    }
+
+    /// Returns a new parameter environment with the same clauses, but
+    /// which "reveals" the true results of projections in all cases
+    /// (even for associated types that are specializable). This is
+    /// the desired behavior during codegen and certain other special
+    /// contexts; normally though we want to use `Reveal::UserFacing`,
+    /// which is the default.
+    /// All opaque types in the caller_bounds of the `ParamEnv`
+    /// will be normalized to their underlying types.
+    /// See PR #65989 and issue #65918 for more details
+    pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
+        if self.packed.tag().reveal == traits::Reveal::All {
+            return self;
+        }
+
+        ParamEnv::new(
+            tcx.reveal_opaque_types_in_bounds(self.caller_bounds()),
+            traits::Reveal::All,
+            self.constness(),
+        )
+    }
+
+    /// Returns this same environment but with no caller bounds.
+    #[inline]
+    pub fn without_caller_bounds(self) -> Self {
+        Self::new(List::empty(), self.reveal(), self.constness())
+    }
+
+    /// Creates a suitable environment in which to perform trait
+    /// queries on the given value. When type-checking, this is simply
+    /// the pair of the environment plus value. But when reveal is set to
+    /// All, then if `value` does not reference any type parameters, we will
+    /// pair it with the empty environment. This improves caching and is generally
+    /// invisible.
+    ///
+    /// N.B., we preserve the environment when type-checking because it
+    /// is possible for the user to have wacky where-clauses like
+    /// `where Box<u32>: Copy`, which are clearly never
+    /// satisfiable. We generally want to behave as if they were true,
+    /// although the surrounding function is never reachable.
+    pub fn and<T: TypeVisitable<TyCtxt<'tcx>>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
+        match self.reveal() {
+            traits::Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
+
+            traits::Reveal::All => {
+                if value.is_global() {
+                    ParamEnvAnd { param_env: self.without_caller_bounds(), value }
+                } else {
+                    ParamEnvAnd { param_env: self, value }
+                }
+            }
+        }
+    }
+}
+
+impl<'tcx, T> ParamEnvAnd<'tcx, T> {
+    pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
+        (self.param_env, self.value)
+    }
+}
+
+impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("ParamEnv")
+            .field("caller_bounds", &self.caller_bounds())
+            .field("reveal", &self.reveal())
+            .field("constness", &self.constness())
+            .finish()
+    }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        self.caller_bounds().hash_stable(hcx, hasher);
+        self.reveal().hash_stable(hcx, hasher);
+        self.constness().hash_stable(hcx, hasher);
+    }
+}
+
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
+    fn try_fold_with<F: ty::fold::FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(ParamEnv::new(
+            self.caller_bounds().try_fold_with(folder)?,
+            self.reveal().try_fold_with(folder)?,
+            self.constness(),
+        ))
+    }
+}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ParamEnv<'tcx> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.caller_bounds().visit_with(visitor)?;
+        self.reveal().visit_with(visitor)
+    }
+}
+
+impl_tag! {
+    impl Tag for ParamTag;
+    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
+    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::NotConst },
+    ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const    },
+    ParamTag { reveal: traits::Reveal::All,        constness: hir::Constness::Const    },
+}

From 24c89cdc5ae77c4da791329a578d8fbdc0d641f0 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 22:17:53 +0000
Subject: [PATCH 13/38] Move `ty::{Term, TermKind}` to their own little module
 (cute)

---
 compiler/rustc_middle/src/ty/mod.rs  | 162 +------------------------
 compiler/rustc_middle/src/ty/term.rs | 169 +++++++++++++++++++++++++++
 2 files changed, 171 insertions(+), 160 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/term.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index f77a93a906bb1..ead294ec8c34d 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -41,7 +41,6 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
 use rustc_hir::Node;
 use rustc_index::IndexVec;
 use rustc_macros::HashStable;
-use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::{Decodable, Encodable};
 use rustc_session::lint::LintBuffer;
 pub use rustc_session::lint::RegisteredTools;
@@ -56,10 +55,6 @@ pub use vtable::*;
 
 use std::fmt::Debug;
 use std::hash::{Hash, Hasher};
-use std::marker::PhantomData;
-use std::mem;
-use std::num::NonZeroUsize;
-use std::ops::ControlFlow;
 use std::{fmt, str};
 
 pub use crate::ty::diagnostics::*;
@@ -150,6 +145,7 @@ mod bound_constness;
 mod impl_polarity;
 mod param_env;
 mod predicate;
+mod term;
 mod visibility;
 
 pub use bound_constness::BoundConstness;
@@ -161,6 +157,7 @@ pub use predicate::{
     PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
     RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
 };
+pub use term::{Term, TermKind};
 pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
@@ -398,165 +395,10 @@ pub struct CratePredicatesMap<'tcx> {
     pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct Term<'tcx> {
-    ptr: NonZeroUsize,
-    marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
-}
-
-impl Debug for Term<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let data = if let Some(ty) = self.ty() {
-            format!("Term::Ty({:?})", ty)
-        } else if let Some(ct) = self.ct() {
-            format!("Term::Ct({:?})", ct)
-        } else {
-            unreachable!()
-        };
-        f.write_str(&data)
-    }
-}
-
-impl<'tcx> From<Ty<'tcx>> for Term<'tcx> {
-    fn from(ty: Ty<'tcx>) -> Self {
-        TermKind::Ty(ty).pack()
-    }
-}
-
-impl<'tcx> From<Const<'tcx>> for Term<'tcx> {
-    fn from(c: Const<'tcx>) -> Self {
-        TermKind::Const(c).pack()
-    }
-}
-
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        self.unpack().hash_stable(hcx, hasher);
-    }
-}
-
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
-    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
-        self,
-        folder: &mut F,
-    ) -> Result<Self, F::Error> {
-        Ok(self.unpack().try_fold_with(folder)?.pack())
-    }
-}
-
-impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
-    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
-        self.unpack().visit_with(visitor)
-    }
-}
-
-impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Term<'tcx> {
-    fn encode(&self, e: &mut E) {
-        self.unpack().encode(e)
-    }
-}
-
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Term<'tcx> {
-    fn decode(d: &mut D) -> Self {
-        let res: TermKind<'tcx> = Decodable::decode(d);
-        res.pack()
-    }
-}
-
-impl<'tcx> Term<'tcx> {
-    #[inline]
-    pub fn unpack(self) -> TermKind<'tcx> {
-        let ptr = self.ptr.get();
-        // SAFETY: use of `Interned::new_unchecked` here is ok because these
-        // pointers were originally created from `Interned` types in `pack()`,
-        // and this is just going in the other direction.
-        unsafe {
-            match ptr & TAG_MASK {
-                TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
-                    &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
-                ))),
-                CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
-                    &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
-                ))),
-                _ => core::intrinsics::unreachable(),
-            }
-        }
-    }
-
-    pub fn ty(&self) -> Option<Ty<'tcx>> {
-        if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None }
-    }
-
-    pub fn ct(&self) -> Option<Const<'tcx>> {
-        if let TermKind::Const(c) = self.unpack() { Some(c) } else { None }
-    }
-
-    pub fn into_arg(self) -> GenericArg<'tcx> {
-        match self.unpack() {
-            TermKind::Ty(ty) => ty.into(),
-            TermKind::Const(c) => c.into(),
-        }
-    }
-
-    /// This function returns the inner `AliasTy` if this term is a projection.
-    ///
-    /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
-    /// deal with constants.
-    pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
-        match self.unpack() {
-            TermKind::Ty(ty) => match ty.kind() {
-                ty::Alias(kind, alias_ty) => match kind {
-                    AliasKind::Projection => Some(*alias_ty),
-                    AliasKind::Opaque => None,
-                },
-                _ => None,
-            },
-            TermKind::Const(ct) => match ct.kind() {
-                ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)),
-                _ => None,
-            },
-        }
-    }
-
-    pub fn is_infer(&self) -> bool {
-        match self.unpack() {
-            TermKind::Ty(ty) => ty.is_ty_var(),
-            TermKind::Const(ct) => ct.is_ct_infer(),
-        }
-    }
-}
-
 const TAG_MASK: usize = 0b11;
 const TYPE_TAG: usize = 0b00;
 const CONST_TAG: usize = 0b01;
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable)]
-pub enum TermKind<'tcx> {
-    Ty(Ty<'tcx>),
-    Const(Const<'tcx>),
-}
-
-impl<'tcx> TermKind<'tcx> {
-    #[inline]
-    fn pack(self) -> Term<'tcx> {
-        let (tag, ptr) = match self {
-            TermKind::Ty(ty) => {
-                // Ensure we can use the tag bits.
-                assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
-                (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
-            }
-            TermKind::Const(ct) => {
-                // Ensure we can use the tag bits.
-                assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
-                (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
-            }
-        };
-
-        Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData }
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum ParamTerm {
     Ty(ParamTy),
diff --git a/compiler/rustc_middle/src/ty/term.rs b/compiler/rustc_middle/src/ty/term.rs
new file mode 100644
index 0000000000000..4b0ab1930191b
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/term.rs
@@ -0,0 +1,169 @@
+use std::fmt;
+use std::marker::PhantomData;
+use std::mem;
+use std::num::NonZeroUsize;
+use std::ops::ControlFlow;
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_query_system::ich::StableHashingContext;
+
+use crate::ty::{
+    self, AliasKind, AliasTy, Const, ConstKind, Decodable, Encodable, FallibleTypeFolder,
+    GenericArg, Interned, Ty, TyCtxt, TyDecoder, TyEncoder, TypeFoldable, TypeVisitable,
+    TypeVisitor, WithCachedTypeInfo, CONST_TAG, TAG_MASK, TYPE_TAG,
+};
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Term<'tcx> {
+    ptr: NonZeroUsize,
+    marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable)]
+pub enum TermKind<'tcx> {
+    Ty(Ty<'tcx>),
+    Const(Const<'tcx>),
+}
+
+impl<'tcx> Term<'tcx> {
+    #[inline]
+    pub fn unpack(self) -> TermKind<'tcx> {
+        let ptr = self.ptr.get();
+        // SAFETY: use of `Interned::new_unchecked` here is ok because these
+        // pointers were originally created from `Interned` types in `pack()`,
+        // and this is just going in the other direction.
+        unsafe {
+            match ptr & TAG_MASK {
+                TYPE_TAG => TermKind::Ty(Ty(Interned::new_unchecked(
+                    &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>),
+                ))),
+                CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked(
+                    &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
+                ))),
+                _ => core::intrinsics::unreachable(),
+            }
+        }
+    }
+
+    pub fn ty(&self) -> Option<Ty<'tcx>> {
+        if let TermKind::Ty(ty) = self.unpack() { Some(ty) } else { None }
+    }
+
+    pub fn ct(&self) -> Option<Const<'tcx>> {
+        if let TermKind::Const(c) = self.unpack() { Some(c) } else { None }
+    }
+
+    pub fn into_arg(self) -> GenericArg<'tcx> {
+        match self.unpack() {
+            TermKind::Ty(ty) => ty.into(),
+            TermKind::Const(c) => c.into(),
+        }
+    }
+
+    /// This function returns the inner `AliasTy` if this term is a projection.
+    ///
+    /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
+    /// deal with constants.
+    pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+        match self.unpack() {
+            TermKind::Ty(ty) => match ty.kind() {
+                ty::Alias(kind, alias_ty) => match kind {
+                    AliasKind::Projection => Some(*alias_ty),
+                    AliasKind::Opaque => None,
+                },
+                _ => None,
+            },
+            TermKind::Const(ct) => match ct.kind() {
+                ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)),
+                _ => None,
+            },
+        }
+    }
+
+    pub fn is_infer(&self) -> bool {
+        match self.unpack() {
+            TermKind::Ty(ty) => ty.is_ty_var(),
+            TermKind::Const(ct) => ct.is_ct_infer(),
+        }
+    }
+}
+
+impl<'tcx> TermKind<'tcx> {
+    #[inline]
+    pub(super) fn pack(self) -> Term<'tcx> {
+        let (tag, ptr) = match self {
+            TermKind::Ty(ty) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
+                (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
+            }
+            TermKind::Const(ct) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
+                (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
+            }
+        };
+
+        Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData }
+    }
+}
+
+impl fmt::Debug for Term<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let data = if let Some(ty) = self.ty() {
+            format!("Term::Ty({:?})", ty)
+        } else if let Some(ct) = self.ct() {
+            format!("Term::Ct({:?})", ct)
+        } else {
+            unreachable!()
+        };
+        f.write_str(&data)
+    }
+}
+
+impl<'tcx> From<Ty<'tcx>> for Term<'tcx> {
+    fn from(ty: Ty<'tcx>) -> Self {
+        TermKind::Ty(ty).pack()
+    }
+}
+
+impl<'tcx> From<Const<'tcx>> for Term<'tcx> {
+    fn from(c: Const<'tcx>) -> Self {
+        TermKind::Const(c).pack()
+    }
+}
+
+impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Term<'tcx> {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        self.unpack().hash_stable(hcx, hasher);
+    }
+}
+
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
+    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(self.unpack().try_fold_with(folder)?.pack())
+    }
+}
+
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {
+    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        self.unpack().visit_with(visitor)
+    }
+}
+
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Term<'tcx> {
+    fn encode(&self, e: &mut E) {
+        self.unpack().encode(e)
+    }
+}
+
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Term<'tcx> {
+    fn decode(d: &mut D) -> Self {
+        let res: TermKind<'tcx> = Decodable::decode(d);
+        res.pack()
+    }
+}

From 79f92ae2da0bdfab1f4fcf1f0c6cb45fa19a6c65 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 22:28:17 +0000
Subject: [PATCH 14/38] Move `ty::Ty` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs | 8 ++------
 compiler/rustc_middle/src/ty/ty_.rs | 9 +++++++++
 2 files changed, 11 insertions(+), 6 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/ty_.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index ead294ec8c34d..c767b1cbdbe28 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -146,6 +146,7 @@ mod impl_polarity;
 mod param_env;
 mod predicate;
 mod term;
+mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
 mod visibility;
 
 pub use bound_constness::BoundConstness;
@@ -158,6 +159,7 @@ pub use predicate::{
     RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
 };
 pub use term::{Term, TermKind};
+pub use ty_::Ty;
 pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
@@ -326,12 +328,6 @@ pub struct CReaderCacheKey {
     pub pos: usize,
 }
 
-/// Use this rather than `TyKind`, whenever possible.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
-#[rustc_diagnostic_item = "Ty"]
-#[rustc_pass_by_value]
-pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
-
 impl ty::EarlyBoundRegion {
     /// Does this early bound region have a name? Early bound regions normally
     /// always have names except when using anonymous lifetimes (`'_`).
diff --git a/compiler/rustc_middle/src/ty/ty_.rs b/compiler/rustc_middle/src/ty/ty_.rs
new file mode 100644
index 0000000000000..50e9712966ae3
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/ty_.rs
@@ -0,0 +1,9 @@
+use crate::ty::{Interned, TyKind, WithCachedTypeInfo};
+
+/// Use this rather than `TyKind`, whenever possible.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
+#[rustc_diagnostic_item = "Ty"]
+#[rustc_pass_by_value]
+pub struct Ty<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
+
+// FIXME: move `Ty` inherent impls here (and possibly change structure wrt `sty` mod)

From a409b9848cdece7852aabd897f5916f847991506 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 22:30:46 +0000
Subject: [PATCH 15/38] Move `ty::AliasRelationDirection` to its own little
 module (cute)

---
 .../src/ty/alias_relation_direction.rs         | 17 +++++++++++++++++
 compiler/rustc_middle/src/ty/mod.rs            | 18 ++----------------
 2 files changed, 19 insertions(+), 16 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/alias_relation_direction.rs

diff --git a/compiler/rustc_middle/src/ty/alias_relation_direction.rs b/compiler/rustc_middle/src/ty/alias_relation_direction.rs
new file mode 100644
index 0000000000000..35fb40a32eb9c
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/alias_relation_direction.rs
@@ -0,0 +1,17 @@
+use std::fmt;
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, Debug)]
+pub enum AliasRelationDirection {
+    Equate,
+    Subtype,
+}
+
+impl fmt::Display for AliasRelationDirection {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            AliasRelationDirection::Equate => write!(f, "=="),
+            AliasRelationDirection::Subtype => write!(f, "<:"),
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c767b1cbdbe28..d7eb481e3e568 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -141,6 +141,7 @@ mod structural_impls;
 mod sty;
 mod typeck_results;
 
+mod alias_relation_direction;
 mod bound_constness;
 mod impl_polarity;
 mod param_env;
@@ -149,6 +150,7 @@ mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
 mod visibility;
 
+pub use alias_relation_direction::AliasRelationDirection;
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
 pub use param_env::{ParamEnv, ParamEnvAnd};
@@ -361,22 +363,6 @@ pub enum Clause<'tcx> {
     ConstArgHasType(Const<'tcx>, Ty<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, Debug)]
-pub enum AliasRelationDirection {
-    Equate,
-    Subtype,
-}
-
-impl std::fmt::Display for AliasRelationDirection {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match self {
-            AliasRelationDirection::Equate => write!(f, "=="),
-            AliasRelationDirection::Subtype => write!(f, "<:"),
-        }
-    }
-}
-
 /// The crate outlives map is computed during typeck and contains the
 /// outlives of every item in the local crate. You should not use it
 /// directly, because to do so will make your pass dependent on the

From 29a7901c404d6bc24bd74c2793a9feb02f3e3808 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 22:38:14 +0000
Subject: [PATCH 16/38] Move `ty::OpaqueHiddenType` to its own little module
 (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 85 +-----------------
 .../rustc_middle/src/ty/opaque_hidden_type.rs | 87 +++++++++++++++++++
 2 files changed, 90 insertions(+), 82 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/opaque_hidden_type.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index d7eb481e3e568..6374649f214d6 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -17,7 +17,7 @@ pub use self::AssocItemContainer::*;
 pub use self::BorrowKind::*;
 pub use self::IntVarValue::*;
 pub use self::Variance::*;
-use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
+use crate::error::TypeMismatchReason;
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
 use crate::mir::{Body, GeneratorLayout};
@@ -34,7 +34,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
@@ -144,6 +143,7 @@ mod typeck_results;
 mod alias_relation_direction;
 mod bound_constness;
 mod impl_polarity;
+mod opaque_hidden_type;
 mod param_env;
 mod predicate;
 mod term;
@@ -153,6 +153,7 @@ mod visibility;
 pub use alias_relation_direction::AliasRelationDirection;
 pub use bound_constness::BoundConstness;
 pub use impl_polarity::ImplPolarity;
+pub use opaque_hidden_type::OpaqueHiddenType;
 pub use param_env::{ParamEnv, ParamEnvAnd};
 pub use predicate::{
     CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
@@ -412,86 +413,6 @@ pub struct OpaqueTypeKey<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
 
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
-pub struct OpaqueHiddenType<'tcx> {
-    /// The span of this particular definition of the opaque type. So
-    /// for example:
-    ///
-    /// ```ignore (incomplete snippet)
-    /// type Foo = impl Baz;
-    /// fn bar() -> Foo {
-    /// //          ^^^ This is the span we are looking for!
-    /// }
-    /// ```
-    ///
-    /// In cases where the fn returns `(impl Trait, impl Trait)` or
-    /// other such combinations, the result is currently
-    /// over-approximated, but better than nothing.
-    pub span: Span,
-
-    /// The type variable that represents the value of the opaque type
-    /// that we require. In other words, after we compile this function,
-    /// we will be created a constraint like:
-    /// ```ignore (pseudo-rust)
-    /// Foo<'a, T> = ?C
-    /// ```
-    /// where `?C` is the value of this type variable. =) It may
-    /// naturally refer to the type and lifetime parameters in scope
-    /// in this function, though ultimately it should only reference
-    /// those that are arguments to `Foo` in the constraint above. (In
-    /// other words, `?C` should not include `'b`, even though it's a
-    /// lifetime parameter on `foo`.)
-    pub ty: Ty<'tcx>,
-}
-
-impl<'tcx> OpaqueHiddenType<'tcx> {
-    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
-        // Found different concrete types for the opaque type.
-        let sub_diag = if self.span == other.span {
-            TypeMismatchReason::ConflictType { span: self.span }
-        } else {
-            TypeMismatchReason::PreviousUse { span: self.span }
-        };
-        tcx.sess.emit_err(OpaqueHiddenTypeMismatch {
-            self_ty: self.ty,
-            other_ty: other.ty,
-            other_span: other.span,
-            sub: sub_diag,
-        })
-    }
-
-    #[instrument(level = "debug", skip(tcx), ret)]
-    pub fn remap_generic_params_to_declaration_params(
-        self,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        tcx: TyCtxt<'tcx>,
-        // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
-        ignore_errors: bool,
-    ) -> Self {
-        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
-        // Use substs to build up a reverse map from regions to their
-        // identity mappings. This is necessary because of `impl
-        // Trait` lifetimes are computed by replacing existing
-        // lifetimes with 'static and remapping only those used in the
-        // `impl Trait` return type, resulting in the parameters
-        // shifting.
-        let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
-        debug!(?id_substs);
-
-        // This zip may have several times the same lifetime in `substs` paired with a different
-        // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
-        // it will pick the last one, which is the one we introduced in the impl-trait desugaring.
-        let map = substs.iter().zip(id_substs).collect();
-        debug!("map = {:#?}", map);
-
-        // Convert the type from the function into a type valid outside
-        // the function, by replacing invalid regions with 'static,
-        // after producing an error for each of them.
-        self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors))
-    }
-}
-
 /// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
 /// identified by both a universe, as well as a name residing within that universe. Distinct bound
 /// regions/types/consts within the same universe simply have an unknown relationship to one
diff --git a/compiler/rustc_middle/src/ty/opaque_hidden_type.rs b/compiler/rustc_middle/src/ty/opaque_hidden_type.rs
new file mode 100644
index 0000000000000..db9aec621d21c
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/opaque_hidden_type.rs
@@ -0,0 +1,87 @@
+use rustc_errors::ErrorGuaranteed;
+use rustc_span::Span;
+
+use crate::error::OpaqueHiddenTypeMismatch;
+use crate::ty::{
+    opaque_types, InternalSubsts, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeMismatchReason,
+};
+
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
+pub struct OpaqueHiddenType<'tcx> {
+    /// The span of this particular definition of the opaque type. So
+    /// for example:
+    ///
+    /// ```ignore (incomplete snippet)
+    /// type Foo = impl Baz;
+    /// fn bar() -> Foo {
+    /// //          ^^^ This is the span we are looking for!
+    /// }
+    /// ```
+    ///
+    /// In cases where the fn returns `(impl Trait, impl Trait)` or
+    /// other such combinations, the result is currently
+    /// over-approximated, but better than nothing.
+    pub span: Span,
+
+    /// The type variable that represents the value of the opaque type
+    /// that we require. In other words, after we compile this function,
+    /// we will be created a constraint like:
+    /// ```ignore (pseudo-rust)
+    /// Foo<'a, T> = ?C
+    /// ```
+    /// where `?C` is the value of this type variable. =) It may
+    /// naturally refer to the type and lifetime parameters in scope
+    /// in this function, though ultimately it should only reference
+    /// those that are arguments to `Foo` in the constraint above. (In
+    /// other words, `?C` should not include `'b`, even though it's a
+    /// lifetime parameter on `foo`.)
+    pub ty: Ty<'tcx>,
+}
+
+impl<'tcx> OpaqueHiddenType<'tcx> {
+    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
+        // Found different concrete types for the opaque type.
+        let sub_diag = if self.span == other.span {
+            TypeMismatchReason::ConflictType { span: self.span }
+        } else {
+            TypeMismatchReason::PreviousUse { span: self.span }
+        };
+        tcx.sess.emit_err(OpaqueHiddenTypeMismatch {
+            self_ty: self.ty,
+            other_ty: other.ty,
+            other_span: other.span,
+            sub: sub_diag,
+        })
+    }
+
+    #[instrument(level = "debug", skip(tcx), ret)]
+    pub fn remap_generic_params_to_declaration_params(
+        self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        tcx: TyCtxt<'tcx>,
+        // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
+        ignore_errors: bool,
+    ) -> Self {
+        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+
+        // Use substs to build up a reverse map from regions to their
+        // identity mappings. This is necessary because of `impl
+        // Trait` lifetimes are computed by replacing existing
+        // lifetimes with 'static and remapping only those used in the
+        // `impl Trait` return type, resulting in the parameters
+        // shifting.
+        let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
+        debug!(?id_substs);
+
+        // This zip may have several times the same lifetime in `substs` paired with a different
+        // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
+        // it will pick the last one, which is the one we introduced in the impl-trait desugaring.
+        let map = substs.iter().zip(id_substs).collect();
+        debug!("map = {:#?}", map);
+
+        // Convert the type from the function into a type valid outside
+        // the function, by replacing invalid regions with 'static,
+        // after producing an error for each of them.
+        self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors))
+    }
+}

From 71e0bb40d11cb4348c879d1ec97e5d4e7a407ebc Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 22:46:37 +0000
Subject: [PATCH 17/38] Move `ty::VariantDef` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs         | 138 +------------------
 compiler/rustc_middle/src/ty/variant_def.rs | 143 ++++++++++++++++++++
 2 files changed, 145 insertions(+), 136 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/variant_def.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6374649f214d6..7adea58b00adc 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -148,6 +148,7 @@ mod param_env;
 mod predicate;
 mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
+mod variant_def;
 mod visibility;
 
 pub use alias_relation_direction::AliasRelationDirection;
@@ -163,6 +164,7 @@ pub use predicate::{
 };
 pub use term::{Term, TermKind};
 pub use ty_::Ty;
+pub use variant_def::VariantDef;
 pub use visibility::Visibility;
 
 pub struct ResolverOutputs {
@@ -475,142 +477,6 @@ bitflags! {
     }
 }
 
-/// Definition of a variant -- a struct's fields or an enum variant.
-#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
-pub struct VariantDef {
-    /// `DefId` that identifies the variant itself.
-    /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
-    pub def_id: DefId,
-    /// `DefId` that identifies the variant's constructor.
-    /// If this variant is a struct variant, then this is `None`.
-    pub ctor: Option<(CtorKind, DefId)>,
-    /// Variant or struct name.
-    pub name: Symbol,
-    /// Discriminant of this variant.
-    pub discr: VariantDiscr,
-    /// Fields of this variant.
-    pub fields: IndexVec<FieldIdx, FieldDef>,
-    /// Flags of the variant (e.g. is field list non-exhaustive)?
-    flags: VariantFlags,
-}
-
-impl VariantDef {
-    /// Creates a new `VariantDef`.
-    ///
-    /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
-    /// represents an enum variant).
-    ///
-    /// `ctor_did` is the `DefId` that identifies the constructor of unit or
-    /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`.
-    ///
-    /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that
-    /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having
-    /// to go through the redirect of checking the ctor's attributes - but compiling a small crate
-    /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
-    /// built-in trait), and we do not want to load attributes twice.
-    ///
-    /// If someone speeds up attribute loading to not be a performance concern, they can
-    /// remove this hack and use the constructor `DefId` everywhere.
-    pub fn new(
-        name: Symbol,
-        variant_did: Option<DefId>,
-        ctor: Option<(CtorKind, DefId)>,
-        discr: VariantDiscr,
-        fields: IndexVec<FieldIdx, FieldDef>,
-        adt_kind: AdtKind,
-        parent_did: DefId,
-        recovered: bool,
-        is_field_list_non_exhaustive: bool,
-    ) -> Self {
-        debug!(
-            "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
-             fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
-            name, variant_did, ctor, discr, fields, adt_kind, parent_did,
-        );
-
-        let mut flags = VariantFlags::NO_VARIANT_FLAGS;
-        if is_field_list_non_exhaustive {
-            flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
-        }
-
-        if recovered {
-            flags |= VariantFlags::IS_RECOVERED;
-        }
-
-        VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
-    }
-
-    /// Is this field list non-exhaustive?
-    #[inline]
-    pub fn is_field_list_non_exhaustive(&self) -> bool {
-        self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
-    }
-
-    /// Was this variant obtained as part of recovering from a syntactic error?
-    #[inline]
-    pub fn is_recovered(&self) -> bool {
-        self.flags.intersects(VariantFlags::IS_RECOVERED)
-    }
-
-    /// Computes the `Ident` of this variant by looking up the `Span`
-    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
-        Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
-    }
-
-    #[inline]
-    pub fn ctor_kind(&self) -> Option<CtorKind> {
-        self.ctor.map(|(kind, _)| kind)
-    }
-
-    #[inline]
-    pub fn ctor_def_id(&self) -> Option<DefId> {
-        self.ctor.map(|(_, def_id)| def_id)
-    }
-
-    /// Returns the one field in this variant.
-    ///
-    /// `panic!`s if there are no fields or multiple fields.
-    #[inline]
-    pub fn single_field(&self) -> &FieldDef {
-        assert!(self.fields.len() == 1);
-
-        &self.fields[FieldIdx::from_u32(0)]
-    }
-}
-
-impl PartialEq for VariantDef {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        // There should be only one `VariantDef` for each `def_id`, therefore
-        // it is fine to implement `PartialEq` only based on `def_id`.
-        //
-        // Below, we exhaustively destructure `self` and `other` so that if the
-        // definition of `VariantDef` changes, a compile-error will be produced,
-        // reminding us to revisit this assumption.
-
-        let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
-        let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
-        lhs_def_id == rhs_def_id
-    }
-}
-
-impl Eq for VariantDef {}
-
-impl Hash for VariantDef {
-    #[inline]
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        // There should be only one `VariantDef` for each `def_id`, therefore
-        // it is fine to implement `Hash` only based on `def_id`.
-        //
-        // Below, we exhaustively destructure `self` so that if the definition
-        // of `VariantDef` changes, a compile-error will be produced, reminding
-        // us to revisit this assumption.
-
-        let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
-        def_id.hash(s)
-    }
-}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum VariantDiscr {
     /// Explicit value for this variant, i.e., `X = 123`.
diff --git a/compiler/rustc_middle/src/ty/variant_def.rs b/compiler/rustc_middle/src/ty/variant_def.rs
new file mode 100644
index 0000000000000..e05eddc10af5e
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/variant_def.rs
@@ -0,0 +1,143 @@
+use std::hash::{Hash, Hasher};
+
+use rustc_hir::def_id::DefId;
+use rustc_index::IndexVec;
+use rustc_span::symbol::{Ident, Symbol};
+
+use crate::ty::{AdtKind, CtorKind, FieldDef, FieldIdx, TyCtxt, VariantDiscr, VariantFlags};
+
+/// Definition of a variant -- a struct's fields or an enum variant.
+#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
+pub struct VariantDef {
+    /// `DefId` that identifies the variant itself.
+    /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
+    pub def_id: DefId,
+    /// `DefId` that identifies the variant's constructor.
+    /// If this variant is a struct variant, then this is `None`.
+    pub ctor: Option<(CtorKind, DefId)>,
+    /// Variant or struct name.
+    pub name: Symbol,
+    /// Discriminant of this variant.
+    pub discr: VariantDiscr,
+    /// Fields of this variant.
+    pub fields: IndexVec<FieldIdx, FieldDef>,
+    /// Flags of the variant (e.g. is field list non-exhaustive)?
+    flags: VariantFlags,
+}
+
+impl VariantDef {
+    /// Creates a new `VariantDef`.
+    ///
+    /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
+    /// represents an enum variant).
+    ///
+    /// `ctor_did` is the `DefId` that identifies the constructor of unit or
+    /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`.
+    ///
+    /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that
+    /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having
+    /// to go through the redirect of checking the ctor's attributes - but compiling a small crate
+    /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
+    /// built-in trait), and we do not want to load attributes twice.
+    ///
+    /// If someone speeds up attribute loading to not be a performance concern, they can
+    /// remove this hack and use the constructor `DefId` everywhere.
+    pub fn new(
+        name: Symbol,
+        variant_did: Option<DefId>,
+        ctor: Option<(CtorKind, DefId)>,
+        discr: VariantDiscr,
+        fields: IndexVec<FieldIdx, FieldDef>,
+        adt_kind: AdtKind,
+        parent_did: DefId,
+        recovered: bool,
+        is_field_list_non_exhaustive: bool,
+    ) -> Self {
+        debug!(
+            "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
+             fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
+            name, variant_did, ctor, discr, fields, adt_kind, parent_did,
+        );
+
+        let mut flags = VariantFlags::NO_VARIANT_FLAGS;
+        if is_field_list_non_exhaustive {
+            flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
+        }
+
+        if recovered {
+            flags |= VariantFlags::IS_RECOVERED;
+        }
+
+        VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
+    }
+
+    /// Is this field list non-exhaustive?
+    #[inline]
+    pub fn is_field_list_non_exhaustive(&self) -> bool {
+        self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
+    }
+
+    /// Was this variant obtained as part of recovering from a syntactic error?
+    #[inline]
+    pub fn is_recovered(&self) -> bool {
+        self.flags.intersects(VariantFlags::IS_RECOVERED)
+    }
+
+    /// Computes the `Ident` of this variant by looking up the `Span`
+    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
+        Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
+    }
+
+    #[inline]
+    pub fn ctor_kind(&self) -> Option<CtorKind> {
+        self.ctor.map(|(kind, _)| kind)
+    }
+
+    #[inline]
+    pub fn ctor_def_id(&self) -> Option<DefId> {
+        self.ctor.map(|(_, def_id)| def_id)
+    }
+
+    /// Returns the one field in this variant.
+    ///
+    /// `panic!`s if there are no fields or multiple fields.
+    #[inline]
+    pub fn single_field(&self) -> &FieldDef {
+        assert!(self.fields.len() == 1);
+
+        &self.fields[FieldIdx::from_u32(0)]
+    }
+}
+
+impl PartialEq for VariantDef {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        // There should be only one `VariantDef` for each `def_id`, therefore
+        // it is fine to implement `PartialEq` only based on `def_id`.
+        //
+        // Below, we exhaustively destructure `self` and `other` so that if the
+        // definition of `VariantDef` changes, a compile-error will be produced,
+        // reminding us to revisit this assumption.
+
+        let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
+        let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
+        lhs_def_id == rhs_def_id
+    }
+}
+
+impl Eq for VariantDef {}
+
+impl Hash for VariantDef {
+    #[inline]
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        // There should be only one `VariantDef` for each `def_id`, therefore
+        // it is fine to implement `Hash` only based on `def_id`.
+        //
+        // Below, we exhaustively destructure `self` so that if the definition
+        // of `VariantDef` changes, a compile-error will be produced, reminding
+        // us to revisit this assumption.
+
+        let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
+        def_id.hash(s)
+    }
+}

From 8be9b84bb3b8847560227ca09aeabb824740cf34 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:00:35 +0000
Subject: [PATCH 18/38] Move `ty::FieldDef` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/field_def.rs | 64 +++++++++++++++++++++++
 compiler/rustc_middle/src/ty/mod.rs       | 60 ++-------------------
 2 files changed, 67 insertions(+), 57 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/field_def.rs

diff --git a/compiler/rustc_middle/src/ty/field_def.rs b/compiler/rustc_middle/src/ty/field_def.rs
new file mode 100644
index 0000000000000..638123e290d70
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/field_def.rs
@@ -0,0 +1,64 @@
+use std::hash::{Hash, Hasher};
+
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::{Ident, Symbol};
+
+use crate::ty::{SubstsRef, Ty, TyCtxt, Visibility};
+
+#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
+pub struct FieldDef {
+    pub did: DefId,
+    pub name: Symbol,
+    pub vis: Visibility<DefId>,
+}
+
+impl PartialEq for FieldDef {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        // There should be only one `FieldDef` for each `did`, therefore it is
+        // fine to implement `PartialEq` only based on `did`.
+        //
+        // Below, we exhaustively destructure `self` so that if the definition
+        // of `FieldDef` changes, a compile-error will be produced, reminding
+        // us to revisit this assumption.
+
+        let Self { did: lhs_did, name: _, vis: _ } = &self;
+
+        let Self { did: rhs_did, name: _, vis: _ } = other;
+
+        lhs_did == rhs_did
+    }
+}
+
+impl Eq for FieldDef {}
+
+impl Hash for FieldDef {
+    #[inline]
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        // There should be only one `FieldDef` for each `did`, therefore it is
+        // fine to implement `Hash` only based on `did`.
+        //
+        // Below, we exhaustively destructure `self` so that if the definition
+        // of `FieldDef` changes, a compile-error will be produced, reminding
+        // us to revisit this assumption.
+
+        let Self { did, name: _, vis: _ } = &self;
+
+        did.hash(s)
+    }
+}
+
+impl<'tcx> FieldDef {
+    /// Returns the type of this field. The resulting type is not normalized. The `subst` is
+    /// typically obtained via the second field of [`TyKind::Adt`].
+    ///
+    /// [`TyKind::Adt`]: crate::ty::TyKind::Adt
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
+        tcx.type_of(self.did).subst(tcx, subst)
+    }
+
+    /// Computes the `Ident` of this variant by looking up the `Span`
+    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
+        Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7adea58b00adc..367c0e1553e18 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -53,7 +53,7 @@ pub use subst::*;
 pub use vtable::*;
 
 use std::fmt::Debug;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 use std::{fmt, str};
 
 pub use crate::ty::diagnostics::*;
@@ -142,6 +142,7 @@ mod typeck_results;
 
 mod alias_relation_direction;
 mod bound_constness;
+mod field_def;
 mod impl_polarity;
 mod opaque_hidden_type;
 mod param_env;
@@ -153,6 +154,7 @@ mod visibility;
 
 pub use alias_relation_direction::AliasRelationDirection;
 pub use bound_constness::BoundConstness;
+pub use field_def::FieldDef;
 pub use impl_polarity::ImplPolarity;
 pub use opaque_hidden_type::OpaqueHiddenType;
 pub use param_env::{ParamEnv, ParamEnvAnd};
@@ -490,62 +492,6 @@ pub enum VariantDiscr {
     Relative(u32),
 }
 
-#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
-pub struct FieldDef {
-    pub did: DefId,
-    pub name: Symbol,
-    pub vis: Visibility<DefId>,
-}
-
-impl PartialEq for FieldDef {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        // There should be only one `FieldDef` for each `did`, therefore it is
-        // fine to implement `PartialEq` only based on `did`.
-        //
-        // Below, we exhaustively destructure `self` so that if the definition
-        // of `FieldDef` changes, a compile-error will be produced, reminding
-        // us to revisit this assumption.
-
-        let Self { did: lhs_did, name: _, vis: _ } = &self;
-
-        let Self { did: rhs_did, name: _, vis: _ } = other;
-
-        lhs_did == rhs_did
-    }
-}
-
-impl Eq for FieldDef {}
-
-impl Hash for FieldDef {
-    #[inline]
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        // There should be only one `FieldDef` for each `did`, therefore it is
-        // fine to implement `Hash` only based on `did`.
-        //
-        // Below, we exhaustively destructure `self` so that if the definition
-        // of `FieldDef` changes, a compile-error will be produced, reminding
-        // us to revisit this assumption.
-
-        let Self { did, name: _, vis: _ } = &self;
-
-        did.hash(s)
-    }
-}
-
-impl<'tcx> FieldDef {
-    /// Returns the type of this field. The resulting type is not normalized. The `subst` is
-    /// typically obtained via the second field of [`TyKind::Adt`].
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
-        tcx.type_of(self.did).subst(tcx, subst)
-    }
-
-    /// Computes the `Ident` of this variant by looking up the `Span`
-    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
-        Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
-    }
-}
-
 #[derive(Debug, PartialEq, Eq)]
 pub enum ImplOverlapKind {
     /// These impls are always allowed to overlap.

From cacaab652172937c61e54de4f43be74a7b6e4487 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:03:36 +0000
Subject: [PATCH 19/38] Move `ty::{Placeholder, PlaceholderConst,
 PlaceholderRegion, PlaceholderType}` to their own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs         | 19 ++-----------------
 compiler/rustc_middle/src/ty/placeholder.rs | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+), 17 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/placeholder.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 367c0e1553e18..c870226b6e4c7 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -146,6 +146,7 @@ mod field_def;
 mod impl_polarity;
 mod opaque_hidden_type;
 mod param_env;
+mod placeholder;
 mod predicate;
 mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
@@ -158,6 +159,7 @@ pub use field_def::FieldDef;
 pub use impl_polarity::ImplPolarity;
 pub use opaque_hidden_type::OpaqueHiddenType;
 pub use param_env::{ParamEnv, ParamEnvAnd};
+pub use placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
 pub use predicate::{
     CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
     PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
@@ -417,21 +419,6 @@ pub struct OpaqueTypeKey<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
 
-/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
-/// identified by both a universe, as well as a name residing within that universe. Distinct bound
-/// regions/types/consts within the same universe simply have an unknown relationship to one
-/// another.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-#[derive(HashStable, TyEncodable, TyDecodable)]
-pub struct Placeholder<T> {
-    pub universe: UniverseIndex,
-    pub bound: T,
-}
-
-pub type PlaceholderRegion = Placeholder<BoundRegion>;
-
-pub type PlaceholderType = Placeholder<BoundTy>;
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
 #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
 pub struct BoundConst<'tcx> {
@@ -439,8 +426,6 @@ pub struct BoundConst<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
-pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
-
 // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
 // the constness of trait bounds is being propagated correctly.
 impl<'tcx> PolyTraitRef<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/placeholder.rs b/compiler/rustc_middle/src/ty/placeholder.rs
new file mode 100644
index 0000000000000..d5f25c0afa7f4
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/placeholder.rs
@@ -0,0 +1,18 @@
+use crate::ty::{BoundRegion, BoundTy, BoundVar, UniverseIndex};
+
+pub type PlaceholderRegion = Placeholder<BoundRegion>;
+
+pub type PlaceholderType = Placeholder<BoundTy>;
+
+pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
+
+/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
+/// identified by both a universe, as well as a name residing within that universe. Distinct bound
+/// regions/types/consts within the same universe simply have an unknown relationship to one
+/// another.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(HashStable, TyEncodable, TyDecodable)]
+pub struct Placeholder<T> {
+    pub universe: UniverseIndex,
+    pub bound: T,
+}

From 3c0e0cee9124402fd940256afe77df8f01a35957 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:07:59 +0000
Subject: [PATCH 20/38] Move `ty::SymbolName` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs         | 29 ++-------------------
 compiler/rustc_middle/src/ty/symbol_name.rs | 29 +++++++++++++++++++++
 2 files changed, 31 insertions(+), 27 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/symbol_name.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c870226b6e4c7..0d062d279e47b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -54,7 +54,6 @@ pub use vtable::*;
 
 use std::fmt::Debug;
 use std::hash::Hash;
-use std::{fmt, str};
 
 pub use crate::ty::diagnostics::*;
 pub use rustc_type_ir::AliasKind::*;
@@ -148,6 +147,7 @@ mod opaque_hidden_type;
 mod param_env;
 mod placeholder;
 mod predicate;
+mod symbol_name;
 mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
 mod variant_def;
@@ -166,6 +166,7 @@ pub use predicate::{
     PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
     RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
 };
+pub use symbol_name::SymbolName;
 pub use term::{Term, TermKind};
 pub use ty_::Ty;
 pub use variant_def::VariantDef;
@@ -1130,32 +1131,6 @@ pub struct CrateInherentImpls {
     pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
-pub struct SymbolName<'tcx> {
-    /// `&str` gives a consistent ordering, which ensures reproducible builds.
-    pub name: &'tcx str,
-}
-
-impl<'tcx> SymbolName<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> {
-        SymbolName {
-            name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) },
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for SymbolName<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.name, fmt)
-    }
-}
-
-impl<'tcx> fmt::Debug for SymbolName<'tcx> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.name, fmt)
-    }
-}
-
 #[derive(Debug, Default, Copy, Clone)]
 pub struct InferVarInfo {
     /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
diff --git a/compiler/rustc_middle/src/ty/symbol_name.rs b/compiler/rustc_middle/src/ty/symbol_name.rs
new file mode 100644
index 0000000000000..4024f283d6c0c
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/symbol_name.rs
@@ -0,0 +1,29 @@
+use std::{fmt, str};
+
+use crate::ty::TyCtxt;
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
+pub struct SymbolName<'tcx> {
+    /// `&str` gives a consistent ordering, which ensures reproducible builds.
+    pub name: &'tcx str,
+}
+
+impl<'tcx> SymbolName<'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, name: &str) -> SymbolName<'tcx> {
+        SymbolName {
+            name: unsafe { str::from_utf8_unchecked(tcx.arena.alloc_slice(name.as_bytes())) },
+        }
+    }
+}
+
+impl<'tcx> fmt::Display for SymbolName<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.name, fmt)
+    }
+}
+
+impl<'tcx> fmt::Debug for SymbolName<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.name, fmt)
+    }
+}

From 0810f8833c53b481af2883db902af545f628936f Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:14:36 +0000
Subject: [PATCH 21/38] Move/merge impls out of `ty/mod.rs`

---
 compiler/rustc_middle/src/ty/mod.rs | 28 +---------------------------
 compiler/rustc_middle/src/ty/sty.rs | 26 +++++++++++++++++++++++++-
 2 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 0d062d279e47b..4b67ae6a54efc 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -44,7 +44,7 @@ use rustc_serialize::{Decodable, Encodable};
 use rustc_session::lint::LintBuffer;
 pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
@@ -338,14 +338,6 @@ pub struct CReaderCacheKey {
     pub pos: usize,
 }
 
-impl ty::EarlyBoundRegion {
-    /// Does this early bound region have a name? Early bound regions normally
-    /// always have names except when using anonymous lifetimes (`'_`).
-    pub fn has_name(&self) -> bool {
-        self.name != kw::UnderscoreLifetime && self.name != kw::Empty
-    }
-}
-
 #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 /// A clause is something that can appear in where bounds or be inferred
@@ -427,24 +419,6 @@ pub struct BoundConst<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
-// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
-// the constness of trait bounds is being propagated correctly.
-impl<'tcx> PolyTraitRef<'tcx> {
-    #[inline]
-    pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> {
-        self.map_bound(|trait_ref| ty::TraitPredicate {
-            trait_ref,
-            constness,
-            polarity: ty::ImplPolarity::Positive,
-        })
-    }
-
-    #[inline]
-    pub fn without_const(self) -> PolyTraitPredicate<'tcx> {
-        self.with_constness(BoundConstness::NotConst)
-    }
-}
-
 #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
 pub struct Destructor {
     /// The `DefId` of the destructor method
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 646384eebc888..e9dcb787735bf 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -5,11 +5,11 @@
 use crate::infer::canonical::Canonical;
 use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use crate::ty::visit::ValidateBoundVars;
-use crate::ty::InferTy::*;
 use crate::ty::{
     self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
     TypeVisitableExt, TypeVisitor,
 };
+use crate::ty::{BoundConstness, InferTy::*, PolyTraitPredicate};
 use crate::ty::{List, ParamEnv};
 use hir::def::DefKind;
 use polonius_engine::Atom;
@@ -895,6 +895,22 @@ impl<'tcx> PolyTraitRef<'tcx> {
     pub fn def_id(&self) -> DefId {
         self.skip_binder().def_id
     }
+
+    #[inline]
+    pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> {
+        self.map_bound(|trait_ref| ty::TraitPredicate {
+            trait_ref,
+            constness,
+            polarity: ty::ImplPolarity::Positive,
+        })
+    }
+
+    // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
+    // the constness of trait bounds is being propagated correctly.
+    #[inline]
+    pub fn without_const(self) -> PolyTraitPredicate<'tcx> {
+        self.with_constness(BoundConstness::NotConst)
+    }
 }
 
 impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> {
@@ -1451,6 +1467,14 @@ pub struct EarlyBoundRegion {
     pub name: Symbol,
 }
 
+impl EarlyBoundRegion {
+    /// Does this early bound region have a name? Early bound regions normally
+    /// always have names except when using anonymous lifetimes (`'_`).
+    pub fn has_name(&self) -> bool {
+        self.name != kw::UnderscoreLifetime && self.name != kw::Empty
+    }
+}
+
 impl fmt::Debug for EarlyBoundRegion {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}, {}", self.index, self.name)

From 32fe94684e8553ec11a970f6ee410f2d33155a30 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:22:37 +0000
Subject: [PATCH 22/38] Move `ty::{ResolverAstLowering, ResolverGlobalCtxt,
 ResolverOutputs}` to their own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 77 ++----------------
 .../rustc_middle/src/ty/resolver_outputs.rs   | 79 +++++++++++++++++++
 2 files changed, 84 insertions(+), 72 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/resolver_outputs.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 4b67ae6a54efc..e968d0160022f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -18,8 +18,6 @@ pub use self::BorrowKind::*;
 pub use self::IntVarValue::*;
 pub use self::Variance::*;
 use crate::error::TypeMismatchReason;
-use crate::metadata::ModChild;
-use crate::middle::privacy::EffectiveVisibilities;
 use crate::mir::{Body, GeneratorLayout};
 use crate::ty;
 use crate::ty::fast_reject::SimplifiedType;
@@ -28,24 +26,20 @@ pub use adt::*;
 pub use assoc::*;
 pub use generics::*;
 use rustc_ast as ast;
-use rustc_ast::node_id::NodeMap;
 use rustc_attr as attr;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::steal::Steal;
 use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
 use rustc_hir::Node;
-use rustc_index::IndexVec;
 use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable};
-use rustc_session::lint::LintBuffer;
 pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{ExpnId, ExpnKind, Span};
+use rustc_span::{ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 use rustc_type_ir::WithCachedTypeInfo;
@@ -147,6 +141,7 @@ mod opaque_hidden_type;
 mod param_env;
 mod placeholder;
 mod predicate;
+mod resolver_outputs;
 mod symbol_name;
 mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
@@ -166,75 +161,13 @@ pub use predicate::{
     PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
     RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
 };
+pub use resolver_outputs::{ResolverAstLowering, ResolverGlobalCtxt, ResolverOutputs};
 pub use symbol_name::SymbolName;
 pub use term::{Term, TermKind};
 pub use ty_::Ty;
 pub use variant_def::VariantDef;
 pub use visibility::Visibility;
 
-pub struct ResolverOutputs {
-    pub global_ctxt: ResolverGlobalCtxt,
-    pub ast_lowering: ResolverAstLowering,
-}
-
-#[derive(Debug)]
-pub struct ResolverGlobalCtxt {
-    pub visibilities: FxHashMap<LocalDefId, Visibility>,
-    /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
-    pub has_pub_restricted: bool,
-    /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
-    pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
-    pub effective_visibilities: EffectiveVisibilities,
-    pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
-    pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
-    pub module_children: LocalDefIdMap<Vec<ModChild>>,
-    pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
-    pub main_def: Option<MainDefinition>,
-    pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
-    /// A list of proc macro LocalDefIds, written out in the order in which
-    /// they are declared in the static array generated by proc_macro_harness.
-    pub proc_macros: Vec<LocalDefId>,
-    /// Mapping from ident span to path span for paths that don't exist as written, but that
-    /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
-    pub confused_type_with_std_module: FxHashMap<Span, Span>,
-    pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
-    pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
-    pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
-}
-
-/// Resolutions that should only be used for lowering.
-/// This struct is meant to be consumed by lowering.
-#[derive(Debug)]
-pub struct ResolverAstLowering {
-    pub legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
-
-    /// Resolutions for nodes that have a single resolution.
-    pub partial_res_map: NodeMap<hir::def::PartialRes>,
-    /// Resolutions for import nodes, which have multiple resolutions in different namespaces.
-    pub import_res_map: NodeMap<hir::def::PerNS<Option<Res<ast::NodeId>>>>,
-    /// Resolutions for labels (node IDs of their corresponding blocks or loops).
-    pub label_res_map: NodeMap<ast::NodeId>,
-    /// Resolutions for lifetimes.
-    pub lifetimes_res_map: NodeMap<LifetimeRes>,
-    /// Lifetime parameters that lowering will have to introduce.
-    pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
-
-    pub next_node_id: ast::NodeId,
-
-    pub node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
-    pub def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
-
-    pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
-    /// A small map keeping true kinds of built-in macros that appear to be fn-like on
-    /// the surface (`macro` items in libcore), but are actually attributes or derives.
-    pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
-    /// List functions and methods for which lifetime elision was successful.
-    pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
-
-    /// Lints that were emitted by the resolver and early lints.
-    pub lint_buffer: Steal<LintBuffer>,
-}
-
 #[derive(Clone, Copy, Debug)]
 pub struct MainDefinition {
     pub res: Res<ast::NodeId>,
diff --git a/compiler/rustc_middle/src/ty/resolver_outputs.rs b/compiler/rustc_middle/src/ty/resolver_outputs.rs
new file mode 100644
index 0000000000000..59a7a729f1e5e
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/resolver_outputs.rs
@@ -0,0 +1,79 @@
+use rustc_ast as ast;
+use rustc_ast::node_id::NodeMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
+use rustc_data_structures::steal::Steal;
+use rustc_hir as hir;
+use rustc_hir::def::{DocLinkResMap, LifetimeRes, Res};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
+use rustc_index::IndexVec;
+use rustc_session::lint::LintBuffer;
+use rustc_span::hygiene::MacroKind;
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::{ExpnId, Span};
+
+use crate::metadata::ModChild;
+use crate::middle::privacy::EffectiveVisibilities;
+use crate::ty::{MainDefinition, Visibility};
+
+pub struct ResolverOutputs {
+    pub global_ctxt: ResolverGlobalCtxt,
+    pub ast_lowering: ResolverAstLowering,
+}
+
+#[derive(Debug)]
+pub struct ResolverGlobalCtxt {
+    pub visibilities: FxHashMap<LocalDefId, Visibility>,
+    /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
+    pub has_pub_restricted: bool,
+    /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
+    pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
+    pub effective_visibilities: EffectiveVisibilities,
+    pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
+    pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
+    pub module_children: LocalDefIdMap<Vec<ModChild>>,
+    pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
+    pub main_def: Option<MainDefinition>,
+    pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
+    /// A list of proc macro LocalDefIds, written out in the order in which
+    /// they are declared in the static array generated by proc_macro_harness.
+    pub proc_macros: Vec<LocalDefId>,
+    /// Mapping from ident span to path span for paths that don't exist as written, but that
+    /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
+    pub confused_type_with_std_module: FxHashMap<Span, Span>,
+    pub doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
+    pub doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
+    pub all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
+}
+
+/// Resolutions that should only be used for lowering.
+/// This struct is meant to be consumed by lowering.
+#[derive(Debug)]
+pub struct ResolverAstLowering {
+    pub legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
+
+    /// Resolutions for nodes that have a single resolution.
+    pub partial_res_map: NodeMap<hir::def::PartialRes>,
+    /// Resolutions for import nodes, which have multiple resolutions in different namespaces.
+    pub import_res_map: NodeMap<hir::def::PerNS<Option<Res<ast::NodeId>>>>,
+    /// Resolutions for labels (node IDs of their corresponding blocks or loops).
+    pub label_res_map: NodeMap<ast::NodeId>,
+    /// Resolutions for lifetimes.
+    pub lifetimes_res_map: NodeMap<LifetimeRes>,
+    /// Lifetime parameters that lowering will have to introduce.
+    pub extra_lifetime_params_map: NodeMap<Vec<(Ident, ast::NodeId, LifetimeRes)>>,
+
+    pub next_node_id: ast::NodeId,
+
+    pub node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
+    pub def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
+
+    pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
+    /// A small map keeping true kinds of built-in macros that appear to be fn-like on
+    /// the surface (`macro` items in libcore), but are actually attributes or derives.
+    pub builtin_macro_kinds: FxHashMap<LocalDefId, MacroKind>,
+    /// List functions and methods for which lifetime elision was successful.
+    pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
+
+    /// Lints that were emitted by the resolver and early lints.
+    pub lint_buffer: Steal<LintBuffer>,
+}

From 9db043f42d678790cbb7d3f1b7dae423e8dd89d3 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:28:55 +0000
Subject: [PATCH 23/38] Move `ty::MainDefinition` to its own little module
 (cute)

---
 .../rustc_middle/src/ty/main_definition.rs     | 18 ++++++++++++++++++
 compiler/rustc_middle/src/ty/mod.rs            | 15 ++-------------
 2 files changed, 20 insertions(+), 13 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/main_definition.rs

diff --git a/compiler/rustc_middle/src/ty/main_definition.rs b/compiler/rustc_middle/src/ty/main_definition.rs
new file mode 100644
index 0000000000000..6637fb8e158b0
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/main_definition.rs
@@ -0,0 +1,18 @@
+use rustc_span::Span;
+
+use rustc_ast as ast;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+
+#[derive(Clone, Copy, Debug)]
+pub struct MainDefinition {
+    pub res: Res<ast::NodeId>,
+    pub is_import: bool,
+    pub span: Span,
+}
+
+impl MainDefinition {
+    pub fn opt_fn_def_id(self) -> Option<DefId> {
+        if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index e968d0160022f..a9d3c506a8f39 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -137,6 +137,7 @@ mod alias_relation_direction;
 mod bound_constness;
 mod field_def;
 mod impl_polarity;
+mod main_definition;
 mod opaque_hidden_type;
 mod param_env;
 mod placeholder;
@@ -152,6 +153,7 @@ pub use alias_relation_direction::AliasRelationDirection;
 pub use bound_constness::BoundConstness;
 pub use field_def::FieldDef;
 pub use impl_polarity::ImplPolarity;
+pub use main_definition::MainDefinition;
 pub use opaque_hidden_type::OpaqueHiddenType;
 pub use param_env::{ParamEnv, ParamEnvAnd};
 pub use placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
@@ -168,19 +170,6 @@ pub use ty_::Ty;
 pub use variant_def::VariantDef;
 pub use visibility::Visibility;
 
-#[derive(Clone, Copy, Debug)]
-pub struct MainDefinition {
-    pub res: Res<ast::NodeId>,
-    pub is_import: bool,
-    pub span: Span,
-}
-
-impl MainDefinition {
-    pub fn opt_fn_def_id(self) -> Option<DefId> {
-        if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None }
-    }
-}
-
 /// The "header" of an impl is everything outside the body: a Self type, a trait
 /// ref (in the case of a trait impl), and a set of predicates (from the
 /// bounds / where-clauses).

From 5e441b8a0786df7f63481afc827ffce7938412a7 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:37:32 +0000
Subject: [PATCH 24/38] Move `ty::Clause` to its own little module (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 27 +-----------------
 compiler/rustc_middle/src/ty/predicate.rs     |  6 ++--
 .../rustc_middle/src/ty/predicate/clause.rs   | 28 +++++++++++++++++++
 3 files changed, 33 insertions(+), 28 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/clause.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a9d3c506a8f39..075c4c000db59 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -158,7 +158,7 @@ pub use opaque_hidden_type::OpaqueHiddenType;
 pub use param_env::{ParamEnv, ParamEnvAnd};
 pub use placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
 pub use predicate::{
-    CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
+    Clause, CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
     PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
     PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
     RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
@@ -260,31 +260,6 @@ pub struct CReaderCacheKey {
     pub pos: usize,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-/// A clause is something that can appear in where bounds or be inferred
-/// by implied bounds.
-pub enum Clause<'tcx> {
-    /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
-    /// the `Self` type of the trait reference and `A`, `B`, and `C`
-    /// would be the type parameters.
-    Trait(TraitPredicate<'tcx>),
-
-    /// `where 'a: 'b`
-    RegionOutlives(RegionOutlivesPredicate<'tcx>),
-
-    /// `where T: 'a`
-    TypeOutlives(TypeOutlivesPredicate<'tcx>),
-
-    /// `where <T as TraitRef>::Name == X`, approximately.
-    /// See the `ProjectionPredicate` struct for details.
-    Projection(ProjectionPredicate<'tcx>),
-
-    /// Ensures that a const generic argument to a parameter `const N: u8`
-    /// is of type `u8`.
-    ConstArgHasType(Const<'tcx>, Ty<'tcx>),
-}
-
 /// The crate outlives map is computed during typeck and contains the
 /// outlives of every item in the local crate. You should not use it
 /// directly, because to do so will make your pass dependent on the
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index c4673a0aac005..9ef8cfcdd93eb 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -6,10 +6,11 @@ use rustc_hir::def_id::DefId;
 use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
-    self, AliasRelationDirection, Binder, BoundConstness, Clause, ClosureKind, Const,
-    DebruijnIndex, EarlyBinder, GenericArg, SubstsRef, Term, Ty, TypeFlags,
+    self, AliasRelationDirection, Binder, BoundConstness, ClosureKind, Const, DebruijnIndex,
+    EarlyBinder, GenericArg, SubstsRef, Term, Ty, TypeFlags,
 };
 
+mod clause;
 mod coerce_predicate;
 mod instantiated_predicates;
 mod outlives_predicate;
@@ -18,6 +19,7 @@ mod subtype_predicate;
 mod to_predicate;
 mod trait_predicate;
 
+pub use clause::Clause;
 pub use coerce_predicate::{CoercePredicate, PolyCoercePredicate};
 pub use instantiated_predicates::InstantiatedPredicates;
 pub use outlives_predicate::{
diff --git a/compiler/rustc_middle/src/ty/predicate/clause.rs b/compiler/rustc_middle/src/ty/predicate/clause.rs
new file mode 100644
index 0000000000000..8c13d68bcce6d
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/clause.rs
@@ -0,0 +1,28 @@
+use crate::ty::{
+    Const, ProjectionPredicate, RegionOutlivesPredicate, TraitPredicate, Ty, TypeOutlivesPredicate,
+};
+
+/// A clause is something that can appear in where bounds or be inferred
+/// by implied bounds.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum Clause<'tcx> {
+    /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
+    /// the `Self` type of the trait reference and `A`, `B`, and `C`
+    /// would be the type parameters.
+    Trait(TraitPredicate<'tcx>),
+
+    /// `where 'a: 'b`
+    RegionOutlives(RegionOutlivesPredicate<'tcx>),
+
+    /// `where T: 'a`
+    TypeOutlives(TypeOutlivesPredicate<'tcx>),
+
+    /// `where <T as TraitRef>::Name == X`, approximately.
+    /// See the `ProjectionPredicate` struct for details.
+    Projection(ProjectionPredicate<'tcx>),
+
+    /// Ensures that a const generic argument to a parameter `const N: u8`
+    /// is of type `u8`.
+    ConstArgHasType(Const<'tcx>, Ty<'tcx>),
+}

From 7a41522233f9325c133d5432f3d0e87256e544de Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Wed, 3 May 2023 23:41:38 +0000
Subject: [PATCH 25/38] Move `ty::CratePredicatesMap` to its own little module
 (cute)

---
 compiler/rustc_middle/src/ty/mod.rs           | 23 ++++---------------
 compiler/rustc_middle/src/ty/predicate.rs     |  2 ++
 .../src/ty/predicate/crate_predicates_map.rs  | 19 +++++++++++++++
 3 files changed, 26 insertions(+), 18 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/predicate/crate_predicates_map.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 075c4c000db59..2f0adf7813686 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -158,10 +158,11 @@ pub use opaque_hidden_type::OpaqueHiddenType;
 pub use param_env::{ParamEnv, ParamEnvAnd};
 pub use placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
 pub use predicate::{
-    Clause, CoercePredicate, InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate,
-    PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
-    PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
-    RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
+    Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates, OutlivesPredicate,
+    PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
+    PolySubtypePredicate, PolyTraitPredicate, PolyTypeOutlivesPredicate, Predicate, PredicateKind,
+    ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate,
+    TypeOutlivesPredicate,
 };
 pub use resolver_outputs::{ResolverAstLowering, ResolverGlobalCtxt, ResolverOutputs};
 pub use symbol_name::SymbolName;
@@ -260,20 +261,6 @@ pub struct CReaderCacheKey {
     pub pos: usize,
 }
 
-/// The crate outlives map is computed during typeck and contains the
-/// outlives of every item in the local crate. You should not use it
-/// directly, because to do so will make your pass dependent on the
-/// HIR of every item in the local crate. Instead, use
-/// `tcx.inferred_outlives_of()` to get the outlives for a *particular*
-/// item.
-#[derive(HashStable, Debug)]
-pub struct CratePredicatesMap<'tcx> {
-    /// For each struct with outlive bounds, maps to a vector of the
-    /// predicate of its outlive bounds. If an item has no outlives
-    /// bounds, it will have no entry.
-    pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
-}
-
 const TAG_MASK: usize = 0b11;
 const TYPE_TAG: usize = 0b00;
 const CONST_TAG: usize = 0b01;
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 9ef8cfcdd93eb..18d9ba26551ac 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -12,6 +12,7 @@ use crate::ty::{
 
 mod clause;
 mod coerce_predicate;
+mod crate_predicates_map;
 mod instantiated_predicates;
 mod outlives_predicate;
 mod projection_predicate;
@@ -21,6 +22,7 @@ mod trait_predicate;
 
 pub use clause::Clause;
 pub use coerce_predicate::{CoercePredicate, PolyCoercePredicate};
+pub use crate_predicates_map::CratePredicatesMap;
 pub use instantiated_predicates::InstantiatedPredicates;
 pub use outlives_predicate::{
     OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate,
diff --git a/compiler/rustc_middle/src/ty/predicate/crate_predicates_map.rs b/compiler/rustc_middle/src/ty/predicate/crate_predicates_map.rs
new file mode 100644
index 0000000000000..28a411fba679b
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/predicate/crate_predicates_map.rs
@@ -0,0 +1,19 @@
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::DefId;
+use rustc_span::Span;
+
+use crate::ty::Clause;
+
+/// The crate outlives map is computed during typeck and contains the
+/// outlives of every item in the local crate. You should not use it
+/// directly, because to do so will make your pass dependent on the
+/// HIR of every item in the local crate. Instead, use
+/// `tcx.inferred_outlives_of()` to get the outlives for a *particular*
+/// item.
+#[derive(HashStable, Debug)]
+pub struct CratePredicatesMap<'tcx> {
+    /// For each struct with outlive bounds, maps to a vector of the
+    /// predicate of its outlive bounds. If an item has no outlives
+    /// bounds, it will have no entry.
+    pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
+}

From a1e3cb48a1d613df6b1eeb812b536a6430d7ff9e Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Thu, 4 May 2023 14:23:52 +0000
Subject: [PATCH 26/38] Move `ty::ImplTraitInTraitData` to its own little
 module (cute)

---
 .../rustc_middle/src/ty/impl_trait_in_trait_data.rs    |  9 +++++++++
 compiler/rustc_middle/src/ty/mod.rs                    | 10 ++--------
 2 files changed, 11 insertions(+), 8 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/impl_trait_in_trait_data.rs

diff --git a/compiler/rustc_middle/src/ty/impl_trait_in_trait_data.rs b/compiler/rustc_middle/src/ty/impl_trait_in_trait_data.rs
new file mode 100644
index 0000000000000..39375ade298cd
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/impl_trait_in_trait_data.rs
@@ -0,0 +1,9 @@
+use rustc_hir::def_id::DefId;
+
+/// Useful source information about where a desugared associated type for an
+/// RPITIT originated from.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)]
+pub enum ImplTraitInTraitData {
+    Trait { fn_def_id: DefId, opaque_def_id: DefId },
+    Impl { fn_def_id: DefId },
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 2f0adf7813686..925a9ba9ad17a 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -137,6 +137,7 @@ mod alias_relation_direction;
 mod bound_constness;
 mod field_def;
 mod impl_polarity;
+mod impl_trait_in_trait_data;
 mod main_definition;
 mod opaque_hidden_type;
 mod param_env;
@@ -153,6 +154,7 @@ pub use alias_relation_direction::AliasRelationDirection;
 pub use bound_constness::BoundConstness;
 pub use field_def::FieldDef;
 pub use impl_polarity::ImplPolarity;
+pub use impl_trait_in_trait_data::ImplTraitInTraitData;
 pub use main_definition::MainDefinition;
 pub use opaque_hidden_type::OpaqueHiddenType;
 pub use param_env::{ParamEnv, ParamEnvAnd};
@@ -378,14 +380,6 @@ pub enum ImplOverlapKind {
     Issue33140,
 }
 
-/// Useful source information about where a desugared associated type for an
-/// RPITIT originated from.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable)]
-pub enum ImplTraitInTraitData {
-    Trait { fn_def_id: DefId, opaque_def_id: DefId },
-    Impl { fn_def_id: DefId },
-}
-
 impl<'tcx> TyCtxt<'tcx> {
     pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
         self.typeck(self.hir().body_owner_def_id(body))

From 9acb574602fd4994c55f902c883595277785999b Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Thu, 4 May 2023 15:18:04 +0000
Subject: [PATCH 27/38] Move `ty::{BoundConst, CReaderCacheKey,
 ClosureSizeProfileData, CrateInherentImpls, CrateVariancesMap, Destructor,
 DestructuredConst, ImplHeader, ImplOverlapKind, ImplSubject, InferVarInfo,
 OpaqueTypeKey, VariantDiscr, VariantFlags}` to their own little modules
 (cute)

---
 compiler/rustc_middle/src/ty/bound_const.rs   |   8 +
 .../rustc_middle/src/ty/c_reader_cache_key.rs |   9 +
 .../src/ty/closure_size_profile_data.rs       |  10 +
 .../src/ty/crate_inherent_impls.rs            |  15 ++
 .../src/ty/crate_variances_map.rs             |  17 ++
 compiler/rustc_middle/src/ty/destructor.rs    |  10 +
 .../rustc_middle/src/ty/destructured_const.rs |   8 +
 compiler/rustc_middle/src/ty/impl_header.rs   |  14 ++
 .../rustc_middle/src/ty/impl_overlap_kind.rs  |  41 ++++
 compiler/rustc_middle/src/ty/impl_subject.rs  |   7 +
 .../rustc_middle/src/ty/infer_var_info.rs     |  12 ++
 compiler/rustc_middle/src/ty/mod.rs           | 202 +++---------------
 .../rustc_middle/src/ty/opaque_type_key.rs    |  10 +
 compiler/rustc_middle/src/ty/variant_discr.rs |  14 ++
 compiler/rustc_middle/src/ty/variant_flags.rs |  11 +
 15 files changed, 215 insertions(+), 173 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/bound_const.rs
 create mode 100644 compiler/rustc_middle/src/ty/c_reader_cache_key.rs
 create mode 100644 compiler/rustc_middle/src/ty/closure_size_profile_data.rs
 create mode 100644 compiler/rustc_middle/src/ty/crate_inherent_impls.rs
 create mode 100644 compiler/rustc_middle/src/ty/crate_variances_map.rs
 create mode 100644 compiler/rustc_middle/src/ty/destructor.rs
 create mode 100644 compiler/rustc_middle/src/ty/destructured_const.rs
 create mode 100644 compiler/rustc_middle/src/ty/impl_header.rs
 create mode 100644 compiler/rustc_middle/src/ty/impl_overlap_kind.rs
 create mode 100644 compiler/rustc_middle/src/ty/impl_subject.rs
 create mode 100644 compiler/rustc_middle/src/ty/infer_var_info.rs
 create mode 100644 compiler/rustc_middle/src/ty/opaque_type_key.rs
 create mode 100644 compiler/rustc_middle/src/ty/variant_discr.rs
 create mode 100644 compiler/rustc_middle/src/ty/variant_flags.rs

diff --git a/compiler/rustc_middle/src/ty/bound_const.rs b/compiler/rustc_middle/src/ty/bound_const.rs
new file mode 100644
index 0000000000000..c200e021dd873
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/bound_const.rs
@@ -0,0 +1,8 @@
+use crate::ty::{BoundVar, Ty};
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
+pub struct BoundConst<'tcx> {
+    pub var: BoundVar,
+    pub ty: Ty<'tcx>,
+}
diff --git a/compiler/rustc_middle/src/ty/c_reader_cache_key.rs b/compiler/rustc_middle/src/ty/c_reader_cache_key.rs
new file mode 100644
index 0000000000000..3383cd8cd8e86
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/c_reader_cache_key.rs
@@ -0,0 +1,9 @@
+use rustc_hir::def_id::CrateNum;
+
+/// Contains information needed to resolve types and (in the future) look up
+/// the types of AST nodes.
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct CReaderCacheKey {
+    pub cnum: Option<CrateNum>,
+    pub pos: usize,
+}
diff --git a/compiler/rustc_middle/src/ty/closure_size_profile_data.rs b/compiler/rustc_middle/src/ty/closure_size_profile_data.rs
new file mode 100644
index 0000000000000..c2d7e93d31112
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/closure_size_profile_data.rs
@@ -0,0 +1,10 @@
+use crate::ty::Ty;
+
+#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct ClosureSizeProfileData<'tcx> {
+    /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields`
+    pub before_feature_tys: Ty<'tcx>,
+    /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields`
+    pub after_feature_tys: Ty<'tcx>,
+}
diff --git a/compiler/rustc_middle/src/ty/crate_inherent_impls.rs b/compiler/rustc_middle/src/ty/crate_inherent_impls.rs
new file mode 100644
index 0000000000000..49904b4c7d765
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/crate_inherent_impls.rs
@@ -0,0 +1,15 @@
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
+
+use crate::ty::SimplifiedType;
+
+/// A map for the local crate mapping each type to a vector of its
+/// inherent impls. This is not meant to be used outside of coherence;
+/// rather, you should request the vector for a specific type via
+/// `tcx.inherent_impls(def_id)` so as to minimize your dependencies
+/// (constructing this map requires touching the entire crate).
+#[derive(Clone, Debug, Default, HashStable)]
+pub struct CrateInherentImpls {
+    pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
+    pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>,
+}
diff --git a/compiler/rustc_middle/src/ty/crate_variances_map.rs b/compiler/rustc_middle/src/ty/crate_variances_map.rs
new file mode 100644
index 0000000000000..4c7ca77dd8656
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/crate_variances_map.rs
@@ -0,0 +1,17 @@
+use rustc_hir::def_id::DefIdMap;
+
+use crate::ty;
+
+/// The crate variances map is computed during typeck and contains the
+/// variance of every item in the local crate. You should not use it
+/// directly, because to do so will make your pass dependent on the
+/// HIR of every item in the local crate. Instead, use
+/// `tcx.variances_of()` to get the variance for a *particular*
+/// item.
+#[derive(HashStable, Debug)]
+pub struct CrateVariancesMap<'tcx> {
+    /// For each item with generics, maps to a vector of the variance
+    /// of its generics. If an item has no generics, it will have no
+    /// entry.
+    pub variances: DefIdMap<&'tcx [ty::Variance]>,
+}
diff --git a/compiler/rustc_middle/src/ty/destructor.rs b/compiler/rustc_middle/src/ty/destructor.rs
new file mode 100644
index 0000000000000..308c5eef93319
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/destructor.rs
@@ -0,0 +1,10 @@
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+
+#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
+pub struct Destructor {
+    /// The `DefId` of the destructor method
+    pub did: DefId,
+    /// The constness of the destructor method
+    pub constness: hir::Constness,
+}
diff --git a/compiler/rustc_middle/src/ty/destructured_const.rs b/compiler/rustc_middle/src/ty/destructured_const.rs
new file mode 100644
index 0000000000000..a59c02e11f305
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/destructured_const.rs
@@ -0,0 +1,8 @@
+use crate::ty::{self, VariantIdx};
+
+/// The constituent parts of a type level constant of kind ADT or array.
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct DestructuredConst<'tcx> {
+    pub variant: Option<VariantIdx>,
+    pub fields: &'tcx [ty::Const<'tcx>],
+}
diff --git a/compiler/rustc_middle/src/ty/impl_header.rs b/compiler/rustc_middle/src/ty/impl_header.rs
new file mode 100644
index 0000000000000..a82e127351ab5
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/impl_header.rs
@@ -0,0 +1,14 @@
+use rustc_hir::def_id::DefId;
+
+use crate::ty::{Predicate, TraitRef, Ty};
+
+/// The "header" of an impl is everything outside the body: a Self type, a trait
+/// ref (in the case of a trait impl), and a set of predicates (from the
+/// bounds / where-clauses).
+#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
+pub struct ImplHeader<'tcx> {
+    pub impl_def_id: DefId,
+    pub self_ty: Ty<'tcx>,
+    pub trait_ref: Option<TraitRef<'tcx>>,
+    pub predicates: Vec<Predicate<'tcx>>,
+}
diff --git a/compiler/rustc_middle/src/ty/impl_overlap_kind.rs b/compiler/rustc_middle/src/ty/impl_overlap_kind.rs
new file mode 100644
index 0000000000000..fc7ef2050b598
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/impl_overlap_kind.rs
@@ -0,0 +1,41 @@
+#[derive(Debug, PartialEq, Eq)]
+pub enum ImplOverlapKind {
+    /// These impls are always allowed to overlap.
+    Permitted {
+        /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
+        marker: bool,
+    },
+    /// These impls are allowed to overlap, but that raises
+    /// an issue #33140 future-compatibility warning.
+    ///
+    /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's
+    /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different.
+    ///
+    /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied
+    /// that difference, making what reduces to the following set of impls:
+    ///
+    /// ```compile_fail,(E0119)
+    /// trait Trait {}
+    /// impl Trait for dyn Send + Sync {}
+    /// impl Trait for dyn Sync + Send {}
+    /// ```
+    ///
+    /// Obviously, once we made these types be identical, that code causes a coherence
+    /// error and a fairly big headache for us. However, luckily for us, the trait
+    /// `Trait` used in this case is basically a marker trait, and therefore having
+    /// overlapping impls for it is sound.
+    ///
+    /// To handle this, we basically regard the trait as a marker trait, with an additional
+    /// future-compatibility warning. To avoid accidentally "stabilizing" this feature,
+    /// it has the following restrictions:
+    ///
+    /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be
+    /// positive impls.
+    /// 2. The trait-ref of both impls must be equal.
+    /// 3. The trait-ref of both impls must be a trait object type consisting only of
+    /// marker traits.
+    /// 4. Neither of the impls can have any where-clauses.
+    ///
+    /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed.
+    Issue33140,
+}
diff --git a/compiler/rustc_middle/src/ty/impl_subject.rs b/compiler/rustc_middle/src/ty/impl_subject.rs
new file mode 100644
index 0000000000000..ab420f025922d
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/impl_subject.rs
@@ -0,0 +1,7 @@
+use crate::ty::{TraitRef, Ty};
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
+pub enum ImplSubject<'tcx> {
+    Trait(TraitRef<'tcx>),
+    Inherent(Ty<'tcx>),
+}
diff --git a/compiler/rustc_middle/src/ty/infer_var_info.rs b/compiler/rustc_middle/src/ty/infer_var_info.rs
new file mode 100644
index 0000000000000..d1c457fcf8941
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/infer_var_info.rs
@@ -0,0 +1,12 @@
+#[derive(Debug, Default, Copy, Clone)]
+pub struct InferVarInfo {
+    /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
+    /// obligation, where:
+    ///
+    ///  * `Foo` is not `Sized`
+    ///  * `(): Foo` may be satisfied
+    pub self_in_trait: bool,
+    /// This is true if we identified that this Ty (`?T`) is found in a `<_ as
+    /// _>::AssocType = ?T`
+    pub output: bool,
+}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 925a9ba9ad17a..fa4f4da1e0f5a 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -27,14 +27,12 @@ pub use assoc::*;
 pub use generics::*;
 use rustc_ast as ast;
 use rustc_attr as attr;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Node;
-use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable};
 pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
@@ -46,9 +44,6 @@ use rustc_type_ir::WithCachedTypeInfo;
 pub use subst::*;
 pub use vtable::*;
 
-use std::fmt::Debug;
-use std::hash::Hash;
-
 pub use crate::ty::diagnostics::*;
 pub use rustc_type_ir::AliasKind::*;
 pub use rustc_type_ir::DynKind::*;
@@ -134,12 +129,24 @@ mod sty;
 mod typeck_results;
 
 mod alias_relation_direction;
+mod bound_const;
 mod bound_constness;
+mod c_reader_cache_key;
+mod closure_size_profile_data;
+mod crate_inherent_impls;
+mod crate_variances_map;
+mod destructor;
+mod destructured_const;
 mod field_def;
+mod impl_header;
+mod impl_overlap_kind;
 mod impl_polarity;
+mod impl_subject;
 mod impl_trait_in_trait_data;
+mod infer_var_info;
 mod main_definition;
 mod opaque_hidden_type;
+mod opaque_type_key;
 mod param_env;
 mod placeholder;
 mod predicate;
@@ -148,15 +155,29 @@ mod symbol_name;
 mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
 mod variant_def;
+mod variant_discr;
+mod variant_flags;
 mod visibility;
 
 pub use alias_relation_direction::AliasRelationDirection;
+pub use bound_const::BoundConst;
 pub use bound_constness::BoundConstness;
+pub use c_reader_cache_key::CReaderCacheKey;
+pub use closure_size_profile_data::ClosureSizeProfileData;
+pub use crate_inherent_impls::CrateInherentImpls;
+pub use crate_variances_map::CrateVariancesMap;
+pub use destructor::Destructor;
+pub use destructured_const::DestructuredConst;
 pub use field_def::FieldDef;
+pub use impl_header::ImplHeader;
+pub use impl_overlap_kind::ImplOverlapKind;
 pub use impl_polarity::ImplPolarity;
+pub use impl_subject::ImplSubject;
 pub use impl_trait_in_trait_data::ImplTraitInTraitData;
+pub use infer_var_info::InferVarInfo;
 pub use main_definition::MainDefinition;
 pub use opaque_hidden_type::OpaqueHiddenType;
+pub use opaque_type_key::OpaqueTypeKey;
 pub use param_env::{ParamEnv, ParamEnvAnd};
 pub use placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
 pub use predicate::{
@@ -171,34 +192,10 @@ pub use symbol_name::SymbolName;
 pub use term::{Term, TermKind};
 pub use ty_::Ty;
 pub use variant_def::VariantDef;
+pub use variant_discr::VariantDiscr;
+pub use variant_flags::VariantFlags;
 pub use visibility::Visibility;
 
-/// The "header" of an impl is everything outside the body: a Self type, a trait
-/// ref (in the case of a trait impl), and a set of predicates (from the
-/// bounds / where-clauses).
-#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
-pub struct ImplHeader<'tcx> {
-    pub impl_def_id: DefId,
-    pub self_ty: Ty<'tcx>,
-    pub trait_ref: Option<TraitRef<'tcx>>,
-    pub predicates: Vec<Predicate<'tcx>>,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
-pub enum ImplSubject<'tcx> {
-    Trait(TraitRef<'tcx>),
-    Inherent(Ty<'tcx>),
-}
-
-#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct ClosureSizeProfileData<'tcx> {
-    /// Tuple containing the types of closure captures before the feature `capture_disjoint_fields`
-    pub before_feature_tys: Ty<'tcx>,
-    /// Tuple containing the types of closure captures after the feature `capture_disjoint_fields`
-    pub after_feature_tys: Ty<'tcx>,
-}
-
 impl TyCtxt<'_> {
     #[inline]
     pub fn opt_parent(self, id: DefId) -> Option<DefId> {
@@ -241,27 +238,6 @@ impl TyCtxt<'_> {
         true
     }
 }
-/// The crate variances map is computed during typeck and contains the
-/// variance of every item in the local crate. You should not use it
-/// directly, because to do so will make your pass dependent on the
-/// HIR of every item in the local crate. Instead, use
-/// `tcx.variances_of()` to get the variance for a *particular*
-/// item.
-#[derive(HashStable, Debug)]
-pub struct CrateVariancesMap<'tcx> {
-    /// For each item with generics, maps to a vector of the variance
-    /// of its generics. If an item has no generics, it will have no
-    /// entry.
-    pub variances: DefIdMap<&'tcx [ty::Variance]>,
-}
-
-// Contains information needed to resolve types and (in the future) look up
-// the types of AST nodes.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub struct CReaderCacheKey {
-    pub cnum: Option<CrateNum>,
-    pub pos: usize,
-}
 
 const TAG_MASK: usize = 0b11;
 const TYPE_TAG: usize = 0b00;
@@ -291,95 +267,6 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct OpaqueTypeKey<'tcx> {
-    pub def_id: LocalDefId,
-    pub substs: SubstsRef<'tcx>,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
-#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
-pub struct BoundConst<'tcx> {
-    pub var: BoundVar,
-    pub ty: Ty<'tcx>,
-}
-
-#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
-pub struct Destructor {
-    /// The `DefId` of the destructor method
-    pub did: DefId,
-    /// The constness of the destructor method
-    pub constness: hir::Constness,
-}
-
-bitflags! {
-    #[derive(HashStable, TyEncodable, TyDecodable)]
-    pub struct VariantFlags: u8 {
-        const NO_VARIANT_FLAGS        = 0;
-        /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
-        const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
-        /// Indicates whether this variant was obtained as part of recovering from
-        /// a syntactic error. May be incomplete or bogus.
-        const IS_RECOVERED = 1 << 1;
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
-pub enum VariantDiscr {
-    /// Explicit value for this variant, i.e., `X = 123`.
-    /// The `DefId` corresponds to the embedded constant.
-    Explicit(DefId),
-
-    /// The previous variant's discriminant plus one.
-    /// For efficiency reasons, the distance from the
-    /// last `Explicit` discriminant is being stored,
-    /// or `0` for the first variant, if it has none.
-    Relative(u32),
-}
-
-#[derive(Debug, PartialEq, Eq)]
-pub enum ImplOverlapKind {
-    /// These impls are always allowed to overlap.
-    Permitted {
-        /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
-        marker: bool,
-    },
-    /// These impls are allowed to overlap, but that raises
-    /// an issue #33140 future-compatibility warning.
-    ///
-    /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's
-    /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different.
-    ///
-    /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied
-    /// that difference, making what reduces to the following set of impls:
-    ///
-    /// ```compile_fail,(E0119)
-    /// trait Trait {}
-    /// impl Trait for dyn Send + Sync {}
-    /// impl Trait for dyn Sync + Send {}
-    /// ```
-    ///
-    /// Obviously, once we made these types be identical, that code causes a coherence
-    /// error and a fairly big headache for us. However, luckily for us, the trait
-    /// `Trait` used in this case is basically a marker trait, and therefore having
-    /// overlapping impls for it is sound.
-    ///
-    /// To handle this, we basically regard the trait as a marker trait, with an additional
-    /// future-compatibility warning. To avoid accidentally "stabilizing" this feature,
-    /// it has the following restrictions:
-    ///
-    /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be
-    /// positive impls.
-    /// 2. The trait-ref of both impls must be equal.
-    /// 3. The trait-ref of both impls must be a trait object type consisting only of
-    /// marker traits.
-    /// 4. Neither of the impls can have any where-clauses.
-    ///
-    /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed.
-    Issue33140,
-}
-
 impl<'tcx> TyCtxt<'tcx> {
     pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
         self.typeck(self.hir().body_owner_def_id(body))
@@ -972,37 +859,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
     };
 }
 
-/// A map for the local crate mapping each type to a vector of its
-/// inherent impls. This is not meant to be used outside of coherence;
-/// rather, you should request the vector for a specific type via
-/// `tcx.inherent_impls(def_id)` so as to minimize your dependencies
-/// (constructing this map requires touching the entire crate).
-#[derive(Clone, Debug, Default, HashStable)]
-pub struct CrateInherentImpls {
-    pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
-    pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>,
-}
-
-#[derive(Debug, Default, Copy, Clone)]
-pub struct InferVarInfo {
-    /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
-    /// obligation, where:
-    ///
-    ///  * `Foo` is not `Sized`
-    ///  * `(): Foo` may be satisfied
-    pub self_in_trait: bool,
-    /// This is true if we identified that this Ty (`?T`) is found in a `<_ as
-    /// _>::AssocType = ?T`
-    pub output: bool,
-}
-
-/// The constituent parts of a type level constant of kind ADT or array.
-#[derive(Copy, Clone, Debug, HashStable)]
-pub struct DestructuredConst<'tcx> {
-    pub variant: Option<VariantIdx>,
-    pub fields: &'tcx [ty::Const<'tcx>],
-}
-
 // Some types are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 mod size_asserts {
diff --git a/compiler/rustc_middle/src/ty/opaque_type_key.rs b/compiler/rustc_middle/src/ty/opaque_type_key.rs
new file mode 100644
index 0000000000000..56920b571fd44
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/opaque_type_key.rs
@@ -0,0 +1,10 @@
+use rustc_hir::def_id::LocalDefId;
+
+use crate::ty::SubstsRef;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct OpaqueTypeKey<'tcx> {
+    pub def_id: LocalDefId,
+    pub substs: SubstsRef<'tcx>,
+}
diff --git a/compiler/rustc_middle/src/ty/variant_discr.rs b/compiler/rustc_middle/src/ty/variant_discr.rs
new file mode 100644
index 0000000000000..f792e4e3bd096
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/variant_discr.rs
@@ -0,0 +1,14 @@
+use rustc_hir::def_id::DefId;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
+pub enum VariantDiscr {
+    /// Explicit value for this variant, i.e., `X = 123`.
+    /// The `DefId` corresponds to the embedded constant.
+    Explicit(DefId),
+
+    /// The previous variant's discriminant plus one.
+    /// For efficiency reasons, the distance from the
+    /// last `Explicit` discriminant is being stored,
+    /// or `0` for the first variant, if it has none.
+    Relative(u32),
+}
diff --git a/compiler/rustc_middle/src/ty/variant_flags.rs b/compiler/rustc_middle/src/ty/variant_flags.rs
new file mode 100644
index 0000000000000..07b530ce4b3d5
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/variant_flags.rs
@@ -0,0 +1,11 @@
+bitflags! {
+    #[derive(HashStable, TyEncodable, TyDecodable)]
+    pub struct VariantFlags: u8 {
+        const NO_VARIANT_FLAGS = 0;
+        /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
+        const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
+        /// Indicates whether this variant was obtained as part of recovering from
+        /// a syntactic error. May be incomplete or bogus.
+        const IS_RECOVERED = 1 << 1;
+    }
+}

From 3c941b245ace0948254dc8e84d0ff8d534fe49c4 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Thu, 4 May 2023 15:30:56 +0000
Subject: [PATCH 28/38] Rearange [pub] uses

---
 compiler/rustc_middle/src/ty/mod.rs | 213 ++++++++++++++--------------
 1 file changed, 106 insertions(+), 107 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index fa4f4da1e0f5a..7f6e7adb4b933 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -11,20 +11,6 @@
 
 #![allow(rustc::usage_of_ty_tykind)]
 
-pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
-pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
-pub use self::AssocItemContainer::*;
-pub use self::BorrowKind::*;
-pub use self::IntVarValue::*;
-pub use self::Variance::*;
-use crate::error::TypeMismatchReason;
-use crate::mir::{Body, GeneratorLayout};
-use crate::ty;
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::util::Discr;
-pub use adt::*;
-pub use assoc::*;
-pub use generics::*;
 use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::intern::Interned;
@@ -34,58 +20,17 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Node;
 use rustc_serialize::{Decodable, Encodable};
-pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
-pub use rustc_target::abi::{ReprFlags, ReprOptions};
 use rustc_type_ir::WithCachedTypeInfo;
-pub use subst::*;
-pub use vtable::*;
-
-pub use crate::ty::diagnostics::*;
-pub use rustc_type_ir::AliasKind::*;
-pub use rustc_type_ir::DynKind::*;
-pub use rustc_type_ir::InferTy::*;
-pub use rustc_type_ir::RegionKind::*;
-pub use rustc_type_ir::TyKind::*;
-pub use rustc_type_ir::*;
 
-pub use self::binding::BindingMode;
-pub use self::binding::BindingMode::*;
-pub use self::closure::{
-    is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
-    CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
-    RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
-    CAPTURE_STRUCT_LOCAL,
-};
-pub use self::consts::{
-    Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
-};
-pub use self::context::{
-    tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
-};
-pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
-pub use self::list::List;
-pub use self::parameterized::ParameterizedOverTcx;
-pub use self::rvalue_scopes::RvalueScopes;
-pub use self::sty::BoundRegionKind::*;
-pub use self::sty::{
-    AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
-    BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
-    EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
-    FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
-    InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
-    PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
-    Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
-};
-pub use self::trait_def::TraitDef;
-pub use self::typeck_results::{
-    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
-    UserTypeAnnotationIndex,
-};
+use self::fast_reject::SimplifiedType;
+use self::util::Discr;
+use crate::error::TypeMismatchReason;
+use crate::mir::{Body, GeneratorLayout};
+use crate::ty;
 
 pub mod _match;
 pub mod abstract_const;
@@ -111,90 +56,144 @@ pub mod vtable;
 pub mod walk;
 
 mod adt;
-mod assoc;
-mod closure;
-mod consts;
-mod context;
-mod diagnostics;
-mod erase_regions;
-mod generics;
-mod impls_ty;
-mod instance;
-mod list;
-mod opaque_types;
-mod parameterized;
-mod rvalue_scopes;
-mod structural_impls;
-mod sty;
-mod typeck_results;
-
 mod alias_relation_direction;
+mod assoc;
 mod bound_const;
 mod bound_constness;
 mod c_reader_cache_key;
+mod closure;
 mod closure_size_profile_data;
+mod consts;
+mod context;
 mod crate_inherent_impls;
 mod crate_variances_map;
 mod destructor;
 mod destructured_const;
+mod diagnostics;
+mod erase_regions;
 mod field_def;
+mod generics;
 mod impl_header;
 mod impl_overlap_kind;
 mod impl_polarity;
 mod impl_subject;
 mod impl_trait_in_trait_data;
+mod impls_ty;
 mod infer_var_info;
+mod instance;
+mod list;
 mod main_definition;
 mod opaque_hidden_type;
 mod opaque_type_key;
+mod opaque_types;
 mod param_env;
+mod parameterized;
 mod placeholder;
 mod predicate;
 mod resolver_outputs;
+mod rvalue_scopes;
+mod structural_impls;
+mod sty;
 mod symbol_name;
 mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
+mod typeck_results;
 mod variant_def;
 mod variant_discr;
 mod variant_flags;
 mod visibility;
 
-pub use alias_relation_direction::AliasRelationDirection;
-pub use bound_const::BoundConst;
-pub use bound_constness::BoundConstness;
-pub use c_reader_cache_key::CReaderCacheKey;
-pub use closure_size_profile_data::ClosureSizeProfileData;
-pub use crate_inherent_impls::CrateInherentImpls;
-pub use crate_variances_map::CrateVariancesMap;
-pub use destructor::Destructor;
-pub use destructured_const::DestructuredConst;
-pub use field_def::FieldDef;
-pub use impl_header::ImplHeader;
-pub use impl_overlap_kind::ImplOverlapKind;
-pub use impl_polarity::ImplPolarity;
-pub use impl_subject::ImplSubject;
-pub use impl_trait_in_trait_data::ImplTraitInTraitData;
-pub use infer_var_info::InferVarInfo;
-pub use main_definition::MainDefinition;
-pub use opaque_hidden_type::OpaqueHiddenType;
-pub use opaque_type_key::OpaqueTypeKey;
-pub use param_env::{ParamEnv, ParamEnvAnd};
-pub use placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
-pub use predicate::{
+pub use rustc_session::lint::RegisteredTools;
+pub use rustc_target::abi::{ReprFlags, ReprOptions};
+pub use rustc_type_ir::AliasKind::*;
+pub use rustc_type_ir::DynKind::*;
+pub use rustc_type_ir::InferTy::*;
+pub use rustc_type_ir::RegionKind::*;
+pub use rustc_type_ir::TyKind::*;
+pub use rustc_type_ir::*;
+
+pub use self::adt::*;
+pub use self::alias_relation_direction::AliasRelationDirection;
+pub use self::assoc::*;
+pub use self::binding::BindingMode;
+pub use self::binding::BindingMode::*;
+pub use self::bound_const::BoundConst;
+pub use self::bound_constness::BoundConstness;
+pub use self::c_reader_cache_key::CReaderCacheKey;
+pub use self::closure::{
+    is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
+    CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
+    RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
+    CAPTURE_STRUCT_LOCAL,
+};
+pub use self::closure_size_profile_data::ClosureSizeProfileData;
+pub use self::consts::{
+    Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+};
+pub use self::context::{
+    tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
+};
+pub use self::crate_inherent_impls::CrateInherentImpls;
+pub use self::crate_variances_map::CrateVariancesMap;
+pub use self::destructor::Destructor;
+pub use self::destructured_const::DestructuredConst;
+pub use self::diagnostics::*;
+pub use self::field_def::FieldDef;
+pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
+pub use self::generics::*;
+pub use self::impl_header::ImplHeader;
+pub use self::impl_overlap_kind::ImplOverlapKind;
+pub use self::impl_polarity::ImplPolarity;
+pub use self::impl_subject::ImplSubject;
+pub use self::impl_trait_in_trait_data::ImplTraitInTraitData;
+pub use self::infer_var_info::InferVarInfo;
+pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
+pub use self::list::List;
+pub use self::main_definition::MainDefinition;
+pub use self::opaque_hidden_type::OpaqueHiddenType;
+pub use self::opaque_type_key::OpaqueTypeKey;
+pub use self::param_env::{ParamEnv, ParamEnvAnd};
+pub use self::parameterized::ParameterizedOverTcx;
+pub use self::placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
+pub use self::predicate::{
     Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates, OutlivesPredicate,
     PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
     PolySubtypePredicate, PolyTraitPredicate, PolyTypeOutlivesPredicate, Predicate, PredicateKind,
     ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate,
     TypeOutlivesPredicate,
 };
-pub use resolver_outputs::{ResolverAstLowering, ResolverGlobalCtxt, ResolverOutputs};
-pub use symbol_name::SymbolName;
-pub use term::{Term, TermKind};
-pub use ty_::Ty;
-pub use variant_def::VariantDef;
-pub use variant_discr::VariantDiscr;
-pub use variant_flags::VariantFlags;
-pub use visibility::Visibility;
+pub use self::resolver_outputs::{ResolverAstLowering, ResolverGlobalCtxt, ResolverOutputs};
+pub use self::rvalue_scopes::RvalueScopes;
+pub use self::sty::BoundRegionKind::*;
+pub use self::sty::{
+    AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
+    BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
+    EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
+    FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
+    InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
+    PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
+    Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
+};
+pub use self::subst::*;
+pub use self::symbol_name::SymbolName;
+pub use self::term::{Term, TermKind};
+pub use self::trait_def::TraitDef;
+pub use self::ty_::Ty;
+pub use self::typeck_results::{
+    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
+    UserTypeAnnotationIndex,
+};
+pub use self::variant_def::VariantDef;
+pub use self::variant_discr::VariantDiscr;
+pub use self::variant_flags::VariantFlags;
+pub use self::visibility::Visibility;
+pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
+pub use self::vtable::*;
+pub use self::AssocItemContainer::*;
+pub use self::BorrowKind::*;
+pub use self::IntVarValue::*;
+pub use self::Variance::*;
 
 impl TyCtxt<'_> {
     #[inline]

From 2c556f5709aa12f0ae3bdbbc4269d38e6ce2da9c Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 10:09:00 +0000
Subject: [PATCH 29/38] group `ty::coherence` in one file

---
 compiler/rustc_middle/src/ty/coherence.rs     | 111 ++++++++++++++++++
 .../src/ty/crate_inherent_impls.rs            |  15 ---
 compiler/rustc_middle/src/ty/impl_header.rs   |  14 ---
 .../rustc_middle/src/ty/impl_overlap_kind.rs  |  41 -------
 compiler/rustc_middle/src/ty/impl_polarity.rs |  36 ------
 compiler/rustc_middle/src/ty/impl_subject.rs  |   7 --
 compiler/rustc_middle/src/ty/mod.rs           |  15 +--
 7 files changed, 116 insertions(+), 123 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/coherence.rs
 delete mode 100644 compiler/rustc_middle/src/ty/crate_inherent_impls.rs
 delete mode 100644 compiler/rustc_middle/src/ty/impl_header.rs
 delete mode 100644 compiler/rustc_middle/src/ty/impl_overlap_kind.rs
 delete mode 100644 compiler/rustc_middle/src/ty/impl_polarity.rs
 delete mode 100644 compiler/rustc_middle/src/ty/impl_subject.rs

diff --git a/compiler/rustc_middle/src/ty/coherence.rs b/compiler/rustc_middle/src/ty/coherence.rs
new file mode 100644
index 0000000000000..fe37ff602764b
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/coherence.rs
@@ -0,0 +1,111 @@
+use std::fmt;
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
+
+use crate::ty::{Predicate, SimplifiedType, TraitRef, Ty};
+
+/// A map for the local crate mapping each type to a vector of its
+/// inherent impls. This is not meant to be used outside of coherence;
+/// rather, you should request the vector for a specific type via
+/// `tcx.inherent_impls(def_id)` so as to minimize your dependencies
+/// (constructing this map requires touching the entire crate).
+#[derive(Clone, Debug, Default, HashStable)]
+pub struct CrateInherentImpls {
+    pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
+    pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>,
+}
+
+#[derive(Debug, PartialEq, Eq)]
+pub enum ImplOverlapKind {
+    /// These impls are always allowed to overlap.
+    Permitted {
+        /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
+        marker: bool,
+    },
+    /// These impls are allowed to overlap, but that raises
+    /// an issue #33140 future-compatibility warning.
+    ///
+    /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's
+    /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different.
+    ///
+    /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied
+    /// that difference, making what reduces to the following set of impls:
+    ///
+    /// ```compile_fail,(E0119)
+    /// trait Trait {}
+    /// impl Trait for dyn Send + Sync {}
+    /// impl Trait for dyn Sync + Send {}
+    /// ```
+    ///
+    /// Obviously, once we made these types be identical, that code causes a coherence
+    /// error and a fairly big headache for us. However, luckily for us, the trait
+    /// `Trait` used in this case is basically a marker trait, and therefore having
+    /// overlapping impls for it is sound.
+    ///
+    /// To handle this, we basically regard the trait as a marker trait, with an additional
+    /// future-compatibility warning. To avoid accidentally "stabilizing" this feature,
+    /// it has the following restrictions:
+    ///
+    /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be
+    /// positive impls.
+    /// 2. The trait-ref of both impls must be equal.
+    /// 3. The trait-ref of both impls must be a trait object type consisting only of
+    /// marker traits.
+    /// 4. Neither of the impls can have any where-clauses.
+    ///
+    /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed.
+    Issue33140,
+}
+
+/// The "header" of an impl is everything outside the body: a Self type, a trait
+/// ref (in the case of a trait impl), and a set of predicates (from the
+/// bounds / where-clauses).
+#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
+pub struct ImplHeader<'tcx> {
+    pub impl_def_id: DefId,
+    pub self_ty: Ty<'tcx>,
+    pub trait_ref: Option<TraitRef<'tcx>>,
+    pub predicates: Vec<Predicate<'tcx>>,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
+pub enum ImplSubject<'tcx> {
+    Trait(TraitRef<'tcx>),
+    Inherent(Ty<'tcx>),
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub enum ImplPolarity {
+    /// `impl Trait for Type`
+    Positive,
+    /// `impl !Trait for Type`
+    Negative,
+    /// `#[rustc_reservation_impl] impl Trait for Type`
+    ///
+    /// This is a "stability hack", not a real Rust feature.
+    /// See #64631 for details.
+    Reservation,
+}
+
+impl ImplPolarity {
+    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
+    pub fn flip(&self) -> Option<ImplPolarity> {
+        match self {
+            ImplPolarity::Positive => Some(ImplPolarity::Negative),
+            ImplPolarity::Negative => Some(ImplPolarity::Positive),
+            ImplPolarity::Reservation => None,
+        }
+    }
+}
+
+impl fmt::Display for ImplPolarity {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Positive => f.write_str("positive"),
+            Self::Negative => f.write_str("negative"),
+            Self::Reservation => f.write_str("reservation"),
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/crate_inherent_impls.rs b/compiler/rustc_middle/src/ty/crate_inherent_impls.rs
deleted file mode 100644
index 49904b4c7d765..0000000000000
--- a/compiler/rustc_middle/src/ty/crate_inherent_impls.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
-
-use crate::ty::SimplifiedType;
-
-/// A map for the local crate mapping each type to a vector of its
-/// inherent impls. This is not meant to be used outside of coherence;
-/// rather, you should request the vector for a specific type via
-/// `tcx.inherent_impls(def_id)` so as to minimize your dependencies
-/// (constructing this map requires touching the entire crate).
-#[derive(Clone, Debug, Default, HashStable)]
-pub struct CrateInherentImpls {
-    pub inherent_impls: LocalDefIdMap<Vec<DefId>>,
-    pub incoherent_impls: FxHashMap<SimplifiedType, Vec<LocalDefId>>,
-}
diff --git a/compiler/rustc_middle/src/ty/impl_header.rs b/compiler/rustc_middle/src/ty/impl_header.rs
deleted file mode 100644
index a82e127351ab5..0000000000000
--- a/compiler/rustc_middle/src/ty/impl_header.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use rustc_hir::def_id::DefId;
-
-use crate::ty::{Predicate, TraitRef, Ty};
-
-/// The "header" of an impl is everything outside the body: a Self type, a trait
-/// ref (in the case of a trait impl), and a set of predicates (from the
-/// bounds / where-clauses).
-#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
-pub struct ImplHeader<'tcx> {
-    pub impl_def_id: DefId,
-    pub self_ty: Ty<'tcx>,
-    pub trait_ref: Option<TraitRef<'tcx>>,
-    pub predicates: Vec<Predicate<'tcx>>,
-}
diff --git a/compiler/rustc_middle/src/ty/impl_overlap_kind.rs b/compiler/rustc_middle/src/ty/impl_overlap_kind.rs
deleted file mode 100644
index fc7ef2050b598..0000000000000
--- a/compiler/rustc_middle/src/ty/impl_overlap_kind.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-#[derive(Debug, PartialEq, Eq)]
-pub enum ImplOverlapKind {
-    /// These impls are always allowed to overlap.
-    Permitted {
-        /// Whether or not the impl is permitted due to the trait being a `#[marker]` trait
-        marker: bool,
-    },
-    /// These impls are allowed to overlap, but that raises
-    /// an issue #33140 future-compatibility warning.
-    ///
-    /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's
-    /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different.
-    ///
-    /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied
-    /// that difference, making what reduces to the following set of impls:
-    ///
-    /// ```compile_fail,(E0119)
-    /// trait Trait {}
-    /// impl Trait for dyn Send + Sync {}
-    /// impl Trait for dyn Sync + Send {}
-    /// ```
-    ///
-    /// Obviously, once we made these types be identical, that code causes a coherence
-    /// error and a fairly big headache for us. However, luckily for us, the trait
-    /// `Trait` used in this case is basically a marker trait, and therefore having
-    /// overlapping impls for it is sound.
-    ///
-    /// To handle this, we basically regard the trait as a marker trait, with an additional
-    /// future-compatibility warning. To avoid accidentally "stabilizing" this feature,
-    /// it has the following restrictions:
-    ///
-    /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be
-    /// positive impls.
-    /// 2. The trait-ref of both impls must be equal.
-    /// 3. The trait-ref of both impls must be a trait object type consisting only of
-    /// marker traits.
-    /// 4. Neither of the impls can have any where-clauses.
-    ///
-    /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed.
-    Issue33140,
-}
diff --git a/compiler/rustc_middle/src/ty/impl_polarity.rs b/compiler/rustc_middle/src/ty/impl_polarity.rs
deleted file mode 100644
index a55f4d395261d..0000000000000
--- a/compiler/rustc_middle/src/ty/impl_polarity.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use std::fmt;
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub enum ImplPolarity {
-    /// `impl Trait for Type`
-    Positive,
-    /// `impl !Trait for Type`
-    Negative,
-    /// `#[rustc_reservation_impl] impl Trait for Type`
-    ///
-    /// This is a "stability hack", not a real Rust feature.
-    /// See #64631 for details.
-    Reservation,
-}
-
-impl ImplPolarity {
-    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
-    pub fn flip(&self) -> Option<ImplPolarity> {
-        match self {
-            ImplPolarity::Positive => Some(ImplPolarity::Negative),
-            ImplPolarity::Negative => Some(ImplPolarity::Positive),
-            ImplPolarity::Reservation => None,
-        }
-    }
-}
-
-impl fmt::Display for ImplPolarity {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Positive => f.write_str("positive"),
-            Self::Negative => f.write_str("negative"),
-            Self::Reservation => f.write_str("reservation"),
-        }
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/impl_subject.rs b/compiler/rustc_middle/src/ty/impl_subject.rs
deleted file mode 100644
index ab420f025922d..0000000000000
--- a/compiler/rustc_middle/src/ty/impl_subject.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-use crate::ty::{TraitRef, Ty};
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]
-pub enum ImplSubject<'tcx> {
-    Trait(TraitRef<'tcx>),
-    Inherent(Ty<'tcx>),
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7f6e7adb4b933..32ce0b9f4b8c7 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -65,7 +65,6 @@ mod closure;
 mod closure_size_profile_data;
 mod consts;
 mod context;
-mod crate_inherent_impls;
 mod crate_variances_map;
 mod destructor;
 mod destructured_const;
@@ -73,10 +72,6 @@ mod diagnostics;
 mod erase_regions;
 mod field_def;
 mod generics;
-mod impl_header;
-mod impl_overlap_kind;
-mod impl_polarity;
-mod impl_subject;
 mod impl_trait_in_trait_data;
 mod impls_ty;
 mod infer_var_info;
@@ -103,6 +98,8 @@ mod variant_discr;
 mod variant_flags;
 mod visibility;
 
+mod coherence;
+
 pub use rustc_session::lint::RegisteredTools;
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use rustc_type_ir::AliasKind::*;
@@ -127,13 +124,15 @@ pub use self::closure::{
     CAPTURE_STRUCT_LOCAL,
 };
 pub use self::closure_size_profile_data::ClosureSizeProfileData;
+pub use self::coherence::{
+    CrateInherentImpls, ImplHeader, ImplOverlapKind, ImplPolarity, ImplSubject,
+};
 pub use self::consts::{
     Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
 };
-pub use self::crate_inherent_impls::CrateInherentImpls;
 pub use self::crate_variances_map::CrateVariancesMap;
 pub use self::destructor::Destructor;
 pub use self::destructured_const::DestructuredConst;
@@ -141,10 +140,6 @@ pub use self::diagnostics::*;
 pub use self::field_def::FieldDef;
 pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 pub use self::generics::*;
-pub use self::impl_header::ImplHeader;
-pub use self::impl_overlap_kind::ImplOverlapKind;
-pub use self::impl_polarity::ImplPolarity;
-pub use self::impl_subject::ImplSubject;
 pub use self::impl_trait_in_trait_data::ImplTraitInTraitData;
 pub use self::infer_var_info::InferVarInfo;
 pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};

From a04bd9b835af598438ea6f037401ffd89678b6b4 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 10:51:47 +0000
Subject: [PATCH 30/38] group `ty::opaque` in one file

---
 compiler/rustc_middle/src/ty/mod.rs           |   7 +-
 .../src/ty/{opaque_types.rs => opaque.rs}     | 100 +++++++++++++++++-
 .../rustc_middle/src/ty/opaque_hidden_type.rs |  87 ---------------
 .../rustc_middle/src/ty/opaque_type_key.rs    |  10 --
 4 files changed, 97 insertions(+), 107 deletions(-)
 rename compiler/rustc_middle/src/ty/{opaque_types.rs => opaque.rs} (69%)
 delete mode 100644 compiler/rustc_middle/src/ty/opaque_hidden_type.rs
 delete mode 100644 compiler/rustc_middle/src/ty/opaque_type_key.rs

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 32ce0b9f4b8c7..5892bb4d35230 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -78,9 +78,7 @@ mod infer_var_info;
 mod instance;
 mod list;
 mod main_definition;
-mod opaque_hidden_type;
-mod opaque_type_key;
-mod opaque_types;
+mod opaque;
 mod param_env;
 mod parameterized;
 mod placeholder;
@@ -145,8 +143,7 @@ pub use self::infer_var_info::InferVarInfo;
 pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
 pub use self::list::List;
 pub use self::main_definition::MainDefinition;
-pub use self::opaque_hidden_type::OpaqueHiddenType;
-pub use self::opaque_type_key::OpaqueTypeKey;
+pub use self::opaque::{OpaqueHiddenType, OpaqueTypeKey};
 pub use self::param_env::{ParamEnv, ParamEnvAnd};
 pub use self::parameterized::ParameterizedOverTcx;
 pub use self::placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque.rs
similarity index 69%
rename from compiler/rustc_middle/src/ty/opaque_types.rs
rename to compiler/rustc_middle/src/ty/opaque.rs
index 72710b78c9373..97dab93ecb74c 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque.rs
@@ -1,15 +1,57 @@
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::ErrorGuaranteed;
+use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::Span;
+
 use crate::error::ConstNotUsedTraitAlias;
+use crate::error::OpaqueHiddenTypeMismatch;
 use crate::ty::fold::{TypeFolder, TypeSuperFoldable};
 use crate::ty::subst::{GenericArg, GenericArgKind};
-use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_span::def_id::DefId;
-use rustc_span::Span;
+use crate::ty::{self, InternalSubsts, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeMismatchReason};
+
+#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
+pub struct OpaqueHiddenType<'tcx> {
+    /// The span of this particular definition of the opaque type. So
+    /// for example:
+    ///
+    /// ```ignore (incomplete snippet)
+    /// type Foo = impl Baz;
+    /// fn bar() -> Foo {
+    /// //          ^^^ This is the span we are looking for!
+    /// }
+    /// ```
+    ///
+    /// In cases where the fn returns `(impl Trait, impl Trait)` or
+    /// other such combinations, the result is currently
+    /// over-approximated, but better than nothing.
+    pub span: Span,
+
+    /// The type variable that represents the value of the opaque type
+    /// that we require. In other words, after we compile this function,
+    /// we will be created a constraint like:
+    /// ```ignore (pseudo-rust)
+    /// Foo<'a, T> = ?C
+    /// ```
+    /// where `?C` is the value of this type variable. =) It may
+    /// naturally refer to the type and lifetime parameters in scope
+    /// in this function, though ultimately it should only reference
+    /// those that are arguments to `Foo` in the constraint above. (In
+    /// other words, `?C` should not include `'b`, even though it's a
+    /// lifetime parameter on `foo`.)
+    pub ty: Ty<'tcx>,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub struct OpaqueTypeKey<'tcx> {
+    pub def_id: LocalDefId,
+    pub substs: SubstsRef<'tcx>,
+}
 
 /// Converts generic params of a TypeFoldable from one
 /// item's generics to another. Usually from a function's generics
 /// list to the opaque type's own generics.
-pub(super) struct ReverseMapper<'tcx> {
+struct ReverseMapper<'tcx> {
     tcx: TyCtxt<'tcx>,
     map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
     /// see call sites to fold_kind_no_missing_regions_error
@@ -26,6 +68,54 @@ pub(super) struct ReverseMapper<'tcx> {
     span: Span,
 }
 
+impl<'tcx> OpaqueHiddenType<'tcx> {
+    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
+        // Found different concrete types for the opaque type.
+        let sub_diag = if self.span == other.span {
+            TypeMismatchReason::ConflictType { span: self.span }
+        } else {
+            TypeMismatchReason::PreviousUse { span: self.span }
+        };
+        tcx.sess.emit_err(OpaqueHiddenTypeMismatch {
+            self_ty: self.ty,
+            other_ty: other.ty,
+            other_span: other.span,
+            sub: sub_diag,
+        })
+    }
+
+    #[instrument(level = "debug", skip(tcx), ret)]
+    pub fn remap_generic_params_to_declaration_params(
+        self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        tcx: TyCtxt<'tcx>,
+        // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
+        ignore_errors: bool,
+    ) -> Self {
+        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+
+        // Use substs to build up a reverse map from regions to their
+        // identity mappings. This is necessary because of `impl
+        // Trait` lifetimes are computed by replacing existing
+        // lifetimes with 'static and remapping only those used in the
+        // `impl Trait` return type, resulting in the parameters
+        // shifting.
+        let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
+        debug!(?id_substs);
+
+        // This zip may have several times the same lifetime in `substs` paired with a different
+        // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
+        // it will pick the last one, which is the one we introduced in the impl-trait desugaring.
+        let map = substs.iter().zip(id_substs).collect();
+        debug!("map = {:#?}", map);
+
+        // Convert the type from the function into a type valid outside
+        // the function, by replacing invalid regions with 'static,
+        // after producing an error for each of them.
+        self.fold_with(&mut ReverseMapper::new(tcx, map, self.span, ignore_errors))
+    }
+}
+
 impl<'tcx> ReverseMapper<'tcx> {
     pub(super) fn new(
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_middle/src/ty/opaque_hidden_type.rs b/compiler/rustc_middle/src/ty/opaque_hidden_type.rs
deleted file mode 100644
index db9aec621d21c..0000000000000
--- a/compiler/rustc_middle/src/ty/opaque_hidden_type.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-use rustc_errors::ErrorGuaranteed;
-use rustc_span::Span;
-
-use crate::error::OpaqueHiddenTypeMismatch;
-use crate::ty::{
-    opaque_types, InternalSubsts, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeMismatchReason,
-};
-
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
-pub struct OpaqueHiddenType<'tcx> {
-    /// The span of this particular definition of the opaque type. So
-    /// for example:
-    ///
-    /// ```ignore (incomplete snippet)
-    /// type Foo = impl Baz;
-    /// fn bar() -> Foo {
-    /// //          ^^^ This is the span we are looking for!
-    /// }
-    /// ```
-    ///
-    /// In cases where the fn returns `(impl Trait, impl Trait)` or
-    /// other such combinations, the result is currently
-    /// over-approximated, but better than nothing.
-    pub span: Span,
-
-    /// The type variable that represents the value of the opaque type
-    /// that we require. In other words, after we compile this function,
-    /// we will be created a constraint like:
-    /// ```ignore (pseudo-rust)
-    /// Foo<'a, T> = ?C
-    /// ```
-    /// where `?C` is the value of this type variable. =) It may
-    /// naturally refer to the type and lifetime parameters in scope
-    /// in this function, though ultimately it should only reference
-    /// those that are arguments to `Foo` in the constraint above. (In
-    /// other words, `?C` should not include `'b`, even though it's a
-    /// lifetime parameter on `foo`.)
-    pub ty: Ty<'tcx>,
-}
-
-impl<'tcx> OpaqueHiddenType<'tcx> {
-    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
-        // Found different concrete types for the opaque type.
-        let sub_diag = if self.span == other.span {
-            TypeMismatchReason::ConflictType { span: self.span }
-        } else {
-            TypeMismatchReason::PreviousUse { span: self.span }
-        };
-        tcx.sess.emit_err(OpaqueHiddenTypeMismatch {
-            self_ty: self.ty,
-            other_ty: other.ty,
-            other_span: other.span,
-            sub: sub_diag,
-        })
-    }
-
-    #[instrument(level = "debug", skip(tcx), ret)]
-    pub fn remap_generic_params_to_declaration_params(
-        self,
-        opaque_type_key: OpaqueTypeKey<'tcx>,
-        tcx: TyCtxt<'tcx>,
-        // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
-        ignore_errors: bool,
-    ) -> Self {
-        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
-        // Use substs to build up a reverse map from regions to their
-        // identity mappings. This is necessary because of `impl
-        // Trait` lifetimes are computed by replacing existing
-        // lifetimes with 'static and remapping only those used in the
-        // `impl Trait` return type, resulting in the parameters
-        // shifting.
-        let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
-        debug!(?id_substs);
-
-        // This zip may have several times the same lifetime in `substs` paired with a different
-        // lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
-        // it will pick the last one, which is the one we introduced in the impl-trait desugaring.
-        let map = substs.iter().zip(id_substs).collect();
-        debug!("map = {:#?}", map);
-
-        // Convert the type from the function into a type valid outside
-        // the function, by replacing invalid regions with 'static,
-        // after producing an error for each of them.
-        self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors))
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/opaque_type_key.rs b/compiler/rustc_middle/src/ty/opaque_type_key.rs
deleted file mode 100644
index 56920b571fd44..0000000000000
--- a/compiler/rustc_middle/src/ty/opaque_type_key.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use rustc_hir::def_id::LocalDefId;
-
-use crate::ty::SubstsRef;
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable, Lift)]
-#[derive(TypeFoldable, TypeVisitable)]
-pub struct OpaqueTypeKey<'tcx> {
-    pub def_id: LocalDefId,
-    pub substs: SubstsRef<'tcx>,
-}

From 335f7ca1b261b4532c45c0d7ac51d04485fd6e1d Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 16:30:46 +0000
Subject: [PATCH 31/38] Move `BoundConst` to `ty::consts`

---
 compiler/rustc_middle/src/ty/bound_const.rs |  8 --------
 compiler/rustc_middle/src/ty/consts/kind.rs | 20 ++++++++++++--------
 compiler/rustc_middle/src/ty/mod.rs         |  5 ++---
 3 files changed, 14 insertions(+), 19 deletions(-)
 delete mode 100644 compiler/rustc_middle/src/ty/bound_const.rs

diff --git a/compiler/rustc_middle/src/ty/bound_const.rs b/compiler/rustc_middle/src/ty/bound_const.rs
deleted file mode 100644
index c200e021dd873..0000000000000
--- a/compiler/rustc_middle/src/ty/bound_const.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use crate::ty::{BoundVar, Ty};
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
-#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
-pub struct BoundConst<'tcx> {
-    pub var: BoundVar,
-    pub ty: Ty<'tcx>,
-}
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 1ac2cd13982b9..c39ae6d57c9de 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,17 +1,14 @@
-use super::Const;
-use crate::mir;
-use crate::mir::interpret::{AllocId, ConstValue, Scalar};
-use crate::ty::abstract_const::CastKind;
-use crate::ty::subst::{InternalSubsts, SubstsRef};
-use crate::ty::ParamEnv;
-use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_target::abi::Size;
 
-use super::ScalarInt;
+use crate::mir;
+use crate::mir::interpret::{AllocId, ConstValue, Scalar};
+use crate::ty::abstract_const::CastKind;
+use crate::ty::subst::{InternalSubsts, SubstsRef};
+use crate::ty::{self, BoundVar, Const, List, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
 
 /// An unevaluated (potentially generic) constant used in the type-system.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
@@ -74,6 +71,13 @@ pub enum ConstKind<'tcx> {
     Expr(Expr<'tcx>),
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
+pub struct BoundConst<'tcx> {
+    pub var: BoundVar,
+    pub ty: Ty<'tcx>,
+}
+
 impl<'tcx> From<ty::ConstVid<'tcx>> for ConstKind<'tcx> {
     fn from(const_vid: ty::ConstVid<'tcx>) -> Self {
         InferConst::Var(const_vid).into()
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 5892bb4d35230..9c06422dff186 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -58,7 +58,6 @@ pub mod walk;
 mod adt;
 mod alias_relation_direction;
 mod assoc;
-mod bound_const;
 mod bound_constness;
 mod c_reader_cache_key;
 mod closure;
@@ -112,7 +111,6 @@ pub use self::alias_relation_direction::AliasRelationDirection;
 pub use self::assoc::*;
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
-pub use self::bound_const::BoundConst;
 pub use self::bound_constness::BoundConstness;
 pub use self::c_reader_cache_key::CReaderCacheKey;
 pub use self::closure::{
@@ -126,7 +124,8 @@ pub use self::coherence::{
     CrateInherentImpls, ImplHeader, ImplOverlapKind, ImplPolarity, ImplSubject,
 };
 pub use self::consts::{
-    Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+    BoundConst, Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt,
+    UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,

From b6237e6b9b98ab0d04b43c6f53fba089923fa65b Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 16:52:59 +0000
Subject: [PATCH 32/38] Group adt adjesent types into `ty::adt`

---
 compiler/rustc_middle/src/ty/adt.rs           | 537 ++++++++++++------
 compiler/rustc_middle/src/ty/field_def.rs     |  64 ---
 compiler/rustc_middle/src/ty/mod.rs           |  18 +-
 compiler/rustc_middle/src/ty/variant_def.rs   | 143 -----
 compiler/rustc_middle/src/ty/variant_discr.rs |  14 -
 compiler/rustc_middle/src/ty/variant_flags.rs |  11 -
 6 files changed, 382 insertions(+), 405 deletions(-)
 delete mode 100644 compiler/rustc_middle/src/ty/field_def.rs
 delete mode 100644 compiler/rustc_middle/src/ty/variant_def.rs
 delete mode 100644 compiler/rustc_middle/src/ty/variant_discr.rs
 delete mode 100644 compiler/rustc_middle/src/ty/variant_flags.rs

diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index ad9891a5dca68..97950f2a11ae1 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -1,56 +1,30 @@
-use crate::mir::interpret::ErrorHandled;
-use crate::ty;
-use crate::ty::util::{Discr, IntTypeExt};
+use std::cell::RefCell;
+use std::cmp::Ordering;
+use std::hash::{Hash, Hasher};
+use std::ops::Range;
+use std::str;
+
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::intern::Interned;
-use rustc_data_structures::stable_hasher::HashingControls;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::DataTypeKind;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT};
 
-use std::cell::RefCell;
-use std::cmp::Ordering;
-use std::hash::{Hash, Hasher};
-use std::ops::Range;
-use std::str;
-
-use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr};
+use crate::mir::interpret::ErrorHandled;
+use crate::ty::util::{Discr, IntTypeExt};
+use crate::ty::{self, Destructor, FieldIdx, GenericPredicates, SubstsRef, Ty, TyCtxt, Visibility};
 
-bitflags! {
-    #[derive(HashStable, TyEncodable, TyDecodable)]
-    pub struct AdtFlags: u16 {
-        const NO_ADT_FLAGS        = 0;
-        /// Indicates whether the ADT is an enum.
-        const IS_ENUM             = 1 << 0;
-        /// Indicates whether the ADT is a union.
-        const IS_UNION            = 1 << 1;
-        /// Indicates whether the ADT is a struct.
-        const IS_STRUCT           = 1 << 2;
-        /// Indicates whether the ADT is a struct and has a constructor.
-        const HAS_CTOR            = 1 << 3;
-        /// Indicates whether the type is `PhantomData`.
-        const IS_PHANTOM_DATA     = 1 << 4;
-        /// Indicates whether the type has a `#[fundamental]` attribute.
-        const IS_FUNDAMENTAL      = 1 << 5;
-        /// Indicates whether the type is `Box`.
-        const IS_BOX              = 1 << 6;
-        /// Indicates whether the type is `ManuallyDrop`.
-        const IS_MANUALLY_DROP    = 1 << 7;
-        /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
-        /// (i.e., this flag is never set unless this ADT is an enum).
-        const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
-        /// Indicates whether the type is `UnsafeCell`.
-        const IS_UNSAFE_CELL              = 1 << 9;
-    }
-}
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
+#[rustc_pass_by_value]
+pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>);
 
 /// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`.
 ///
@@ -97,69 +71,98 @@ pub struct AdtDefData {
     repr: ReprOptions,
 }
 
-impl PartialOrd for AdtDefData {
-    fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> {
-        Some(self.cmp(&other))
+bitflags! {
+    #[derive(HashStable, TyEncodable, TyDecodable)]
+    pub struct AdtFlags: u16 {
+        const NO_ADT_FLAGS        = 0;
+        /// Indicates whether the ADT is an enum.
+        const IS_ENUM             = 1 << 0;
+        /// Indicates whether the ADT is a union.
+        const IS_UNION            = 1 << 1;
+        /// Indicates whether the ADT is a struct.
+        const IS_STRUCT           = 1 << 2;
+        /// Indicates whether the ADT is a struct and has a constructor.
+        const HAS_CTOR            = 1 << 3;
+        /// Indicates whether the type is `PhantomData`.
+        const IS_PHANTOM_DATA     = 1 << 4;
+        /// Indicates whether the type has a `#[fundamental]` attribute.
+        const IS_FUNDAMENTAL      = 1 << 5;
+        /// Indicates whether the type is `Box`.
+        const IS_BOX              = 1 << 6;
+        /// Indicates whether the type is `ManuallyDrop`.
+        const IS_MANUALLY_DROP    = 1 << 7;
+        /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
+        /// (i.e., this flag is never set unless this ADT is an enum).
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
+        /// Indicates whether the type is `UnsafeCell`.
+        const IS_UNSAFE_CELL              = 1 << 9;
     }
 }
 
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `Ord` only based on `did`.
-impl Ord for AdtDefData {
-    fn cmp(&self, other: &AdtDefData) -> Ordering {
-        self.did.cmp(&other.did)
-    }
+#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
+pub enum AdtKind {
+    Struct,
+    Union,
+    Enum,
 }
 
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `PartialEq` only based on `did`.
-impl PartialEq for AdtDefData {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        self.did == other.did
-    }
+/// Definition of a variant -- a struct's fields or an enum variant.
+#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
+pub struct VariantDef {
+    /// `DefId` that identifies the variant itself.
+    /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
+    pub def_id: DefId,
+    /// `DefId` that identifies the variant's constructor.
+    /// If this variant is a struct variant, then this is `None`.
+    pub ctor: Option<(CtorKind, DefId)>,
+    /// Variant or struct name.
+    pub name: Symbol,
+    /// Discriminant of this variant.
+    pub discr: VariantDiscr,
+    /// Fields of this variant.
+    pub fields: IndexVec<FieldIdx, FieldDef>,
+    /// Flags of the variant (e.g. is field list non-exhaustive)?
+    flags: VariantFlags,
 }
 
-impl Eq for AdtDefData {}
-
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `Hash` only based on `did`.
-impl Hash for AdtDefData {
-    #[inline]
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        self.did.hash(s)
+bitflags! {
+    #[derive(HashStable, TyEncodable, TyDecodable)]
+    pub struct VariantFlags: u8 {
+        const NO_VARIANT_FLAGS = 0;
+        /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
+        const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
+        /// Indicates whether this variant was obtained as part of recovering from
+        /// a syntactic error. May be incomplete or bogus.
+        const IS_RECOVERED = 1 << 1;
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for AdtDefData {
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        thread_local! {
-            static CACHE: RefCell<FxHashMap<(usize, HashingControls), Fingerprint>> = Default::default();
-        }
-
-        let hash: Fingerprint = CACHE.with(|cache| {
-            let addr = self as *const AdtDefData as usize;
-            let hashing_controls = hcx.hashing_controls();
-            *cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| {
-                let ty::AdtDefData { did, ref variants, ref flags, ref repr } = *self;
-
-                let mut hasher = StableHasher::new();
-                did.hash_stable(hcx, &mut hasher);
-                variants.hash_stable(hcx, &mut hasher);
-                flags.hash_stable(hcx, &mut hasher);
-                repr.hash_stable(hcx, &mut hasher);
-
-                hasher.finish()
-            })
-        });
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
+pub enum VariantDiscr {
+    /// Explicit value for this variant, i.e., `X = 123`.
+    /// The `DefId` corresponds to the embedded constant.
+    Explicit(DefId),
+
+    /// The previous variant's discriminant plus one.
+    /// For efficiency reasons, the distance from the
+    /// last `Explicit` discriminant is being stored,
+    /// or `0` for the first variant, if it has none.
+    Relative(u32),
+}
 
-        hash.hash_stable(hcx, hasher);
-    }
+#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
+pub struct FieldDef {
+    pub did: DefId,
+    pub name: Symbol,
+    pub vis: Visibility<DefId>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)]
-#[rustc_pass_by_value]
-pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>);
+#[derive(Clone, Copy, Debug)]
+#[derive(HashStable)]
+pub enum Representability {
+    Representable,
+    Infinite,
+}
 
 impl<'tcx> AdtDef<'tcx> {
     #[inline]
@@ -186,73 +189,7 @@ impl<'tcx> AdtDef<'tcx> {
     pub fn repr(self) -> ReprOptions {
         self.0.0.repr
     }
-}
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
-pub enum AdtKind {
-    Struct,
-    Union,
-    Enum,
-}
-
-impl Into<DataTypeKind> for AdtKind {
-    fn into(self) -> DataTypeKind {
-        match self {
-            AdtKind::Struct => DataTypeKind::Struct,
-            AdtKind::Union => DataTypeKind::Union,
-            AdtKind::Enum => DataTypeKind::Enum,
-        }
-    }
-}
-
-impl AdtDefData {
-    /// Creates a new `AdtDefData`.
-    pub(super) fn new(
-        tcx: TyCtxt<'_>,
-        did: DefId,
-        kind: AdtKind,
-        variants: IndexVec<VariantIdx, VariantDef>,
-        repr: ReprOptions,
-    ) -> Self {
-        debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
-        let mut flags = AdtFlags::NO_ADT_FLAGS;
-
-        if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
-            debug!("found non-exhaustive variant list for {:?}", did);
-            flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
-        }
-
-        flags |= match kind {
-            AdtKind::Enum => AdtFlags::IS_ENUM,
-            AdtKind::Union => AdtFlags::IS_UNION,
-            AdtKind::Struct => AdtFlags::IS_STRUCT,
-        };
-
-        if kind == AdtKind::Struct && variants[FIRST_VARIANT].ctor.is_some() {
-            flags |= AdtFlags::HAS_CTOR;
-        }
-
-        if tcx.has_attr(did, sym::fundamental) {
-            flags |= AdtFlags::IS_FUNDAMENTAL;
-        }
-        if Some(did) == tcx.lang_items().phantom_data() {
-            flags |= AdtFlags::IS_PHANTOM_DATA;
-        }
-        if Some(did) == tcx.lang_items().owned_box() {
-            flags |= AdtFlags::IS_BOX;
-        }
-        if Some(did) == tcx.lang_items().manually_drop() {
-            flags |= AdtFlags::IS_MANUALLY_DROP;
-        }
-        if Some(did) == tcx.lang_items().unsafe_cell_type() {
-            flags |= AdtFlags::IS_UNSAFE_CELL;
-        }
-
-        AdtDefData { did, variants, flags, repr }
-    }
-}
 
-impl<'tcx> AdtDef<'tcx> {
     /// Returns `true` if this is a struct.
     #[inline]
     pub fn is_struct(self) -> bool {
@@ -559,9 +496,287 @@ impl<'tcx> AdtDef<'tcx> {
     }
 }
 
-#[derive(Clone, Copy, Debug)]
-#[derive(HashStable)]
-pub enum Representability {
-    Representable,
-    Infinite,
+impl AdtDefData {
+    /// Creates a new `AdtDefData`.
+    pub(super) fn new(
+        tcx: TyCtxt<'_>,
+        did: DefId,
+        kind: AdtKind,
+        variants: IndexVec<VariantIdx, VariantDef>,
+        repr: ReprOptions,
+    ) -> Self {
+        debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
+        let mut flags = AdtFlags::NO_ADT_FLAGS;
+
+        if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
+            debug!("found non-exhaustive variant list for {:?}", did);
+            flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
+        }
+
+        flags |= match kind {
+            AdtKind::Enum => AdtFlags::IS_ENUM,
+            AdtKind::Union => AdtFlags::IS_UNION,
+            AdtKind::Struct => AdtFlags::IS_STRUCT,
+        };
+
+        if kind == AdtKind::Struct && variants[FIRST_VARIANT].ctor.is_some() {
+            flags |= AdtFlags::HAS_CTOR;
+        }
+
+        if tcx.has_attr(did, sym::fundamental) {
+            flags |= AdtFlags::IS_FUNDAMENTAL;
+        }
+        if Some(did) == tcx.lang_items().phantom_data() {
+            flags |= AdtFlags::IS_PHANTOM_DATA;
+        }
+        if Some(did) == tcx.lang_items().owned_box() {
+            flags |= AdtFlags::IS_BOX;
+        }
+        if Some(did) == tcx.lang_items().manually_drop() {
+            flags |= AdtFlags::IS_MANUALLY_DROP;
+        }
+        if Some(did) == tcx.lang_items().unsafe_cell_type() {
+            flags |= AdtFlags::IS_UNSAFE_CELL;
+        }
+
+        AdtDefData { did, variants, flags, repr }
+    }
+}
+
+impl PartialOrd for AdtDefData {
+    fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> {
+        Some(self.cmp(&other))
+    }
+}
+
+/// There should be only one AdtDef for each `did`, therefore
+/// it is fine to implement `Ord` only based on `did`.
+impl Ord for AdtDefData {
+    fn cmp(&self, other: &AdtDefData) -> Ordering {
+        self.did.cmp(&other.did)
+    }
+}
+
+/// There should be only one AdtDef for each `did`, therefore
+/// it is fine to implement `PartialEq` only based on `did`.
+impl PartialEq for AdtDefData {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        self.did == other.did
+    }
+}
+
+impl Eq for AdtDefData {}
+
+/// There should be only one AdtDef for each `did`, therefore
+/// it is fine to implement `Hash` only based on `did`.
+impl Hash for AdtDefData {
+    #[inline]
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        self.did.hash(s)
+    }
+}
+
+impl<'a> HashStable<StableHashingContext<'a>> for AdtDefData {
+    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
+        thread_local! {
+            static CACHE: RefCell<FxHashMap<(usize, HashingControls), Fingerprint>> = Default::default();
+        }
+
+        let hash: Fingerprint = CACHE.with(|cache| {
+            let addr = self as *const AdtDefData as usize;
+            let hashing_controls = hcx.hashing_controls();
+            *cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| {
+                let ty::AdtDefData { did, ref variants, ref flags, ref repr } = *self;
+
+                let mut hasher = StableHasher::new();
+                did.hash_stable(hcx, &mut hasher);
+                variants.hash_stable(hcx, &mut hasher);
+                flags.hash_stable(hcx, &mut hasher);
+                repr.hash_stable(hcx, &mut hasher);
+
+                hasher.finish()
+            })
+        });
+
+        hash.hash_stable(hcx, hasher);
+    }
+}
+
+impl Into<DataTypeKind> for AdtKind {
+    fn into(self) -> DataTypeKind {
+        match self {
+            AdtKind::Struct => DataTypeKind::Struct,
+            AdtKind::Union => DataTypeKind::Union,
+            AdtKind::Enum => DataTypeKind::Enum,
+        }
+    }
+}
+
+impl VariantDef {
+    /// Creates a new `VariantDef`.
+    ///
+    /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
+    /// represents an enum variant).
+    ///
+    /// `ctor_did` is the `DefId` that identifies the constructor of unit or
+    /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`.
+    ///
+    /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that
+    /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having
+    /// to go through the redirect of checking the ctor's attributes - but compiling a small crate
+    /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
+    /// built-in trait), and we do not want to load attributes twice.
+    ///
+    /// If someone speeds up attribute loading to not be a performance concern, they can
+    /// remove this hack and use the constructor `DefId` everywhere.
+    pub fn new(
+        name: Symbol,
+        variant_did: Option<DefId>,
+        ctor: Option<(CtorKind, DefId)>,
+        discr: VariantDiscr,
+        fields: IndexVec<FieldIdx, FieldDef>,
+        adt_kind: AdtKind,
+        parent_did: DefId,
+        recovered: bool,
+        is_field_list_non_exhaustive: bool,
+    ) -> Self {
+        debug!(
+            "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
+             fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
+            name, variant_did, ctor, discr, fields, adt_kind, parent_did,
+        );
+
+        let mut flags = VariantFlags::NO_VARIANT_FLAGS;
+        if is_field_list_non_exhaustive {
+            flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
+        }
+
+        if recovered {
+            flags |= VariantFlags::IS_RECOVERED;
+        }
+
+        VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
+    }
+
+    /// Is this field list non-exhaustive?
+    #[inline]
+    pub fn is_field_list_non_exhaustive(&self) -> bool {
+        self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
+    }
+
+    /// Was this variant obtained as part of recovering from a syntactic error?
+    #[inline]
+    pub fn is_recovered(&self) -> bool {
+        self.flags.intersects(VariantFlags::IS_RECOVERED)
+    }
+
+    /// Computes the `Ident` of this variant by looking up the `Span`
+    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
+        Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
+    }
+
+    #[inline]
+    pub fn ctor_kind(&self) -> Option<CtorKind> {
+        self.ctor.map(|(kind, _)| kind)
+    }
+
+    #[inline]
+    pub fn ctor_def_id(&self) -> Option<DefId> {
+        self.ctor.map(|(_, def_id)| def_id)
+    }
+
+    /// Returns the one field in this variant.
+    ///
+    /// `panic!`s if there are no fields or multiple fields.
+    #[inline]
+    pub fn single_field(&self) -> &FieldDef {
+        assert!(self.fields.len() == 1);
+
+        &self.fields[FieldIdx::from_u32(0)]
+    }
+}
+
+impl PartialEq for VariantDef {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        // There should be only one `VariantDef` for each `def_id`, therefore
+        // it is fine to implement `PartialEq` only based on `def_id`.
+        //
+        // Below, we exhaustively destructure `self` and `other` so that if the
+        // definition of `VariantDef` changes, a compile-error will be produced,
+        // reminding us to revisit this assumption.
+
+        let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
+        let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
+        lhs_def_id == rhs_def_id
+    }
+}
+
+impl Eq for VariantDef {}
+
+impl Hash for VariantDef {
+    #[inline]
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        // There should be only one `VariantDef` for each `def_id`, therefore
+        // it is fine to implement `Hash` only based on `def_id`.
+        //
+        // Below, we exhaustively destructure `self` so that if the definition
+        // of `VariantDef` changes, a compile-error will be produced, reminding
+        // us to revisit this assumption.
+
+        let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
+        def_id.hash(s)
+    }
+}
+
+impl<'tcx> FieldDef {
+    /// Returns the type of this field. The resulting type is not normalized. The `subst` is
+    /// typically obtained via the second field of [`TyKind::Adt`].
+    ///
+    /// [`TyKind::Adt`]: crate::ty::TyKind::Adt
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
+        tcx.type_of(self.did).subst(tcx, subst)
+    }
+
+    /// Computes the `Ident` of this variant by looking up the `Span`
+    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
+        Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
+    }
+}
+
+impl PartialEq for FieldDef {
+    #[inline]
+    fn eq(&self, other: &Self) -> bool {
+        // There should be only one `FieldDef` for each `did`, therefore it is
+        // fine to implement `PartialEq` only based on `did`.
+        //
+        // Below, we exhaustively destructure `self` so that if the definition
+        // of `FieldDef` changes, a compile-error will be produced, reminding
+        // us to revisit this assumption.
+
+        let Self { did: lhs_did, name: _, vis: _ } = &self;
+
+        let Self { did: rhs_did, name: _, vis: _ } = other;
+
+        lhs_did == rhs_did
+    }
+}
+
+impl Eq for FieldDef {}
+
+impl Hash for FieldDef {
+    #[inline]
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        // There should be only one `FieldDef` for each `did`, therefore it is
+        // fine to implement `Hash` only based on `did`.
+        //
+        // Below, we exhaustively destructure `self` so that if the definition
+        // of `FieldDef` changes, a compile-error will be produced, reminding
+        // us to revisit this assumption.
+
+        let Self { did, name: _, vis: _ } = &self;
+
+        did.hash(s)
+    }
 }
diff --git a/compiler/rustc_middle/src/ty/field_def.rs b/compiler/rustc_middle/src/ty/field_def.rs
deleted file mode 100644
index 638123e290d70..0000000000000
--- a/compiler/rustc_middle/src/ty/field_def.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-use std::hash::{Hash, Hasher};
-
-use rustc_hir::def_id::DefId;
-use rustc_span::symbol::{Ident, Symbol};
-
-use crate::ty::{SubstsRef, Ty, TyCtxt, Visibility};
-
-#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
-pub struct FieldDef {
-    pub did: DefId,
-    pub name: Symbol,
-    pub vis: Visibility<DefId>,
-}
-
-impl PartialEq for FieldDef {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        // There should be only one `FieldDef` for each `did`, therefore it is
-        // fine to implement `PartialEq` only based on `did`.
-        //
-        // Below, we exhaustively destructure `self` so that if the definition
-        // of `FieldDef` changes, a compile-error will be produced, reminding
-        // us to revisit this assumption.
-
-        let Self { did: lhs_did, name: _, vis: _ } = &self;
-
-        let Self { did: rhs_did, name: _, vis: _ } = other;
-
-        lhs_did == rhs_did
-    }
-}
-
-impl Eq for FieldDef {}
-
-impl Hash for FieldDef {
-    #[inline]
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        // There should be only one `FieldDef` for each `did`, therefore it is
-        // fine to implement `Hash` only based on `did`.
-        //
-        // Below, we exhaustively destructure `self` so that if the definition
-        // of `FieldDef` changes, a compile-error will be produced, reminding
-        // us to revisit this assumption.
-
-        let Self { did, name: _, vis: _ } = &self;
-
-        did.hash(s)
-    }
-}
-
-impl<'tcx> FieldDef {
-    /// Returns the type of this field. The resulting type is not normalized. The `subst` is
-    /// typically obtained via the second field of [`TyKind::Adt`].
-    ///
-    /// [`TyKind::Adt`]: crate::ty::TyKind::Adt
-    pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
-        tcx.type_of(self.did).subst(tcx, subst)
-    }
-
-    /// Computes the `Ident` of this variant by looking up the `Span`
-    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
-        Ident::new(self.name, tcx.def_ident_span(self.did).unwrap())
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 9c06422dff186..ca8b79f1910ce 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -16,7 +16,7 @@ use rustc_attr as attr;
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Node;
 use rustc_serialize::{Decodable, Encodable};
@@ -62,6 +62,7 @@ mod bound_constness;
 mod c_reader_cache_key;
 mod closure;
 mod closure_size_profile_data;
+mod coherence;
 mod consts;
 mod context;
 mod crate_variances_map;
@@ -69,7 +70,6 @@ mod destructor;
 mod destructured_const;
 mod diagnostics;
 mod erase_regions;
-mod field_def;
 mod generics;
 mod impl_trait_in_trait_data;
 mod impls_ty;
@@ -90,13 +90,8 @@ mod symbol_name;
 mod term;
 mod ty_; // FIXME: rename to `ty` once we don't import `crate::ty` here
 mod typeck_results;
-mod variant_def;
-mod variant_discr;
-mod variant_flags;
 mod visibility;
 
-mod coherence;
-
 pub use rustc_session::lint::RegisteredTools;
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
 pub use rustc_type_ir::AliasKind::*;
@@ -106,7 +101,10 @@ pub use rustc_type_ir::RegionKind::*;
 pub use rustc_type_ir::TyKind::*;
 pub use rustc_type_ir::*;
 
-pub use self::adt::*;
+pub use self::adt::{
+    AdtDef, AdtDefData, AdtFlags, AdtKind, FieldDef, Representability, VariantDef, VariantDiscr,
+    VariantFlags,
+};
 pub use self::alias_relation_direction::AliasRelationDirection;
 pub use self::assoc::*;
 pub use self::binding::BindingMode;
@@ -134,7 +132,6 @@ pub use self::crate_variances_map::CrateVariancesMap;
 pub use self::destructor::Destructor;
 pub use self::destructured_const::DestructuredConst;
 pub use self::diagnostics::*;
-pub use self::field_def::FieldDef;
 pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 pub use self::generics::*;
 pub use self::impl_trait_in_trait_data::ImplTraitInTraitData;
@@ -175,9 +172,6 @@ pub use self::typeck_results::{
     GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
     UserTypeAnnotationIndex,
 };
-pub use self::variant_def::VariantDef;
-pub use self::variant_discr::VariantDiscr;
-pub use self::variant_flags::VariantFlags;
 pub use self::visibility::Visibility;
 pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 pub use self::vtable::*;
diff --git a/compiler/rustc_middle/src/ty/variant_def.rs b/compiler/rustc_middle/src/ty/variant_def.rs
deleted file mode 100644
index e05eddc10af5e..0000000000000
--- a/compiler/rustc_middle/src/ty/variant_def.rs
+++ /dev/null
@@ -1,143 +0,0 @@
-use std::hash::{Hash, Hasher};
-
-use rustc_hir::def_id::DefId;
-use rustc_index::IndexVec;
-use rustc_span::symbol::{Ident, Symbol};
-
-use crate::ty::{AdtKind, CtorKind, FieldDef, FieldIdx, TyCtxt, VariantDiscr, VariantFlags};
-
-/// Definition of a variant -- a struct's fields or an enum variant.
-#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
-pub struct VariantDef {
-    /// `DefId` that identifies the variant itself.
-    /// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
-    pub def_id: DefId,
-    /// `DefId` that identifies the variant's constructor.
-    /// If this variant is a struct variant, then this is `None`.
-    pub ctor: Option<(CtorKind, DefId)>,
-    /// Variant or struct name.
-    pub name: Symbol,
-    /// Discriminant of this variant.
-    pub discr: VariantDiscr,
-    /// Fields of this variant.
-    pub fields: IndexVec<FieldIdx, FieldDef>,
-    /// Flags of the variant (e.g. is field list non-exhaustive)?
-    flags: VariantFlags,
-}
-
-impl VariantDef {
-    /// Creates a new `VariantDef`.
-    ///
-    /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef`
-    /// represents an enum variant).
-    ///
-    /// `ctor_did` is the `DefId` that identifies the constructor of unit or
-    /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`.
-    ///
-    /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that
-    /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having
-    /// to go through the redirect of checking the ctor's attributes - but compiling a small crate
-    /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any
-    /// built-in trait), and we do not want to load attributes twice.
-    ///
-    /// If someone speeds up attribute loading to not be a performance concern, they can
-    /// remove this hack and use the constructor `DefId` everywhere.
-    pub fn new(
-        name: Symbol,
-        variant_did: Option<DefId>,
-        ctor: Option<(CtorKind, DefId)>,
-        discr: VariantDiscr,
-        fields: IndexVec<FieldIdx, FieldDef>,
-        adt_kind: AdtKind,
-        parent_did: DefId,
-        recovered: bool,
-        is_field_list_non_exhaustive: bool,
-    ) -> Self {
-        debug!(
-            "VariantDef::new(name = {:?}, variant_did = {:?}, ctor = {:?}, discr = {:?},
-             fields = {:?}, adt_kind = {:?}, parent_did = {:?})",
-            name, variant_did, ctor, discr, fields, adt_kind, parent_did,
-        );
-
-        let mut flags = VariantFlags::NO_VARIANT_FLAGS;
-        if is_field_list_non_exhaustive {
-            flags |= VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE;
-        }
-
-        if recovered {
-            flags |= VariantFlags::IS_RECOVERED;
-        }
-
-        VariantDef { def_id: variant_did.unwrap_or(parent_did), ctor, name, discr, fields, flags }
-    }
-
-    /// Is this field list non-exhaustive?
-    #[inline]
-    pub fn is_field_list_non_exhaustive(&self) -> bool {
-        self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
-    }
-
-    /// Was this variant obtained as part of recovering from a syntactic error?
-    #[inline]
-    pub fn is_recovered(&self) -> bool {
-        self.flags.intersects(VariantFlags::IS_RECOVERED)
-    }
-
-    /// Computes the `Ident` of this variant by looking up the `Span`
-    pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
-        Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())
-    }
-
-    #[inline]
-    pub fn ctor_kind(&self) -> Option<CtorKind> {
-        self.ctor.map(|(kind, _)| kind)
-    }
-
-    #[inline]
-    pub fn ctor_def_id(&self) -> Option<DefId> {
-        self.ctor.map(|(_, def_id)| def_id)
-    }
-
-    /// Returns the one field in this variant.
-    ///
-    /// `panic!`s if there are no fields or multiple fields.
-    #[inline]
-    pub fn single_field(&self) -> &FieldDef {
-        assert!(self.fields.len() == 1);
-
-        &self.fields[FieldIdx::from_u32(0)]
-    }
-}
-
-impl PartialEq for VariantDef {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool {
-        // There should be only one `VariantDef` for each `def_id`, therefore
-        // it is fine to implement `PartialEq` only based on `def_id`.
-        //
-        // Below, we exhaustively destructure `self` and `other` so that if the
-        // definition of `VariantDef` changes, a compile-error will be produced,
-        // reminding us to revisit this assumption.
-
-        let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
-        let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
-        lhs_def_id == rhs_def_id
-    }
-}
-
-impl Eq for VariantDef {}
-
-impl Hash for VariantDef {
-    #[inline]
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        // There should be only one `VariantDef` for each `def_id`, therefore
-        // it is fine to implement `Hash` only based on `def_id`.
-        //
-        // Below, we exhaustively destructure `self` so that if the definition
-        // of `VariantDef` changes, a compile-error will be produced, reminding
-        // us to revisit this assumption.
-
-        let Self { def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
-        def_id.hash(s)
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/variant_discr.rs b/compiler/rustc_middle/src/ty/variant_discr.rs
deleted file mode 100644
index f792e4e3bd096..0000000000000
--- a/compiler/rustc_middle/src/ty/variant_discr.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use rustc_hir::def_id::DefId;
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
-pub enum VariantDiscr {
-    /// Explicit value for this variant, i.e., `X = 123`.
-    /// The `DefId` corresponds to the embedded constant.
-    Explicit(DefId),
-
-    /// The previous variant's discriminant plus one.
-    /// For efficiency reasons, the distance from the
-    /// last `Explicit` discriminant is being stored,
-    /// or `0` for the first variant, if it has none.
-    Relative(u32),
-}
diff --git a/compiler/rustc_middle/src/ty/variant_flags.rs b/compiler/rustc_middle/src/ty/variant_flags.rs
deleted file mode 100644
index 07b530ce4b3d5..0000000000000
--- a/compiler/rustc_middle/src/ty/variant_flags.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-bitflags! {
-    #[derive(HashStable, TyEncodable, TyDecodable)]
-    pub struct VariantFlags: u8 {
-        const NO_VARIANT_FLAGS = 0;
-        /// Indicates whether the field list of this variant is `#[non_exhaustive]`.
-        const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
-        /// Indicates whether this variant was obtained as part of recovering from
-        /// a syntactic error. May be incomplete or bogus.
-        const IS_RECOVERED = 1 << 1;
-    }
-}

From 413370b41be84037b63d94d2f02cf3e9aa948340 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 17:34:18 +0000
Subject: [PATCH 33/38] Move `rustc_middle::{ty=>}::resolver_outputs`

... and add `MainDefinition` to it
---
 compiler/rustc_ast_lowering/src/item.rs        |  3 ++-
 compiler/rustc_ast_lowering/src/lib.rs         |  5 +----
 .../src/lifetime_collector.rs                  |  2 +-
 compiler/rustc_interface/src/passes.rs         |  5 +++--
 compiler/rustc_middle/src/arena.rs             |  4 ++--
 compiler/rustc_middle/src/lib.rs               |  1 +
 compiler/rustc_middle/src/query/mod.rs         |  4 ++--
 .../src/{ty => }/resolver_outputs.rs           | 17 +++++++++++++++--
 .../rustc_middle/src/ty/main_definition.rs     | 18 ------------------
 compiler/rustc_middle/src/ty/mod.rs            |  4 ----
 compiler/rustc_passes/src/errors.rs            |  3 ++-
 compiler/rustc_resolve/src/lib.rs              |  8 +++++---
 12 files changed, 34 insertions(+), 40 deletions(-)
 rename compiler/rustc_middle/src/{ty => }/resolver_outputs.rs (90%)
 delete mode 100644 compiler/rustc_middle/src/ty/main_definition.rs

diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 3d154a93fb2da..9c646642187f7 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -13,7 +13,8 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::PredicateOrigin;
 use rustc_index::{Idx, IndexSlice, IndexVec};
-use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
+use rustc_middle::resolver_outputs::ResolverAstLowering;
+use rustc_middle::ty::TyCtxt;
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident};
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 0d21c8a84d028..edf5ac17ffc4e 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -62,10 +62,7 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
-use rustc_middle::{
-    span_bug,
-    ty::{ResolverAstLowering, TyCtxt},
-};
+use rustc_middle::{resolver_outputs::ResolverAstLowering, span_bug, ty::TyCtxt};
 use rustc_session::parse::{add_feature_diagnostics, feature_err};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::DesugaringKind;
diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
index 3989fc486193e..241768dea2665 100644
--- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs
+++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs
@@ -2,8 +2,8 @@ use super::ResolverAstLoweringExt;
 use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
 use rustc_ast::{FnRetTy, GenericBounds, Lifetime, NodeId, PathSegment, PolyTraitRef, Ty, TyKind};
 use rustc_hir::def::LifetimeRes;
+use rustc_middle::resolver_outputs::ResolverAstLowering;
 use rustc_middle::span_bug;
-use rustc_middle::ty::ResolverAstLowering;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::Span;
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 48401eabd1ed1..30073c65d5830 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -17,6 +17,7 @@ use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintSto
 use rustc_metadata::creader::CStore;
 use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
+use rustc_middle::resolver_outputs::{ResolverAstLowering, ResolverOutputs};
 use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
 use rustc_mir_build as mir_build;
@@ -557,7 +558,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
 fn resolver_for_lowering<'tcx>(
     tcx: TyCtxt<'tcx>,
     (): (),
-) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
+) -> &'tcx Steal<(ResolverAstLowering, Lrc<ast::Crate>)> {
     let arenas = Resolver::arenas();
     let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
     let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
@@ -567,7 +568,7 @@ fn resolver_for_lowering<'tcx>(
     // Make sure we don't mutate the cstore from here on.
     tcx.untracked().cstore.leak();
 
-    let ty::ResolverOutputs {
+    let ResolverOutputs {
         global_ctxt: untracked_resolutions,
         ast_lowering: untracked_resolver_for_lowering,
     } = resolver.into_outputs();
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 6a1a2a061ddd6..88c573586f792 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -31,13 +31,13 @@ macro_rules! arena_types {
             [decode] borrowck_result:
                 rustc_middle::mir::BorrowCheckResult<'tcx>,
             [] resolver: rustc_data_structures::steal::Steal<(
-                rustc_middle::ty::ResolverAstLowering,
+                rustc_middle::resolver_outputs::ResolverAstLowering,
                 rustc_data_structures::sync::Lrc<rustc_ast::Crate>,
             )>,
             [] output_filenames: std::sync::Arc<rustc_session::config::OutputFilenames>,
             [] metadata_loader: rustc_data_structures::steal::Steal<Box<rustc_session::cstore::MetadataLoaderDyn>>,
             [] crate_for_resolver: rustc_data_structures::steal::Steal<(rustc_ast::Crate, rustc_ast::AttrVec)>,
-            [] resolutions: rustc_middle::ty::ResolverGlobalCtxt,
+            [] resolutions: rustc_middle::resolver_outputs::ResolverGlobalCtxt,
             [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
             [decode] code_region: rustc_middle::mir::coverage::CodeRegion,
             [] const_allocs: rustc_middle::mir::interpret::Allocation,
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index e9172e767e036..e3256cfffc768 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -98,6 +98,7 @@ pub mod lint;
 pub mod metadata;
 pub mod middle;
 pub mod mir;
+pub mod resolver_outputs;
 pub mod thir;
 pub mod traits;
 pub mod ty;
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index b425c7600ac68..29798c21c5c50 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -37,13 +37,13 @@ rustc_queries! {
         desc { "perform lints prior to macro expansion" }
     }
 
-    query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
+    query resolutions(_: ()) -> &'tcx crate::resolver_outputs::ResolverGlobalCtxt {
         feedable
         no_hash
         desc { "getting the resolver outputs" }
     }
 
-    query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)> {
+    query resolver_for_lowering(_: ()) -> &'tcx Steal<(crate::resolver_outputs::ResolverAstLowering, Lrc<ast::Crate>)> {
         eval_always
         no_hash
         desc { "getting the resolver for lowering" }
diff --git a/compiler/rustc_middle/src/ty/resolver_outputs.rs b/compiler/rustc_middle/src/resolver_outputs.rs
similarity index 90%
rename from compiler/rustc_middle/src/ty/resolver_outputs.rs
rename to compiler/rustc_middle/src/resolver_outputs.rs
index 59a7a729f1e5e..1cb7a259d97f3 100644
--- a/compiler/rustc_middle/src/ty/resolver_outputs.rs
+++ b/compiler/rustc_middle/src/resolver_outputs.rs
@@ -3,7 +3,7 @@ use rustc_ast::node_id::NodeMap;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::steal::Steal;
 use rustc_hir as hir;
-use rustc_hir::def::{DocLinkResMap, LifetimeRes, Res};
+use rustc_hir::def::{DefKind, DocLinkResMap, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
 use rustc_index::IndexVec;
 use rustc_session::lint::LintBuffer;
@@ -13,7 +13,7 @@ use rustc_span::{ExpnId, Span};
 
 use crate::metadata::ModChild;
 use crate::middle::privacy::EffectiveVisibilities;
-use crate::ty::{MainDefinition, Visibility};
+use crate::ty::Visibility;
 
 pub struct ResolverOutputs {
     pub global_ctxt: ResolverGlobalCtxt,
@@ -77,3 +77,16 @@ pub struct ResolverAstLowering {
     /// Lints that were emitted by the resolver and early lints.
     pub lint_buffer: Steal<LintBuffer>,
 }
+
+#[derive(Clone, Copy, Debug)]
+pub struct MainDefinition {
+    pub res: Res<ast::NodeId>,
+    pub is_import: bool,
+    pub span: Span,
+}
+
+impl MainDefinition {
+    pub fn opt_fn_def_id(self) -> Option<DefId> {
+        if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/main_definition.rs b/compiler/rustc_middle/src/ty/main_definition.rs
deleted file mode 100644
index 6637fb8e158b0..0000000000000
--- a/compiler/rustc_middle/src/ty/main_definition.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-use rustc_span::Span;
-
-use rustc_ast as ast;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
-
-#[derive(Clone, Copy, Debug)]
-pub struct MainDefinition {
-    pub res: Res<ast::NodeId>,
-    pub is_import: bool,
-    pub span: Span,
-}
-
-impl MainDefinition {
-    pub fn opt_fn_def_id(self) -> Option<DefId> {
-        if let Res::Def(DefKind::Fn, def_id) = self.res { Some(def_id) } else { None }
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index ca8b79f1910ce..3a97a9bb57a99 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -76,13 +76,11 @@ mod impls_ty;
 mod infer_var_info;
 mod instance;
 mod list;
-mod main_definition;
 mod opaque;
 mod param_env;
 mod parameterized;
 mod placeholder;
 mod predicate;
-mod resolver_outputs;
 mod rvalue_scopes;
 mod structural_impls;
 mod sty;
@@ -138,7 +136,6 @@ pub use self::impl_trait_in_trait_data::ImplTraitInTraitData;
 pub use self::infer_var_info::InferVarInfo;
 pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
 pub use self::list::List;
-pub use self::main_definition::MainDefinition;
 pub use self::opaque::{OpaqueHiddenType, OpaqueTypeKey};
 pub use self::param_env::{ParamEnv, ParamEnvAnd};
 pub use self::parameterized::ParameterizedOverTcx;
@@ -150,7 +147,6 @@ pub use self::predicate::{
     ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate,
     TypeOutlivesPredicate,
 };
-pub use self::resolver_outputs::{ResolverAstLowering, ResolverGlobalCtxt, ResolverOutputs};
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 99fc69d1bec7b..4e70bc488bdfe 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -11,7 +11,8 @@ use rustc_errors::{
 };
 use rustc_hir::{self as hir, ExprKind, Target};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
-use rustc_middle::ty::{MainDefinition, Ty};
+use rustc_middle::resolver_outputs::MainDefinition;
+use rustc_middle::ty::Ty;
 use rustc_span::{Span, Symbol, DUMMY_SP};
 
 use crate::check_attr::ProcMacroKind;
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index e46463579fe45..a863ddfd7d12d 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -44,9 +44,11 @@ use rustc_index::IndexVec;
 use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
+use rustc_middle::resolver_outputs::{
+    MainDefinition, ResolverAstLowering, ResolverGlobalCtxt, ResolverOutputs,
+};
 use rustc_middle::span_bug;
-use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
-use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
+use rustc_middle::ty::{self, RegisteredTools, TyCtxt};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::LintBuffer;
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
@@ -1408,7 +1410,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             doc_link_traits_in_scope: self.doc_link_traits_in_scope,
             all_macro_rules: self.all_macro_rules,
         };
-        let ast_lowering = ty::ResolverAstLowering {
+        let ast_lowering = ResolverAstLowering {
             legacy_const_generic_args: self.legacy_const_generic_args,
             partial_res_map: self.partial_res_map,
             import_res_map: self.import_res_map,

From e3de9923423fb7191ff74862a1cf76d4431edbc7 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 17:59:33 +0000
Subject: [PATCH 34/38] Group `ty::Predicate` internals in one file

---
 .../rustc_middle/src/ty/bound_constness.rs    |  34 ---
 compiler/rustc_middle/src/ty/mod.rs           |   6 +-
 compiler/rustc_middle/src/ty/predicate.rs     | 285 ++++++++++++++++--
 .../rustc_middle/src/ty/predicate/clause.rs   |  28 --
 .../src/ty/predicate/coerce_predicate.rs      |  11 -
 .../src/ty/predicate/outlives_predicate.rs    |  11 -
 .../src/ty/predicate/projection_predicate.rs  |  75 -----
 .../src/ty/predicate/subtype_predicate.rs     |  14 -
 .../src/ty/predicate/trait_predicate.rs       |  98 ------
 9 files changed, 266 insertions(+), 296 deletions(-)
 delete mode 100644 compiler/rustc_middle/src/ty/bound_constness.rs
 delete mode 100644 compiler/rustc_middle/src/ty/predicate/clause.rs
 delete mode 100644 compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs
 delete mode 100644 compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs
 delete mode 100644 compiler/rustc_middle/src/ty/predicate/projection_predicate.rs
 delete mode 100644 compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs
 delete mode 100644 compiler/rustc_middle/src/ty/predicate/trait_predicate.rs

diff --git a/compiler/rustc_middle/src/ty/bound_constness.rs b/compiler/rustc_middle/src/ty/bound_constness.rs
deleted file mode 100644
index 2f771fc711676..0000000000000
--- a/compiler/rustc_middle/src/ty/bound_constness.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-use rustc_hir as hir;
-use std::fmt;
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
-pub enum BoundConstness {
-    /// `T: Trait`
-    NotConst,
-    /// `T: ~const Trait`
-    ///
-    /// Requires resolving to const only when we are in a const context.
-    ConstIfConst,
-}
-
-impl BoundConstness {
-    /// Reduce `self` and `constness` to two possible combined states instead of four.
-    pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
-        match (constness, self) {
-            (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
-            (_, this) => {
-                *this = BoundConstness::NotConst;
-                hir::Constness::NotConst
-            }
-        }
-    }
-}
-
-impl fmt::Display for BoundConstness {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::NotConst => f.write_str("normal"),
-            Self::ConstIfConst => f.write_str("`~const`"),
-        }
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3a97a9bb57a99..bffba7360f4fe 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -58,7 +58,6 @@ pub mod walk;
 mod adt;
 mod alias_relation_direction;
 mod assoc;
-mod bound_constness;
 mod c_reader_cache_key;
 mod closure;
 mod closure_size_profile_data;
@@ -107,7 +106,6 @@ pub use self::alias_relation_direction::AliasRelationDirection;
 pub use self::assoc::*;
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
-pub use self::bound_constness::BoundConstness;
 pub use self::c_reader_cache_key::CReaderCacheKey;
 pub use self::closure::{
     is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
@@ -141,8 +139,8 @@ pub use self::param_env::{ParamEnv, ParamEnvAnd};
 pub use self::parameterized::ParameterizedOverTcx;
 pub use self::placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
 pub use self::predicate::{
-    Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates, OutlivesPredicate,
-    PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
+    BoundConstness, Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates,
+    OutlivesPredicate, PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
     PolySubtypePredicate, PolyTraitPredicate, PolyTypeOutlivesPredicate, Predicate, PredicateKind,
     ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate,
     TypeOutlivesPredicate,
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 18d9ba26551ac..6ce40907d6812 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -1,37 +1,23 @@
-pub use crate::ty::context::{
-    tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
-};
+use std::fmt;
+
 use rustc_data_structures::intern::Interned;
+use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
-    self, AliasRelationDirection, Binder, BoundConstness, ClosureKind, Const, DebruijnIndex,
-    EarlyBinder, GenericArg, SubstsRef, Term, Ty, TypeFlags,
+    self, AliasRelationDirection, AliasTy, Binder, ClosureKind, Const, DebruijnIndex, EarlyBinder,
+    GenericArg, ImplPolarity, ParamEnv, PolyTraitRef, SubstsRef, Term, TraitRef, Ty, TyCtxt,
+    TypeFlags,
 };
 
-mod clause;
-mod coerce_predicate;
 mod crate_predicates_map;
 mod instantiated_predicates;
-mod outlives_predicate;
-mod projection_predicate;
-mod subtype_predicate;
 mod to_predicate;
-mod trait_predicate;
 
-pub use clause::Clause;
-pub use coerce_predicate::{CoercePredicate, PolyCoercePredicate};
 pub use crate_predicates_map::CratePredicatesMap;
 pub use instantiated_predicates::InstantiatedPredicates;
-pub use outlives_predicate::{
-    OutlivesPredicate, PolyRegionOutlivesPredicate, PolyTypeOutlivesPredicate,
-    RegionOutlivesPredicate, TypeOutlivesPredicate,
-};
-pub use projection_predicate::{PolyProjectionPredicate, ProjectionPredicate};
-pub use subtype_predicate::{PolySubtypePredicate, SubtypePredicate};
 pub use to_predicate::ToPredicate;
-pub use trait_predicate::{PolyTraitPredicate, TraitPredicate};
 
 /// Use this rather than `PredicateKind`, whenever possible.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
@@ -96,6 +82,114 @@ pub enum PredicateKind<'tcx> {
     AliasRelate(Term<'tcx>, Term<'tcx>, AliasRelationDirection),
 }
 
+/// A clause is something that can appear in where bounds or be inferred
+/// by implied bounds.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub enum Clause<'tcx> {
+    /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
+    /// the `Self` type of the trait reference and `A`, `B`, and `C`
+    /// would be the type parameters.
+    Trait(TraitPredicate<'tcx>),
+
+    /// `where 'a: 'b`
+    RegionOutlives(RegionOutlivesPredicate<'tcx>),
+
+    /// `where T: 'a`
+    TypeOutlives(TypeOutlivesPredicate<'tcx>),
+
+    /// `where <T as TraitRef>::Name == X`, approximately.
+    /// See the `ProjectionPredicate` struct for details.
+    Projection(ProjectionPredicate<'tcx>),
+
+    /// Ensures that a const generic argument to a parameter `const N: u8`
+    /// is of type `u8`.
+    ConstArgHasType(Const<'tcx>, Ty<'tcx>),
+}
+
+pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
+
+/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
+/// whether the `a` type is the type that we should label as "expected" when
+/// presenting user diagnostics.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct SubtypePredicate<'tcx> {
+    pub a_is_expected: bool,
+    pub a: Ty<'tcx>,
+    pub b: Ty<'tcx>,
+}
+
+pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
+
+/// Encodes that we have to coerce *from* the `a` type to the `b` type.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct CoercePredicate<'tcx> {
+    pub a: Ty<'tcx>,
+    pub b: Ty<'tcx>,
+}
+
+pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct TraitPredicate<'tcx> {
+    pub trait_ref: TraitRef<'tcx>,
+
+    pub constness: BoundConstness,
+
+    /// If polarity is Positive: we are proving that the trait is implemented.
+    ///
+    /// If polarity is Negative: we are proving that a negative impl of this trait
+    /// exists. (Note that coherence also checks whether negative impls of supertraits
+    /// exist via a series of predicates.)
+    ///
+    /// If polarity is Reserved: that's a bug.
+    pub polarity: ImplPolarity,
+}
+
+pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
+pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
+pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
+pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
+
+/// `A: B`
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct OutlivesPredicate<A, B>(pub A, pub B);
+
+pub type PolyProjectionPredicate<'tcx> = ty::Binder<'tcx, ProjectionPredicate<'tcx>>;
+
+/// This kind of predicate has no *direct* correspondent in the
+/// syntax, but it roughly corresponds to the syntactic forms:
+///
+/// 1. `T: TraitRef<..., Item = Type>`
+/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
+///
+/// In particular, form #1 is "desugared" to the combination of a
+/// normal trait predicate (`T: TraitRef<...>`) and one of these
+/// predicates. Form #2 is a broader form in that it also permits
+/// equality between arbitrary types. Processing an instance of
+/// Form #2 eventually yields one of these `ProjectionPredicate`
+/// instances to normalize the LHS.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
+pub struct ProjectionPredicate<'tcx> {
+    pub projection_ty: AliasTy<'tcx>,
+    pub term: Term<'tcx>,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
+pub enum BoundConstness {
+    /// `T: Trait`
+    NotConst,
+    /// `T: ~const Trait`
+    ///
+    /// Requires resolving to const only when we are in a const context.
+    ConstIfConst,
+}
+
 impl<'tcx> Predicate<'tcx> {
     /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
     #[inline]
@@ -195,7 +289,7 @@ impl<'tcx> Predicate<'tcx> {
     pub fn subst_supertrait(
         self,
         tcx: TyCtxt<'tcx>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
+        trait_ref: &PolyTraitRef<'tcx>,
     ) -> Predicate<'tcx> {
         // The interaction between HRTB and supertraits is not entirely
         // obvious. Let me walk you (and myself) through an example.
@@ -354,3 +448,152 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
         rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
     }
 }
+
+impl<'tcx> TraitPredicate<'tcx> {
+    pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) {
+        *param_env = param_env.with_constness(self.constness.and(param_env.constness()))
+    }
+
+    /// Remap the constness of this predicate before emitting it for diagnostics.
+    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
+        // this is different to `remap_constness` that callees want to print this predicate
+        // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the
+        // param_env is not const because it is always satisfied in non-const contexts.
+        if let hir::Constness::NotConst = param_env.constness() {
+            self.constness = ty::BoundConstness::NotConst;
+        }
+    }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn def_id(self) -> DefId {
+        self.trait_ref.def_id
+    }
+
+    pub fn self_ty(self) -> Ty<'tcx> {
+        self.trait_ref.self_ty()
+    }
+
+    #[inline]
+    pub fn is_const_if_const(self) -> bool {
+        self.constness == BoundConstness::ConstIfConst
+    }
+
+    pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
+        match (self.constness, constness) {
+            (BoundConstness::NotConst, _)
+            | (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
+            (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
+        }
+    }
+
+    pub fn without_const(mut self) -> Self {
+        self.constness = BoundConstness::NotConst;
+        self
+    }
+}
+
+impl<'tcx> PolyTraitPredicate<'tcx> {
+    pub fn def_id(self) -> DefId {
+        // Ok to skip binder since trait `DefId` does not care about regions.
+        self.skip_binder().def_id()
+    }
+
+    pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
+        self.map_bound(|trait_ref| trait_ref.self_ty())
+    }
+
+    /// Remap the constness of this predicate before emitting it for diagnostics.
+    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
+        *self = self.map_bound(|mut p| {
+            p.remap_constness_diag(param_env);
+            p
+        });
+    }
+
+    #[inline]
+    pub fn is_const_if_const(self) -> bool {
+        self.skip_binder().is_const_if_const()
+    }
+
+    #[inline]
+    pub fn polarity(self) -> ImplPolarity {
+        self.skip_binder().polarity
+    }
+}
+
+impl<'tcx> ProjectionPredicate<'tcx> {
+    pub fn self_ty(self) -> Ty<'tcx> {
+        self.projection_ty.self_ty()
+    }
+
+    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
+        Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
+    }
+
+    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
+        self.projection_ty.trait_def_id(tcx)
+    }
+
+    pub fn def_id(self) -> DefId {
+        self.projection_ty.def_id
+    }
+}
+
+impl<'tcx> PolyProjectionPredicate<'tcx> {
+    /// Returns the `DefId` of the trait of the associated item being projected.
+    #[inline]
+    pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
+        self.skip_binder().projection_ty.trait_def_id(tcx)
+    }
+
+    /// Get the [PolyTraitRef] required for this projection to be well formed.
+    /// Note that for generic associated types the predicates of the associated
+    /// type also need to be checked.
+    #[inline]
+    pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
+        // Note: unlike with `TraitRef::to_poly_trait_ref()`,
+        // `self.0.trait_ref` is permitted to have escaping regions.
+        // This is because here `self` has a `Binder` and so does our
+        // return value, so we are preserving the number of binding
+        // levels.
+        self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
+    }
+
+    pub fn term(&self) -> ty::Binder<'tcx, Term<'tcx>> {
+        self.map_bound(|predicate| predicate.term)
+    }
+
+    /// The `DefId` of the `TraitItem` for the associated type.
+    ///
+    /// Note that this is not the `DefId` of the `TraitRef` containing this
+    /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
+    pub fn projection_def_id(&self) -> DefId {
+        // Ok to skip binder since trait `DefId` does not care about regions.
+        self.skip_binder().projection_ty.def_id
+    }
+}
+
+impl BoundConstness {
+    /// Reduce `self` and `constness` to two possible combined states instead of four.
+    pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
+        match (constness, self) {
+            (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
+            (_, this) => {
+                *this = BoundConstness::NotConst;
+                hir::Constness::NotConst
+            }
+        }
+    }
+}
+
+impl fmt::Display for BoundConstness {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::NotConst => f.write_str("normal"),
+            Self::ConstIfConst => f.write_str("`~const`"),
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/predicate/clause.rs b/compiler/rustc_middle/src/ty/predicate/clause.rs
deleted file mode 100644
index 8c13d68bcce6d..0000000000000
--- a/compiler/rustc_middle/src/ty/predicate/clause.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use crate::ty::{
-    Const, ProjectionPredicate, RegionOutlivesPredicate, TraitPredicate, Ty, TypeOutlivesPredicate,
-};
-
-/// A clause is something that can appear in where bounds or be inferred
-/// by implied bounds.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub enum Clause<'tcx> {
-    /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
-    /// the `Self` type of the trait reference and `A`, `B`, and `C`
-    /// would be the type parameters.
-    Trait(TraitPredicate<'tcx>),
-
-    /// `where 'a: 'b`
-    RegionOutlives(RegionOutlivesPredicate<'tcx>),
-
-    /// `where T: 'a`
-    TypeOutlives(TypeOutlivesPredicate<'tcx>),
-
-    /// `where <T as TraitRef>::Name == X`, approximately.
-    /// See the `ProjectionPredicate` struct for details.
-    Projection(ProjectionPredicate<'tcx>),
-
-    /// Ensures that a const generic argument to a parameter `const N: u8`
-    /// is of type `u8`.
-    ConstArgHasType(Const<'tcx>, Ty<'tcx>),
-}
diff --git a/compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs b/compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs
deleted file mode 100644
index caf6c772e1b63..0000000000000
--- a/compiler/rustc_middle/src/ty/predicate/coerce_predicate.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-use crate::ty::{self, Ty};
-
-pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
-
-/// Encodes that we have to coerce *from* the `a` type to the `b` type.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct CoercePredicate<'tcx> {
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
diff --git a/compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs b/compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs
deleted file mode 100644
index ecf44be6799db..0000000000000
--- a/compiler/rustc_middle/src/ty/predicate/outlives_predicate.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-use crate::ty::{self, Ty};
-
-pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
-pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
-pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
-pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
-
-/// `A: B`
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct OutlivesPredicate<A, B>(pub A, pub B);
diff --git a/compiler/rustc_middle/src/ty/predicate/projection_predicate.rs b/compiler/rustc_middle/src/ty/predicate/projection_predicate.rs
deleted file mode 100644
index b79fefeed174b..0000000000000
--- a/compiler/rustc_middle/src/ty/predicate/projection_predicate.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use crate::ty::{self, AliasTy, PolyTraitRef, Term, Ty, TyCtxt};
-use rustc_hir::def_id::DefId;
-
-pub type PolyProjectionPredicate<'tcx> = ty::Binder<'tcx, ProjectionPredicate<'tcx>>;
-
-/// This kind of predicate has no *direct* correspondent in the
-/// syntax, but it roughly corresponds to the syntactic forms:
-///
-/// 1. `T: TraitRef<..., Item = Type>`
-/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
-///
-/// In particular, form #1 is "desugared" to the combination of a
-/// normal trait predicate (`T: TraitRef<...>`) and one of these
-/// predicates. Form #2 is a broader form in that it also permits
-/// equality between arbitrary types. Processing an instance of
-/// Form #2 eventually yields one of these `ProjectionPredicate`
-/// instances to normalize the LHS.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct ProjectionPredicate<'tcx> {
-    pub projection_ty: AliasTy<'tcx>,
-    pub term: Term<'tcx>,
-}
-
-impl<'tcx> ProjectionPredicate<'tcx> {
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.projection_ty.self_ty()
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
-        Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
-    }
-
-    pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.projection_ty.trait_def_id(tcx)
-    }
-
-    pub fn def_id(self) -> DefId {
-        self.projection_ty.def_id
-    }
-}
-
-impl<'tcx> PolyProjectionPredicate<'tcx> {
-    /// Returns the `DefId` of the trait of the associated item being projected.
-    #[inline]
-    pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
-        self.skip_binder().projection_ty.trait_def_id(tcx)
-    }
-
-    /// Get the [PolyTraitRef] required for this projection to be well formed.
-    /// Note that for generic associated types the predicates of the associated
-    /// type also need to be checked.
-    #[inline]
-    pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
-        // Note: unlike with `TraitRef::to_poly_trait_ref()`,
-        // `self.0.trait_ref` is permitted to have escaping regions.
-        // This is because here `self` has a `Binder` and so does our
-        // return value, so we are preserving the number of binding
-        // levels.
-        self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
-    }
-
-    pub fn term(&self) -> ty::Binder<'tcx, Term<'tcx>> {
-        self.map_bound(|predicate| predicate.term)
-    }
-
-    /// The `DefId` of the `TraitItem` for the associated type.
-    ///
-    /// Note that this is not the `DefId` of the `TraitRef` containing this
-    /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
-    pub fn projection_def_id(&self) -> DefId {
-        // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().projection_ty.def_id
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs b/compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs
deleted file mode 100644
index 82b87635790b9..0000000000000
--- a/compiler/rustc_middle/src/ty/predicate/subtype_predicate.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use crate::ty::{self, Ty};
-
-pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
-
-/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
-/// whether the `a` type is the type that we should label as "expected" when
-/// presenting user diagnostics.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct SubtypePredicate<'tcx> {
-    pub a_is_expected: bool,
-    pub a: Ty<'tcx>,
-    pub b: Ty<'tcx>,
-}
diff --git a/compiler/rustc_middle/src/ty/predicate/trait_predicate.rs b/compiler/rustc_middle/src/ty/predicate/trait_predicate.rs
deleted file mode 100644
index 9dfb1152223a4..0000000000000
--- a/compiler/rustc_middle/src/ty/predicate/trait_predicate.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-
-use crate::ty::{self, BoundConstness, ImplPolarity, ParamEnv, TraitRef, Ty, TyCtxt};
-
-pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct TraitPredicate<'tcx> {
-    pub trait_ref: TraitRef<'tcx>,
-
-    pub constness: BoundConstness,
-
-    /// If polarity is Positive: we are proving that the trait is implemented.
-    ///
-    /// If polarity is Negative: we are proving that a negative impl of this trait
-    /// exists. (Note that coherence also checks whether negative impls of supertraits
-    /// exist via a series of predicates.)
-    ///
-    /// If polarity is Reserved: that's a bug.
-    pub polarity: ImplPolarity,
-}
-
-impl<'tcx> TraitPredicate<'tcx> {
-    pub fn remap_constness(&mut self, param_env: &mut ParamEnv<'tcx>) {
-        *param_env = param_env.with_constness(self.constness.and(param_env.constness()))
-    }
-
-    /// Remap the constness of this predicate before emitting it for diagnostics.
-    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
-        // this is different to `remap_constness` that callees want to print this predicate
-        // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the
-        // param_env is not const because it is always satisfied in non-const contexts.
-        if let hir::Constness::NotConst = param_env.constness() {
-            self.constness = ty::BoundConstness::NotConst;
-        }
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
-    }
-
-    pub fn def_id(self) -> DefId {
-        self.trait_ref.def_id
-    }
-
-    pub fn self_ty(self) -> Ty<'tcx> {
-        self.trait_ref.self_ty()
-    }
-
-    #[inline]
-    pub fn is_const_if_const(self) -> bool {
-        self.constness == BoundConstness::ConstIfConst
-    }
-
-    pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
-        match (self.constness, constness) {
-            (BoundConstness::NotConst, _)
-            | (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
-            (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
-        }
-    }
-
-    pub fn without_const(mut self) -> Self {
-        self.constness = BoundConstness::NotConst;
-        self
-    }
-}
-
-impl<'tcx> PolyTraitPredicate<'tcx> {
-    pub fn def_id(self) -> DefId {
-        // Ok to skip binder since trait `DefId` does not care about regions.
-        self.skip_binder().def_id()
-    }
-
-    pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
-        self.map_bound(|trait_ref| trait_ref.self_ty())
-    }
-
-    /// Remap the constness of this predicate before emitting it for diagnostics.
-    pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) {
-        *self = self.map_bound(|mut p| {
-            p.remap_constness_diag(param_env);
-            p
-        });
-    }
-
-    #[inline]
-    pub fn is_const_if_const(self) -> bool {
-        self.skip_binder().is_const_if_const()
-    }
-
-    #[inline]
-    pub fn polarity(self) -> ImplPolarity {
-        self.skip_binder().polarity
-    }
-}

From 07e0e75f4dafae5759e12d85a59f6a43120eda90 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 18:44:47 +0000
Subject: [PATCH 35/38] Move `ParamTerm` to `term.rs`

---
 compiler/rustc_middle/src/ty/mod.rs  | 16 +-------
 compiler/rustc_middle/src/ty/term.rs | 59 +++++++++++++++++-----------
 2 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index bffba7360f4fe..9b1afee9bfabb 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -158,7 +158,7 @@ pub use self::sty::{
 };
 pub use self::subst::*;
 pub use self::symbol_name::SymbolName;
-pub use self::term::{Term, TermKind};
+pub use self::term::{ParamTerm, Term, TermKind};
 pub use self::trait_def::TraitDef;
 pub use self::ty_::Ty;
 pub use self::typeck_results::{
@@ -221,20 +221,6 @@ const TAG_MASK: usize = 0b11;
 const TYPE_TAG: usize = 0b00;
 const CONST_TAG: usize = 0b01;
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum ParamTerm {
-    Ty(ParamTy),
-    Const(ParamConst),
-}
-
-impl ParamTerm {
-    pub fn index(self) -> usize {
-        match self {
-            ParamTerm::Ty(ty) => ty.index as usize,
-            ParamTerm::Const(ct) => ct.index as usize,
-        }
-    }
-}
 pub trait ToPolyTraitRef<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
 }
diff --git a/compiler/rustc_middle/src/ty/term.rs b/compiler/rustc_middle/src/ty/term.rs
index 4b0ab1930191b..dcca01d71499d 100644
--- a/compiler/rustc_middle/src/ty/term.rs
+++ b/compiler/rustc_middle/src/ty/term.rs
@@ -9,8 +9,8 @@ use rustc_query_system::ich::StableHashingContext;
 
 use crate::ty::{
     self, AliasKind, AliasTy, Const, ConstKind, Decodable, Encodable, FallibleTypeFolder,
-    GenericArg, Interned, Ty, TyCtxt, TyDecoder, TyEncoder, TypeFoldable, TypeVisitable,
-    TypeVisitor, WithCachedTypeInfo, CONST_TAG, TAG_MASK, TYPE_TAG,
+    GenericArg, Interned, ParamConst, ParamTy, Ty, TyCtxt, TyDecoder, TyEncoder, TypeFoldable,
+    TypeVisitable, TypeVisitor, WithCachedTypeInfo, CONST_TAG, TAG_MASK, TYPE_TAG,
 };
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -26,6 +26,12 @@ pub enum TermKind<'tcx> {
     Const(Const<'tcx>),
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum ParamTerm {
+    Ty(ParamTy),
+    Const(ParamConst),
+}
+
 impl<'tcx> Term<'tcx> {
     #[inline]
     pub fn unpack(self) -> TermKind<'tcx> {
@@ -89,26 +95,6 @@ impl<'tcx> Term<'tcx> {
     }
 }
 
-impl<'tcx> TermKind<'tcx> {
-    #[inline]
-    pub(super) fn pack(self) -> Term<'tcx> {
-        let (tag, ptr) = match self {
-            TermKind::Ty(ty) => {
-                // Ensure we can use the tag bits.
-                assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
-                (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
-            }
-            TermKind::Const(ct) => {
-                // Ensure we can use the tag bits.
-                assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
-                (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
-            }
-        };
-
-        Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData }
-    }
-}
-
 impl fmt::Debug for Term<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let data = if let Some(ty) = self.ty() {
@@ -167,3 +153,32 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Term<'tcx> {
         res.pack()
     }
 }
+
+impl<'tcx> TermKind<'tcx> {
+    #[inline]
+    pub(super) fn pack(self) -> Term<'tcx> {
+        let (tag, ptr) = match self {
+            TermKind::Ty(ty) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0);
+                (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize)
+            }
+            TermKind::Const(ct) => {
+                // Ensure we can use the tag bits.
+                assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
+                (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
+            }
+        };
+
+        Term { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData }
+    }
+}
+
+impl ParamTerm {
+    pub fn index(self) -> usize {
+        match self {
+            ParamTerm::Ty(ty) => ty.index as usize,
+            ParamTerm::Const(ct) => ct.index as usize,
+        }
+    }
+}

From fa016bc0a234c3f2f779461dd776eea4b825c112 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 20:14:16 +0000
Subject: [PATCH 36/38] Destribute placeholders

---
 compiler/rustc_middle/src/ty/consts.rs      | 12 ++++++++----
 compiler/rustc_middle/src/ty/mod.rs         | 10 ++++++----
 compiler/rustc_middle/src/ty/placeholder.rs |  8 +-------
 compiler/rustc_middle/src/ty/region.rs      |  3 +++
 compiler/rustc_middle/src/ty/ty_.rs         |  4 +++-
 5 files changed, 21 insertions(+), 16 deletions(-)
 create mode 100644 compiler/rustc_middle/src/ty/region.rs

diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index e7107c28bf407..5804a7ea70291 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,12 +1,14 @@
-use crate::middle::resolve_bound_vars as rbv;
-use crate::mir::interpret::LitToConstInput;
-use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use std::fmt;
+
 use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::HashStable;
-use std::fmt;
+
+use crate::middle::resolve_bound_vars as rbv;
+use crate::mir::interpret::LitToConstInput;
+use crate::ty::{self, BoundVar, InternalSubsts, ParamEnv, ParamEnvAnd, Placeholder, Ty, TyCtxt};
 
 mod int;
 mod kind;
@@ -37,6 +39,8 @@ pub struct ConstData<'tcx> {
     pub kind: ConstKind<'tcx>,
 }
 
+pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
+
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(ConstData<'_>, 40);
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 9b1afee9bfabb..c20ad1486d299 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -80,6 +80,7 @@ mod param_env;
 mod parameterized;
 mod placeholder;
 mod predicate;
+mod region;
 mod rvalue_scopes;
 mod structural_impls;
 mod sty;
@@ -118,8 +119,8 @@ pub use self::coherence::{
     CrateInherentImpls, ImplHeader, ImplOverlapKind, ImplPolarity, ImplSubject,
 };
 pub use self::consts::{
-    BoundConst, Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt,
-    UnevaluatedConst, ValTree,
+    BoundConst, Const, ConstData, ConstInt, ConstKind, Expr, InferConst, PlaceholderConst,
+    ScalarInt, UnevaluatedConst, ValTree,
 };
 pub use self::context::{
     tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
@@ -137,7 +138,7 @@ pub use self::list::List;
 pub use self::opaque::{OpaqueHiddenType, OpaqueTypeKey};
 pub use self::param_env::{ParamEnv, ParamEnvAnd};
 pub use self::parameterized::ParameterizedOverTcx;
-pub use self::placeholder::{Placeholder, PlaceholderConst, PlaceholderRegion, PlaceholderType};
+pub use self::placeholder::Placeholder;
 pub use self::predicate::{
     BoundConstness, Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates,
     OutlivesPredicate, PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
@@ -145,6 +146,7 @@ pub use self::predicate::{
     ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate,
     TypeOutlivesPredicate,
 };
+pub use self::region::PlaceholderRegion;
 pub use self::rvalue_scopes::RvalueScopes;
 pub use self::sty::BoundRegionKind::*;
 pub use self::sty::{
@@ -160,7 +162,7 @@ pub use self::subst::*;
 pub use self::symbol_name::SymbolName;
 pub use self::term::{ParamTerm, Term, TermKind};
 pub use self::trait_def::TraitDef;
-pub use self::ty_::Ty;
+pub use self::ty_::{PlaceholderType, Ty};
 pub use self::typeck_results::{
     CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
     GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
diff --git a/compiler/rustc_middle/src/ty/placeholder.rs b/compiler/rustc_middle/src/ty/placeholder.rs
index d5f25c0afa7f4..eb7e72f79fca7 100644
--- a/compiler/rustc_middle/src/ty/placeholder.rs
+++ b/compiler/rustc_middle/src/ty/placeholder.rs
@@ -1,10 +1,4 @@
-use crate::ty::{BoundRegion, BoundTy, BoundVar, UniverseIndex};
-
-pub type PlaceholderRegion = Placeholder<BoundRegion>;
-
-pub type PlaceholderType = Placeholder<BoundTy>;
-
-pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
+use crate::ty::UniverseIndex;
 
 /// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
 /// identified by both a universe, as well as a name residing within that universe. Distinct bound
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
new file mode 100644
index 0000000000000..a9d25fd181850
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -0,0 +1,3 @@
+use crate::ty::{BoundRegion, Placeholder};
+
+pub type PlaceholderRegion = Placeholder<BoundRegion>;
diff --git a/compiler/rustc_middle/src/ty/ty_.rs b/compiler/rustc_middle/src/ty/ty_.rs
index 50e9712966ae3..1347c1b84a574 100644
--- a/compiler/rustc_middle/src/ty/ty_.rs
+++ b/compiler/rustc_middle/src/ty/ty_.rs
@@ -1,4 +1,4 @@
-use crate::ty::{Interned, TyKind, WithCachedTypeInfo};
+use crate::ty::{BoundTy, Interned, Placeholder, TyKind, WithCachedTypeInfo};
 
 /// Use this rather than `TyKind`, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
@@ -6,4 +6,6 @@ use crate::ty::{Interned, TyKind, WithCachedTypeInfo};
 #[rustc_pass_by_value]
 pub struct Ty<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
 
+pub type PlaceholderType = Placeholder<BoundTy>;
+
 // FIXME: move `Ty` inherent impls here (and possibly change structure wrt `sty` mod)

From 5793896ddddb6340c672bd88b45edcd9e056178c Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 20:29:39 +0000
Subject: [PATCH 37/38] Move `InferVarInfo` to `ty_.rs`

---
 compiler/rustc_middle/src/ty/infer_var_info.rs | 12 ------------
 compiler/rustc_middle/src/ty/mod.rs            |  4 +---
 compiler/rustc_middle/src/ty/ty_.rs            | 13 +++++++++++++
 3 files changed, 14 insertions(+), 15 deletions(-)
 delete mode 100644 compiler/rustc_middle/src/ty/infer_var_info.rs

diff --git a/compiler/rustc_middle/src/ty/infer_var_info.rs b/compiler/rustc_middle/src/ty/infer_var_info.rs
deleted file mode 100644
index d1c457fcf8941..0000000000000
--- a/compiler/rustc_middle/src/ty/infer_var_info.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#[derive(Debug, Default, Copy, Clone)]
-pub struct InferVarInfo {
-    /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
-    /// obligation, where:
-    ///
-    ///  * `Foo` is not `Sized`
-    ///  * `(): Foo` may be satisfied
-    pub self_in_trait: bool,
-    /// This is true if we identified that this Ty (`?T`) is found in a `<_ as
-    /// _>::AssocType = ?T`
-    pub output: bool,
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c20ad1486d299..3902b398f6f1b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -72,7 +72,6 @@ mod erase_regions;
 mod generics;
 mod impl_trait_in_trait_data;
 mod impls_ty;
-mod infer_var_info;
 mod instance;
 mod list;
 mod opaque;
@@ -132,7 +131,6 @@ pub use self::diagnostics::*;
 pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
 pub use self::generics::*;
 pub use self::impl_trait_in_trait_data::ImplTraitInTraitData;
-pub use self::infer_var_info::InferVarInfo;
 pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
 pub use self::list::List;
 pub use self::opaque::{OpaqueHiddenType, OpaqueTypeKey};
@@ -162,7 +160,7 @@ pub use self::subst::*;
 pub use self::symbol_name::SymbolName;
 pub use self::term::{ParamTerm, Term, TermKind};
 pub use self::trait_def::TraitDef;
-pub use self::ty_::{PlaceholderType, Ty};
+pub use self::ty_::{InferVarInfo, PlaceholderType, Ty};
 pub use self::typeck_results::{
     CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
     GeneratorDiagnosticData, GeneratorInteriorTypeCause, TypeckResults, UserType,
diff --git a/compiler/rustc_middle/src/ty/ty_.rs b/compiler/rustc_middle/src/ty/ty_.rs
index 1347c1b84a574..de9d2495c3ef8 100644
--- a/compiler/rustc_middle/src/ty/ty_.rs
+++ b/compiler/rustc_middle/src/ty/ty_.rs
@@ -8,4 +8,17 @@ pub struct Ty<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>)
 
 pub type PlaceholderType = Placeholder<BoundTy>;
 
+#[derive(Debug, Default, Copy, Clone)]
+pub struct InferVarInfo {
+    /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
+    /// obligation, where:
+    ///
+    ///  * `Foo` is not `Sized`
+    ///  * `(): Foo` may be satisfied
+    pub self_in_trait: bool,
+    /// This is true if we identified that this Ty (`?T`) is found in a `<_ as
+    /// _>::AssocType = ?T`
+    pub output: bool,
+}
+
 // FIXME: move `Ty` inherent impls here (and possibly change structure wrt `sty` mod)

From 7fad53e0dbc68230de303276dfc4d6b56bff4df4 Mon Sep 17 00:00:00 2001
From: Maybe Waffle <waffle.lapkin@gmail.com>
Date: Fri, 5 May 2023 20:33:04 +0000
Subject: [PATCH 38/38] Move `AliasRelationDirection` to `predicate.rs`

---
 .../src/ty/alias_relation_direction.rs        | 17 ---------------
 compiler/rustc_middle/src/ty/mod.rs           | 12 +++++------
 compiler/rustc_middle/src/ty/predicate.rs     | 21 ++++++++++++++++---
 3 files changed, 23 insertions(+), 27 deletions(-)
 delete mode 100644 compiler/rustc_middle/src/ty/alias_relation_direction.rs

diff --git a/compiler/rustc_middle/src/ty/alias_relation_direction.rs b/compiler/rustc_middle/src/ty/alias_relation_direction.rs
deleted file mode 100644
index 35fb40a32eb9c..0000000000000
--- a/compiler/rustc_middle/src/ty/alias_relation_direction.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-use std::fmt;
-
-#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, Debug)]
-pub enum AliasRelationDirection {
-    Equate,
-    Subtype,
-}
-
-impl fmt::Display for AliasRelationDirection {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            AliasRelationDirection::Equate => write!(f, "=="),
-            AliasRelationDirection::Subtype => write!(f, "<:"),
-        }
-    }
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3902b398f6f1b..856fa4c2fec56 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -56,7 +56,6 @@ pub mod vtable;
 pub mod walk;
 
 mod adt;
-mod alias_relation_direction;
 mod assoc;
 mod c_reader_cache_key;
 mod closure;
@@ -102,7 +101,6 @@ pub use self::adt::{
     AdtDef, AdtDefData, AdtFlags, AdtKind, FieldDef, Representability, VariantDef, VariantDiscr,
     VariantFlags,
 };
-pub use self::alias_relation_direction::AliasRelationDirection;
 pub use self::assoc::*;
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
@@ -138,11 +136,11 @@ pub use self::param_env::{ParamEnv, ParamEnvAnd};
 pub use self::parameterized::ParameterizedOverTcx;
 pub use self::placeholder::Placeholder;
 pub use self::predicate::{
-    BoundConstness, Clause, CoercePredicate, CratePredicatesMap, InstantiatedPredicates,
-    OutlivesPredicate, PolyCoercePredicate, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
-    PolySubtypePredicate, PolyTraitPredicate, PolyTypeOutlivesPredicate, Predicate, PredicateKind,
-    ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate,
-    TypeOutlivesPredicate,
+    AliasRelationDirection, BoundConstness, Clause, CoercePredicate, CratePredicatesMap,
+    InstantiatedPredicates, OutlivesPredicate, PolyCoercePredicate, PolyProjectionPredicate,
+    PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
+    PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
+    RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TraitPredicate, TypeOutlivesPredicate,
 };
 pub use self::region::PlaceholderRegion;
 pub use self::rvalue_scopes::RvalueScopes;
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 6ce40907d6812..48a7f7b4698dc 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -6,9 +6,8 @@ use rustc_hir::def_id::DefId;
 use rustc_type_ir::WithCachedTypeInfo;
 
 use crate::ty::{
-    self, AliasRelationDirection, AliasTy, Binder, ClosureKind, Const, DebruijnIndex, EarlyBinder,
-    GenericArg, ImplPolarity, ParamEnv, PolyTraitRef, SubstsRef, Term, TraitRef, Ty, TyCtxt,
-    TypeFlags,
+    self, AliasTy, Binder, ClosureKind, Const, DebruijnIndex, EarlyBinder, GenericArg,
+    ImplPolarity, ParamEnv, PolyTraitRef, SubstsRef, Term, TraitRef, Ty, TyCtxt, TypeFlags,
 };
 
 mod crate_predicates_map;
@@ -190,6 +189,13 @@ pub enum BoundConstness {
     ConstIfConst,
 }
 
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(HashStable, Debug)]
+pub enum AliasRelationDirection {
+    Equate,
+    Subtype,
+}
+
 impl<'tcx> Predicate<'tcx> {
     /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
     #[inline]
@@ -597,3 +603,12 @@ impl fmt::Display for BoundConstness {
         }
     }
 }
+
+impl fmt::Display for AliasRelationDirection {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            AliasRelationDirection::Equate => write!(f, "=="),
+            AliasRelationDirection::Subtype => write!(f, "<:"),
+        }
+    }
+}