about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-10-04 01:20:08 +0000
committerbors <bors@rust-lang.org>2024-10-04 01:20:08 +0000
commit7067e4aee45c18cfa1c6af3bf79bd097684fb294 (patch)
tree9fbdede4a3ab4c6a89ce22da75da75dfe35cb392
parente1e3cac26dcbce45bafe5644b7555edac3a1a92f (diff)
parentee227dec8c84fc5a65ef798af93863a97794502e (diff)
downloadrust-7067e4aee45c18cfa1c6af3bf79bd097684fb294.tar.gz
rust-7067e4aee45c18cfa1c6af3bf79bd097684fb294.zip
Auto merge of #131191 - nnethercote:lattice_op, r=lcnr
Merge `glb` and `lub` modules

Tons of code is duplicated across them, and it's easy to factor that out.

r? `@lcnr`
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs13
-rw-r--r--compiler/rustc_infer/src/infer/relate/glb.rs159
-rw-r--r--compiler/rustc_infer/src/infer/relate/lattice.rs302
-rw-r--r--compiler/rustc_infer/src/infer/relate/lub.rs158
-rw-r--r--compiler/rustc_infer/src/infer/relate/mod.rs2
5 files changed, 231 insertions, 403 deletions
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 3b2ef3fe981..4a8c7387ddc 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -1,4 +1,4 @@
-//! There are four type combiners: [TypeRelating], [Lub], and [Glb],
+//! There are four type combiners: [TypeRelating], `Lub`, and `Glb`,
 //! and `NllTypeRelating` in rustc_borrowck, which is only used for NLL.
 //!
 //! Each implements the trait [TypeRelation] and contains methods for
@@ -26,8 +26,7 @@ use rustc_middle::ty::{self, InferConst, IntType, Ty, TyCtxt, TypeVisitableExt,
 pub use rustc_next_trait_solver::relate::combine::*;
 use tracing::debug;
 
-use super::glb::Glb;
-use super::lub::Lub;
+use super::lattice::{LatticeOp, LatticeOpKind};
 use super::type_relating::TypeRelating;
 use super::{RelateResult, StructurallyRelateAliases};
 use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace, relate};
@@ -303,12 +302,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         TypeRelating::new(self, StructurallyRelateAliases::No, ty::Contravariant)
     }
 
-    pub fn lub<'a>(&'a mut self) -> Lub<'a, 'infcx, 'tcx> {
-        Lub::new(self)
+    pub(crate) fn lub<'a>(&'a mut self) -> LatticeOp<'a, 'infcx, 'tcx> {
+        LatticeOp::new(self, LatticeOpKind::Lub)
     }
 
-    pub fn glb<'a>(&'a mut self) -> Glb<'a, 'infcx, 'tcx> {
-        Glb::new(self)
+    pub(crate) fn glb<'a>(&'a mut self) -> LatticeOp<'a, 'infcx, 'tcx> {
+        LatticeOp::new(self, LatticeOpKind::Glb)
     }
 
     pub fn register_obligations(
diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs
deleted file mode 100644
index ed108f42969..00000000000
--- a/compiler/rustc_infer/src/infer/relate/glb.rs
+++ /dev/null
@@ -1,159 +0,0 @@
-//! Greatest lower bound. See [`lattice`].
-
-use rustc_middle::traits::solve::Goal;
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::Span;
-use tracing::{debug, instrument};
-
-use super::StructurallyRelateAliases;
-use super::combine::{CombineFields, PredicateEmittingRelation};
-use super::lattice::{self, LatticeDir};
-use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
-use crate::traits::ObligationCause;
-
-/// "Greatest lower bound" (common subtype)
-pub struct Glb<'combine, 'infcx, 'tcx> {
-    fields: &'combine mut CombineFields<'infcx, 'tcx>,
-}
-
-impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> {
-    pub fn new(fields: &'combine mut CombineFields<'infcx, 'tcx>) -> Glb<'combine, 'infcx, 'tcx> {
-        Glb { fields }
-    }
-}
-
-impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.fields.tcx()
-    }
-
-    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
-        &mut self,
-        variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T> {
-        match variance {
-            ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b),
-            ty::Covariant => self.relate(a, b),
-            // FIXME(#41044) -- not correct, need test
-            ty::Bivariant => Ok(a),
-            ty::Contravariant => self.fields.lub().relate(a, b),
-        }
-    }
-
-    #[instrument(skip(self), level = "trace")]
-    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        lattice::super_lattice_tys(self, a, b)
-    }
-
-    #[instrument(skip(self), level = "trace")]
-    fn regions(
-        &mut self,
-        a: ty::Region<'tcx>,
-        b: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
-        // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
-        Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().lub_regions(
-            self.cx(),
-            origin,
-            a,
-            b,
-        ))
-    }
-
-    #[instrument(skip(self), level = "trace")]
-    fn consts(
-        &mut self,
-        a: ty::Const<'tcx>,
-        b: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        self.fields.infcx.super_combine_consts(self, a, b)
-    }
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<TyCtxt<'tcx>>,
-    {
-        // GLB of a binder and itself is just itself
-        if a == b {
-            return Ok(a);
-        }
-
-        debug!("binders(a={:?}, b={:?})", a, b);
-        if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
-            // When higher-ranked types are involved, computing the GLB is
-            // very challenging, switch to invariance. This is obviously
-            // overly conservative but works ok in practice.
-            self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
-            Ok(a)
-        } else {
-            Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
-        }
-    }
-}
-
-impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> {
-    fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
-        self.fields.infcx
-    }
-
-    fn cause(&self) -> &ObligationCause<'tcx> {
-        &self.fields.trace.cause
-    }
-
-    fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
-        let mut sub = self.fields.sub();
-        sub.relate(v, a)?;
-        sub.relate(v, b)?;
-        Ok(())
-    }
-
-    fn define_opaque_types(&self) -> DefineOpaqueTypes {
-        self.fields.define_opaque_types
-    }
-}
-
-impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
-    fn span(&self) -> Span {
-        self.fields.trace.span()
-    }
-
-    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
-        StructurallyRelateAliases::No
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.fields.param_env
-    }
-
-    fn register_predicates(
-        &mut self,
-        obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
-    ) {
-        self.fields.register_predicates(obligations);
-    }
-
-    fn register_goals(
-        &mut self,
-        obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
-    ) {
-        self.fields.register_obligations(obligations);
-    }
-
-    fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
-        self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate(
-            a.into(),
-            b.into(),
-            // FIXME(deferred_projection_equality): This isn't right, I think?
-            ty::AliasRelationDirection::Equate,
-        ))]);
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs
index 1d3f45465d6..9564baa6ab2 100644
--- a/compiler/rustc_infer/src/infer/relate/lattice.rs
+++ b/compiler/rustc_infer/src/infer/relate/lattice.rs
@@ -17,99 +17,247 @@
 //!
 //! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
 
-use rustc_middle::ty::relate::RelateResult;
-use rustc_middle::ty::{self, Ty, TyVar};
-use tracing::instrument;
+use rustc_middle::traits::solve::Goal;
+use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
+use rustc_middle::ty::{self, Ty, TyCtxt, TyVar, TypeVisitableExt};
+use rustc_span::Span;
+use tracing::{debug, instrument};
 
-use super::combine::PredicateEmittingRelation;
-use crate::infer::{DefineOpaqueTypes, InferCtxt};
-use crate::traits::ObligationCause;
+use super::StructurallyRelateAliases;
+use super::combine::{CombineFields, PredicateEmittingRelation};
+use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
 
-/// Trait for returning data about a lattice, and for abstracting
-/// over the "direction" of the lattice operation (LUB/GLB).
-///
-/// GLB moves "down" the lattice (to smaller values); LUB moves
-/// "up" the lattice (to bigger values).
-pub(crate) trait LatticeDir<'f, 'tcx>: PredicateEmittingRelation<InferCtxt<'tcx>> {
-    fn infcx(&self) -> &'f InferCtxt<'tcx>;
+#[derive(Clone, Copy)]
+pub(crate) enum LatticeOpKind {
+    Glb,
+    Lub,
+}
+
+impl LatticeOpKind {
+    fn invert(self) -> Self {
+        match self {
+            LatticeOpKind::Glb => LatticeOpKind::Lub,
+            LatticeOpKind::Lub => LatticeOpKind::Glb,
+        }
+    }
+}
+
+/// A greatest lower bound" (common subtype) or least upper bound (common supertype).
+pub(crate) struct LatticeOp<'combine, 'infcx, 'tcx> {
+    fields: &'combine mut CombineFields<'infcx, 'tcx>,
+    kind: LatticeOpKind,
+}
+
+impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> {
+    pub(crate) fn new(
+        fields: &'combine mut CombineFields<'infcx, 'tcx>,
+        kind: LatticeOpKind,
+    ) -> LatticeOp<'combine, 'infcx, 'tcx> {
+        LatticeOp { fields, kind }
+    }
+}
+
+impl<'tcx> TypeRelation<TyCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
+        self.fields.tcx()
+    }
 
-    fn cause(&self) -> &ObligationCause<'tcx>;
+    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
+        &mut self,
+        variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
+        a: T,
+        b: T,
+    ) -> RelateResult<'tcx, T> {
+        match variance {
+            ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b),
+            ty::Covariant => self.relate(a, b),
+            // FIXME(#41044) -- not correct, need test
+            ty::Bivariant => Ok(a),
+            ty::Contravariant => {
+                self.kind = self.kind.invert();
+                let res = self.relate(a, b);
+                self.kind = self.kind.invert();
+                res
+            }
+        }
+    }
+
+    /// Relates two types using a given lattice.
+    #[instrument(skip(self), level = "trace")]
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        if a == b {
+            return Ok(a);
+        }
+
+        let infcx = self.fields.infcx;
+
+        let a = infcx.shallow_resolve(a);
+        let b = infcx.shallow_resolve(b);
+
+        match (a.kind(), b.kind()) {
+            // If one side is known to be a variable and one is not,
+            // create a variable (`v`) to represent the LUB. Make sure to
+            // relate `v` to the non-type-variable first (by passing it
+            // first to `relate_bound`). Otherwise, we would produce a
+            // subtype obligation that must then be processed.
+            //
+            // Example: if the LHS is a type variable, and RHS is
+            // `Box<i32>`, then we current compare `v` to the RHS first,
+            // which will instantiate `v` with `Box<i32>`. Then when `v`
+            // is compared to the LHS, we instantiate LHS with `Box<i32>`.
+            // But if we did in reverse order, we would create a `v <:
+            // LHS` (or vice versa) constraint and then instantiate
+            // `v`. This would require further processing to achieve same
+            // end-result; in particular, this screws up some of the logic
+            // in coercion, which expects LUB to figure out that the LHS
+            // is (e.g.) `Box<i32>`. A more obvious solution might be to
+            // iterate on the subtype obligations that are returned, but I
+            // think this suffices. -nmatsakis
+            (&ty::Infer(TyVar(..)), _) => {
+                let v = infcx.next_ty_var(self.fields.trace.cause.span);
+                self.relate_bound(v, b, a)?;
+                Ok(v)
+            }
+            (_, &ty::Infer(TyVar(..))) => {
+                let v = infcx.next_ty_var(self.fields.trace.cause.span);
+                self.relate_bound(v, a, b)?;
+                Ok(v)
+            }
+
+            (
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
+                &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
+            ) if a_def_id == b_def_id => infcx.super_combine_tys(self, a, b),
+
+            (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
+            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
+                if self.fields.define_opaque_types == DefineOpaqueTypes::Yes
+                    && def_id.is_local()
+                    && !infcx.next_trait_solver() =>
+            {
+                self.register_goals(infcx.handle_opaque_type(
+                    a,
+                    b,
+                    self.span(),
+                    self.param_env(),
+                )?);
+                Ok(a)
+            }
+
+            _ => infcx.super_combine_tys(self, a, b),
+        }
+    }
 
-    fn define_opaque_types(&self) -> DefineOpaqueTypes;
+    #[instrument(skip(self), level = "trace")]
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        b: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
+        let mut inner = self.fields.infcx.inner.borrow_mut();
+        let mut constraints = inner.unwrap_region_constraints();
+        Ok(match self.kind {
+            // GLB(&'static u8, &'a u8) == &RegionLUB('static, 'a) u8 == &'static u8
+            LatticeOpKind::Glb => constraints.lub_regions(self.cx(), origin, a, b),
 
+            // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
+            LatticeOpKind::Lub => constraints.glb_regions(self.cx(), origin, a, b),
+        })
+    }
+
+    #[instrument(skip(self), level = "trace")]
+    fn consts(
+        &mut self,
+        a: ty::Const<'tcx>,
+        b: ty::Const<'tcx>,
+    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
+        self.fields.infcx.super_combine_consts(self, a, b)
+    }
+
+    fn binders<T>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        b: ty::Binder<'tcx, T>,
+    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
+    where
+        T: Relate<TyCtxt<'tcx>>,
+    {
+        // GLB/LUB of a binder and itself is just itself
+        if a == b {
+            return Ok(a);
+        }
+
+        debug!("binders(a={:?}, b={:?})", a, b);
+        if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
+            // When higher-ranked types are involved, computing the GLB/LUB is
+            // very challenging, switch to invariance. This is obviously
+            // overly conservative but works ok in practice.
+            self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
+            Ok(a)
+        } else {
+            Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
+        }
+    }
+}
+
+impl<'combine, 'infcx, 'tcx> LatticeOp<'combine, 'infcx, 'tcx> {
     // Relates the type `v` to `a` and `b` such that `v` represents
     // the LUB/GLB of `a` and `b` as appropriate.
     //
     // Subtle hack: ordering *may* be significant here. This method
     // relates `v` to `a` first, which may help us to avoid unnecessary
     // type variable obligations. See caller for details.
-    fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
+    fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
+        let mut sub = self.fields.sub();
+        match self.kind {
+            LatticeOpKind::Glb => {
+                sub.relate(v, a)?;
+                sub.relate(v, b)?;
+            }
+            LatticeOpKind::Lub => {
+                sub.relate(a, v)?;
+                sub.relate(b, v)?;
+            }
+        }
+        Ok(())
+    }
 }
 
-/// Relates two types using a given lattice.
-#[instrument(skip(this), level = "debug")]
-pub fn super_lattice_tys<'a, 'tcx: 'a, L>(
-    this: &mut L,
-    a: Ty<'tcx>,
-    b: Ty<'tcx>,
-) -> RelateResult<'tcx, Ty<'tcx>>
-where
-    L: LatticeDir<'a, 'tcx>,
-{
-    if a == b {
-        return Ok(a);
+impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for LatticeOp<'_, '_, 'tcx> {
+    fn span(&self) -> Span {
+        self.fields.trace.span()
     }
 
-    let infcx = this.infcx();
-
-    let a = infcx.shallow_resolve(a);
-    let b = infcx.shallow_resolve(b);
-
-    match (a.kind(), b.kind()) {
-        // If one side is known to be a variable and one is not,
-        // create a variable (`v`) to represent the LUB. Make sure to
-        // relate `v` to the non-type-variable first (by passing it
-        // first to `relate_bound`). Otherwise, we would produce a
-        // subtype obligation that must then be processed.
-        //
-        // Example: if the LHS is a type variable, and RHS is
-        // `Box<i32>`, then we current compare `v` to the RHS first,
-        // which will instantiate `v` with `Box<i32>`. Then when `v`
-        // is compared to the LHS, we instantiate LHS with `Box<i32>`.
-        // But if we did in reverse order, we would create a `v <:
-        // LHS` (or vice versa) constraint and then instantiate
-        // `v`. This would require further processing to achieve same
-        // end-result; in particular, this screws up some of the logic
-        // in coercion, which expects LUB to figure out that the LHS
-        // is (e.g.) `Box<i32>`. A more obvious solution might be to
-        // iterate on the subtype obligations that are returned, but I
-        // think this suffices. -nmatsakis
-        (&ty::Infer(TyVar(..)), _) => {
-            let v = infcx.next_ty_var(this.cause().span);
-            this.relate_bound(v, b, a)?;
-            Ok(v)
-        }
-        (_, &ty::Infer(TyVar(..))) => {
-            let v = infcx.next_ty_var(this.cause().span);
-            this.relate_bound(v, a, b)?;
-            Ok(v)
-        }
+    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
+        StructurallyRelateAliases::No
+    }
 
-        (
-            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
-            &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }),
-        ) if a_def_id == b_def_id => infcx.super_combine_tys(this, a, b),
-
-        (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _)
-        | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
-            if this.define_opaque_types() == DefineOpaqueTypes::Yes
-                && def_id.is_local()
-                && !this.infcx().next_trait_solver() =>
-        {
-            this.register_goals(infcx.handle_opaque_type(a, b, this.span(), this.param_env())?);
-            Ok(a)
-        }
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.fields.param_env
+    }
+
+    fn register_predicates(
+        &mut self,
+        obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
+    ) {
+        self.fields.register_predicates(obligations);
+    }
+
+    fn register_goals(
+        &mut self,
+        obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
+    ) {
+        self.fields.register_obligations(obligations);
+    }
 
-        _ => infcx.super_combine_tys(this, a, b),
+    fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
+        self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate(
+            a.into(),
+            b.into(),
+            // FIXME(deferred_projection_equality): This isn't right, I think?
+            ty::AliasRelationDirection::Equate,
+        ))]);
     }
 }
diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs
deleted file mode 100644
index 35c7ab5000d..00000000000
--- a/compiler/rustc_infer/src/infer/relate/lub.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-//! Least upper bound. See [`lattice`].
-
-use rustc_middle::traits::solve::Goal;
-use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::Span;
-use tracing::{debug, instrument};
-
-use super::StructurallyRelateAliases;
-use super::combine::{CombineFields, PredicateEmittingRelation};
-use super::lattice::{self, LatticeDir};
-use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin};
-use crate::traits::ObligationCause;
-
-/// "Least upper bound" (common supertype)
-pub struct Lub<'combine, 'infcx, 'tcx> {
-    fields: &'combine mut CombineFields<'infcx, 'tcx>,
-}
-
-impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> {
-    pub fn new(fields: &'combine mut CombineFields<'infcx, 'tcx>) -> Lub<'combine, 'infcx, 'tcx> {
-        Lub { fields }
-    }
-}
-
-impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
-    fn cx(&self) -> TyCtxt<'tcx> {
-        self.fields.tcx()
-    }
-
-    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
-        &mut self,
-        variance: ty::Variance,
-        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
-        a: T,
-        b: T,
-    ) -> RelateResult<'tcx, T> {
-        match variance {
-            ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b),
-            ty::Covariant => self.relate(a, b),
-            // FIXME(#41044) -- not correct, need test
-            ty::Bivariant => Ok(a),
-            ty::Contravariant => self.fields.glb().relate(a, b),
-        }
-    }
-
-    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        lattice::super_lattice_tys(self, a, b)
-    }
-
-    #[instrument(skip(self), level = "trace")]
-    fn regions(
-        &mut self,
-        a: ty::Region<'tcx>,
-        b: ty::Region<'tcx>,
-    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
-        let origin = SubregionOrigin::Subtype(Box::new(self.fields.trace.clone()));
-        // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
-        Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
-            self.cx(),
-            origin,
-            a,
-            b,
-        ))
-    }
-
-    #[instrument(skip(self), level = "trace")]
-    fn consts(
-        &mut self,
-        a: ty::Const<'tcx>,
-        b: ty::Const<'tcx>,
-    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
-        self.fields.infcx.super_combine_consts(self, a, b)
-    }
-
-    fn binders<T>(
-        &mut self,
-        a: ty::Binder<'tcx, T>,
-        b: ty::Binder<'tcx, T>,
-    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
-    where
-        T: Relate<TyCtxt<'tcx>>,
-    {
-        // LUB of a binder and itself is just itself
-        if a == b {
-            return Ok(a);
-        }
-
-        debug!("binders(a={:?}, b={:?})", a, b);
-        if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
-            // When higher-ranked types are involved, computing the LUB is
-            // very challenging, switch to invariance. This is obviously
-            // overly conservative but works ok in practice.
-            self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
-            Ok(a)
-        } else {
-            Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
-        }
-    }
-}
-
-impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
-    fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
-        self.fields.infcx
-    }
-
-    fn cause(&self) -> &ObligationCause<'tcx> {
-        &self.fields.trace.cause
-    }
-
-    fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
-        let mut sub = self.fields.sub();
-        sub.relate(a, v)?;
-        sub.relate(b, v)?;
-        Ok(())
-    }
-
-    fn define_opaque_types(&self) -> DefineOpaqueTypes {
-        self.fields.define_opaque_types
-    }
-}
-
-impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
-    fn span(&self) -> Span {
-        self.fields.trace.span()
-    }
-
-    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
-        StructurallyRelateAliases::No
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.fields.param_env
-    }
-
-    fn register_predicates(
-        &mut self,
-        obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
-    ) {
-        self.fields.register_predicates(obligations);
-    }
-
-    fn register_goals(
-        &mut self,
-        obligations: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
-    ) {
-        self.fields.register_obligations(obligations)
-    }
-
-    fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
-        self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate(
-            a.into(),
-            b.into(),
-            // FIXME(deferred_projection_equality): This isn't right, I think?
-            ty::AliasRelationDirection::Equate,
-        ))]);
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/relate/mod.rs b/compiler/rustc_infer/src/infer/relate/mod.rs
index 183ea5b3309..edc0c4f078a 100644
--- a/compiler/rustc_infer/src/infer/relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/relate/mod.rs
@@ -10,8 +10,6 @@ pub use self::combine::{CombineFields, PredicateEmittingRelation};
 #[allow(hidden_glob_reexports)]
 pub(super) mod combine;
 mod generalize;
-mod glb;
 mod higher_ranked;
 mod lattice;
-mod lub;
 mod type_relating;