about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs9
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs76
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs47
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs33
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs8
-rw-r--r--compiler/rustc_lint/src/context.rs67
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs12
-rw-r--r--compiler/rustc_middle/src/ty/error.rs29
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs6
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs62
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs513
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs23
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs88
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs181
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs43
17 files changed, 615 insertions, 592 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 47a387e25e3..6a911b23462 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -470,7 +470,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
         }
 
-        ty.print(printer).unwrap().into_buffer()
+        ty.print(&mut printer).unwrap();
+        printer.into_buffer()
     }
 
     /// Returns the name of the provided `Ty` (that must be a reference)'s region with a
@@ -492,7 +493,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             bug!("ty for annotation of borrow region is not a reference");
         };
 
-        region.print(printer).unwrap().into_buffer()
+        region.print(&mut printer).unwrap();
+        printer.into_buffer()
     }
 }
 
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 99424518ad4..6716888290d 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -107,10 +107,10 @@ impl<Prov: Provenance> std::fmt::Display for ImmTy<'_, Prov> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         /// Helper function for printing a scalar to a FmtPrinter
         fn p<'a, 'tcx, Prov: Provenance>(
-            cx: FmtPrinter<'a, 'tcx>,
+            cx: &mut FmtPrinter<'a, 'tcx>,
             s: Scalar<Prov>,
             ty: Ty<'tcx>,
-        ) -> Result<FmtPrinter<'a, 'tcx>, std::fmt::Error> {
+        ) -> Result<(), std::fmt::Error> {
             match s {
                 Scalar::Int(int) => cx.pretty_print_const_scalar_int(int, ty, true),
                 Scalar::Ptr(ptr, _sz) => {
@@ -125,8 +125,9 @@ impl<Prov: Provenance> std::fmt::Display for ImmTy<'_, Prov> {
             match self.imm {
                 Immediate::Scalar(s) => {
                     if let Some(ty) = tcx.lift(self.layout.ty) {
-                        let cx = FmtPrinter::new(tcx, Namespace::ValueNS);
-                        f.write_str(&p(cx, s, ty)?.into_buffer())?;
+                        let s =
+                            FmtPrinter::print_string(tcx, Namespace::ValueNS, |cx| p(cx, s, ty))?;
+                        f.write_str(&s)?;
                         return Ok(());
                     }
                     write!(f, "{:x}: {}", s, self.layout.ty)
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 8c7c360acbf..a82b65b19a8 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -18,11 +18,11 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
         self.tcx
     }
 
-    fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
-        Ok(self)
+    fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
+        Ok(())
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
+    fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
         match *ty.kind() {
             // Types without identity.
             ty::Bool
@@ -43,7 +43,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             // Placeholders (all printed as `_` to uniformize them).
             ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
                 write!(self, "_")?;
-                Ok(self)
+                Ok(())
             }
 
             // Types with identity (print the module path).
@@ -60,44 +60,44 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
         }
     }
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
+    fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
         self.pretty_print_const(ct, false)
     }
 
     fn print_dyn_existential(
-        self,
+        &mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.pretty_print_dyn_existential(predicates)
     }
 
-    fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
+    fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
         self.path.push_str(self.tcx.crate_name(cnum).as_str());
-        Ok(self)
+        Ok(())
     }
 
     fn path_qualified(
-        self,
+        &mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.pretty_path_qualified(self_ty, trait_ref)
     }
 
     fn path_append_impl(
-        self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         _disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.pretty_path_append_impl(
-            |mut cx| {
-                cx = print_prefix(cx)?;
+            |cx| {
+                print_prefix(cx)?;
 
                 cx.path.push_str("::");
 
-                Ok(cx)
+                Ok(())
             },
             self_ty,
             trait_ref,
@@ -105,29 +105,29 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
     }
 
     fn path_append(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self, PrintError> {
-        self = print_prefix(self)?;
+    ) -> Result<(), PrintError> {
+        print_prefix(self)?;
 
         write!(self.path, "::{}", disambiguated_data.data).unwrap();
 
-        Ok(self)
+        Ok(())
     }
 
     fn path_generic_args(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
-        self = print_prefix(self)?;
+    ) -> Result<(), PrintError> {
+        print_prefix(self)?;
         let args =
             args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
         if args.clone().next().is_some() {
             self.generic_delimiters(|cx| cx.comma_sep(args))
         } else {
-            Ok(self)
+            Ok(())
         }
     }
 }
@@ -136,31 +136,31 @@ 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, PrintError>
+    fn comma_sep<T>(&mut self, mut elems: impl Iterator<Item = T>) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self>,
     {
         if let Some(first) = elems.next() {
-            self = first.print(self)?;
+            first.print(self)?;
             for elem in elems {
                 self.path.push_str(", ");
-                self = elem.print(self)?;
+                elem.print(self)?;
             }
         }
-        Ok(self)
+        Ok(())
     }
 
     fn generic_delimiters(
-        mut self,
-        f: impl FnOnce(Self) -> Result<Self, PrintError>,
-    ) -> Result<Self, PrintError> {
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+    ) -> Result<(), PrintError> {
         write!(self, "<")?;
 
-        self = f(self)?;
+        f(self)?;
 
         write!(self, ">")?;
 
-        Ok(self)
+        Ok(())
     }
 
     fn should_print_verbose(&self) -> bool {
@@ -177,5 +177,7 @@ impl Write for AbsolutePathPrinter<'_> {
 }
 
 pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
-    AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path
+    let mut printer = AbsolutePathPrinter { tcx, path: String::new() };
+    printer.print_type(ty).unwrap();
+    printer.path
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 97ab3d0b751..ba118f8110f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -588,60 +588,60 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 self.tcx
             }
 
-            fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
+            fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
                 Err(fmt::Error)
             }
 
-            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self, PrintError> {
+            fn print_type(&mut self, _ty: Ty<'tcx>) -> Result<(), PrintError> {
                 Err(fmt::Error)
             }
 
             fn print_dyn_existential(
-                self,
+                &mut self,
                 _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-            ) -> Result<Self, PrintError> {
+            ) -> Result<(), PrintError> {
                 Err(fmt::Error)
             }
 
-            fn print_const(self, _ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
+            fn print_const(&mut self, _ct: ty::Const<'tcx>) -> Result<(), PrintError> {
                 Err(fmt::Error)
             }
 
-            fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
+            fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
                 self.segments = vec![self.tcx.crate_name(cnum).to_string()];
-                Ok(self)
+                Ok(())
             }
             fn path_qualified(
-                self,
+                &mut self,
                 _self_ty: Ty<'tcx>,
                 _trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self, PrintError> {
+            ) -> Result<(), PrintError> {
                 Err(fmt::Error)
             }
 
             fn path_append_impl(
-                self,
-                _print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+                &mut self,
+                _print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                 _disambiguated_data: &DisambiguatedDefPathData,
                 _self_ty: Ty<'tcx>,
                 _trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self, PrintError> {
+            ) -> Result<(), PrintError> {
                 Err(fmt::Error)
             }
             fn path_append(
-                mut self,
-                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+                &mut self,
+                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                 disambiguated_data: &DisambiguatedDefPathData,
-            ) -> Result<Self, PrintError> {
-                self = print_prefix(self)?;
+            ) -> Result<(), PrintError> {
+                print_prefix(self)?;
                 self.segments.push(disambiguated_data.to_string());
-                Ok(self)
+                Ok(())
             }
             fn path_generic_args(
-                self,
-                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+                &mut self,
+                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                 _args: &[GenericArg<'tcx>],
-            ) -> Result<Self, PrintError> {
+            ) -> Result<(), PrintError> {
                 print_prefix(self)
             }
         }
@@ -652,9 +652,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             // let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
             if did1.krate != did2.krate {
                 let abs_path = |def_id| {
-                    AbsolutePathPrinter { tcx: self.tcx, segments: vec![] }
-                        .print_def_path(def_id, &[])
-                        .map(|p| p.segments)
+                    let mut printer = AbsolutePathPrinter { tcx: self.tcx, segments: vec![] };
+                    printer.print_def_path(def_id, &[]).map(|_| printer.segments)
                 };
 
                 // We compare strings because DefPath can be different
@@ -1071,7 +1070,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         let get_lifetimes = |sig| {
             use rustc_hir::def::Namespace;
-            let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS)
+            let (sig, reg) = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS)
                 .name_all_regions(sig)
                 .unwrap();
             let lts: Vec<String> = reg.into_values().map(|kind| kind.to_string()).collect();
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 7bc414ff522..4beb51da72c 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -200,12 +200,15 @@ fn ty_to_string<'tcx>(
     ty: Ty<'tcx>,
     called_method_def_id: Option<DefId>,
 ) -> String {
-    let printer = fmt_printer(infcx, Namespace::TypeNS);
+    let mut printer = fmt_printer(infcx, Namespace::TypeNS);
     let ty = infcx.resolve_vars_if_possible(ty);
     match (ty.kind(), called_method_def_id) {
         // We don't want the regular output for `fn`s because it includes its path in
         // invalid pseudo-syntax, we want the `fn`-pointer output instead.
-        (ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
+        (ty::FnDef(..), _) => {
+            ty.fn_sig(infcx.tcx).print(&mut printer).unwrap();
+            printer.into_buffer()
+        }
         (_, Some(def_id))
             if ty.is_ty_or_numeric_infer()
                 && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
@@ -218,7 +221,10 @@ fn ty_to_string<'tcx>(
         //
         // We do have to hide the `extern "rust-call"` ABI in that case though,
         // which is too much of a bother for now.
-        _ => ty.print(printer).unwrap().into_buffer(),
+        _ => {
+            ty.print(&mut printer).unwrap();
+            printer.into_buffer()
+        }
     }
 }
 
@@ -285,8 +291,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 if let Some(highlight) = highlight {
                     printer.region_highlight_mode = highlight;
                 }
+                ty.print(&mut printer).unwrap();
                 InferenceDiagnosticsData {
-                    name: ty.print(printer).unwrap().into_buffer(),
+                    name: printer.into_buffer(),
                     span: None,
                     kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
                     parent: None,
@@ -312,8 +319,9 @@ impl<'tcx> InferCtxt<'tcx> {
                     if let Some(highlight) = highlight {
                         printer.region_highlight_mode = highlight;
                     }
+                    ct.print(&mut printer).unwrap();
                     InferenceDiagnosticsData {
-                        name: ct.print(printer).unwrap().into_buffer(),
+                        name: printer.into_buffer(),
                         span: Some(origin.span),
                         kind: UnderspecifiedArgKind::Const { is_parameter: false },
                         parent: None,
@@ -329,8 +337,9 @@ impl<'tcx> InferCtxt<'tcx> {
                     if let Some(highlight) = highlight {
                         printer.region_highlight_mode = highlight;
                     }
+                    ct.print(&mut printer).unwrap();
                     InferenceDiagnosticsData {
-                        name: ct.print(printer).unwrap().into_buffer(),
+                        name: printer.into_buffer(),
                         span: None,
                         kind: UnderspecifiedArgKind::Const { is_parameter: false },
                         parent: None,
@@ -487,7 +496,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 {
                     "Vec<_>".to_string()
                 } else {
-                    fmt_printer(self, Namespace::TypeNS)
+                    let mut printer = fmt_printer(self, Namespace::TypeNS);
+                    printer
                         .comma_sep(generic_args.iter().copied().map(|arg| {
                             if arg.is_suggestable(self.tcx, true) {
                                 return arg;
@@ -512,8 +522,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                     .into(),
                             }
                         }))
-                        .unwrap()
-                        .into_buffer()
+                        .unwrap();
+                    printer.into_buffer()
                 };
 
                 if !have_turbofish {
@@ -525,8 +535,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
             }
             InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
-                let printer = fmt_printer(self, Namespace::ValueNS);
-                let def_path = printer.print_def_path(def_id, args).unwrap().into_buffer();
+                let mut printer = fmt_printer(self, Namespace::ValueNS);
+                printer.print_def_path(def_id, args).unwrap();
+                let def_path = printer.into_buffer();
 
                 // We only care about whether we have to add `&` or `&mut ` for now.
                 // This is the case if the last adjustment is a borrow and the
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 d6a3bc32cc9..c38e5b8cd09 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
@@ -49,8 +49,8 @@ where
         let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
         printer.region_highlight_mode = self.highlight;
 
-        let s = self.value.print(printer)?.into_buffer();
-        f.write_str(&s)
+        self.value.print(&mut printer)?;
+        f.write_str(&printer.into_buffer())
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index faea8bc98aa..00289f9bfb4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -763,9 +763,9 @@ fn foo(&self) -> Self::T { String::new() }
     }
 
     pub fn format_generic_args(&self, args: &[ty::GenericArg<'tcx>]) -> String {
-        FmtPrinter::new(self.tcx, hir::def::Namespace::TypeNS)
-            .path_generic_args(Ok, args)
-            .expect("could not write to `String`.")
-            .into_buffer()
+        FmtPrinter::print_string(self.tcx, hir::def::Namespace::TypeNS, |cx| {
+            cx.path_generic_args(|_| Ok(()), args)
+        })
+        .expect("could not write to `String`.")
     }
 }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 1f08db30860..5b7ba03d9ad 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -1210,35 +1210,35 @@ impl<'tcx> LateContext<'tcx> {
                 self.tcx
             }
 
-            fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
-                Ok(self)
+            fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
+                Ok(())
             }
 
-            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self, PrintError> {
-                Ok(self)
+            fn print_type(&mut self, _ty: Ty<'tcx>) -> Result<(), PrintError> {
+                Ok(())
             }
 
             fn print_dyn_existential(
-                self,
+                &mut self,
                 _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-            ) -> Result<Self, PrintError> {
-                Ok(self)
+            ) -> Result<(), PrintError> {
+                Ok(())
             }
 
-            fn print_const(self, _ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
-                Ok(self)
+            fn print_const(&mut self, _ct: ty::Const<'tcx>) -> Result<(), PrintError> {
+                Ok(())
             }
 
-            fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
+            fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
                 self.path = vec![self.tcx.crate_name(cnum)];
-                Ok(self)
+                Ok(())
             }
 
             fn path_qualified(
-                mut self,
+                &mut self,
                 self_ty: Ty<'tcx>,
                 trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self, PrintError> {
+            ) -> Result<(), PrintError> {
                 if trait_ref.is_none() {
                     if let ty::Adt(def, args) = self_ty.kind() {
                         return self.print_def_path(def.did(), args);
@@ -1251,21 +1251,21 @@ impl<'tcx> LateContext<'tcx> {
                         Some(trait_ref) => Symbol::intern(&format!("{trait_ref:?}")),
                         None => Symbol::intern(&format!("<{self_ty}>")),
                     }];
-                    Ok(self)
+                    Ok(())
                 })
             }
 
             fn path_append_impl(
-                self,
-                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+                &mut self,
+                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                 _disambiguated_data: &DisambiguatedDefPathData,
                 self_ty: Ty<'tcx>,
                 trait_ref: Option<ty::TraitRef<'tcx>>,
-            ) -> Result<Self, PrintError> {
-                let mut path = print_prefix(self)?;
+            ) -> Result<(), PrintError> {
+                print_prefix(self)?;
 
                 // This shouldn't ever be needed, but just in case:
-                path.path.push(match trait_ref {
+                self.path.push(match trait_ref {
                     Some(trait_ref) => {
                         with_no_trimmed_paths!(Symbol::intern(&format!(
                             "<impl {} for {}>",
@@ -1278,38 +1278,37 @@ impl<'tcx> LateContext<'tcx> {
                     }
                 });
 
-                Ok(path)
+                Ok(())
             }
 
             fn path_append(
-                self,
-                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+                &mut self,
+                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                 disambiguated_data: &DisambiguatedDefPathData,
-            ) -> Result<Self, PrintError> {
-                let mut path = print_prefix(self)?;
+            ) -> Result<(), PrintError> {
+                print_prefix(self)?;
 
                 // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
                 if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
-                    return Ok(path);
+                    return Ok(());
                 }
 
-                path.path.push(Symbol::intern(&disambiguated_data.data.to_string()));
-                Ok(path)
+                self.path.push(Symbol::intern(&disambiguated_data.data.to_string()));
+                Ok(())
             }
 
             fn path_generic_args(
-                self,
-                print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+                &mut self,
+                print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
                 _args: &[GenericArg<'tcx>],
-            ) -> Result<Self, PrintError> {
+            ) -> Result<(), PrintError> {
                 print_prefix(self)
             }
         }
 
-        AbsolutePathPrinter { tcx: self.tcx, path: vec![] }
-            .print_def_path(def_id, &[])
-            .unwrap()
-            .path
+        let mut printer = AbsolutePathPrinter { tcx: self.tcx, path: vec![] };
+        printer.print_def_path(def_id, &[]).unwrap();
+        printer.path
     }
 
     /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`.
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index dee25df53bd..12057f5e1cb 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -998,9 +998,9 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                         ty::tls::with(|tcx| {
                             let variant_def = &tcx.adt_def(adt_did).variant(variant);
                             let args = tcx.lift(args).expect("could not lift for printing");
-                            let name = FmtPrinter::new(tcx, Namespace::ValueNS)
-                                .print_def_path(variant_def.def_id, args)?
-                                .into_buffer();
+                            let name = FmtPrinter::print_string(tcx, Namespace::ValueNS, |cx| {
+                                cx.print_def_path(variant_def.def_id, args)
+                            })?;
 
                             match variant_def.ctor_kind() {
                                 Some(CtorKind::Const) => fmt.write_str(&name),
@@ -1740,7 +1740,7 @@ fn pretty_print_const_value_tcx<'tcx>(
                         let args = tcx.lift(args).unwrap();
                         let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
                         cx.print_alloc_ids = true;
-                        let cx = cx.print_value_path(variant_def.def_id, args)?;
+                        cx.print_value_path(variant_def.def_id, args)?;
                         fmt.write_str(&cx.into_buffer())?;
 
                         match variant_def.ctor_kind() {
@@ -1775,14 +1775,14 @@ fn pretty_print_const_value_tcx<'tcx>(
             let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
             cx.print_alloc_ids = true;
             let ty = tcx.lift(ty).unwrap();
-            cx = cx.pretty_print_const_scalar(scalar, ty)?;
+            cx.pretty_print_const_scalar(scalar, ty)?;
             fmt.write_str(&cx.into_buffer())?;
             return Ok(());
         }
         (ConstValue::ZeroSized, ty::FnDef(d, s)) => {
             let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
             cx.print_alloc_ids = true;
-            let cx = cx.print_value_path(*d, s)?;
+            cx.print_value_path(*d, s)?;
             fmt.write_str(&cx.into_buffer())?;
             return Ok(());
         }
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 8b4375f0270..184a70ed4cb 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -315,26 +315,25 @@ impl<'tcx> Ty<'tcx> {
 impl<'tcx> TyCtxt<'tcx> {
     pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
         let mut type_limit = 50;
-        let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
-            .pretty_print_type(ty)
-            .expect("could not write to `String`")
-            .into_buffer();
+        let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
+            cx.pretty_print_type(ty)
+        })
+        .expect("could not write to `String`");
         if regular.len() <= length_limit {
             return regular;
         }
         let mut short;
         loop {
             // Look for the longest properly trimmed path that still fits in length_limit.
-            short = with_forced_trimmed_paths!(
-                FmtPrinter::new_with_limit(
+            short = with_forced_trimmed_paths!({
+                let mut cx = FmtPrinter::new_with_limit(
                     self,
                     hir::def::Namespace::TypeNS,
                     rustc_session::Limit(type_limit),
-                )
-                .pretty_print_type(ty)
-                .expect("could not write to `String`")
-                .into_buffer()
-            );
+                );
+                cx.pretty_print_type(ty).expect("could not write to `String`");
+                cx.into_buffer()
+            });
             if short.len() <= length_limit || type_limit == 0 {
                 break;
             }
@@ -344,10 +343,10 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
-        let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
-            .pretty_print_type(ty)
-            .expect("could not write to `String`")
-            .into_buffer();
+        let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
+            cx.pretty_print_type(ty)
+        })
+        .expect("could not write to `String`");
 
         if !self.sess.opts.unstable_opts.write_long_types_to_disk {
             return (regular, None);
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index a7d6e97c941..cebefbccc11 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -298,9 +298,9 @@ fn fmt_instance(
     ty::tls::with(|tcx| {
         let args = tcx.lift(instance.args).expect("could not lift for printing");
 
-        let s = FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length)
-            .print_def_path(instance.def_id(), args)?
-            .into_buffer();
+        let mut cx = FmtPrinter::new_with_limit(tcx, Namespace::ValueNS, type_length);
+        cx.print_def_path(instance.def_id(), args)?;
+        let s = cx.into_buffer();
         f.write_str(&s)
     })?;
 
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 164e4232e4c..80af8a92553 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -15,7 +15,7 @@ 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> {
-    fn print(&self, cx: P) -> Result<P, PrintError>;
+    fn print(&self, cx: &mut P) -> Result<(), PrintError>;
 }
 
 /// Interface for outputting user-facing "type-system entities"
@@ -31,70 +31,70 @@ pub trait Printer<'tcx>: Sized {
     fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
 
     fn print_def_path(
-        self,
+        &mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.default_print_def_path(def_id, args)
     }
 
     fn print_impl_path(
-        self,
+        &mut self,
         impl_def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.default_print_impl_path(impl_def_id, args, self_ty, trait_ref)
     }
 
-    fn print_region(self, region: ty::Region<'tcx>) -> Result<Self, PrintError>;
+    fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError>;
 
-    fn print_type(self, ty: Ty<'tcx>) -> Result<Self, PrintError>;
+    fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError>;
 
     fn print_dyn_existential(
-        self,
+        &mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self, PrintError>;
+    ) -> Result<(), PrintError>;
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError>;
+    fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError>;
 
-    fn path_crate(self, cnum: CrateNum) -> Result<Self, PrintError>;
+    fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError>;
 
     fn path_qualified(
-        self,
+        &mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError>;
+    ) -> Result<(), PrintError>;
 
     fn path_append_impl(
-        self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError>;
+    ) -> Result<(), PrintError>;
 
     fn path_append(
-        self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self, PrintError>;
+    ) -> Result<(), PrintError>;
 
     fn path_generic_args(
-        self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self, PrintError>;
+    ) -> Result<(), PrintError>;
 
     // Defaults (should not be overridden):
 
     #[instrument(skip(self), level = "debug")]
     fn default_print_def_path(
-        self,
+        &mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         let key = self.tcx().def_key(def_id);
         debug!(?key);
 
@@ -161,7 +161,7 @@ pub trait Printer<'tcx>: Sized {
                 }
 
                 self.path_append(
-                    |cx: Self| {
+                    |cx: &mut Self| {
                         if trait_qualify_parent {
                             let trait_ref = ty::TraitRef::new(
                                 cx.tcx(),
@@ -180,12 +180,12 @@ pub trait Printer<'tcx>: Sized {
     }
 
     fn default_print_impl_path(
-        self,
+        &mut self,
         impl_def_id: DefId,
         _args: &'tcx [GenericArg<'tcx>],
         self_ty: Ty<'tcx>,
         impl_trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         debug!(
             "default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
             impl_def_id, self_ty, impl_trait_ref
@@ -286,25 +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> {
-    fn print(&self, cx: P) -> Result<P, PrintError> {
+    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
         cx.print_region(*self)
     }
 }
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
-    fn print(&self, cx: P) -> Result<P, PrintError> {
+    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
         cx.print_type(*self)
     }
 }
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
-    fn print(&self, cx: P) -> Result<P, PrintError> {
+    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
         cx.print_dyn_existential(self)
     }
 }
 
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
-    fn print(&self, cx: P) -> Result<P, PrintError> {
+    fn print(&self, cx: &mut P) -> Result<(), 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 38b3096f851..316370977a4 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -42,10 +42,10 @@ macro_rules! p {
         write!(scoped_cx!(), $($data),+)?
     };
     (@print($x:expr)) => {
-        scoped_cx!() = $x.print(scoped_cx!())?
+        $x.print(scoped_cx!())?
     };
     (@$method:ident($($arg:expr),*)) => {
-        scoped_cx!() = scoped_cx!().$method($($arg),*)?
+        scoped_cx!().$method($($arg),*)?
     };
     ($($elem:tt $(($($args:tt)*))?),+) => {{
         $(p!(@ $elem $(($($args)*))?);)+
@@ -209,25 +209,25 @@ impl<'tcx> RegionHighlightMode<'tcx> {
 pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     /// Like `print_def_path` but for value paths.
     fn print_value_path(
-        self,
+        &mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.print_def_path(def_id, args)
     }
 
-    fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, PrintError>
+    fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         value.as_ref().skip_binder().print(self)
     }
 
-    fn wrap_binder<T, F: FnOnce(&T, Self) -> Result<Self, fmt::Error>>(
-        self,
+    fn wrap_binder<T, F: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>(
+        &mut self,
         value: &ty::Binder<'tcx, T>,
         f: F,
-    ) -> Result<Self, PrintError>
+    ) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
@@ -235,40 +235,40 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     }
 
     /// Prints comma-separated elements.
-    fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, PrintError>
+    fn comma_sep<T>(&mut self, mut elems: impl Iterator<Item = T>) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self>,
     {
         if let Some(first) = elems.next() {
-            self = first.print(self)?;
+            first.print(self)?;
             for elem in elems {
                 self.write_str(", ")?;
-                self = elem.print(self)?;
+                elem.print(self)?;
             }
         }
-        Ok(self)
+        Ok(())
     }
 
     /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument
     fn typed_value(
-        mut self,
-        f: impl FnOnce(Self) -> Result<Self, PrintError>,
-        t: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+        t: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         conversion: &str,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.write_str("{")?;
-        self = f(self)?;
+        f(self)?;
         self.write_str(conversion)?;
-        self = t(self)?;
+        t(self)?;
         self.write_str("}")?;
-        Ok(self)
+        Ok(())
     }
 
     /// Prints `<...>` around what `f` prints.
     fn generic_delimiters(
-        self,
-        f: impl FnOnce(Self) -> Result<Self, PrintError>,
-    ) -> Result<Self, PrintError>;
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+    ) -> Result<(), PrintError>;
 
     /// Returns `true` if the region should be printed in
     /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
@@ -282,9 +282,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     /// 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), PrintError> {
+    fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
         if NO_VISIBLE_PATH.with(|flag| flag.get()) {
-            return Ok((self, false));
+            return Ok(false);
         }
 
         let mut callers = Vec::new();
@@ -296,7 +296,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     // 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, bool), PrintError> {
+    fn force_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<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);
@@ -324,7 +324,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         {
             // If `Assoc` is unique, we don't want to talk about `Trait::Assoc`.
             self.write_str(get_local_name(&self, *symbol, def_id, key).as_str())?;
-            return Ok((self, true));
+            return Ok(true);
         }
         if let Some(symbol) = key.get_opt_name() {
             if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = kind
@@ -357,36 +357,35 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             {
             } else {
                 // If not covered above, like for example items out of `impl` blocks, fallback.
-                return Ok((self, false));
+                return Ok(false);
             }
             self.write_str(get_local_name(&self, symbol, def_id, key).as_str())?;
-            return Ok((self, true));
+            return Ok(true);
         }
-        Ok((self, false))
+        Ok(false)
     }
 
     /// 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, bool), PrintError> {
+    fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
         if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
-            let (s, trimmed) = self.force_print_trimmed_def_path(def_id)?;
+            let trimmed = self.force_print_trimmed_def_path(def_id)?;
             if trimmed {
-                return Ok((s, true));
+                return Ok(true);
             }
-            self = s;
         }
         if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
             || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
             || NO_TRIMMED_PATH.with(|flag| flag.get())
             || SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get())
         {
-            return Ok((self, false));
+            return Ok(false);
         }
 
         match self.tcx().trimmed_def_paths(()).get(&def_id) {
-            None => Ok((self, false)),
+            None => Ok(false),
             Some(symbol) => {
                 write!(self, "{}", Ident::with_dummy_span(*symbol))?;
-                Ok((self, true))
+                Ok(true)
             }
         }
     }
@@ -405,10 +404,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     /// This method returns false if we can't print the visible path, so
     /// `print_def_path` can fall back on the item's real definition path.
     fn try_print_visible_def_path_recur(
-        mut self,
+        &mut self,
         def_id: DefId,
         callers: &mut Vec<DefId>,
-    ) -> Result<(Self, bool), PrintError> {
+    ) -> Result<bool, PrintError> {
         define_scoped_cx!(self);
 
         debug!("try_print_visible_def_path: def_id={:?}", def_id);
@@ -417,7 +416,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         // path to the crate followed by the path to the item within the crate.
         if let Some(cnum) = def_id.as_crate_root() {
             if cnum == LOCAL_CRATE {
-                return Ok((self.path_crate(cnum)?, true));
+                self.path_crate(cnum)?;
+                return Ok(true);
             }
 
             // In local mode, when we encounter a crate other than
@@ -440,7 +440,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         // or avoid ending up with `ExternCrateSource::Extern`,
                         // for the injected `std`/`core`.
                         if span.is_dummy() {
-                            return Ok((self.path_crate(cnum)?, true));
+                            self.path_crate(cnum)?;
+                            return Ok(true);
                         }
 
                         // Disable `try_print_trimmed_def_path` behavior within
@@ -448,23 +449,25 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         // in cases where the `extern crate foo` has non-trivial
                         // parents, e.g. it's nested in `impl foo::Trait for Bar`
                         // (see also issues #55779 and #87932).
-                        self = with_no_visible_paths!(self.print_def_path(def_id, &[])?);
+                        with_no_visible_paths!(self.print_def_path(def_id, &[])?);
 
-                        return Ok((self, true));
+                        return Ok(true);
                     }
                     (ExternCrateSource::Path, LOCAL_CRATE) => {
-                        return Ok((self.path_crate(cnum)?, true));
+                        self.path_crate(cnum)?;
+                        return Ok(true);
                     }
                     _ => {}
                 },
                 None => {
-                    return Ok((self.path_crate(cnum)?, true));
+                    self.path_crate(cnum)?;
+                    return Ok(true);
                 }
             }
         }
 
         if def_id.is_local() {
-            return Ok((self, false));
+            return Ok(false);
         }
 
         let visible_parent_map = self.tcx().visible_parent_map(());
@@ -485,7 +488,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         }
 
         let Some(visible_parent) = visible_parent_map.get(&def_id).cloned() else {
-            return Ok((self, false));
+            return Ok(false);
         };
 
         let actual_parent = self.tcx().opt_parent(def_id);
@@ -548,7 +551,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     *name = new_name;
                 } else {
                     // There is no name that is public and isn't `_`, so bail.
-                    return Ok((self, false));
+                    return Ok(false);
                 }
             }
             // Re-exported `extern crate` (#43189).
@@ -560,7 +563,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         debug!("try_print_visible_def_path: data={:?}", data);
 
         if callers.contains(&visible_parent) {
-            return Ok((self, false));
+            return Ok(false);
         }
         callers.push(visible_parent);
         // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
@@ -568,19 +571,19 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         // To support printers that do not implement `PrettyPrinter`, a `Vec` or
         // linked list on the stack would need to be built, before any printing.
         match self.try_print_visible_def_path_recur(visible_parent, callers)? {
-            (cx, false) => return Ok((cx, false)),
-            (cx, true) => self = cx,
+            false => return Ok(false),
+            true => {}
         }
         callers.pop();
-
-        Ok((self.path_append(Ok, &DisambiguatedDefPathData { data, disambiguator: 0 })?, true))
+        self.path_append(|_| Ok(()), &DisambiguatedDefPathData { data, disambiguator: 0 })?;
+        Ok(true)
     }
 
     fn pretty_path_qualified(
-        self,
+        &mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), 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
@@ -601,26 +604,26 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
         }
 
-        self.generic_delimiters(|mut cx| {
+        self.generic_delimiters(|cx| {
             define_scoped_cx!(cx);
 
             p!(print(self_ty));
             if let Some(trait_ref) = trait_ref {
                 p!(" as ", print(trait_ref.print_only_trait_path()));
             }
-            Ok(cx)
+            Ok(())
         })
     }
 
     fn pretty_path_append_impl(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
-        self = print_prefix(self)?;
+    ) -> Result<(), PrintError> {
+        print_prefix(self)?;
 
-        self.generic_delimiters(|mut cx| {
+        self.generic_delimiters(|cx| {
             define_scoped_cx!(cx);
 
             p!("impl ");
@@ -629,11 +632,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
             p!(print(self_ty));
 
-            Ok(cx)
+            Ok(())
         })
     }
 
-    fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
+    fn pretty_print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         match *ty.kind() {
@@ -679,7 +682,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::Infer(infer_ty) => {
                 if self.should_print_verbose() {
                     p!(write("{:?}", ty.kind()));
-                    return Ok(self);
+                    return Ok(());
                 }
 
                 if let ty::TyVar(ty_vid) = infer_ty {
@@ -696,7 +699,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::Param(ref param_ty) => p!(print(param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
                 ty::BoundTyKind::Anon => {
-                    rustc_type_ir::debug_bound_var(&mut self, debruijn, bound_ty.var)?
+                    rustc_type_ir::debug_bound_var(self, debruijn, bound_ty.var)?
                 }
                 ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
                     true => p!(write("{:?}", ty.kind())),
@@ -751,7 +754,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 if self.should_print_verbose() {
                     // FIXME(eddyb) print this with `print_def_path`.
                     p!(write("Opaque({:?}, {})", def_id, args.print_as_list()));
-                    return Ok(self);
+                    return Ok(());
                 }
 
                 let parent = self.tcx().parent(def_id);
@@ -766,17 +769,17 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                                 // If the type alias directly starts with the `impl` of the
                                 // opaque type we're printing, then skip the `::{opaque#1}`.
                                 p!(print_def_path(parent, args));
-                                return Ok(self);
+                                return Ok(());
                             }
                         }
                         // Complex opaque type, e.g. `type Foo = (i32, impl Debug);`
                         p!(print_def_path(def_id, args));
-                        return Ok(self);
+                        return Ok(());
                     }
                     _ => {
                         if with_no_queries() {
                             p!(print_def_path(def_id, &[]));
-                            return Ok(self);
+                            return Ok(());
                         } else {
                             return self.pretty_print_opaque_impl_type(def_id, args);
                         }
@@ -817,7 +820,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     if !args.as_coroutine().is_valid() {
                         p!("unavailable");
                     } else {
-                        self = self.comma_sep(args.as_coroutine().upvar_tys().iter())?;
+                        self.comma_sep(args.as_coroutine().upvar_tys().iter())?;
                     }
                     p!(")");
 
@@ -887,7 +890,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                             print(args.as_closure().sig_as_fn_ptr_ty())
                         );
                         p!(" upvar_tys=(");
-                        self = self.comma_sep(args.as_closure().upvar_tys().iter())?;
+                        self.comma_sep(args.as_closure().upvar_tys().iter())?;
                         p!(")");
                     }
                 }
@@ -897,14 +900,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::Slice(ty) => p!("[", print(ty), "]"),
         }
 
-        Ok(self)
+        Ok(())
     }
 
     fn pretty_print_opaque_impl_type(
-        mut self,
+        &mut self,
         def_id: DefId,
         args: &'tcx ty::List<ty::GenericArg<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         let tcx = self.tcx();
 
         // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
@@ -962,7 +965,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             write!(self, "{}", if first { "" } else { " + " })?;
             write!(self, "{}", if paren_needed { "(" } else { "" })?;
 
-            self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut cx| {
+            self.wrap_binder(&fn_once_trait_ref, |trait_ref, cx| {
                 define_scoped_cx!(cx);
                 // Get the (single) generic ty (the args) of this FnOnce trait ref.
                 let generics = tcx.generics_of(trait_ref.def_id);
@@ -1019,7 +1022,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     }
                 }
 
-                Ok(cx)
+                Ok(())
             })?;
         }
 
@@ -1027,7 +1030,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         for (trait_ref, assoc_items) in traits {
             write!(self, "{}", if first { "" } else { " + " })?;
 
-            self = self.wrap_binder(&trait_ref, |trait_ref, mut cx| {
+            self.wrap_binder(&trait_ref, |trait_ref, cx| {
                 define_scoped_cx!(cx);
                 p!(print(trait_ref.print_only_trait_name()));
 
@@ -1091,7 +1094,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 }
 
                 first = false;
-                Ok(cx)
+                Ok(())
             })?;
         }
 
@@ -1104,7 +1107,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
             for re in lifetimes {
                 write!(self, " + ")?;
-                self = self.print_region(re)?;
+                self.print_region(re)?;
             }
         }
 
@@ -1117,11 +1120,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         {
             let num_args = self.tcx().generics_of(fn_def_id).count();
             write!(self, " {{ ")?;
-            self = self.print_def_path(fn_def_id, &args[..num_args])?;
+            self.print_def_path(fn_def_id, &args[..num_args])?;
             write!(self, "() }}")?;
         }
 
-        Ok(self)
+        Ok(())
     }
 
     /// Insert the trait ref and optionally a projection type associated with it into either the
@@ -1172,9 +1175,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     }
 
     fn pretty_print_inherent_projection(
-        self,
+        &mut self,
         alias_ty: &ty::AliasTy<'tcx>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         let def_key = self.tcx().def_key(alias_ty.def_id);
         self.path_generic_args(
             |cx| {
@@ -1196,14 +1199,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     }
 
     fn pretty_print_dyn_existential(
-        mut self,
+        &mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         // Generate the main trait ref, including associated types.
         let mut first = true;
 
         if let Some(principal) = predicates.principal() {
-            self = self.wrap_binder(&principal, |principal, mut cx| {
+            self.wrap_binder(&principal, |principal, cx| {
                 define_scoped_cx!(cx);
                 p!(print_def_path(principal.def_id, &[]));
 
@@ -1243,8 +1246,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     });
 
                     if !args.is_empty() || !projections.is_empty() {
-                        p!(generic_delimiters(|mut cx| {
-                            cx = cx.comma_sep(args.iter().copied())?;
+                        p!(generic_delimiters(|cx| {
+                            cx.comma_sep(args.iter().copied())?;
                             if !args.is_empty() && !projections.is_empty() {
                                 write!(cx, ", ")?;
                             }
@@ -1252,7 +1255,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         }));
                     }
                 }
-                Ok(cx)
+                Ok(())
             })?;
 
             first = false;
@@ -1283,15 +1286,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             p!(print_def_path(def_id, &[]));
         }
 
-        Ok(self)
+        Ok(())
     }
 
     fn pretty_fn_sig(
-        mut self,
+        &mut self,
         inputs: &[Ty<'tcx>],
         c_variadic: bool,
         output: Ty<'tcx>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         p!("(", comma_sep(inputs.iter().copied()));
@@ -1306,28 +1309,28 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             p!(" -> ", print(output));
         }
 
-        Ok(self)
+        Ok(())
     }
 
     fn pretty_print_const(
-        mut self,
+        &mut self,
         ct: ty::Const<'tcx>,
         print_ty: bool,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         if self.should_print_verbose() {
             p!(write("{:?}", ct));
-            return Ok(self);
+            return Ok(());
         }
 
         macro_rules! print_underscore {
             () => {{
                 if print_ty {
-                    self = self.typed_value(
-                        |mut this| {
+                    self.typed_value(
+                        |this| {
                             write!(this, "_")?;
-                            Ok(this)
+                            Ok(())
                         },
                         |this| this.print_type(ct.ty()),
                         ": ",
@@ -1378,7 +1381,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
-                rustc_type_ir::debug_bound_var(&mut self, debruijn, bound_var)?
+                rustc_type_ir::debug_bound_var(self, debruijn, bound_var)?
             }
             ty::ConstKind::Placeholder(placeholder) => p!(write("{placeholder:?}")),
             // FIXME(generic_const_exprs):
@@ -1386,10 +1389,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             ty::ConstKind::Expr(_) => p!("{{const expr}}"),
             ty::ConstKind::Error(_) => p!("{{const error}}"),
         };
-        Ok(self)
+        Ok(())
     }
 
-    fn pretty_print_const_scalar(self, scalar: Scalar, ty: Ty<'tcx>) -> Result<Self, PrintError> {
+    fn pretty_print_const_scalar(
+        &mut self,
+        scalar: Scalar,
+        ty: Ty<'tcx>,
+    ) -> Result<(), PrintError> {
         match scalar {
             Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty),
             Scalar::Int(int) => {
@@ -1399,10 +1406,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     }
 
     fn pretty_print_const_scalar_ptr(
-        mut self,
+        &mut self,
         ptr: Pointer,
         ty: Ty<'tcx>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         let (alloc_id, offset) = ptr.into_parts();
@@ -1433,7 +1440,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                                 Some(GlobalAlloc::VTable(..)) => p!("<vtable>"),
                                 None => p!("<dangling pointer>"),
                             }
-                            return Ok(self);
+                            return Ok(());
                         }
                     }
                 }
@@ -1444,27 +1451,27 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 if let Some(GlobalAlloc::Function(instance)) =
                     self.tcx().try_get_global_alloc(alloc_id)
                 {
-                    self = self.typed_value(
+                    self.typed_value(
                         |this| this.print_value_path(instance.def_id(), instance.args),
                         |this| this.print_type(ty),
                         " as ",
                     )?;
-                    return Ok(self);
+                    return Ok(());
                 }
             }
             _ => {}
         }
         // Any pointer values not covered by a branch above
-        self = self.pretty_print_const_pointer(ptr, ty)?;
-        Ok(self)
+        self.pretty_print_const_pointer(ptr, ty)?;
+        Ok(())
     }
 
     fn pretty_print_const_scalar_int(
-        mut self,
+        &mut self,
         int: ScalarInt,
         ty: Ty<'tcx>,
         print_ty: bool,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         match ty.kind() {
@@ -1491,10 +1498,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             // Pointer types
             ty::Ref(..) | ty::RawPtr(_) | ty::FnPtr(_) => {
                 let data = int.assert_bits(self.tcx().data_layout.pointer_size);
-                self = self.typed_value(
-                    |mut this| {
+                self.typed_value(
+                    |this| {
                         write!(this, "0x{data:x}")?;
-                        Ok(this)
+                        Ok(())
                     },
                     |this| this.print_type(ty),
                     " as ",
@@ -1502,57 +1509,57 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             }
             // Nontrivial types with scalar bit representation
             _ => {
-                let print = |mut this: Self| {
+                let print = |this: &mut Self| {
                     if int.size() == Size::ZERO {
                         write!(this, "transmute(())")?;
                     } else {
                         write!(this, "transmute(0x{int:x})")?;
                     }
-                    Ok(this)
+                    Ok(())
                 };
-                self = if print_ty {
+                if print_ty {
                     self.typed_value(print, |this| this.print_type(ty), ": ")?
                 } else {
                     print(self)?
                 };
             }
         }
-        Ok(self)
+        Ok(())
     }
 
     /// This is overridden for MIR printing because we only want to hide alloc ids from users, not
     /// from MIR where it is actually useful.
     fn pretty_print_const_pointer<Prov: Provenance>(
-        self,
+        &mut self,
         _: Pointer<Prov>,
         ty: Ty<'tcx>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.typed_value(
-            |mut this| {
+            |this| {
                 this.write_str("&_")?;
-                Ok(this)
+                Ok(())
             },
             |this| this.print_type(ty),
             ": ",
         )
     }
 
-    fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self, PrintError> {
+    fn pretty_print_byte_str(&mut self, byte_str: &'tcx [u8]) -> Result<(), PrintError> {
         write!(self, "b\"{}\"", byte_str.escape_ascii())?;
-        Ok(self)
+        Ok(())
     }
 
     fn pretty_print_const_valtree(
-        mut self,
+        &mut self,
         valtree: ty::ValTree<'tcx>,
         ty: Ty<'tcx>,
         print_ty: bool,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         if self.should_print_verbose() {
             p!(write("ValTree({:?}: ", valtree), print(ty), ")");
-            return Ok(self);
+            return Ok(());
         }
 
         let u8_type = self.tcx().types.u8;
@@ -1573,12 +1580,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         bug!("expected to convert valtree to raw bytes for type {:?}", ty)
                     });
                     p!(write("{:?}", String::from_utf8_lossy(bytes)));
-                    return Ok(self);
+                    return Ok(());
                 }
                 _ => {
                     p!("&");
                     p!(pretty_print_const_valtree(valtree, *inner_ty, print_ty));
-                    return Ok(self);
+                    return Ok(());
                 }
             },
             (ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
@@ -1587,7 +1594,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 });
                 p!("*");
                 p!(pretty_print_byte_str(bytes));
-                return Ok(self);
+                return Ok(());
             }
             // Aggregates, printed as array/tuple/struct/variant construction syntax.
             (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
@@ -1606,10 +1613,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                         p!(")");
                     }
                     ty::Adt(def, _) if def.variants().is_empty() => {
-                        self = self.typed_value(
-                            |mut this| {
+                        self.typed_value(
+                            |this| {
                                 write!(this, "unreachable()")?;
-                                Ok(this)
+                                Ok(())
                             },
                             |this| this.print_type(ty),
                             ": ",
@@ -1641,7 +1648,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     }
                     _ => unreachable!(),
                 }
-                return Ok(self);
+                return Ok(());
             }
             (ty::ValTree::Leaf(leaf), ty::Ref(_, inner_ty, _)) => {
                 p!(write("&"));
@@ -1664,18 +1671,15 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         if print_ty {
             p!(": ", print(ty));
         }
-        Ok(self)
+        Ok(())
     }
 
-    fn pretty_closure_as_impl(
-        mut self,
-        closure: ty::ClosureArgs<'tcx>,
-    ) -> Result<Self, PrintError> {
+    fn pretty_closure_as_impl(&mut self, closure: ty::ClosureArgs<'tcx>) -> Result<(), PrintError> {
         let sig = closure.sig();
         let kind = closure.kind_ty().to_opt_closure_kind().unwrap_or(ty::ClosureKind::Fn);
 
         write!(self, "impl ")?;
-        self.wrap_binder(&sig, |sig, mut cx| {
+        self.wrap_binder(&sig, |sig, cx| {
             define_scoped_cx!(cx);
 
             p!(print(kind), "(");
@@ -1691,7 +1695,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                 p!(" -> ", print(sig.output()));
             }
 
-            Ok(cx)
+            Ok(())
         })
     }
 
@@ -1709,7 +1713,7 @@ pub(crate) fn pretty_print_const<'tcx>(
         let literal = tcx.lift(c).unwrap();
         let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
         cx.print_alloc_ids = true;
-        let cx = cx.pretty_print_const(literal, print_types)?;
+        cx.pretty_print_const(literal, print_types)?;
         fmt.write_str(&cx.into_buffer())?;
         Ok(())
     })
@@ -1760,6 +1764,16 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
         Self::new_with_limit(tcx, ns, limit)
     }
 
+    pub fn print_string(
+        tcx: TyCtxt<'tcx>,
+        ns: Namespace,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+    ) -> Result<String, PrintError> {
+        let mut c = FmtPrinter::new(tcx, ns);
+        f(&mut c)?;
+        Ok(c.into_buffer())
+    }
+
     pub fn new_with_limit(tcx: TyCtxt<'tcx>, ns: Namespace, type_length_limit: Limit) -> Self {
         FmtPrinter(Box::new(FmtPrinterData {
             tcx,
@@ -1820,7 +1834,8 @@ impl<'t> TyCtxt<'t> {
         let def_id = def_id.into_query_param();
         let ns = guess_def_namespace(self, def_id);
         debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
-        FmtPrinter::new(self, ns).print_def_path(def_id, args).unwrap().into_buffer()
+
+        FmtPrinter::print_string(self, ns, |cx| cx.print_def_path(def_id, args)).unwrap()
     }
 
     pub fn value_path_str_with_args(
@@ -1831,7 +1846,8 @@ impl<'t> TyCtxt<'t> {
         let def_id = def_id.into_query_param();
         let ns = guess_def_namespace(self, def_id);
         debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns);
-        FmtPrinter::new(self, ns).print_value_path(def_id, args).unwrap().into_buffer()
+
+        FmtPrinter::print_string(self, ns, |cx| cx.print_value_path(def_id, args)).unwrap()
     }
 }
 
@@ -1848,21 +1864,21 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
     }
 
     fn print_def_path(
-        mut self,
+        &mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
         if args.is_empty() {
             match self.try_print_trimmed_def_path(def_id)? {
-                (cx, true) => return Ok(cx),
-                (cx, false) => self = cx,
+                true => return Ok(()),
+                false => {}
             }
 
             match self.try_print_visible_def_path(def_id)? {
-                (cx, true) => return Ok(cx),
-                (cx, false) => self = cx,
+                true => return Ok(()),
+                false => {}
             }
         }
 
@@ -1883,7 +1899,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
                 let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
                 let span = self.tcx.def_span(def_id);
 
-                self = self.print_def_path(parent_def_id, &[])?;
+                self.print_def_path(parent_def_id, &[])?;
 
                 // HACK(eddyb) copy of `path_append` to avoid
                 // constructing a `DisambiguatedDefPathData`.
@@ -1899,40 +1915,40 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
                 )?;
                 self.empty_path = false;
 
-                return Ok(self);
+                return Ok(());
             }
         }
 
         self.default_print_def_path(def_id, args)
     }
 
-    fn print_region(self, region: ty::Region<'tcx>) -> Result<Self, PrintError> {
+    fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError> {
         self.pretty_print_region(region)
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
+    fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
         if self.type_length_limit.value_within_limit(self.printed_type_count) {
             self.printed_type_count += 1;
             self.pretty_print_type(ty)
         } else {
             self.truncated = true;
             write!(self, "...")?;
-            Ok(self)
+            Ok(())
         }
     }
 
     fn print_dyn_existential(
-        self,
+        &mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.pretty_print_dyn_existential(predicates)
     }
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
+    fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
         self.pretty_print_const(ct, false)
     }
 
-    fn path_crate(mut self, cnum: CrateNum) -> Result<Self, PrintError> {
+    fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
         self.empty_path = true;
         if cnum == LOCAL_CRATE {
             if self.tcx.sess.at_least_rust_2018() {
@@ -1946,52 +1962,52 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
             write!(self, "{}", self.tcx.crate_name(cnum))?;
             self.empty_path = false;
         }
-        Ok(self)
+        Ok(())
     }
 
     fn path_qualified(
-        mut self,
+        &mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
-        self = self.pretty_path_qualified(self_ty, trait_ref)?;
+    ) -> Result<(), PrintError> {
+        self.pretty_path_qualified(self_ty, trait_ref)?;
         self.empty_path = false;
-        Ok(self)
+        Ok(())
     }
 
     fn path_append_impl(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         _disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
-        self = self.pretty_path_append_impl(
-            |mut cx| {
-                cx = print_prefix(cx)?;
+    ) -> Result<(), PrintError> {
+        self.pretty_path_append_impl(
+            |cx| {
+                print_prefix(cx)?;
                 if !cx.empty_path {
                     write!(cx, "::")?;
                 }
 
-                Ok(cx)
+                Ok(())
             },
             self_ty,
             trait_ref,
         )?;
         self.empty_path = false;
-        Ok(self)
+        Ok(())
     }
 
     fn path_append(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self, PrintError> {
-        self = print_prefix(self)?;
+    ) -> Result<(), PrintError> {
+        print_prefix(self)?;
 
         // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
         if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
-            return Ok(self);
+            return Ok(());
         }
 
         let name = disambiguated_data.data.name();
@@ -2006,19 +2022,19 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
         }
 
         let verbose = self.should_print_verbose();
-        disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?;
+        disambiguated_data.fmt_maybe_verbose(self, verbose)?;
 
         self.empty_path = false;
 
-        Ok(self)
+        Ok(())
     }
 
     fn path_generic_args(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
-        self = print_prefix(self)?;
+    ) -> Result<(), PrintError> {
+        print_prefix(self)?;
 
         let tcx = self.tcx;
 
@@ -2052,7 +2068,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
             }
             self.generic_delimiters(|cx| cx.comma_sep(args.into_iter()))
         } else {
-            Ok(self)
+            Ok(())
         }
     }
 }
@@ -2071,29 +2087,29 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
     }
 
     fn print_value_path(
-        mut self,
+        &mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         let was_in_value = std::mem::replace(&mut self.in_value, true);
-        self = self.print_def_path(def_id, args)?;
+        self.print_def_path(def_id, args)?;
         self.in_value = was_in_value;
 
-        Ok(self)
+        Ok(())
     }
 
-    fn in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, PrintError>
+    fn in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         self.pretty_in_binder(value)
     }
 
-    fn wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, PrintError>>(
-        self,
+    fn wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), PrintError>>(
+        &mut self,
         value: &ty::Binder<'tcx, T>,
         f: C,
-    ) -> Result<Self, PrintError>
+    ) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
@@ -2101,33 +2117,33 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
     }
 
     fn typed_value(
-        mut self,
-        f: impl FnOnce(Self) -> Result<Self, PrintError>,
-        t: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+        t: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         conversion: &str,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.write_str("{")?;
-        self = f(self)?;
+        f(self)?;
         self.write_str(conversion)?;
         let was_in_value = std::mem::replace(&mut self.in_value, false);
-        self = t(self)?;
+        t(self)?;
         self.in_value = was_in_value;
         self.write_str("}")?;
-        Ok(self)
+        Ok(())
     }
 
     fn generic_delimiters(
-        mut self,
-        f: impl FnOnce(Self) -> Result<Self, PrintError>,
-    ) -> Result<Self, PrintError> {
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+    ) -> Result<(), PrintError> {
         write!(self, "<")?;
 
         let was_in_value = std::mem::replace(&mut self.in_value, false);
-        let mut inner = f(self)?;
-        inner.in_value = was_in_value;
+        f(self)?;
+        self.in_value = was_in_value;
 
-        write!(inner, ">")?;
-        Ok(inner)
+        write!(self, ">")?;
+        Ok(())
     }
 
     fn should_print_region(&self, region: ty::Region<'tcx>) -> bool {
@@ -2176,18 +2192,18 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
     }
 
     fn pretty_print_const_pointer<Prov: Provenance>(
-        self,
+        &mut self,
         p: Pointer<Prov>,
         ty: Ty<'tcx>,
-    ) -> Result<Self, PrintError> {
-        let print = |mut this: Self| {
+    ) -> Result<(), PrintError> {
+        let print = |this: &mut Self| {
             define_scoped_cx!(this);
             if this.print_alloc_ids {
                 p!(write("{:?}", p));
             } else {
                 p!("&_");
             }
-            Ok(this)
+            Ok(())
         };
         self.typed_value(print, |this| this.print_type(ty), ": ")
     }
@@ -2195,19 +2211,19 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
 
 // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`.
 impl<'tcx> FmtPrinter<'_, 'tcx> {
-    pub fn pretty_print_region(mut self, region: ty::Region<'tcx>) -> Result<Self, fmt::Error> {
+    pub fn pretty_print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), fmt::Error> {
         define_scoped_cx!(self);
 
         // Watch out for region highlights.
         let highlight = self.region_highlight_mode;
         if let Some(n) = highlight.region_highlighted(region) {
             p!(write("'{}", n));
-            return Ok(self);
+            return Ok(());
         }
 
         if self.should_print_verbose() {
             p!(write("{:?}", region));
-            return Ok(self);
+            return Ok(());
         }
 
         let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
@@ -2220,7 +2236,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             ty::ReEarlyBound(ref data) => {
                 if data.name != kw::Empty {
                     p!(write("{}", data.name));
-                    return Ok(self);
+                    return Ok(());
                 }
             }
             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
@@ -2232,32 +2248,32 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                     && br.is_named()
                 {
                     p!(write("{}", name));
-                    return Ok(self);
+                    return Ok(());
                 }
 
                 if let Some((region, counter)) = highlight.highlight_bound_region {
                     if br == region {
                         p!(write("'{}", counter));
-                        return Ok(self);
+                        return Ok(());
                     }
                 }
             }
             ty::ReVar(region_vid) if identify_regions => {
                 p!(write("{:?}", region_vid));
-                return Ok(self);
+                return Ok(());
             }
             ty::ReVar(_) => {}
             ty::ReErased => {}
             ty::ReError(_) => {}
             ty::ReStatic => {
                 p!("'static");
-                return Ok(self);
+                return Ok(());
             }
         }
 
         p!("'_");
 
-        Ok(self)
+        Ok(())
     }
 }
 
@@ -2340,9 +2356,9 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
 // `region_index` and `used_region_names`.
 impl<'tcx> FmtPrinter<'_, 'tcx> {
     pub fn name_all_regions<T>(
-        mut self,
+        &mut self,
         value: &ty::Binder<'tcx, T>,
-    ) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
+    ) -> Result<(T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
@@ -2417,10 +2433,10 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         // anyways.
         let (new_value, map) = if self.should_print_verbose() {
             for var in value.bound_vars().iter() {
-                start_or_continue(&mut self, "for<", ", ");
+                start_or_continue(self, "for<", ", ");
                 write!(self, "{var:?}")?;
             }
-            start_or_continue(&mut self, "", "> ");
+            start_or_continue(self, "", "> ");
             (value.clone().skip_binder(), BTreeMap::default())
         } else {
             let tcx = self.tcx;
@@ -2484,8 +2500,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                 };
 
                 if !trim_path {
-                    start_or_continue(&mut self, "for<", ", ");
-                    do_continue(&mut self, name);
+                    start_or_continue(self, "for<", ", ");
+                    do_continue(self, name);
                 }
                 ty::Region::new_late_bound(
                     tcx,
@@ -2502,42 +2518,42 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             let new_value = value.clone().skip_binder().fold_with(&mut folder);
             let region_map = folder.region_map;
             if !trim_path {
-                start_or_continue(&mut self, "", "> ");
+                start_or_continue(self, "", "> ");
             }
             (new_value, region_map)
         };
 
         self.binder_depth += 1;
         self.region_index = region_index;
-        Ok((self, new_value, map))
+        Ok((new_value, map))
     }
 
-    pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
+    pub fn pretty_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), fmt::Error>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         let old_region_index = self.region_index;
-        let (new, new_value, _) = self.name_all_regions(value)?;
-        let mut inner = new_value.print(new)?;
-        inner.region_index = old_region_index;
-        inner.binder_depth -= 1;
-        Ok(inner)
+        let (new_value, _) = self.name_all_regions(value)?;
+        new_value.print(self)?;
+        self.region_index = old_region_index;
+        self.binder_depth -= 1;
+        Ok(())
     }
 
-    pub fn pretty_wrap_binder<T, C: FnOnce(&T, Self) -> Result<Self, fmt::Error>>(
-        self,
+    pub fn pretty_wrap_binder<T, C: FnOnce(&T, &mut Self) -> Result<(), fmt::Error>>(
+        &mut self,
         value: &ty::Binder<'tcx, T>,
         f: C,
-    ) -> Result<Self, fmt::Error>
+    ) -> Result<(), fmt::Error>
     where
         T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
     {
         let old_region_index = self.region_index;
-        let (new, new_value, _) = self.name_all_regions(value)?;
-        let mut inner = f(&new_value, new)?;
-        inner.region_index = old_region_index;
-        inner.binder_depth -= 1;
-        Ok(inner)
+        let (new_value, _) = self.name_all_regions(value)?;
+        f(&new_value, self)?;
+        self.region_index = old_region_index;
+        self.binder_depth -= 1;
+        Ok(())
     }
 
     fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
@@ -2597,7 +2613,7 @@ impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
 where
     T: Print<'tcx, P> + TypeFoldable<TyCtxt<'tcx>>,
 {
-    fn print(&self, cx: P) -> Result<P, PrintError> {
+    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
         cx.in_binder(self)
     }
 }
@@ -2607,10 +2623,10 @@ where
     T: Print<'tcx, P>,
     U: Print<'tcx, P>,
 {
-    fn print(&self, mut cx: P) -> Result<P, PrintError> {
+    fn print(&self, cx: &mut P) -> Result<(), PrintError> {
         define_scoped_cx!(cx);
         p!(print(self.0), ": ", print(self.1));
-        Ok(cx)
+        Ok(())
     }
 }
 
@@ -2620,9 +2636,10 @@ macro_rules! forward_display_to_print {
         $(#[allow(unused_lifetimes)] impl<'tcx> fmt::Display for $ty {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 ty::tls::with(|tcx| {
-                    let cx = tcx.lift(*self)
+                    let mut cx = FmtPrinter::new(tcx, Namespace::TypeNS);
+                    tcx.lift(*self)
                         .expect("could not lift for printing")
-                        .print(FmtPrinter::new(tcx, Namespace::TypeNS))?;
+                        .print(&mut cx)?;
                     f.write_str(&cx.into_buffer())?;
                     Ok(())
                 })
@@ -2634,13 +2651,13 @@ 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 {
-            fn print(&$self, $cx: P) -> Result<P, PrintError> {
+            fn print(&$self, $cx: &mut P) -> Result<(), PrintError> {
                 #[allow(unused_mut)]
                 let mut $cx = $cx;
                 define_scoped_cx!($cx);
                 let _: () = $print;
                 #[allow(unreachable_code)]
-                Ok($cx)
+                Ok(())
             }
         })+
 
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 012bb749412..bf2e61b23b2 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -22,11 +22,10 @@ impl fmt::Debug for ty::TraitDef {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         ty::tls::with(|tcx| {
             with_no_trimmed_paths!({
-                f.write_str(
-                    &FmtPrinter::new(tcx, Namespace::TypeNS)
-                        .print_def_path(self.def_id, &[])?
-                        .into_buffer(),
-                )
+                let s = FmtPrinter::print_string(tcx, Namespace::TypeNS, |cx| {
+                    cx.print_def_path(self.def_id, &[])
+                })?;
+                f.write_str(&s)
             })
         })
     }
@@ -36,11 +35,10 @@ impl<'tcx> fmt::Debug for ty::AdtDef<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         ty::tls::with(|tcx| {
             with_no_trimmed_paths!({
-                f.write_str(
-                    &FmtPrinter::new(tcx, Namespace::TypeNS)
-                        .print_def_path(self.did(), &[])?
-                        .into_buffer(),
-                )
+                let s = FmtPrinter::print_string(tcx, Namespace::TypeNS, |cx| {
+                    cx.print_def_path(self.did(), &[])
+                })?;
+                f.write_str(&s)
             })
         })
     }
@@ -350,9 +348,8 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
                 let ConstKind::Value(valtree) = lifted.kind() else {
                     bug!("we checked that this is a valtree")
                 };
-                let cx = FmtPrinter::new(tcx, Namespace::ValueNS);
-                let cx =
-                    cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?;
+                let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
+                cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?;
                 f.write_str(&cx.into_buffer())
             });
         }
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 5f22b89ea49..53925eeaaa0 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -199,16 +199,16 @@ struct SymbolPrinter<'tcx> {
 // `PrettyPrinter` aka pretty printing of e.g. types in paths,
 // symbol names should have their own printing machinery.
 
-impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
+impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    fn print_region(self, _region: ty::Region<'_>) -> Result<Self, PrintError> {
-        Ok(self)
+    fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
+        Ok(())
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
+    fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
             ty::FnDef(def_id, args)
@@ -220,17 +220,17 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
             // -Zverbose flag, so we cannot reuse it here.
             ty::Array(ty, size) => {
                 self.write_str("[")?;
-                self = self.print_type(ty)?;
+                self.print_type(ty)?;
                 self.write_str("; ")?;
                 if let Some(size) = size.try_to_target_usize(self.tcx()) {
                     write!(self, "{size}")?
                 } else if let ty::ConstKind::Param(param) = size.kind() {
-                    self = param.print(self)?
+                    param.print(self)?
                 } else {
                     self.write_str("_")?
                 }
                 self.write_str("]")?;
-                Ok(self)
+                Ok(())
             }
 
             ty::Alias(ty::Inherent, _) => panic!("unexpected inherent projection"),
@@ -240,21 +240,21 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
     }
 
     fn print_dyn_existential(
-        mut self,
+        &mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         let mut first = true;
         for p in predicates {
             if !first {
                 write!(self, "+")?;
             }
             first = false;
-            self = p.print(self)?;
+            p.print(self)?;
         }
-        Ok(self)
+        Ok(())
     }
 
-    fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
+    fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> {
         // only print integers
         match (ct.kind(), ct.ty().kind()) {
             (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
@@ -269,18 +269,18 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
             }
             _ => self.write_str("_")?,
         }
-        Ok(self)
+        Ok(())
     }
 
-    fn path_crate(self, cnum: CrateNum) -> Result<Self, PrintError> {
+    fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
         self.write_str(self.tcx.crate_name(cnum).as_str())?;
-        Ok(self)
+        Ok(())
     }
     fn path_qualified(
-        self,
+        &mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         // Similar to `pretty_path_qualified`, but for the other
         // types that are printed as paths (see `print_type` above).
         match self_ty.kind() {
@@ -295,15 +295,15 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
     }
 
     fn path_append_impl(
-        self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         _disambiguated_data: &DisambiguatedDefPathData,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.pretty_path_append_impl(
-            |mut cx| {
-                cx = print_prefix(cx)?;
+            |cx| {
+                print_prefix(cx)?;
 
                 if cx.keep_within_component {
                     // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it.
@@ -312,22 +312,22 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
                     cx.path.finalize_pending_component();
                 }
 
-                Ok(cx)
+                Ok(())
             },
             self_ty,
             trait_ref,
         )
     }
     fn path_append(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self, PrintError> {
-        self = print_prefix(self)?;
+    ) -> Result<(), PrintError> {
+        print_prefix(self)?;
 
         // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs.
         if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data {
-            return Ok(self);
+            return Ok(());
         }
 
         if self.keep_within_component {
@@ -339,14 +339,14 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
 
         write!(self, "{}", disambiguated_data.data)?;
 
-        Ok(self)
+        Ok(())
     }
     fn path_generic_args(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
-        self = print_prefix(self)?;
+    ) -> Result<(), PrintError> {
+        print_prefix(self)?;
 
         let args =
             args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
@@ -354,42 +354,42 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         if args.clone().next().is_some() {
             self.generic_delimiters(|cx| cx.comma_sep(args))
         } else {
-            Ok(self)
+            Ok(())
         }
     }
 }
 
-impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> {
+impl<'tcx> PrettyPrinter<'tcx> for 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, PrintError>
+    fn comma_sep<T>(&mut self, mut elems: impl Iterator<Item = T>) -> Result<(), PrintError>
     where
         T: Print<'tcx, Self>,
     {
         if let Some(first) = elems.next() {
-            self = first.print(self)?;
+            first.print(self)?;
             for elem in elems {
                 self.write_str(",")?;
-                self = elem.print(self)?;
+                elem.print(self)?;
             }
         }
-        Ok(self)
+        Ok(())
     }
 
     fn generic_delimiters(
-        mut self,
-        f: impl FnOnce(Self) -> Result<Self, PrintError>,
-    ) -> Result<Self, PrintError> {
+        &mut self,
+        f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
+    ) -> Result<(), PrintError> {
         write!(self, "<")?;
 
         let kept_within_component = mem::replace(&mut self.keep_within_component, true);
-        self = f(self)?;
+        f(self)?;
         self.keep_within_component = kept_within_component;
 
         write!(self, ">")?;
 
-        Ok(self)
+        Ok(())
     }
 }
 
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 89b8b1518b0..ad3d291dfa0 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -30,7 +30,7 @@ pub(super) fn mangle<'tcx>(
     let args = tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.args);
 
     let prefix = "_R";
-    let mut cx = &mut SymbolMangler {
+    let mut cx: SymbolMangler<'_> = SymbolMangler {
         tcx,
         start_offset: prefix.len(),
         paths: FxHashMap::default(),
@@ -49,13 +49,13 @@ pub(super) fn mangle<'tcx>(
         _ => None,
     };
 
-    cx = if let Some(shim_kind) = shim_kind {
+    if let Some(shim_kind) = shim_kind {
         cx.path_append_ns(|cx| cx.print_def_path(def_id, args), 'S', 0, shim_kind).unwrap()
     } else {
         cx.print_def_path(def_id, args).unwrap()
     };
     if let Some(instantiating_crate) = instantiating_crate {
-        cx = cx.print_def_path(instantiating_crate.as_def_id(), &[]).unwrap();
+        cx.print_def_path(instantiating_crate.as_def_id(), &[]).unwrap();
     }
     std::mem::take(&mut cx.out)
 }
@@ -65,7 +65,7 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
     trait_ref: ty::PolyExistentialTraitRef<'tcx>,
 ) -> String {
     // FIXME(flip1995): See comment in `mangle_typeid_for_fnabi`.
-    let mut cx = &mut SymbolMangler {
+    let mut cx = SymbolMangler {
         tcx,
         start_offset: 0,
         paths: FxHashMap::default(),
@@ -74,7 +74,7 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
         binders: vec![],
         out: String::new(),
     };
-    cx = cx.print_def_path(trait_ref.def_id(), &[]).unwrap();
+    cx.print_def_path(trait_ref.def_id(), &[]).unwrap();
     std::mem::take(&mut cx.out)
 }
 
@@ -179,32 +179,32 @@ impl<'tcx> SymbolMangler<'tcx> {
         self.push(ident);
     }
 
-    fn path_append_ns<'a>(
-        mut self: &'a mut Self,
-        print_prefix: impl FnOnce(&'a mut Self) -> Result<&'a mut Self, PrintError>,
+    fn path_append_ns(
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         ns: char,
         disambiguator: u64,
         name: &str,
-    ) -> Result<&'a mut Self, PrintError> {
+    ) -> Result<(), PrintError> {
         self.push("N");
         self.out.push(ns);
-        self = print_prefix(self)?;
+        print_prefix(self)?;
         self.push_disambiguator(disambiguator as u64);
         self.push_ident(name);
-        Ok(self)
+        Ok(())
     }
 
-    fn print_backref(&mut self, i: usize) -> Result<&mut Self, PrintError> {
+    fn print_backref(&mut self, i: usize) -> Result<(), PrintError> {
         self.push("B");
         self.push_integer_62((i - self.start_offset) as u64);
-        Ok(self)
+        Ok(())
     }
 
-    fn in_binder<'a, T>(
-        mut self: &'a mut Self,
+    fn in_binder<T>(
+        &mut self,
         value: &ty::Binder<'tcx, T>,
-        print_value: impl FnOnce(&'a mut Self, &T) -> Result<&'a mut Self, PrintError>,
-    ) -> Result<&'a mut Self, PrintError>
+        print_value: impl FnOnce(&mut Self, &T) -> Result<(), PrintError>,
+    ) -> Result<(), PrintError>
     where
         T: TypeVisitable<TyCtxt<'tcx>>,
     {
@@ -222,45 +222,45 @@ impl<'tcx> SymbolMangler<'tcx> {
         lifetime_depths.end += lifetimes;
 
         self.binders.push(BinderLevel { lifetime_depths });
-        self = print_value(self, value.as_ref().skip_binder())?;
+        print_value(self, value.as_ref().skip_binder())?;
         self.binders.pop();
 
-        Ok(self)
+        Ok(())
     }
 }
 
-impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
+impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
     fn print_def_path(
-        mut self,
+        &mut self,
         def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         if let Some(&i) = self.paths.get(&(def_id, args)) {
             return self.print_backref(i);
         }
         let start = self.out.len();
 
-        self = self.default_print_def_path(def_id, args)?;
+        self.default_print_def_path(def_id, args)?;
 
         // Only cache paths that do not refer to an enclosing
         // binder (which would change depending on context).
         if !args.iter().any(|k| k.has_escaping_bound_vars()) {
             self.paths.insert((def_id, args), start);
         }
-        Ok(self)
+        Ok(())
     }
 
     fn print_impl_path(
-        mut self,
+        &mut self,
         impl_def_id: DefId,
         args: &'tcx [GenericArg<'tcx>],
         mut self_ty: Ty<'tcx>,
         mut impl_trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         let key = self.tcx.def_key(impl_def_id);
         let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
 
@@ -288,7 +288,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         // Encode impl generic params if the substitutions contain parameters (implying
         // polymorphization is enabled) and this isn't an inherent impl.
         if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) {
-            self = self.path_generic_args(
+            self.path_generic_args(
                 |this| {
                     this.path_append_ns(
                         |cx| cx.print_def_path(parent_def_id, &[]),
@@ -301,19 +301,19 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             )?;
         } else {
             self.push_disambiguator(key.disambiguated_data.disambiguator as u64);
-            self = self.print_def_path(parent_def_id, &[])?;
+            self.print_def_path(parent_def_id, &[])?;
         }
 
-        self = self_ty.print(self)?;
+        self_ty.print(self)?;
 
         if let Some(trait_ref) = impl_trait_ref {
-            self = self.print_def_path(trait_ref.def_id, trait_ref.args)?;
+            self.print_def_path(trait_ref.def_id, trait_ref.args)?;
         }
 
-        Ok(self)
+        Ok(())
     }
 
-    fn print_region(self, region: ty::Region<'_>) -> Result<Self, PrintError> {
+    fn print_region(&mut self, region: ty::Region<'_>) -> Result<(), PrintError> {
         let i = match *region {
             // Erased lifetimes use the index 0, for a
             // shorter mangling of `L_`.
@@ -332,10 +332,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         };
         self.push("L");
         self.push_integer_62(i as u64);
-        Ok(self)
+        Ok(())
     }
 
-    fn print_type(mut self, ty: Ty<'tcx>) -> Result<Self, PrintError> {
+    fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
         // Basic types, never cached (single-character).
         let basic_type = match ty.kind() {
             ty::Bool => "b",
@@ -365,7 +365,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         };
         if !basic_type.is_empty() {
             self.push(basic_type);
-            return Ok(self);
+            return Ok(());
         }
 
         if let Some(&i) = self.types.get(&ty) {
@@ -391,9 +391,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                     hir::Mutability::Mut => "Q",
                 });
                 if !r.is_erased() {
-                    self = r.print(self)?;
+                    r.print(self)?;
                 }
-                self = ty.print(self)?;
+                ty.print(self)?;
             }
 
             ty::RawPtr(mt) => {
@@ -401,23 +401,23 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                     hir::Mutability::Not => "P",
                     hir::Mutability::Mut => "O",
                 });
-                self = mt.ty.print(self)?;
+                mt.ty.print(self)?;
             }
 
             ty::Array(ty, len) => {
                 self.push("A");
-                self = ty.print(self)?;
-                self = self.print_const(len)?;
+                ty.print(self)?;
+                self.print_const(len)?;
             }
             ty::Slice(ty) => {
                 self.push("S");
-                self = ty.print(self)?;
+                ty.print(self)?;
             }
 
             ty::Tuple(tys) => {
                 self.push("T");
                 for ty in tys.iter() {
-                    self = ty.print(self)?;
+                    ty.print(self)?;
                 }
                 self.push("E");
             }
@@ -428,15 +428,15 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
             | ty::Closure(def_id, args)
             | ty::Coroutine(def_id, args, _) => {
-                self = self.print_def_path(def_id, args)?;
+                self.print_def_path(def_id, args)?;
             }
             ty::Foreign(def_id) => {
-                self = self.print_def_path(def_id, &[])?;
+                self.print_def_path(def_id, &[])?;
             }
 
             ty::FnPtr(sig) => {
                 self.push("F");
-                self = self.in_binder(&sig, |mut cx, sig| {
+                self.in_binder(&sig, |cx, sig| {
                     if sig.unsafety == hir::Unsafety::Unsafe {
                         cx.push("U");
                     }
@@ -454,7 +454,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         }
                     }
                     for &ty in sig.inputs() {
-                        cx = ty.print(cx)?;
+                        ty.print(cx)?;
                     }
                     if sig.c_variadic {
                         cx.push("v");
@@ -470,8 +470,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                     // FIXME(dyn-star): need to update v0 mangling docs
                     ty::DynStar => "D*",
                 });
-                self = self.print_dyn_existential(predicates)?;
-                self = r.print(self)?;
+                self.print_dyn_existential(predicates)?;
+                r.print(self)?;
             }
 
             ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"),
@@ -484,13 +484,13 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         if !ty.has_escaping_bound_vars() {
             self.types.insert(ty, start);
         }
-        Ok(self)
+        Ok(())
     }
 
     fn print_dyn_existential(
-        mut self,
+        &mut self,
         predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), 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
@@ -517,7 +517,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         // [<Trait> [{<Projection>}]] [{<Auto>}]
         // Since any predicates after the first one shouldn't change the binders,
         // just put them all in the binders of the first.
-        self = self.in_binder(&predicates[0], |mut cx, _| {
+        self.in_binder(&predicates[0], |cx, _| {
             for predicate in predicates.iter() {
                 // It would be nice to be able to validate bound vars here, but
                 // projections can actually include bound vars from super traits
@@ -528,30 +528,30 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         // Use a type that can't appear in defaults of type parameters.
                         let dummy_self = Ty::new_fresh(cx.tcx, 0);
                         let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self);
-                        cx = cx.print_def_path(trait_ref.def_id, trait_ref.args)?;
+                        cx.print_def_path(trait_ref.def_id, trait_ref.args)?;
                     }
                     ty::ExistentialPredicate::Projection(projection) => {
                         let name = cx.tcx.associated_item(projection.def_id).name;
                         cx.push("p");
                         cx.push_ident(name.as_str());
-                        cx = match projection.term.unpack() {
+                        match projection.term.unpack() {
                             ty::TermKind::Ty(ty) => ty.print(cx),
                             ty::TermKind::Const(c) => c.print(cx),
                         }?;
                     }
                     ty::ExistentialPredicate::AutoTrait(def_id) => {
-                        cx = cx.print_def_path(*def_id, &[])?;
+                        cx.print_def_path(*def_id, &[])?;
                     }
                 }
             }
-            Ok(cx)
+            Ok(())
         })?;
 
         self.push("E");
-        Ok(self)
+        Ok(())
     }
 
-    fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self, PrintError> {
+    fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), 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() {
@@ -570,12 +570,13 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             | ty::ConstKind::Error(_) => {
                 // Never cached (single-character).
                 self.push("p");
-                return Ok(self);
+                return Ok(());
             }
         }
 
         if let Some(&i) = self.consts.get(&ct) {
-            return self.print_backref(i);
+            self.print_backref(i)?;
+            return Ok(());
         }
 
         let start = self.out.len();
@@ -583,7 +584,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
         match ty.kind() {
             ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
-                self = ty.print(self)?;
+                ty.print(self)?;
 
                 let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all());
 
@@ -645,7 +646,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                             .ty;
                         // FIXME(const_generics): add an assert that we only do this for valtrees.
                         let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
-                        self = dereferenced_const.print(self)?;
+                        dereferenced_const.print(self)?;
                     }
                 }
             }
@@ -654,22 +655,22 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                 let contents = self.tcx.destructure_const(ct);
                 let fields = contents.fields.iter().copied();
 
-                let print_field_list = |mut this: Self| {
+                let print_field_list = |this: &mut Self| {
                     for field in fields.clone() {
-                        this = field.print(this)?;
+                        field.print(this)?;
                     }
                     this.push("E");
-                    Ok(this)
+                    Ok(())
                 };
 
                 match *ct.ty().kind() {
                     ty::Array(..) | ty::Slice(_) => {
                         self.push("A");
-                        self = print_field_list(self)?;
+                        print_field_list(self)?;
                     }
                     ty::Tuple(..) => {
                         self.push("T");
-                        self = print_field_list(self)?;
+                        print_field_list(self)?;
                     }
                     ty::Adt(def, args) => {
                         let variant_idx =
@@ -677,7 +678,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                         let variant_def = &def.variant(variant_idx);
 
                         self.push("V");
-                        self = self.print_def_path(variant_def.def_id, args)?;
+                        self.print_def_path(variant_def.def_id, args)?;
 
                         match variant_def.ctor_kind() {
                             Some(CtorKind::Const) => {
@@ -685,7 +686,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                             }
                             Some(CtorKind::Fn) => {
                                 self.push("T");
-                                self = print_field_list(self)?;
+                                print_field_list(self)?;
                             }
                             None => {
                                 self.push("S");
@@ -701,7 +702,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                                     );
                                     self.push_ident(field_name.unwrap_or(kw::Empty).as_str());
 
-                                    self = field.print(self)?;
+                                    field.print(self)?;
                                 }
                                 self.push("E");
                             }
@@ -720,47 +721,47 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         if !ct.has_escaping_bound_vars() {
             self.consts.insert(ct, start);
         }
-        Ok(self)
+        Ok(())
     }
 
-    fn path_crate(self, cnum: CrateNum) -> Result<Self, PrintError> {
+    fn path_crate(&mut self, cnum: CrateNum) -> Result<(), 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());
         let name = self.tcx.crate_name(cnum);
         self.push_ident(name.as_str());
-        Ok(self)
+        Ok(())
     }
 
     fn path_qualified(
-        mut self,
+        &mut self,
         self_ty: Ty<'tcx>,
         trait_ref: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         assert!(trait_ref.is_some());
         let trait_ref = trait_ref.unwrap();
 
         self.push("Y");
-        self = self_ty.print(self)?;
+        self_ty.print(self)?;
         self.print_def_path(trait_ref.def_id, trait_ref.args)
     }
 
     fn path_append_impl(
-        self,
-        _: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        _: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         _: &DisambiguatedDefPathData,
         _: Ty<'tcx>,
         _: Option<ty::TraitRef<'tcx>>,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         // Inlined into `print_impl_path`
         unreachable!()
     }
 
     fn path_append(
-        self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         disambiguated_data: &DisambiguatedDefPathData,
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), PrintError> {
         let ns = match disambiguated_data.data {
             // Extern block segments can be skipped, names from extern blocks
             // are effectively living in their parent modules.
@@ -797,10 +798,10 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
     }
 
     fn path_generic_args(
-        mut self,
-        print_prefix: impl FnOnce(Self) -> Result<Self, PrintError>,
+        &mut self,
+        print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
         args: &[GenericArg<'tcx>],
-    ) -> Result<Self, PrintError> {
+    ) -> Result<(), 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(),
@@ -816,23 +817,23 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
         }
 
         self.push("I");
-        self = print_prefix(self)?;
+        print_prefix(self)?;
         for arg in args {
             match arg.unpack() {
                 GenericArgKind::Lifetime(lt) => {
-                    self = lt.print(self)?;
+                    lt.print(self)?;
                 }
                 GenericArgKind::Type(ty) => {
-                    self = ty.print(self)?;
+                    ty.print(self)?;
                 }
                 GenericArgKind::Const(c) => {
                     self.push("K");
-                    self = c.print(self)?;
+                    c.print(self)?;
                 }
             }
         }
         self.push("E");
 
-        Ok(self)
+        Ok(())
     }
 }
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 b382474213e..1245b4a7756 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
@@ -246,14 +246,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         if pred_str.len() > 50 {
             // We don't need to save the type to a file, we will be talking about this type already
             // in a separate note when we explain the obligation, so it will be available that way.
-            pred_str = predicate
-                .print(FmtPrinter::new_with_limit(
-                    self.tcx,
-                    Namespace::TypeNS,
-                    rustc_session::Limit(6),
-                ))
-                .unwrap()
-                .into_buffer();
+            let mut cx: FmtPrinter<'_, '_> =
+                FmtPrinter::new_with_limit(self.tcx, Namespace::TypeNS, rustc_session::Limit(6));
+            predicate.print(&mut cx).unwrap();
+            pred_str = cx.into_buffer();
         }
         let mut err = struct_span_err!(
             self.tcx.sess,
@@ -1408,17 +1404,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
                 })
                 .unwrap_or_else(|| {
-                    with_forced_trimmed_paths!(format!(
-                        "type mismatch resolving `{}`",
-                        self.resolve_vars_if_possible(predicate)
-                            .print(FmtPrinter::new_with_limit(
-                                self.tcx,
-                                Namespace::TypeNS,
-                                rustc_session::Limit(10),
-                            ))
-                            .unwrap()
-                            .into_buffer()
-                    ))
+                    let mut cx = FmtPrinter::new_with_limit(
+                        self.tcx,
+                        Namespace::TypeNS,
+                        rustc_session::Limit(10),
+                    );
+                    with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", {
+                        self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
+                        cx.into_buffer()
+                    }))
                 });
             let mut diag = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271, "{msg}");
 
@@ -1463,14 +1457,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                         ty.span,
                         with_forced_trimmed_paths!(Cow::from(format!(
                             "type mismatch resolving `{}`",
-                            self.resolve_vars_if_possible(predicate)
-                                .print(FmtPrinter::new_with_limit(
+                            {
+                                let mut cx = FmtPrinter::new_with_limit(
                                     self.tcx,
                                     Namespace::TypeNS,
                                     rustc_session::Limit(5),
-                                ))
-                                .unwrap()
-                                .into_buffer()
+                                );
+                                self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
+                                cx.into_buffer()
+                            }
                         ))),
                     )),
                     _ => None,