Lift `TraitRef` into `rustc_type_ir`
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6f0bd05..ccc45e2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -22,6 +22,7 @@
     Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
     TerminatorKind, VarBindingForm,
 };
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{
     self, suggest_constraining_type_params, PredicateKind, ToPredicate, Ty, TyCtxt,
     TypeSuperVisitable, TypeVisitor,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 76daa1d6..2740e96 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -532,8 +532,11 @@
 
         if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
             let tcx = self.tcx();
-            let trait_ref =
-                ty::TraitRef::from_lang_item(tcx, LangItem::Copy, self.last_span, [place_ty.ty]);
+            let trait_ref = ty::TraitRef::new(
+                tcx,
+                tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
+                [place_ty.ty],
+            );
 
             // To have a `Copy` operand, the type `T` of the
             // value must be `Copy`. Note that we prove that `T: Copy`,
@@ -1273,10 +1276,9 @@
 
                 self.check_rvalue(body, rv, location);
                 if !self.unsized_feature_enabled() {
-                    let trait_ref = ty::TraitRef::from_lang_item(
+                    let trait_ref = ty::TraitRef::new(
                         tcx,
-                        LangItem::Sized,
-                        self.last_span,
+                        tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                         [place_ty],
                     );
                     self.prove_trait_ref(
@@ -1925,8 +1927,11 @@
                         Operand::Move(place) => {
                             // Make sure that repeated elements implement `Copy`.
                             let ty = place.ty(body, tcx).ty;
-                            let trait_ref =
-                                ty::TraitRef::from_lang_item(tcx, LangItem::Copy, span, [ty]);
+                            let trait_ref = ty::TraitRef::new(
+                                tcx,
+                                tcx.require_lang_item(LangItem::Copy, Some(span)),
+                                [ty],
+                            );
 
                             self.prove_trait_ref(
                                 trait_ref,
@@ -1939,7 +1944,11 @@
             }
 
             &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
-                let trait_ref = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, span, [ty]);
+                let trait_ref = ty::TraitRef::new(
+                    tcx,
+                    tcx.require_lang_item(LangItem::Sized, Some(span)),
+                    [ty],
+                );
 
                 self.prove_trait_ref(
                     trait_ref,
@@ -1952,7 +1961,11 @@
             Rvalue::ShallowInitBox(operand, ty) => {
                 self.check_operand(operand, location);
 
-                let trait_ref = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, span, [*ty]);
+                let trait_ref = ty::TraitRef::new(
+                    tcx,
+                    tcx.require_lang_item(LangItem::Sized, Some(span)),
+                    [*ty],
+                );
 
                 self.prove_trait_ref(
                     trait_ref,
@@ -2050,10 +2063,9 @@
 
                     CastKind::PointerCoercion(PointerCoercion::Unsize) => {
                         let &ty = ty;
-                        let trait_ref = ty::TraitRef::from_lang_item(
+                        let trait_ref = ty::TraitRef::new(
                             tcx,
-                            LangItem::CoerceUnsized,
-                            span,
+                            tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
                             [op.ty(body, tcx), ty],
                         );
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index dda8f3e..247a288 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -8,7 +8,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::{self, CallSource};
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintTraitRefExt as _};
 use rustc_middle::ty::{
     self, suggest_constraining_type_param, Closure, FnDef, FnPtr, GenericArgKind, GenericArgsRef,
     Param, TraitRef, Ty,
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 4696917..40560a5 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -94,6 +94,12 @@
     ErrCode,
 );
 
+impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
+    }
+}
+
 into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
 
 impl IntoDiagArg for bool {
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 0b6c60e..8f0aba1 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -14,6 +14,7 @@
 use rustc_infer::infer::{self, RegionResolutionError};
 use rustc_infer::traits::Obligation;
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index 8a1dbc1..2873542 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -3,6 +3,7 @@
 
 use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::Unsafety;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{ImplPolarity::*, ImplTraitHeader, TraitDef, TyCtxt};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::ErrorGuaranteed;
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 11bd3e52..de12475 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -5,6 +5,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index bc6ecae..38dfa8d 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -17,6 +17,7 @@
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::traits::FulfillmentError;
 use rustc_middle::query::Key;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, suggest_constraining_type_param};
 use rustc_middle::ty::{AdtDef, Ty, TyCtxt, TypeVisitableExt};
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index ff0377d..88ba937 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -758,10 +758,9 @@
             self.tcx,
             self.cause.clone(),
             self.param_env,
-            ty::TraitRef::from_lang_item(
+            ty::TraitRef::new(
                 self.tcx,
-                hir::LangItem::PointerLike,
-                self.cause.span,
+                self.tcx.require_lang_item(hir::LangItem::PointerLike, Some(self.cause.span)),
                 [a],
             ),
         ));
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 804413a..ab53a93 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -25,7 +25,9 @@
 use rustc_infer::infer::{self, RegionVariableOrigin};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
-use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
+use rustc_middle::ty::print::{
+    with_crate_prefix, with_forced_trimmed_paths, PrintTraitRefExt as _,
+};
 use rustc_middle::ty::IsSuggestable;
 use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::DefIdSet;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 6370794..4d2b225 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -70,7 +70,7 @@
 use rustc_hir::lang_items::LangItem;
 use rustc_macros::extension;
 use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError};
+use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError, PrintTraitRefExt as _};
 use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::{
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 01e75d59..ba4ddc1 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -12,7 +12,7 @@
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::error::ExpectedFound;
-use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
+use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode};
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, RePlaceholder, Region, TyCtxt};
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 0931bb2..62ba9ef 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -30,7 +30,7 @@
 use rustc_middle::bug;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError};
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError, PrintTraitRefExt as _};
 use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt};
 use rustc_session::lint::{BuiltinLintDiag, LintExpectationId};
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index a65b3a4..329d5f3 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -8,7 +8,7 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_type_ir::ConstKind as IrConstKind;
-use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo};
+use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
 
 mod int;
 mod kind;
@@ -30,7 +30,7 @@
 #[rustc_pass_by_value]
 pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
 
-impl<'tcx> IntoKind for Const<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> {
     type Kind = ConstKind<'tcx>;
 
     fn kind(self) -> ConstKind<'tcx> {
@@ -48,12 +48,6 @@
     }
 }
 
-impl<'tcx> ConstTy<TyCtxt<'tcx>> for Const<'tcx> {
-    fn ty(self) -> Ty<'tcx> {
-        self.ty()
-    }
-}
-
 /// Typed constant value.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable)]
@@ -180,7 +174,7 @@
     }
 }
 
-impl<'tcx> rustc_type_ir::new::Const<TyCtxt<'tcx>> for Const<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
     fn new_anon_bound(
         tcx: TyCtxt<'tcx>,
         debruijn: ty::DebruijnIndex,
@@ -189,6 +183,10 @@
     ) -> Self {
         Const::new_bound(tcx, debruijn, var, ty)
     }
+
+    fn ty(self) -> Ty<'tcx> {
+        self.ty()
+    }
 }
 
 impl<'tcx> Const<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index ed15f61..0464be2 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -140,6 +140,19 @@
     fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
         self.mk_canonical_var_infos(infos)
     }
+
+    type GenericsOf = &'tcx ty::Generics;
+    fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics {
+        self.generics_of(def_id)
+    }
+
+    fn check_and_mk_args(
+        self,
+        def_id: DefId,
+        args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
+    ) -> ty::GenericArgsRef<'tcx> {
+        self.check_and_mk_args(def_id, args)
+    }
 }
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index b9dc283..904c0c3 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -39,6 +39,16 @@
     marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
 }
 
+impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
+    fn type_at(self, i: usize) -> Ty<'tcx> {
+        self.type_at(i)
+    }
+
+    fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
+        GenericArgs::identity_for_item(tcx, def_id)
+    }
+}
+
 #[cfg(parallel_compiler)]
 unsafe impl<'tcx> rustc_data_structures::sync::DynSend for GenericArg<'tcx> where
     &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSend
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index f380aea..04655c5 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -145,6 +145,12 @@
     pub host_effect_index: Option<usize>,
 }
 
+impl<'tcx> rustc_type_ir::inherent::GenericsOf<TyCtxt<'tcx>> for &'tcx Generics {
+    fn count(&self) -> usize {
+        self.parent_count + self.own_params.len()
+    }
+}
+
 impl<'tcx> Generics {
     /// Looks through the generics and all parents to find the index of the
     /// given param def-id. This is in comparison to the `param_def_id_to_index`
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 73b20f0..12cefc2 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -530,7 +530,7 @@
 #[rustc_pass_by_value]
 pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
 
-impl<'tcx> IntoKind for Ty<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Ty<'tcx> {
     type Kind = TyKind<'tcx>;
 
     fn kind(self) -> TyKind<'tcx> {
@@ -981,7 +981,7 @@
 
 pub type PlaceholderRegion = Placeholder<BoundRegion>;
 
-impl PlaceholderLike for PlaceholderRegion {
+impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderRegion {
     fn universe(self) -> UniverseIndex {
         self.universe
     }
@@ -1001,7 +1001,7 @@
 
 pub type PlaceholderType = Placeholder<BoundTy>;
 
-impl PlaceholderLike for PlaceholderType {
+impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderType {
     fn universe(self) -> UniverseIndex {
         self.universe
     }
@@ -1028,7 +1028,7 @@
 
 pub type PlaceholderConst = Placeholder<BoundVar>;
 
-impl PlaceholderLike for PlaceholderConst {
+impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderConst {
     fn universe(self) -> UniverseIndex {
         self.universe
     }
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 48d900e..2279e27 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -2,19 +2,19 @@
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
-use rustc_hir::LangItem;
 use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
-use rustc_span::Span;
 use rustc_type_ir::ClauseKind as IrClauseKind;
 use rustc_type_ir::PredicateKind as IrPredicateKind;
+use rustc_type_ir::TraitRef as IrTraitRef;
 use std::cmp::Ordering;
 
 use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{
-    self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArg, GenericArgs,
-    GenericArgsRef, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
+    self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArgsRef,
+    PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
 };
 
+pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
 pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
 pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
 
@@ -326,76 +326,6 @@
     }
 }
 
-/// A complete reference to a trait. These take numerous guises in syntax,
-/// but perhaps the most recognizable form is in a where-clause:
-/// ```ignore (illustrative)
-/// T: Foo<U>
-/// ```
-/// This would be represented by a trait-reference where the `DefId` is the
-/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
-/// and `U` as parameter 1.
-///
-/// Trait references also appear in object types like `Foo<U>`, but in
-/// that case the `Self` parameter is absent from the generic parameters.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
-#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
-pub struct TraitRef<'tcx> {
-    pub def_id: DefId,
-    pub args: GenericArgsRef<'tcx>,
-    /// This field exists to prevent the creation of `TraitRef` without
-    /// calling [`TraitRef::new`].
-    pub(super) _use_trait_ref_new_instead: (),
-}
-
-impl<'tcx> TraitRef<'tcx> {
-    pub fn new(
-        tcx: TyCtxt<'tcx>,
-        trait_def_id: DefId,
-        args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
-    ) -> Self {
-        let args = tcx.check_and_mk_args(trait_def_id, args);
-        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
-    }
-
-    pub fn from_lang_item(
-        tcx: TyCtxt<'tcx>,
-        trait_lang_item: LangItem,
-        span: Span,
-        args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
-    ) -> Self {
-        let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span));
-        Self::new(tcx, trait_def_id, args)
-    }
-
-    pub fn from_method(
-        tcx: TyCtxt<'tcx>,
-        trait_id: DefId,
-        args: GenericArgsRef<'tcx>,
-    ) -> ty::TraitRef<'tcx> {
-        let defs = tcx.generics_of(trait_id);
-        ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.own_params.len()]))
-    }
-
-    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
-    /// are the parameters defined on trait.
-    pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> {
-        ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id))
-    }
-
-    pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
-        ty::TraitRef::new(
-            tcx,
-            self.def_id,
-            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
-        )
-    }
-
-    #[inline]
-    pub fn self_ty(&self) -> Ty<'tcx> {
-        self.args.type_at(0)
-    }
-}
-
 pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
 
 impl<'tcx> PolyTraitRef<'tcx> {
@@ -408,12 +338,6 @@
     }
 }
 
-impl<'tcx> IntoDiagArg for TraitRef<'tcx> {
-    fn into_diag_arg(self) -> DiagArgValue {
-        self.to_string().into_diag_arg()
-    }
-}
-
 /// An existential reference to a trait, where `Self` is erased.
 /// For example, the trait object `Trait<'a, 'b, X, Y>` is:
 /// ```ignore (illustrative)
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index eecd7dc..d0bae91 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -1,6 +1,7 @@
 use crate::ty::GenericArg;
 use crate::ty::{self, Ty, TyCtxt};
 
+use hir::def::Namespace;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
@@ -11,6 +12,8 @@
 mod pretty;
 pub use self::pretty::*;
 
+use super::Lift;
+
 pub type PrintError = std::fmt::Error;
 
 pub trait Print<'tcx, P> {
@@ -334,3 +337,17 @@
         format!("module `{}`", tcx.def_path_str(def_id))
     }
 }
+
+impl<T> rustc_type_ir::ir_print::IrPrint<T> for TyCtxt<'_>
+where
+    T: Copy + for<'a, 'tcx> Lift<TyCtxt<'tcx>, Lifted: Print<'tcx, FmtPrinter<'a, 'tcx>>>,
+{
+    fn print(t: &T, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        ty::tls::with(|tcx| {
+            let mut cx = FmtPrinter::new(tcx, Namespace::TypeNS);
+            tcx.lift(*t).expect("could not lift for printing").print(&mut cx)?;
+            fmt.write_str(&cx.into_buffer())?;
+            Ok(())
+        })
+    }
+}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 46dcd18..14a628a 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -16,7 +16,7 @@
 use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPathDataName};
 use rustc_hir::LangItem;
-use rustc_macros::Lift;
+use rustc_macros::{extension, Lift};
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -2919,16 +2919,17 @@
     }
 }
 
+#[extension(pub trait PrintTraitRefExt<'tcx>)]
 impl<'tcx> ty::TraitRef<'tcx> {
-    pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
+    fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> {
         TraitRefPrintOnlyTraitPath(self)
     }
 
-    pub fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> {
+    fn print_trait_sugared(self) -> TraitRefPrintSugared<'tcx> {
         TraitRefPrintSugared(self)
     }
 
-    pub fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
+    fn print_only_trait_name(self) -> TraitRefPrintOnlyTraitName<'tcx> {
         TraitRefPrintOnlyTraitName(self)
     }
 }
@@ -3032,6 +3033,10 @@
 define_print! {
     (self, cx):
 
+    ty::TraitRef<'tcx> {
+        p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
+    }
+
     ty::TypeAndMut<'tcx> {
         p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
     }
@@ -3113,10 +3118,6 @@
         p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
     }
 
-    ty::TraitRef<'tcx> {
-        p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
-    }
-
     TraitRefPrintOnlyTraitPath<'tcx> {
         p!(print_def_path(self.0.def_id, self.0.args));
     }
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 3d9be15..8842ecd 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -19,7 +19,7 @@
 #[rustc_pass_by_value]
 pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
 
-impl<'tcx> rustc_type_ir::IntoKind for Region<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::IntoKind for Region<'tcx> {
     type Kind = RegionKind<'tcx>;
 
     fn kind(self) -> RegionKind<'tcx> {
@@ -137,7 +137,7 @@
     }
 }
 
-impl<'tcx> rustc_type_ir::new::Region<TyCtxt<'tcx>> for Region<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> {
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
     }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 78a7071..a7770f7 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -132,12 +132,6 @@
     }
 }
 
-impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        with_no_trimmed_paths!(fmt::Display::fmt(self, f))
-    }
-}
-
 impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> {
     fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
         this: WithInfcx<'_, Infcx, &Self>,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 32b9709..a97244d 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -942,7 +942,7 @@
     }
 }
 
-impl<'tcx, T> rustc_type_ir::BoundVars<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+impl<'tcx, T> rustc_type_ir::inherent::BoundVars<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
     fn bound_vars(&self) -> &'tcx List<ty::BoundVariableKind> {
         self.bound_vars
     }
@@ -1812,7 +1812,7 @@
     }
 }
 
-impl<'tcx> rustc_type_ir::new::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
+impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
         Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
     }
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index cbab200..ddfb42a 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -32,10 +32,9 @@
     source_ty: Ty<'tcx>,
     target_ty: Ty<'tcx>,
 ) -> Result<CustomCoerceUnsized, ErrorGuaranteed> {
-    let trait_ref = ty::TraitRef::from_lang_item(
+    let trait_ref = ty::TraitRef::new(
         tcx.tcx,
-        LangItem::CoerceUnsized,
-        tcx.span,
+        tcx.require_lang_item(LangItem::CoerceUnsized, Some(tcx.span)),
         [source_ty, target_ty],
     );
 
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index c437ded..755f5cf 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -1,11 +1,11 @@
 use std::cmp::Ordering;
 
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_type_ir::new::{Const, Region, Ty};
+use rustc_type_ir::inherent::*;
 use rustc_type_ir::visit::TypeVisitableExt;
 use rustc_type_ir::{
-    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy,
-    InferCtxtLike, Interner, IntoKind, PlaceholderLike,
+    self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, InferCtxtLike,
+    Interner,
 };
 
 /// Whether we're canonicalizing a query input or the query response.
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index e64d2eb..c814301 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -20,6 +20,7 @@
 use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
 use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
 use rustc_middle::query::Providers;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, Const, GenericParamDefKind};
 use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 7228a9b..b442446 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -4,7 +4,7 @@
     SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
+use rustc_middle::ty::{self, print::PrintTraitRefExt as _, ClosureKind, PolyTraitRef, Ty};
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index f886c58..454c7a5 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -368,7 +368,7 @@
                 }
             };
         let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
-            ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
+            ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output])
         });
 
         let pred = tupled_inputs_and_output
@@ -414,7 +414,7 @@
             )?;
         let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
             |AsyncCallableRelevantTypes { output_coroutine_ty: output_ty, .. }| {
-                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output_ty])
+                ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output_ty])
             },
         );
 
@@ -576,10 +576,9 @@
                     // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
                     // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
                     // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
-                    let sized_predicate = ty::TraitRef::from_lang_item(
+                    let sized_predicate = ty::TraitRef::new(
                         tcx,
-                        LangItem::Sized,
-                        DUMMY_SP,
+                        tcx.require_lang_item(LangItem::Sized, None),
                         [ty::GenericArg::from(goal.predicate.self_ty())],
                     );
                     // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 0fde9dd..083cc0a 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -16,7 +16,7 @@
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
 use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
-use rustc_span::{ErrorGuaranteed, DUMMY_SP};
+use rustc_span::ErrorGuaranteed;
 
 impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
     fn self_ty(self) -> Ty<'tcx> {
@@ -307,7 +307,7 @@
                 }
             };
         let output_is_sized_pred = tupled_inputs_and_output.map_bound(|(_, output)| {
-            ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
+            ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, None), [output])
         });
 
         let pred = tupled_inputs_and_output
@@ -346,7 +346,11 @@
             )?;
         let output_is_sized_pred = tupled_inputs_and_output_and_coroutine.map_bound(
             |AsyncCallableRelevantTypes { output_coroutine_ty, .. }| {
-                ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output_coroutine_ty])
+                ty::TraitRef::new(
+                    tcx,
+                    tcx.require_lang_item(LangItem::Sized, None),
+                    [output_coroutine_ty],
+                )
             },
         );
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 31f9ac1..898f83e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -10,6 +10,7 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_macros::{extension, LintDiagnostic};
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
 use rustc_parse_format::{ParseMode, Parser, Piece, Position};
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index a687ec0..db53d1e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -538,10 +538,12 @@
                             self.tcx,
                             obligation.cause.clone(),
                             obligation.param_env,
-                            ty::TraitRef::from_lang_item(
+                            ty::TraitRef::new(
                                 self.tcx,
-                                hir::LangItem::Sized,
-                                obligation.cause.span,
+                                self.tcx.require_lang_item(
+                                    hir::LangItem::Sized,
+                                    Some(obligation.cause.span),
+                                ),
                                 [base_ty],
                             ),
                         );
@@ -4044,10 +4046,9 @@
                         let node = tcx.hir_node_by_def_id(hir.get_parent_item(expr.hir_id).def_id);
 
                         let pred = ty::Binder::dummy(ty::TraitPredicate {
-                            trait_ref: ty::TraitRef::from_lang_item(
+                            trait_ref: ty::TraitRef::new(
                                 tcx,
-                                LangItem::Clone,
-                                span,
+                                tcx.require_lang_item(LangItem::Clone, Some(span)),
                                 [*ty],
                             ),
                             polarity: ty::PredicatePolarity::Positive,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 0989d49..b72a4b4 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -37,7 +37,9 @@
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print};
+use rustc_middle::ty::print::{
+    with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitRefExt as _,
+};
 use rustc_middle::ty::{
     self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
     TypeVisitable, TypeVisitableExt,
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 587f2f7..6b9593b 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -973,9 +973,12 @@
                 //
                 // NOTE: This should be kept in sync with the similar code in
                 // `rustc_ty_utils::instance::resolve_associated_item()`.
-                let node_item =
-                    specialization_graph::assoc_def(selcx.tcx(), impl_data.impl_def_id, obligation.predicate.def_id)
-                        .map_err(|ErrorGuaranteed { .. }| ())?;
+                let node_item = specialization_graph::assoc_def(
+                    selcx.tcx(),
+                    impl_data.impl_def_id,
+                    obligation.predicate.def_id,
+                )
+                .map_err(|ErrorGuaranteed { .. }| ())?;
 
                 if node_item.is_final() {
                     // Non-specializable items are always projectable.
@@ -1018,7 +1021,8 @@
                     lang_items.async_fn_trait(),
                     lang_items.async_fn_mut_trait(),
                     lang_items.async_fn_once_trait(),
-                ].contains(&Some(trait_ref.def_id))
+                ]
+                .contains(&Some(trait_ref.def_id))
                 {
                     true
                 } else if lang_items.async_fn_kind_helper() == Some(trait_ref.def_id) {
@@ -1031,7 +1035,7 @@
                         true
                     } else {
                         obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some()
-                        && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
+                            && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some()
                     }
                 } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) {
                     match self_ty.kind() {
@@ -1158,12 +1162,20 @@
                         // Otherwise, type parameters, opaques, and unnormalized projections have
                         // unit metadata if they're known (e.g. by the param_env) to be sized.
                         ty::Param(_) | ty::Alias(..)
-                            if self_ty != tail || selcx.infcx.predicate_must_hold_modulo_regions(
-                                &obligation.with(
-                                    selcx.tcx(),
-                                    ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]),
-                                ),
-                            ) =>
+                            if self_ty != tail
+                                || selcx.infcx.predicate_must_hold_modulo_regions(
+                                    &obligation.with(
+                                        selcx.tcx(),
+                                        ty::TraitRef::new(
+                                            selcx.tcx(),
+                                            selcx.tcx().require_lang_item(
+                                                LangItem::Sized,
+                                                Some(obligation.cause.span()),
+                                            ),
+                                            [self_ty],
+                                        ),
+                                    ),
+                                ) =>
                         {
                             true
                         }
@@ -1226,7 +1238,7 @@
                     obligation.cause.span,
                     format!("Cannot project an associated type from `{impl_source:?}`"),
                 );
-                return Err(())
+                return Err(());
             }
         };
 
@@ -1555,10 +1567,9 @@
                 // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`.
                 // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't
                 // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`.
-                let sized_predicate = ty::TraitRef::from_lang_item(
+                let sized_predicate = ty::TraitRef::new(
                     tcx,
-                    LangItem::Sized,
-                    obligation.cause.span(),
+                    tcx.require_lang_item(LangItem::Sized, Some(obligation.cause.span())),
                     [self_ty],
                 );
                 obligations.push(obligation.with(tcx, sized_predicate));
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 22e0ee3..e9117b9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -735,7 +735,11 @@
             output_ty,
             &mut nested,
         );
-        let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]);
+        let tr = ty::TraitRef::new(
+            self.tcx(),
+            self.tcx().require_lang_item(LangItem::Sized, Some(cause.span)),
+            [output_ty],
+        );
         nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr));
 
         Ok(nested)
@@ -1009,10 +1013,12 @@
         } else {
             nested.push(obligation.with(
                 self.tcx(),
-                ty::TraitRef::from_lang_item(
+                ty::TraitRef::new(
                     self.tcx(),
-                    LangItem::AsyncFnKindHelper,
-                    obligation.cause.span,
+                    self.tcx().require_lang_item(
+                        LangItem::AsyncFnKindHelper,
+                        Some(obligation.cause.span),
+                    ),
                     [kind_ty, Ty::from_closure_kind(self.tcx(), goal_kind)],
                 ),
             ));
@@ -1241,10 +1247,9 @@
                     .collect();
 
                 // We can only make objects from sized types.
-                let tr = ty::TraitRef::from_lang_item(
+                let tr = ty::TraitRef::new(
                     tcx,
-                    LangItem::Sized,
-                    obligation.cause.span,
+                    tcx.require_lang_item(LangItem::Sized, Some(obligation.cause.span)),
                     [source],
                 );
                 nested.push(predicate_to_obligation(tr.to_predicate(tcx)));
@@ -1474,10 +1479,9 @@
                         cause.clone(),
                         obligation.recursion_depth + 1,
                         self_ty.rebind(ty::TraitPredicate {
-                            trait_ref: ty::TraitRef::from_lang_item(
+                            trait_ref: ty::TraitRef::new(
                                 self.tcx(),
-                                LangItem::Destruct,
-                                cause.span,
+                                self.tcx().require_lang_item(LangItem::Destruct, Some(cause.span)),
                                 [nested_ty.into(), host_effect_param],
                             ),
                             polarity: ty::PredicatePolarity::Positive,
@@ -1507,10 +1511,9 @@
                 | ty::Infer(_)
                 | ty::Placeholder(_) => {
                     let predicate = self_ty.rebind(ty::TraitPredicate {
-                        trait_ref: ty::TraitRef::from_lang_item(
+                        trait_ref: ty::TraitRef::new(
                             self.tcx(),
-                            LangItem::Destruct,
-                            cause.span,
+                            self.tcx().require_lang_item(LangItem::Destruct, Some(cause.span)),
                             [nested_ty.into(), host_effect_param],
                         ),
                         polarity: ty::PredicatePolarity::Positive,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index dc00598..a4b0f8b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -41,6 +41,7 @@
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::_match::MatchAgainstFreshVars;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, PolyProjectionPredicate, ToPredicate};
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 390e711..fe3f66f 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -11,6 +11,7 @@
 
 pub mod specialization_graph;
 use rustc_infer::infer::DefineOpaqueTypes;
+use rustc_middle::ty::print::PrintTraitRefExt as _;
 use specialization_graph::GraphExt;
 
 use crate::errors::NegativePositiveConflict;
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 28ee76f..1531e2f 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -525,8 +525,11 @@
     fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
         if !subty.has_escaping_bound_vars() {
             let cause = self.cause(cause);
-            let trait_ref =
-                ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [subty]);
+            let trait_ref = ty::TraitRef::new(
+                self.tcx(),
+                self.tcx().require_lang_item(LangItem::Sized, Some(cause.span)),
+                [subty],
+            );
             self.out.push(traits::Obligation::with_depth(
                 self.tcx(),
                 cause,
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
deleted file mode 100644
index 57f961a..0000000
--- a/compiler/rustc_type_ir/src/binder.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-use crate::Interner;
-
-pub trait BoundVars<I: Interner> {
-    fn bound_vars(&self) -> I::BoundVars;
-
-    fn has_no_bound_vars(&self) -> bool;
-}
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index f041c58..f7c7ec2 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -6,8 +6,9 @@
 use std::hash::Hash;
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::inherent::*;
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{Interner, PlaceholderLike, UniverseIndex};
+use crate::{Interner, UniverseIndex};
 
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs
new file mode 100644
index 0000000..84aeeae
--- /dev/null
+++ b/compiler/rustc_type_ir/src/inherent.rs
@@ -0,0 +1,49 @@
+use crate::{BoundVar, DebruijnIndex, Interner, UniverseIndex};
+
+pub trait Ty<I: Interner<Ty = Self>> {
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+}
+
+pub trait Region<I: Interner<Region = Self>> {
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
+
+    fn new_static(interner: I) -> Self;
+}
+
+pub trait Const<I: Interner<Const = Self>> {
+    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
+
+    fn ty(self) -> I::Ty;
+}
+
+pub trait GenericsOf<I: Interner> {
+    fn count(&self) -> usize;
+}
+
+pub trait GenericArgs<I: Interner> {
+    fn type_at(self, i: usize) -> I::Ty;
+
+    fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
+}
+
+/// Common capabilities of placeholder kinds
+pub trait PlaceholderLike {
+    fn universe(self) -> UniverseIndex;
+    fn var(self) -> BoundVar;
+
+    fn with_updated_universe(self, ui: UniverseIndex) -> Self;
+
+    fn new(ui: UniverseIndex, var: BoundVar) -> Self;
+}
+
+pub trait IntoKind {
+    type Kind;
+
+    fn kind(self) -> Self::Kind;
+}
+
+pub trait BoundVars<I: Interner> {
+    fn bound_vars(&self) -> I::BoundVars;
+
+    fn has_no_bound_vars(&self) -> bool;
+}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 70f7e58..32f07b1 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -3,13 +3,12 @@
 use std::hash::Hash;
 
 use crate::fold::TypeSuperFoldable;
+use crate::inherent::*;
+use crate::ir_print::IrPrint;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
-use crate::{
-    new, BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TyKind,
-    UniverseIndex,
-};
+use crate::{CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TraitRef, TyKind};
 
-pub trait Interner: Sized + Copy {
+pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
     type DefId: Copy + Debug + Hash + Eq;
     type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
     type AdtDef: Copy + Debug + Hash + Eq;
@@ -18,7 +17,8 @@
         + DebugWithInfcx<Self>
         + Hash
         + Eq
-        + IntoIterator<Item = Self::GenericArg>;
+        + IntoIterator<Item = Self::GenericArg>
+        + GenericArgs<Self>;
     type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type Term: Copy + Debug + Hash + Eq;
 
@@ -38,7 +38,7 @@
         + TypeSuperVisitable<Self>
         + TypeSuperFoldable<Self>
         + Flags
-        + new::Ty<Self>;
+        + Ty<Self>;
     type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
     type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type ParamTy: Copy + Debug + Hash + Eq;
@@ -59,11 +59,10 @@
         + Eq
         + Into<Self::GenericArg>
         + IntoKind<Kind = ConstKind<Self>>
-        + ConstTy<Self>
         + TypeSuperVisitable<Self>
         + TypeSuperFoldable<Self>
         + Flags
-        + new::Const<Self>;
+        + Const<Self>;
     type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq;
     type PlaceholderConst: Copy + Debug + Hash + Eq + PlaceholderLike;
     type ParamConst: Copy + Debug + Hash + Eq;
@@ -79,7 +78,7 @@
         + Into<Self::GenericArg>
         + IntoKind<Kind = RegionKind<Self>>
         + Flags
-        + new::Region<Self>;
+        + Region<Self>;
     type EarlyParamRegion: Copy + Debug + Hash + Eq;
     type LateParamRegion: Copy + Debug + Hash + Eq;
     type BoundRegion: Copy + Debug + Hash + Eq;
@@ -105,26 +104,15 @@
     type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
 
     fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
-}
 
-/// Common capabilities of placeholder kinds
-pub trait PlaceholderLike {
-    fn universe(self) -> UniverseIndex;
-    fn var(self) -> BoundVar;
+    type GenericsOf: GenericsOf<Self>;
+    fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
 
-    fn with_updated_universe(self, ui: UniverseIndex) -> Self;
-
-    fn new(ui: UniverseIndex, var: BoundVar) -> Self;
-}
-
-pub trait IntoKind {
-    type Kind;
-
-    fn kind(self) -> Self::Kind;
-}
-
-pub trait ConstTy<I: Interner> {
-    fn ty(self) -> I::Ty;
+    fn check_and_mk_args(
+        self,
+        def_id: Self::DefId,
+        args: impl IntoIterator<Item: Into<Self::GenericArg>>,
+    ) -> Self::GenericArgs;
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs
new file mode 100644
index 0000000..89c30fc
--- /dev/null
+++ b/compiler/rustc_type_ir/src/ir_print.rs
@@ -0,0 +1,21 @@
+use std::fmt;
+
+use crate::{Interner, TraitRef};
+
+pub trait IrPrint<T> {
+    fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
+}
+
+macro_rules! define_display_via_print {
+    ($($ty:ident,)*) => {
+        $(
+            impl<I: Interner> fmt::Display for $ty<I> {
+                fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                    <I as IrPrint<$ty<I>>>::print(self, fmt)
+                }
+            }
+        )*
+    }
+}
+
+define_display_via_print!(TraitRef,);
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index a978a30..62efa32 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -23,14 +23,14 @@
 #[cfg(feature = "nightly")]
 pub mod codec;
 pub mod fold;
-pub mod new;
+pub mod inherent;
+pub mod ir_print;
+pub mod lift;
 pub mod ty_info;
 pub mod ty_kind;
-pub mod lift;
 
 #[macro_use]
 mod macros;
-mod binder;
 mod canonical;
 mod const_kind;
 mod debug;
@@ -39,8 +39,8 @@
 mod interner;
 mod predicate_kind;
 mod region_kind;
+mod trait_ref;
 
-pub use binder::*;
 pub use canonical::*;
 #[cfg(feature = "nightly")]
 pub use codec::*;
@@ -51,6 +51,7 @@
 pub use interner::*;
 pub use predicate_kind::*;
 pub use region_kind::*;
+pub use trait_ref::*;
 pub use ty_info::*;
 pub use ty_kind::*;
 pub use AliasKind::*;
@@ -58,7 +59,6 @@
 pub use InferTy::*;
 pub use RegionKind::*;
 pub use TyKind::*;
-pub use lift::*;
 
 rustc_index::newtype_index! {
     /// A [De Bruijn index][dbi] is a standard means of representing
diff --git a/compiler/rustc_type_ir/src/lift.rs b/compiler/rustc_type_ir/src/lift.rs
new file mode 100644
index 0000000..839da10
--- /dev/null
+++ b/compiler/rustc_type_ir/src/lift.rs
@@ -0,0 +1,21 @@
+/// A trait implemented for all `X<'a>` types that can be safely and
+/// efficiently converted to `X<'tcx>` as long as they are part of the
+/// provided `TyCtxt<'tcx>`.
+/// This can be done, for example, for `Ty<'tcx>` or `GenericArgsRef<'tcx>`
+/// by looking them up in their respective interners.
+///
+/// However, this is still not the best implementation as it does
+/// need to compare the components, even for interned values.
+/// It would be more efficient if `TypedArena` provided a way to
+/// determine whether the address is in the allocated range.
+///
+/// `None` is returned if the value or one of the components is not part
+/// of the provided context.
+/// For `Ty`, `None` can be returned if either the type interner doesn't
+/// contain the `TyKind` key or if the address of the interned
+/// pointer differs. The latter case is possible if a primitive type,
+/// e.g., `()` or `u8`, was interned in a different context.
+pub trait Lift<I>: std::fmt::Debug {
+    type Lifted: std::fmt::Debug;
+    fn lift_to_tcx(self, tcx: I) -> Option<Self::Lifted>;
+}
diff --git a/compiler/rustc_type_ir/src/new.rs b/compiler/rustc_type_ir/src/new.rs
deleted file mode 100644
index 1572a64..0000000
--- a/compiler/rustc_type_ir/src/new.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use crate::{BoundVar, DebruijnIndex, Interner};
-
-pub trait Ty<I: Interner<Ty = Self>> {
-    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
-}
-
-pub trait Region<I: Interner<Region = Self>> {
-    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
-
-    fn new_static(interner: I) -> Self;
-}
-
-pub trait Const<I: Interner<Const = Self>> {
-    fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
-}
diff --git a/compiler/rustc_type_ir/src/trait_ref.rs b/compiler/rustc_type_ir/src/trait_ref.rs
new file mode 100644
index 0000000..ad1350d
--- /dev/null
+++ b/compiler/rustc_type_ir/src/trait_ref.rs
@@ -0,0 +1,130 @@
+use std::fmt;
+
+use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
+
+use crate::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::inherent::*;
+use crate::lift::Lift;
+use crate::visit::{TypeVisitable, TypeVisitor};
+use crate::Interner;
+
+/// A complete reference to a trait. These take numerous guises in syntax,
+/// but perhaps the most recognizable form is in a where-clause:
+/// ```ignore (illustrative)
+/// T: Foo<U>
+/// ```
+/// This would be represented by a trait-reference where the `DefId` is the
+/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
+/// and `U` as parameter 1.
+///
+/// Trait references also appear in object types like `Foo<U>`, but in
+/// that case the `Self` parameter is absent from the generic parameters.
+#[derive(derivative::Derivative)]
+#[derivative(
+    Clone(bound = ""),
+    Copy(bound = ""),
+    Hash(bound = ""),
+    PartialEq(bound = ""),
+    Eq(bound = "")
+)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct TraitRef<I: Interner> {
+    pub def_id: I::DefId,
+    pub args: I::GenericArgs,
+    /// This field exists to prevent the creation of `TraitRef` without
+    /// calling [`TraitRef::new`].
+    pub(super) _use_trait_ref_new_instead: (),
+}
+
+impl<I: Interner> TraitRef<I> {
+    pub fn new(
+        interner: I,
+        trait_def_id: I::DefId,
+        args: impl IntoIterator<Item: Into<I::GenericArg>>,
+    ) -> Self {
+        let args = interner.check_and_mk_args(trait_def_id, args);
+        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
+    }
+
+    pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
+        let generics = interner.generics_of(trait_id);
+        TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
+    }
+
+    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
+    /// are the parameters defined on trait.
+    pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
+        TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
+    }
+
+    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
+        TraitRef::new(
+            interner,
+            self.def_id,
+            [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
+        )
+    }
+
+    #[inline]
+    pub fn self_ty(&self) -> I::Ty {
+        self.args.type_at(0)
+    }
+}
+
+impl<I: Interner> fmt::Debug for TraitRef<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let TraitRef { def_id, args, _use_trait_ref_new_instead: () } = self;
+        let mut args = args.into_iter().peekable();
+        write!(f, "{def_id:?}")?;
+        if args.peek().is_some() {
+            write!(f, "<")?;
+            for (i, arg) in args.enumerate() {
+                if i > 0 {
+                    write!(f, ", ")?;
+                }
+                write!(f, "{arg:#?}")?;
+            }
+            write!(f, ">")?;
+        }
+        Ok(())
+    }
+}
+
+// FIXME(compiler-errors): Make this into a `Lift_Generic` impl.
+impl<I: Interner, U: Interner> Lift<U> for TraitRef<I>
+where
+    I::DefId: Lift<U, Lifted = U::DefId>,
+    I::GenericArgs: Lift<U, Lifted = U::GenericArgs>,
+{
+    type Lifted = TraitRef<U>;
+
+    fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
+        Some(TraitRef {
+            def_id: self.def_id.lift_to_tcx(tcx)?,
+            args: self.args.lift_to_tcx(tcx)?,
+            _use_trait_ref_new_instead: (),
+        })
+    }
+}
+
+impl<I: Interner> TypeVisitable<I> for TraitRef<I>
+where
+    I::GenericArgs: TypeVisitable<I>,
+{
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
+        self.args.visit_with(visitor)
+    }
+}
+
+impl<I: Interner> TypeFoldable<I> for TraitRef<I>
+where
+    I::GenericArgs: TypeFoldable<I>,
+{
+    fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+        Ok(TraitRef {
+            def_id: self.def_id,
+            args: self.args.try_fold_with(folder)?,
+            _use_trait_ref_new_instead: (),
+        })
+    }
+}
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 2f588c6..3d4125f 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -47,7 +47,8 @@
 use std::fmt;
 use std::ops::ControlFlow;
 
-use crate::{self as ty, BoundVars, Interner, IntoKind, Lrc, TypeFlags};
+use crate::inherent::*;
+use crate::{self as ty, Interner, Lrc, TypeFlags};
 
 /// This trait is implemented for every type that can be visited,
 /// providing the skeleton of the traversal.
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 075d94b..b4e62e3 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -52,6 +52,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::Mutability;
+use rustc_middle::ty::print::PrintTraitRefExt;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::RustcVersion;
 use rustc_span::{
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index 18f4e51..2c2daac 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -5,6 +5,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, AliasTy, ClauseKind, PredicateKind};
+use rustc_middle::ty::print::PrintTraitRefExt;
 use rustc_session::declare_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index d8d26e2..95851a2 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -402,7 +402,7 @@
             tcx,
             ObligationCause::dummy_with_span(body.span),
             ConstCx::new(tcx, body).param_env,
-            TraitRef::from_lang_item(tcx, LangItem::Destruct, body.span, [ty]),
+            TraitRef::new(tcx, tcx.require_lang_item(LangItem::Destruct, Some(body.span)), [ty]),
         );
 
         let infcx = tcx.infer_ctxt().build();