about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs42
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs69
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs4
-rw-r--r--compiler/rustc_lint/src/context.rs66
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs64
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs169
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs42
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs20
9 files changed, 214 insertions, 310 deletions
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index a924afda6f0..54eb14ae8fc 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::DisambiguatedDefPathData;
 use rustc_middle::ty::{
     self,
-    print::{PrettyPrinter, Print, Printer},
+    print::{PrettyPrinter, Print, PrintError, Printer},
     GenericArg, GenericArgKind, Ty, TyCtxt,
 };
 use std::fmt::Write;
@@ -14,23 +14,15 @@ struct AbsolutePathPrinter<'tcx> {
 }
 
 impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
-    type Error = std::fmt::Error;
-
-    type Path = Self;
-    type Region = Self;
-    type Type = Self;
-    type DynExistential = Self;
-    type Const = Self;
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
+    fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
         Ok(self)
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
         match *ty.kind() {
             // Types without identity.
             ty::Bool
@@ -68,18 +60,18 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
         }
     }
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
         self.pretty_print_const(ct, false)
     }
 
     fn print_dyn_existential(
         self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self::DynExistential, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.pretty_print_dyn_existential(predicates)
     }
 
-    fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+    fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
         self.path.push_str(self.tcx.crate_name(cnum).as_str());
         Ok(self)
     }
@@ -88,17 +80,17 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
         self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.pretty_path_qualified(self_ty, trait_ref)
     }
 
     fn path_append_impl(
         self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         _disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.pretty_path_append_impl(
             |mut cx| {
                 cx = print_prefix(cx)?;
@@ -114,9 +106,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
 
     fn path_append(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = print_prefix(self)?;
 
         write!(self.path, "::{}", disambiguated_data.data).unwrap();
@@ -126,9 +118,9 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
 
     fn path_generic_args(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = print_prefix(self)?;
         let args =
             args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
@@ -144,9 +136,9 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
     fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
         false
     }
-    fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
+    fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, PrintError>
     where
-        T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
+        T: Print<'tcx, Self>,
     {
         if let Some(first) = elems.next() {
             self = first.print(self)?;
@@ -160,8 +152,8 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
 
     fn generic_delimiters(
         mut self,
-        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
-    ) -> Result<Self, Self::Error> {
+        f: impl FnOnce(Self) -> Result<Self, PrintError>,
+    ) -> Result<Self, PrintError> {
         write!(self, "<")?;
 
         self = f(self)?;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index d35b318e258..496bb1766a7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -67,7 +67,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::print::with_forced_trimmed_paths;
+use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError};
 use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::{
     self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
@@ -580,76 +580,68 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         struct AbsolutePathPrinter<'tcx> {
             tcx: TyCtxt<'tcx>,
+            segments: Vec<String>,
         }
 
-        struct NonTrivialPath;
-
         impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
-            type Error = NonTrivialPath;
-
-            type Path = Vec<String>;
-            type Region = !;
-            type Type = !;
-            type DynExistential = !;
-            type Const = !;
-
             fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
                 self.tcx
             }
 
-            fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
-                Err(NonTrivialPath)
+            fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
+                Err(fmt::Error)
             }
 
-            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
-                Err(NonTrivialPath)
+            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self, PrintError> {
+                Err(fmt::Error)
             }
 
             fn print_dyn_existential(
                 self,
                 _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-            ) -> Result<Self::DynExistential, Self::Error> {
-                Err(NonTrivialPath)
+            ) -> Result<Self, PrintError> {
+                Err(fmt::Error)
             }
 
-            fn print_const(self, _ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
-                Err(NonTrivialPath)
+            fn print_const(self, _ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
+                Err(fmt::Error)
             }
 
-            fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
-                Ok(vec![self.tcx.crate_name(cnum).to_string()])
+            fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
+                self.segments = vec![self.tcx.crate_name(cnum).to_string()];
+                Ok(self)
             }
             fn path_qualified(
                 self,
                 _self_ty: Ty<'tcx>,
                 _trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self::Path, Self::Error> {
-                Err(NonTrivialPath)
+            ) -> Result<Self, PrintError> {
+                Err(fmt::Error)
             }
 
             fn path_append_impl(
                 self,
-                _print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                _print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
                 _disambiguated_data: &DisambiguatedDefPathData,
                 _self_ty: Ty<'tcx>,
                 _trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self::Path, Self::Error> {
-                Err(NonTrivialPath)
+            ) -> Result<Self, PrintError> {
+                Err(fmt::Error)
             }
             fn path_append(
-                self,
-                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                mut self,
+                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
                 disambiguated_data: &DisambiguatedDefPathData,
-            ) -> Result<Self::Path, Self::Error> {
-                let mut path = print_prefix(self)?;
-                path.push(disambiguated_data.to_string());
-                Ok(path)
+            ) -> Result<Self, PrintError> {
+                self = print_prefix(self)?;
+                self.segments.push(disambiguated_data.to_string());
+                Ok(self)
             }
             fn path_generic_args(
                 self,
-                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
                 _args: &[GenericArg<'tcx>],
-            ) -> Result<Self::Path, Self::Error> {
+            ) -> Result<Self, PrintError> {
                 print_prefix(self)
             }
         }
@@ -659,12 +651,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // are from a local module we could have false positives, e.g.
             // let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
             if did1.krate != did2.krate {
-                let abs_path =
-                    |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]);
+                let abs_path = |def_id| {
+                    AbsolutePathPrinter { tcx: self.tcx, segments: vec![] }
+                        .print_def_path(def_id, &[])
+                        .map(|p| p.segments)
+                };
 
                 // We compare strings because DefPath can be different
                 // for imported and non-imported crates
-                let same_path = || -> Result<_, NonTrivialPath> {
+                let same_path = || -> Result<_, PrintError> {
                     Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2)
                         || abs_path(did1)? == abs_path(did2)?)
                 };
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 4aec28b051f..d6a3bc32cc9 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
@@ -28,7 +28,7 @@ pub struct Highlighted<'tcx, T> {
 
 impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T>
 where
-    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>,
+    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
 {
     fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
         rustc_errors::DiagnosticArgValue::Str(self.to_string().into())
@@ -43,7 +43,7 @@ impl<'tcx, T> Highlighted<'tcx, T> {
 
 impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
 where
-    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>,
+    T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index eb1c6be48e6..1f08db30860 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -31,7 +31,7 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::middle::stability;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_no_trimmed_paths, PrintError};
 use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, TyCtxt};
 use rustc_session::config::ExpectedValues;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
@@ -1200,51 +1200,45 @@ impl<'tcx> LateContext<'tcx> {
     /// }
     /// ```
     pub fn get_def_path(&self, def_id: DefId) -> Vec<Symbol> {
-        pub struct AbsolutePathPrinter<'tcx> {
-            pub tcx: TyCtxt<'tcx>,
+        struct AbsolutePathPrinter<'tcx> {
+            tcx: TyCtxt<'tcx>,
+            path: Vec<Symbol>,
         }
 
         impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
-            type Error = !;
-
-            type Path = Vec<Symbol>;
-            type Region = ();
-            type Type = ();
-            type DynExistential = ();
-            type Const = ();
-
             fn tcx(&self) -> TyCtxt<'tcx> {
                 self.tcx
             }
 
-            fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
-                Ok(())
+            fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
+                Ok(self)
             }
 
-            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
-                Ok(())
+            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self, PrintError> {
+                Ok(self)
             }
 
             fn print_dyn_existential(
                 self,
                 _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-            ) -> Result<Self::DynExistential, Self::Error> {
-                Ok(())
+            ) -> Result<Self, PrintError> {
+                Ok(self)
             }
 
-            fn print_const(self, _ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
-                Ok(())
+            fn print_const(self, _ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
+                Ok(self)
             }
 
-            fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
-                Ok(vec![self.tcx.crate_name(cnum)])
+            fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
+                self.path = vec![self.tcx.crate_name(cnum)];
+                Ok(self)
             }
 
             fn path_qualified(
-                self,
+                mut self,
                 self_ty: Ty<'tcx>,
                 trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self::Path, Self::Error> {
+            ) -> Result<Self, PrintError> {
                 if trait_ref.is_none() {
                     if let ty::Adt(def, args) = self_ty.kind() {
                         return self.print_def_path(def.did(), args);
@@ -1253,24 +1247,25 @@ impl<'tcx> LateContext<'tcx> {
 
                 // This shouldn't ever be needed, but just in case:
                 with_no_trimmed_paths!({
-                    Ok(vec![match trait_ref {
+                    self.path = vec![match trait_ref {
                         Some(trait_ref) => Symbol::intern(&format!("{trait_ref:?}")),
                         None => Symbol::intern(&format!("<{self_ty}>")),
-                    }])
+                    }];
+                    Ok(self)
                 })
             }
 
             fn path_append_impl(
                 self,
-                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
                 _disambiguated_data: &DisambiguatedDefPathData,
                 self_ty: Ty<'tcx>,
                 trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self::Path, Self::Error> {
+            ) -> Result<Self, PrintError> {
                 let mut path = print_prefix(self)?;
 
                 // This shouldn't ever be needed, but just in case:
-                path.push(match trait_ref {
+                path.path.push(match trait_ref {
                     Some(trait_ref) => {
                         with_no_trimmed_paths!(Symbol::intern(&format!(
                             "<impl {} for {}>",
@@ -1288,9 +1283,9 @@ impl<'tcx> LateContext<'tcx> {
 
             fn path_append(
                 self,
-                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
                 disambiguated_data: &DisambiguatedDefPathData,
-            ) -> Result<Self::Path, Self::Error> {
+            ) -> Result<Self, PrintError> {
                 let mut path = print_prefix(self)?;
 
                 // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
@@ -1298,20 +1293,23 @@ impl<'tcx> LateContext<'tcx> {
                     return Ok(path);
                 }
 
-                path.push(Symbol::intern(&disambiguated_data.data.to_string()));
+                path.path.push(Symbol::intern(&disambiguated_data.data.to_string()));
                 Ok(path)
             }
 
             fn path_generic_args(
                 self,
-                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
                 _args: &[GenericArg<'tcx>],
-            ) -> Result<Self::Path, Self::Error> {
+            ) -> Result<Self, PrintError> {
                 print_prefix(self)
             }
         }
 
-        AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap()
+        AbsolutePathPrinter { tcx: self.tcx, path: vec![] }
+            .print_def_path(def_id, &[])
+            .unwrap()
+            .path
     }
 
     /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`.
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index aa8e2e30715..107b44285ac 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -10,13 +10,12 @@ use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 mod pretty;
 pub use self::pretty::*;
 
+pub type PrintError = std::fmt::Error;
+
 // FIXME(eddyb) false positive, the lifetime parameters are used with `P:  Printer<...>`.
 #[allow(unused_lifetimes)]
 pub trait Print<'tcx, P> {
-    type Output;
-    type Error;
-
-    fn print(&self, cx: P) -> Result<Self::Output, Self::Error>;
+    fn print(&self, cx: P) -> Result<P, PrintError>;
 }
 
 /// Interface for outputting user-facing "type-system entities"
@@ -29,21 +28,13 @@ pub trait Print<'tcx, P> {
 //
 // FIXME(eddyb) find a better name; this is more general than "printing".
 pub trait Printer<'tcx>: Sized {
-    type Error;
-
-    type Path;
-    type Region;
-    type Type;
-    type DynExistential;
-    type Const;
-
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
 
     fn print_def_path(
         self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.default_print_def_path(def_id, args)
     }
 
@@ -53,48 +44,48 @@ pub trait Printer<'tcx>: Sized {
         args: &'tcx [GenericArg<'tcx>],
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.default_print_impl_path(impl_def_id, args, self_ty, trait_ref)
     }
 
-    fn print_region(self, region: ty::Region<'tcx>) -> Result<Self::Region, Self::Error>;
+    fn print_region(self, region: ty::Region<'tcx>) -> Result<Self, PrintError>;
 
-    fn print_type(self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>;
+    fn print_type(self, ty: Ty<'tcx>) -> Result<Self, PrintError>;
 
     fn print_dyn_existential(
         self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self::DynExistential, Self::Error>;
+    ) -> Result<Self, PrintError>;
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error>;
+    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError>;
 
-    fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error>;
+    fn path_crate(self, cnum: CrateNum) -> Result<Self, PrintError>;
 
     fn path_qualified(
         self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error>;
+    ) -> Result<Self, PrintError>;
 
     fn path_append_impl(
         self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error>;
+    ) -> Result<Self, PrintError>;
 
     fn path_append(
         self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self::Path, Self::Error>;
+    ) -> Result<Self, PrintError>;
 
     fn path_generic_args(
         self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error>;
+    ) -> Result<Self, PrintError>;
 
     // Defaults (should not be overridden):
 
@@ -103,7 +94,7 @@ pub trait Printer<'tcx>: Sized {
         self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let key = self.tcx().def_key(def_id);
         debug!(?key);
 
@@ -194,7 +185,7 @@ pub trait Printer<'tcx>: Sized {
         _args: &'tcx [GenericArg<'tcx>],
         self_ty: Ty<'tcx>,
         impl_trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         debug!(
             "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
             impl_def_id, self_ty, impl_trait_ref
@@ -295,34 +286,25 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
 }
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'tcx> {
-    type Output = P::Region;
-    type Error = P::Error;
-    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+    fn print(&self, cx: P) -> Result<P, PrintError> {
         cx.print_region(*self)
     }
 }
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
-    type Output = P::Type;
-    type Error = P::Error;
-
-    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+    fn print(&self, cx: P) -> Result<P, PrintError> {
         cx.print_type(*self)
     }
 }
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
-    type Output = P::DynExistential;
-    type Error = P::Error;
-    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+    fn print(&self, cx: P) -> Result<P, PrintError> {
         cx.print_dyn_existential(self)
     }
 }
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
-    type Output = P::Const;
-    type Error = P::Error;
-    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+    fn print(&self, cx: P) -> Result<P, PrintError> {
         cx.print_const(*self)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index e321f0a7b7f..d8010c71497 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -205,29 +205,19 @@ impl<'tcx> RegionHighlightMode<'tcx> {
 }
 
 /// Trait for printers that pretty-print using `fmt::Write` to the printer.
-pub trait PrettyPrinter<'tcx>:
-    Printer<
-        'tcx,
-        Error = fmt::Error,
-        Path = Self,
-        Region = Self,
-        Type = Self,
-        DynExistential = Self,
-        Const = Self,
-    > + fmt::Write
-{
+pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     /// Like `print_def_path` but for value paths.
     fn print_value_path(
         self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.print_def_path(def_id, args)
     }
 
-    fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
+    fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, PrintError>
     where
-        T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
+        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         value.as_ref().skip_binder().print(self)
     }
@@ -236,17 +226,17 @@ pub trait PrettyPrinter<'tcx>:
         self,
         value: &ty::Binder<'tcx, T>,
         f: F,
-    ) -> Result<Self, Self::Error>
+    ) -> Result<Self, PrintError>
     where
-        T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
+        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         f(value.as_ref().skip_binder(), self)
     }
 
     /// Prints comma-separated elements.
-    fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
+    fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, PrintError>
     where
-        T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
+        T: Print<'tcx, Self>,
     {
         if let Some(first) = elems.next() {
             self = first.print(self)?;
@@ -261,10 +251,10 @@ pub trait PrettyPrinter<'tcx>:
     /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
     fn typed_value(
         mut self,
-        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
-        t: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        f: impl FnOnce(Self) -> Result<Self, PrintError>,
+        t: impl FnOnce(Self) -> Result<Self, PrintError>,
         conversion: &str,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.write_str("{")?;
         self = f(self)?;
         self.write_str(conversion)?;
@@ -276,8 +266,8 @@ pub trait PrettyPrinter<'tcx>:
     /// Prints `<...>` around what `f` prints.
     fn generic_delimiters(
         self,
-        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
-    ) -> Result<Self, Self::Error>;
+        f: impl FnOnce(Self) -> Result<Self, PrintError>,
+    ) -> Result<Self, PrintError>;
 
     /// Returns `true` if the region should be printed in
     /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
@@ -291,7 +281,7 @@ pub trait PrettyPrinter<'tcx>:
     /// If possible, this returns a global path resolving to `def_id` that is visible
     /// from at least one local module, and returns `true`. If the crate defining `def_id` is
     /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
-    fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> {
+    fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), PrintError> {
         if NO_VISIBLE_PATH.with(|flag| flag.get()) {
             return Ok((self, false));
         }
@@ -305,10 +295,7 @@ pub trait PrettyPrinter<'tcx>:
     // For enum variants, if they have an unique name, then we only print the name, otherwise we
     // print the enum name and the variant name. Otherwise, we do not print anything and let the
     // caller use the `print_def_path` fallback.
-    fn force_print_trimmed_def_path(
-        mut self,
-        def_id: DefId,
-    ) -> Result<(Self::Path, bool), Self::Error> {
+    fn force_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), PrintError> {
         let key = self.tcx().def_key(def_id);
         let visible_parent_map = self.tcx().visible_parent_map(());
         let kind = self.tcx().def_kind(def_id);
@@ -378,10 +365,7 @@ pub trait PrettyPrinter<'tcx>:
     }
 
     /// Try to see if this path can be trimmed to a unique symbol name.
-    fn try_print_trimmed_def_path(
-        mut self,
-        def_id: DefId,
-    ) -> Result<(Self::Path, bool), Self::Error> {
+    fn try_print_trimmed_def_path(mut self, def_id: DefId) -> Result<(Self, bool), PrintError> {
         if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
             let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?;
             if trimmed {
@@ -423,7 +407,7 @@ pub trait PrettyPrinter<'tcx>:
         mut self,
         def_id: DefId,
         callers: &mut Vec<DefId>,
-    ) -> Result<(Self, bool), Self::Error> {
+    ) -> Result<(Self, bool), PrintError> {
         define_scoped_cx!(self);
 
         debug!("try_print_visible_def_path: def_id={:?}", def_id);
@@ -595,7 +579,7 @@ pub trait PrettyPrinter<'tcx>:
         self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         if trait_ref.is_none() {
             // Inherent impls. Try to print `Foo::bar` for an inherent
             // impl on `Foo`, but fallback to `<Foo>::bar` if self-type is
@@ -629,10 +613,10 @@ pub trait PrettyPrinter<'tcx>:
 
     fn pretty_path_append_impl(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = print_prefix(self)?;
 
         self.generic_delimiters(|mut cx| {
@@ -648,7 +632,7 @@ pub trait PrettyPrinter<'tcx>:
         })
     }
 
-    fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+    fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
         define_scoped_cx!(self);
 
         match *ty.kind() {
@@ -919,7 +903,7 @@ pub trait PrettyPrinter<'tcx>:
         mut self,
         def_id: DefId,
         args: &'tcx ty::List<ty::GenericArg<'tcx>>,
-    ) -> Result<Self::Type, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let tcx = self.tcx();
 
         // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
@@ -1189,7 +1173,7 @@ pub trait PrettyPrinter<'tcx>:
     fn pretty_print_inherent_projection(
         self,
         alias_ty: &ty::AliasTy<'tcx>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let def_key = self.tcx().def_key(alias_ty.def_id);
         self.path_generic_args(
             |cx| {
@@ -1213,7 +1197,7 @@ pub trait PrettyPrinter<'tcx>:
     fn pretty_print_dyn_existential(
         mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self::DynExistential, Self::Error> {
+    ) -> Result<Self, PrintError> {
         // Generate the main trait ref, including associated types.
         let mut first = true;
 
@@ -1306,7 +1290,7 @@ pub trait PrettyPrinter<'tcx>:
         inputs: &[Ty<'tcx>],
         c_variadic: bool,
         output: Ty<'tcx>,
-    ) -> Result<Self, Self::Error> {
+    ) -> Result<Self, PrintError> {
         define_scoped_cx!(self);
 
         p!("(", comma_sep(inputs.iter().copied()));
@@ -1328,7 +1312,7 @@ pub trait PrettyPrinter<'tcx>:
         mut self,
         ct: ty::Const<'tcx>,
         print_ty: bool,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         define_scoped_cx!(self);
 
         if self.should_print_verbose() {
@@ -1404,11 +1388,7 @@ pub trait PrettyPrinter<'tcx>:
         Ok(self)
     }
 
-    fn pretty_print_const_scalar(
-        self,
-        scalar: Scalar,
-        ty: Ty<'tcx>,
-    ) -> Result<Self::Const, Self::Error> {
+    fn pretty_print_const_scalar(self, scalar: Scalar, ty: Ty<'tcx>) -> Result<Self, PrintError> {
         match scalar {
             Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty),
             Scalar::Int(int) => {
@@ -1421,7 +1401,7 @@ pub trait PrettyPrinter<'tcx>:
         mut self,
         ptr: Pointer,
         ty: Ty<'tcx>,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         define_scoped_cx!(self);
 
         let (alloc_id, offset) = ptr.into_parts();
@@ -1483,7 +1463,7 @@ pub trait PrettyPrinter<'tcx>:
         int: ScalarInt,
         ty: Ty<'tcx>,
         print_ty: bool,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         define_scoped_cx!(self);
 
         match ty.kind() {
@@ -1545,7 +1525,7 @@ pub trait PrettyPrinter<'tcx>:
         self,
         _: Pointer<Prov>,
         ty: Ty<'tcx>,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.typed_value(
             |mut this| {
                 this.write_str("&_")?;
@@ -1556,7 +1536,7 @@ pub trait PrettyPrinter<'tcx>:
         )
     }
 
-    fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
+    fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self, PrintError> {
         write!(self, "b\"{}\"", byte_str.escape_ascii())?;
         Ok(self)
     }
@@ -1566,7 +1546,7 @@ pub trait PrettyPrinter<'tcx>:
         valtree: ty::ValTree<'tcx>,
         ty: Ty<'tcx>,
         print_ty: bool,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         define_scoped_cx!(self);
 
         if self.should_print_verbose() {
@@ -1689,7 +1669,7 @@ pub trait PrettyPrinter<'tcx>:
     fn pretty_closure_as_impl(
         mut self,
         closure: ty::ClosureArgs<'tcx>,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let sig = closure.sig();
         let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn);
 
@@ -1862,14 +1842,6 @@ impl fmt::Write for FmtPrinter<'_, '_> {
 }
 
 impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
-    type Error = fmt::Error;
-
-    type Path = Self;
-    type Region = Self;
-    type Type = Self;
-    type DynExistential = Self;
-    type Const = Self;
-
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -1878,7 +1850,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
         mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         define_scoped_cx!(self);
 
         if args.is_empty() {
@@ -1933,11 +1905,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
         self.default_print_def_path(def_id, args)
     }
 
-    fn print_region(self, region: ty::Region<'tcx>) -> Result<Self::Region, Self::Error> {
+    fn print_region(self, region: ty::Region<'tcx>) -> Result<Self, PrintError> {
         self.pretty_print_region(region)
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
         if self.type_length_limit.value_within_limit(self.printed_type_count) {
             self.printed_type_count += 1;
             self.pretty_print_type(ty)
@@ -1951,15 +1923,15 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
     fn print_dyn_existential(
         self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self::DynExistential, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.pretty_print_dyn_existential(predicates)
     }
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
         self.pretty_print_const(ct, false)
     }
 
-    fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+    fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
         self.empty_path = true;
         if cnum == LOCAL_CRATE {
             if self.tcx.sess.at_least_rust_2018() {
@@ -1980,7 +1952,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
         mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = self.pretty_path_qualified(self_ty, trait_ref)?;
         self.empty_path = false;
         Ok(self)
@@ -1988,11 +1960,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
 
     fn path_append_impl(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         _disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = self.pretty_path_append_impl(
             |mut cx| {
                 cx = print_prefix(cx)?;
@@ -2011,9 +1983,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
 
     fn path_append(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = print_prefix(self)?;
 
         // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
@@ -2042,9 +2014,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
 
     fn path_generic_args(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = print_prefix(self)?;
 
         let tcx = self.tcx;
@@ -2101,7 +2073,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
         mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let was_in_value = std::mem::replace(&mut self.in_value, true);
         self = self.print_def_path(def_id, args)?;
         self.in_value = was_in_value;
@@ -2109,30 +2081,30 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
         Ok(self)
     }
 
-    fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, Self::Error>
+    fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, PrintError>
     where
-        T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
+        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         self.pretty_in_binder(value)
     }
 
-    fn wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, Self::Error>>(
+    fn wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, PrintError>>(
         self,
         value: &ty::Binder<'tcx, T>,
         f: C,
-    ) -> Result<Self, Self::Error>
+    ) -> Result<Self, PrintError>
     where
-        T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<TyCtxt<'tcx>>,
+        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         self.pretty_wrap_binder(value, f)
     }
 
     fn typed_value(
         mut self,
-        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
-        t: impl FnOnce(Self) -> Result<Self, Self::Error>,
+        f: impl FnOnce(Self) -> Result<Self, PrintError>,
+        t: impl FnOnce(Self) -> Result<Self, PrintError>,
         conversion: &str,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.write_str("{")?;
         self = f(self)?;
         self.write_str(conversion)?;
@@ -2145,8 +2117,8 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
 
     fn generic_delimiters(
         mut self,
-        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
-    ) -> Result<Self, Self::Error> {
+        f: impl FnOnce(Self) -> Result<Self, PrintError>,
+    ) -> Result<Self, PrintError> {
         write!(self, "<")?;
 
         let was_in_value = std::mem::replace(&mut self.in_value, false);
@@ -2206,7 +2178,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
         self,
         p: Pointer<Prov>,
         ty: Ty<'tcx>,
-    ) -> Result<Self::Const, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let print = |mut this: Self| {
             define_scoped_cx!(this);
             if this.print_alloc_ids {
@@ -2371,7 +2343,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         value: &ty::Binder<'tcx, T>,
     ) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
     where
-        T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
+        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         fn name_by_region_index(
             index: usize,
@@ -2541,7 +2513,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
 
     pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
     where
-        T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
+        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         let old_region_index = self.region_index;
         let (new, new_value, _) = self.name_all_regions(value)?;
@@ -2557,7 +2529,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         f: C,
     ) -> Result<Self, fmt::Error>
     where
-        T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<TyCtxt<'tcx>>,
+        T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         let old_region_index = self.region_index;
         let (new, new_value, _) = self.name_all_regions(value)?;
@@ -2622,24 +2594,19 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
 
 impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
 where
-    T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<TyCtxt<'tcx>>,
+    T: Print<'tcx, P> + TypeFoldable<TyCtxt<'tcx>>,
 {
-    type Output = P;
-    type Error = P::Error;
-
-    fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
+    fn print(&self, cx: P) -> Result<P, PrintError> {
         cx.in_binder(self)
     }
 }
 
 impl<'tcx, T, U, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::OutlivesPredicate<T, U>
 where
-    T: Print<'tcx, P, Output = P, Error = P::Error>,
-    U: Print<'tcx, P, Output = P, Error = P::Error>,
+    T: Print<'tcx, P>,
+    U: Print<'tcx, P>,
 {
-    type Output = P;
-    type Error = P::Error;
-    fn print(&self, mut cx: P) -> Result<Self::Output, Self::Error> {
+    fn print(&self, mut cx: P) -> Result<P, PrintError> {
         define_scoped_cx!(cx);
         p!(print(self.0), ": ", print(self.1));
         Ok(cx)
@@ -2666,9 +2633,7 @@ macro_rules! forward_display_to_print {
 macro_rules! define_print_and_forward_display {
     (($self:ident, $cx:ident): $($ty:ty $print:block)+) => {
         $(impl<'tcx, P: PrettyPrinter<'tcx>> Print<'tcx, P> for $ty {
-            type Output = P;
-            type Error = fmt::Error;
-            fn print(&$self, $cx: P) -> Result<Self::Output, Self::Error> {
+            fn print(&$self, $cx: P) -> Result<P, PrintError> {
                 #[allow(unused_mut)]
                 let mut $cx = $cx;
                 define_scoped_cx!($cx);
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 2fc102bda13..5290da9a25b 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
-use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
+use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_middle::util::common::record_time;
@@ -200,23 +200,15 @@ struct SymbolPrinter<'tcx> {
 // symbol names should have their own printing machinery.
 
 impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
-    type Error = fmt::Error;
-
-    type Path = Self;
-    type Region = Self;
-    type Type = Self;
-    type DynExistential = Self;
-    type Const = Self;
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
+    fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
         Ok(self)
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
             ty::FnDef(def_id, args)
@@ -250,7 +242,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
     fn print_dyn_existential(
         mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self::DynExistential, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let mut first = true;
         for p in predicates {
             if !first {
@@ -262,7 +254,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         Ok(self)
     }
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
         // only print integers
         match (ct.kind(), ct.ty().kind()) {
             (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
@@ -280,7 +272,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         Ok(self)
     }
 
-    fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+    fn path_crate(self, cnum: CrateNum) -> Result<Self, PrintError> {
         self.write_str(self.tcx.crate_name(cnum).as_str())?;
         Ok(self)
     }
@@ -288,7 +280,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         // Similar to `pretty_path_qualified`, but for the other
         // types that are printed as paths (see `print_type` above).
         match self_ty.kind() {
@@ -304,11 +296,11 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
 
     fn path_append_impl(
         self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         _disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self.pretty_path_append_impl(
             |mut cx| {
                 cx = print_prefix(cx)?;
@@ -328,9 +320,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
     }
     fn path_append(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = print_prefix(self)?;
 
         // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
@@ -351,9 +343,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
     }
     fn path_generic_args(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         self = print_prefix(self)?;
 
         let args =
@@ -371,9 +363,9 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> {
     fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
         false
     }
-    fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
+    fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, PrintError>
     where
-        T: Print<'tcx, Self, Output = Self, Error = Self::Error>,
+        T: Print<'tcx, Self>,
     {
         if let Some(first) = elems.next() {
             self = first.print(self)?;
@@ -387,8 +379,8 @@ impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> {
 
     fn generic_delimiters(
         mut self,
-        f: impl FnOnce(Self) -> Result<Self, Self::Error>,
-    ) -> Result<Self, Self::Error> {
+        f: impl FnOnce(Self) -> Result<Self, PrintError>,
+    ) -> Result<Self, PrintError> {
         write!(self, "<")?;
 
         let kept_within_component = mem::replace(&mut self.keep_within_component, true);
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 82b1a772e3d..99c5d016439 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -6,7 +6,7 @@ use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
 use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::print::{Print, Printer};
+use rustc_middle::ty::print::{Print, PrintError, Printer};
 use rustc_middle::ty::{
     self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
     UintTy,
@@ -181,11 +181,11 @@ impl<'tcx> SymbolMangler<'tcx> {
 
     fn path_append_ns<'a>(
         mut self: &'a mut Self,
-        print_prefix: impl FnOnce(&'a mut Self) -> Result<&'a mut Self, !>,
+        print_prefix: impl FnOnce(&'a mut Self) -> Result<&'a mut Self, PrintError>,
         ns: char,
         disambiguator: u64,
         name: &str,
-    ) -> Result<&'a mut Self, !> {
+    ) -> Result<&'a mut Self, PrintError> {
         self.push("N");
         self.out.push(ns);
         self = print_prefix(self)?;
@@ -194,7 +194,7 @@ impl<'tcx> SymbolMangler<'tcx> {
         Ok(self)
     }
 
-    fn print_backref(&mut self, i: usize) -> Result<&mut Self, !> {
+    fn print_backref(&mut self, i: usize) -> Result<&mut Self, PrintError> {
         self.push("B");
         self.push_integer_62((i - self.start_offset) as u64);
         Ok(self)
@@ -203,8 +203,8 @@ impl<'tcx> SymbolMangler<'tcx> {
     fn in_binder<'a, T>(
         mut self: &'a mut Self,
         value: &ty::Binder<'tcx, T>,
-        print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, !>,
-    ) -> Result<&'a mut Self, !>
+        print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, PrintError>,
+    ) -> Result<&'a mut Self, PrintError>
     where
         T: TypeVisitable<TyCtxt<'tcx>>,
     {
@@ -230,14 +230,6 @@ impl<'tcx> SymbolMangler<'tcx> {
 }
 
 impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
-    type Error = !;
-
-    type Path = Self;
-    type Region = Self;
-    type Type = Self;
-    type DynExistential = Self;
-    type Const = Self;
-
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -246,7 +238,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         if let Some(&i) = self.paths.get(&(def_id, args)) {
             return self.print_backref(i);
         }
@@ -268,7 +260,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         args: &'tcx [GenericArg<'tcx>],
         mut self_ty: Ty<'tcx>,
         mut impl_trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let key = self.tcx.def_key(impl_def_id);
         let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
 
@@ -321,7 +313,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         Ok(self)
     }
 
-    fn print_region(self, region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
+    fn print_region(self, region: ty::Region<'_>) -> Result<Self, PrintError> {
         let i = match *region {
             // Erased lifetimes use the index 0, for a
             // shorter mangling of `L_`.
@@ -343,7 +335,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         Ok(self)
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
         // Basic types, never cached (single-character).
         let basic_type = match ty.kind() {
             ty::Bool => "b",
@@ -498,7 +490,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
     fn print_dyn_existential(
         mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self::DynExistential, Self::Error> {
+    ) -> Result<Self, PrintError> {
         // Okay, so this is a bit tricky. Imagine we have a trait object like
         // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the
         // output looks really close to the syntax, where the `Bar = &'a ()` bit
@@ -559,7 +551,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         Ok(self)
     }
 
-    fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+    fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
         // We only mangle a typed value if the const can be evaluated.
         let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all());
         match ct.kind() {
@@ -731,7 +723,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         Ok(self)
     }
 
-    fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+    fn path_crate(self, cnum: CrateNum) -> Result<Self, PrintError> {
         self.push("C");
         let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
         self.push_disambiguator(stable_crate_id.as_u64());
@@ -744,7 +736,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         assert!(trait_ref.is_some());
         let trait_ref = trait_ref.unwrap();
 
@@ -755,20 +747,20 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
     fn path_append_impl(
         self,
-        _: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        _: impl FnOnce(Self) -> Result<Self, PrintError>,
         _: &DisambiguatedDefPathData,
         _: Ty<'tcx>,
         _: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         // Inlined into `print_impl_path`
         unreachable!()
     }
 
     fn path_append(
         self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         let ns = match disambiguated_data.data {
             // Extern block segments can be skipped, names from extern blocks
             // are effectively living in their parent modules.
@@ -806,9 +798,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
     fn path_generic_args(
         mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self::Path, Self::Error> {
+    ) -> Result<Self, PrintError> {
         // Don't print any regions if they're all erased.
         let print_regions = args.iter().any(|arg| match arg.unpack() {
             GenericArgKind::Lifetime(r) => !r.is_erased(),
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 1020144a01b..640bd3fad7c 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
@@ -60,10 +60,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         suggest_increasing_limit: bool,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
     where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+        T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>;
 
     fn report_overflow_error<T>(
         &self,
@@ -73,10 +70,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         mutate: impl FnOnce(&mut Diagnostic),
     ) -> !
     where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug;
+        T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>;
 
     fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed;
 
@@ -227,10 +221,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         mutate: impl FnOnce(&mut Diagnostic),
     ) -> !
     where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+        T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>,
     {
         let mut err = self.build_overflow_error(predicate, span, suggest_increasing_limit);
         mutate(&mut err);
@@ -247,10 +238,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         suggest_increasing_limit: bool,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
     where
-        T: fmt::Display
-            + TypeFoldable<TyCtxt<'tcx>>
-            + Print<'tcx, FmtPrinter<'tcx, 'tcx>, Output = FmtPrinter<'tcx, 'tcx>>,
-        <T as Print<'tcx, FmtPrinter<'tcx, 'tcx>>>::Error: std::fmt::Debug,
+        T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>,
     {
         let predicate = self.resolve_vars_if_possible(predicate.clone());
         let mut pred_str = predicate.to_string();