about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-02-23 09:20:10 +0000
committerbors <bors@rust-lang.org>2023-02-23 09:20:10 +0000
commit07c993eba8b76eae497e98433ae075b00f01be10 (patch)
tree69748b387cb62fabe30006ca5e386aae4db38afb
parenteb909d81464900597b91f3bbf2a6bef10006c9ff (diff)
parent298ae8c721102c36243335653e57a7f94e08f94a (diff)
downloadrust-07c993eba8b76eae497e98433ae075b00f01be10.tar.gz
rust-07c993eba8b76eae497e98433ae075b00f01be10.zip
Auto merge of #108369 - compiler-errors:ty-error-more, r=BoxyUwU
Use `tcx.ty_error_with_guaranteed` in more places, rename variants

1. Use `ty_error_with_guaranteed` more so we don't delay so many span bugs
2. Rename `ty_error_with_guaranteed` to `ty_error`, `ty_error` to `ty_error_misc`. This is to incentivize using the former over the latter in cases where we already are witness to a `ErrorGuaranteed` token.

Second commit is just name replacement, so the first commit can be reviewed on its own with more scrutiny.
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs36
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs39
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs35
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs115
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs59
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs248
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs2
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs2
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs2
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs2
-rw-r--r--compiler/rustc_middle/src/values.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs2
33 files changed, 374 insertions, 313 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index ae1d89de80e..c550e37c63e 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,5 +1,6 @@
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::vec_map::VecMap;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::OpaqueTyOrigin;
 use rustc_infer::infer::TyCtxtInferExt as _;
@@ -149,13 +150,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // once we convert the generic parameters to those of the opaque type.
             if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
                 if prev.ty != ty {
-                    if !ty.references_error() {
+                    let guar = ty.error_reported().err().unwrap_or_else(|| {
                         prev.report_mismatch(
                             &OpaqueHiddenType { ty, span: concrete_type.span },
                             infcx.tcx,
-                        );
-                    }
-                    prev.ty = infcx.tcx.ty_error();
+                        )
+                    });
+                    prev.ty = infcx.tcx.ty_error(guar);
                 }
                 // Pick a better span if there is one.
                 // FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
@@ -247,20 +248,20 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         origin: OpaqueTyOrigin,
     ) -> Ty<'tcx> {
         if let Some(e) = self.tainted_by_errors() {
-            return self.tcx.ty_error_with_guaranteed(e);
+            return self.tcx.ty_error(e);
         }
 
         let definition_ty = instantiated_ty
             .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
             .ty;
 
-        if !check_opaque_type_parameter_valid(
+        if let Err(guar) = check_opaque_type_parameter_valid(
             self.tcx,
             opaque_type_key,
             origin,
             instantiated_ty.span,
         ) {
-            return self.tcx.ty_error();
+            return self.tcx.ty_error(guar);
         }
 
         // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
@@ -325,7 +326,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
             definition_ty
         } else {
             let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
-            self.tcx.ty_error_with_guaranteed(reported)
+            self.tcx.ty_error(reported)
         }
     }
 }
@@ -335,7 +336,7 @@ fn check_opaque_type_parameter_valid(
     opaque_type_key: OpaqueTypeKey<'_>,
     origin: OpaqueTyOrigin,
     span: Span,
-) -> bool {
+) -> Result<(), ErrorGuaranteed> {
     match origin {
         // No need to check return position impl trait (RPIT)
         // because for type and const parameters they are correct
@@ -358,7 +359,7 @@ fn check_opaque_type_parameter_valid(
         // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
         //
         // which would error here on all of the `'static` args.
-        OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
+        OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()),
         // Check these
         OpaqueTyOrigin::TyAlias => {}
     }
@@ -379,13 +380,13 @@ fn check_opaque_type_parameter_valid(
             // Prevent `fn foo() -> Foo<u32>` from being defining.
             let opaque_param = opaque_generics.param_at(i, tcx);
             let kind = opaque_param.kind.descr();
-            tcx.sess.emit_err(NonGenericOpaqueTypeParam {
+
+            return Err(tcx.sess.emit_err(NonGenericOpaqueTypeParam {
                 ty: arg,
                 kind,
                 span,
                 param_span: tcx.def_span(opaque_param.def_id),
-            });
-            return false;
+            }));
         }
     }
 
@@ -396,12 +397,13 @@ fn check_opaque_type_parameter_valid(
                 .into_iter()
                 .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
                 .collect();
-            tcx.sess
+            return Err(tcx
+                .sess
                 .struct_span_err(span, "non-defining opaque type use in defining scope")
                 .span_note(spans, &format!("{} used multiple times", descr))
-                .emit();
-            return false;
+                .emit());
         }
     }
-    true
+
+    Ok(())
 }
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 2dd24fe0340..e2f897a89e8 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -270,12 +270,13 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                 .and(type_op::normalize::Normalize::new(ty))
                 .fully_perform(self.infcx)
                 .unwrap_or_else(|_| {
-                    self.infcx
+                    let guar = self
+                        .infcx
                         .tcx
                         .sess
                         .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
                     TypeOpOutput {
-                        output: self.infcx.tcx.ty_error(),
+                        output: self.infcx.tcx.ty_error(guar),
                         constraints: None,
                         error_info: None,
                     }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index eb0fa1b6859..c4e7e1f8ffa 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -239,7 +239,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
                     decl.hidden_type.span,
                     &format!("could not resolve {:#?}", hidden_type.ty.kind()),
                 );
-                hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported);
+                hidden_type.ty = infcx.tcx.ty_error(reported);
             }
 
             (opaque_type_key, (hidden_type, decl.origin))
@@ -529,9 +529,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         for elem in place.projection.iter() {
             if place_ty.variant_index.is_none() {
-                if place_ty.ty.references_error() {
+                if let Err(guar) = place_ty.ty.error_reported() {
                     assert!(self.errors_reported);
-                    return PlaceTy::from_ty(self.tcx().ty_error());
+                    return PlaceTy::from_ty(self.tcx().ty_error(guar));
                 }
             }
             place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
@@ -763,7 +763,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
     fn error(&mut self) -> Ty<'tcx> {
         self.errors_reported = true;
-        self.tcx().ty_error()
+        self.tcx().ty_error_misc()
     }
 
     fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance {
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 274b264ee10..92dc02c8d3f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -429,7 +429,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     }
                     if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) {
                         self.inferred_params.push(ty.span);
-                        tcx.ty_error().into()
+                        tcx.ty_error_misc().into()
                     } else {
                         self.astconv.ast_ty_to_ty(ty).into()
                     }
@@ -502,14 +502,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 _ => false,
                             }) {
                                 // Avoid ICE #86756 when type error recovery goes awry.
-                                return tcx.ty_error().into();
+                                return tcx.ty_error_misc().into();
                             }
                             tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into()
                         } else if infer_args {
                             self.astconv.ty_infer(Some(param), self.span).into()
                         } else {
                             // We've already errored above about the mismatch.
-                            tcx.ty_error().into()
+                            tcx.ty_error_misc().into()
                         }
                     }
                     GenericParamDefKind::Const { has_default } => {
@@ -518,8 +518,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             .type_of(param.def_id)
                             .no_bound_vars()
                             .expect("const parameter types cannot be generic");
-                        if ty.references_error() {
-                            return tcx.const_error(ty).into();
+                        if let Err(guar) = ty.error_reported() {
+                            return tcx.const_error_with_guaranteed(ty, guar).into();
                         }
                         if !infer_args && has_default {
                             tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
@@ -1239,9 +1239,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         }
                         let reported = err.emit();
                         term = match def_kind {
-                            hir::def::DefKind::AssocTy => {
-                                tcx.ty_error_with_guaranteed(reported).into()
-                            }
+                            hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(),
                             hir::def::DefKind::AssocConst => tcx
                                 .const_error_with_guaranteed(
                                     tcx.type_of(assoc_item_def_id)
@@ -1397,7 +1395,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .map(|trait_ref| tcx.def_span(trait_ref));
             let reported =
                 tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
-            return tcx.ty_error_with_guaranteed(reported);
+            return tcx.ty_error(reported);
         }
 
         // Check that there are no gross object safety violations;
@@ -1414,7 +1412,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     &object_safety_violations,
                 )
                 .emit();
-                return tcx.ty_error_with_guaranteed(reported);
+                return tcx.ty_error(reported);
             }
         }
 
@@ -1523,10 +1521,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         if arg == dummy_self.into() {
                             let param = &generics.params[index];
                             missing_type_params.push(param.name);
-                            return tcx.ty_error().into();
+                            return tcx.ty_error_misc().into();
                         } else if arg.walk().any(|arg| arg == dummy_self.into()) {
                             references_self = true;
-                            return tcx.ty_error().into();
+                            return tcx.ty_error_misc().into();
                         }
                         arg
                     })
@@ -1579,7 +1577,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     false
                 });
                 if references_self {
-                    tcx.sess
+                    let guar = tcx
+                        .sess
                         .delay_span_bug(span, "trait object projection bounds reference `Self`");
                     let substs: Vec<_> = b
                         .projection_ty
@@ -1587,7 +1586,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         .iter()
                         .map(|arg| {
                             if arg.walk().any(|arg| arg == dummy_self.into()) {
-                                return tcx.ty_error().into();
+                                return tcx.ty_error(guar).into();
                             }
                             arg
                         })
@@ -2473,7 +2472,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 &[path_str],
                 item_segment.ident.name,
             );
-            return tcx.ty_error_with_guaranteed(reported)
+            return tcx.ty_error(reported)
         };
 
         debug!("qpath_to_ty: self_type={:?}", self_ty);
@@ -2820,7 +2819,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         let index = generics.param_def_id_to_index[&def_id.to_def_id()];
                         tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
                     }
-                    Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error_with_guaranteed(guar),
+                    Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error(guar),
                     arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
                 }
             }
@@ -2932,7 +2931,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     {
                         err.span_note(impl_.self_ty.span, "not a concrete type");
                     }
-                    tcx.ty_error_with_guaranteed(err.emit())
+                    tcx.ty_error(err.emit())
                 } else {
                     ty
                 }
@@ -2985,7 +2984,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     .sess
                     .delay_span_bug(path.span, "path with `Res::Err` but no error emitted");
                 self.set_tainted_by_errors(e);
-                self.tcx().ty_error_with_guaranteed(e)
+                self.tcx().ty_error(e)
             }
             _ => span_bug!(span, "unexpected resolution: {:?}", path.res),
         }
@@ -3064,7 +3063,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let ty = self.ast_ty_to_ty_inner(qself, false, true);
                 self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, qself, segment, false)
                     .map(|(ty, _, _)| ty)
-                    .unwrap_or_else(|_| tcx.ty_error())
+                    .unwrap_or_else(|guar| tcx.ty_error(guar))
             }
             &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => {
                 let def_id = tcx.require_lang_item(lang_item, Some(span));
@@ -3112,7 +3111,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // handled specially and will not descend into this routine.
                 self.ty_infer(None, ast_ty.span)
             }
-            hir::TyKind::Err => tcx.ty_error(),
+            hir::TyKind::Err => tcx.ty_error_misc(),
         };
 
         self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span);
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 50005582f7c..bdc9ff5cada 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -790,7 +790,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
                     return_span,
                     format!("could not fully resolve: {ty} => {err:?}"),
                 );
-                collected_tys.insert(def_id, tcx.ty_error_with_guaranteed(reported));
+                collected_tys.insert(def_id, tcx.ty_error(reported));
             }
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ed3d50bfafa..a2900037797 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -499,7 +499,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
                 }
                 _ => {}
             }
-            self.tcx().ty_error_with_guaranteed(err.emit())
+            self.tcx().ty_error(err.emit())
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index c013f1bdb31..50073d94ea5 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -319,8 +319,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>>
                 ItemKind::Impl(hir::Impl { self_ty, .. }) => {
                     match self_ty.find_self_aliases() {
                         spans if spans.len() > 0 => {
-                            tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: (), });
-                            tcx.ty_error()
+                            let guar = tcx.sess.emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () });
+                            tcx.ty_error(guar)
                         },
                         _ => icx.to_ty(*self_ty),
                     }
@@ -599,8 +599,9 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
             // // constant does not contain interior mutability.
             // ```
             let tables = self.tcx.typeck(item_def_id);
-            if let Some(_) = tables.tainted_by_errors {
-                self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error() });
+            if let Some(guar) = tables.tainted_by_errors {
+                self.found =
+                    Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
                 return;
             }
             let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
@@ -618,8 +619,8 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
                 debug!(?concrete_type, "found constraint");
                 if let Some(prev) = &mut self.found {
                     if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
-                        prev.report_mismatch(&concrete_type, self.tcx);
-                        prev.ty = self.tcx.ty_error();
+                        let guar = prev.report_mismatch(&concrete_type, self.tcx);
+                        prev.ty = self.tcx.ty_error(guar);
                     }
                 } else {
                     self.found = Some(concrete_type);
@@ -706,7 +707,7 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
                 _ => "item",
             },
         });
-        return tcx.ty_error_with_guaranteed(reported);
+        return tcx.ty_error(reported);
     };
 
     // Only check against typeck if we didn't already error
@@ -814,11 +815,11 @@ fn find_opaque_ty_constraints_for_rpit(
 
     concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
         let table = tcx.typeck(owner_def_id);
-        if let Some(_) = table.tainted_by_errors {
+        if let Some(guar) = table.tainted_by_errors {
             // Some error in the
             // owner fn prevented us from populating
             // the `concrete_opaque_types` table.
-            tcx.ty_error()
+            tcx.ty_error(guar)
         } else {
             table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
                 // We failed to resolve the opaque type or it
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 4ba78601ae8..fe2f6319c1a 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -438,7 +438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let err = self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
 
-                return self.tcx.ty_error_with_guaranteed(err);
+                return self.tcx.ty_error(err);
             }
         };
 
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 0eff3a2f9c2..6c700428323 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -3,6 +3,7 @@
 use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
 
 use hir::def::DefKind;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir_analysis::astconv::AstConv;
@@ -488,17 +489,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             };
         let expected_span =
             expected_sig.cause_span.unwrap_or_else(|| self.tcx.def_span(expr_def_id));
-        self.report_arg_count_mismatch(
-            expected_span,
-            closure_span,
-            expected_args,
-            found_args,
-            true,
-            closure_arg_span,
-        )
-        .emit();
-
-        let error_sig = self.error_sig_of_closure(decl);
+        let guar = self
+            .report_arg_count_mismatch(
+                expected_span,
+                closure_span,
+                expected_args,
+                found_args,
+                true,
+                closure_arg_span,
+            )
+            .emit();
+
+        let error_sig = self.error_sig_of_closure(decl, guar);
 
         self.closure_sigs(expr_def_id, body, error_sig)
     }
@@ -792,13 +794,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Converts the types that the user supplied, in case that doing
     /// so should yield an error, but returns back a signature where
     /// all parameters are of type `TyErr`.
-    fn error_sig_of_closure(&self, decl: &hir::FnDecl<'_>) -> ty::PolyFnSig<'tcx> {
+    fn error_sig_of_closure(
+        &self,
+        decl: &hir::FnDecl<'_>,
+        guar: ErrorGuaranteed,
+    ) -> ty::PolyFnSig<'tcx> {
         let astconv: &dyn AstConv<'_> = self;
+        let err_ty = self.tcx.ty_error(guar);
 
         let supplied_arguments = decl.inputs.iter().map(|a| {
             // Convert the types that the user supplied (if any), but ignore them.
             astconv.ast_ty_to_ty(a);
-            self.tcx.ty_error()
+            err_ty
         });
 
         if let hir::FnRetTy::Return(ref output) = decl.output {
@@ -807,7 +814,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let result = ty::Binder::dummy(self.tcx.mk_fn_sig(
             supplied_arguments,
-            self.tcx.ty_error(),
+            err_ty,
             decl.c_variadic,
             hir::Unsafety::Normal,
             Abi::RustCall,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 706eb3f8647..00b86890b33 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -170,14 +170,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         debug!("Coerce.tys({:?} => {:?})", a, b);
 
         // Just ignore error types.
-        if a.references_error() || b.references_error() {
+        if let Err(guar) = (a, b).error_reported() {
             // Best-effort try to unify these types -- we're already on the error path,
             // so this will have the side-effect of making sure we have no ambiguities
             // due to `[type error]` and `_` not coercing together.
             let _ = self.commit_if_ok(|_| {
                 self.at(&self.cause, self.param_env).define_opaque_types(true).eq(a, b)
             });
-            return success(vec![], self.fcx.tcx.ty_error(), vec![]);
+            return success(vec![], self.fcx.tcx.ty_error(guar), vec![]);
         }
 
         // Coercing from `!` to any type is allowed:
@@ -997,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let (adjustments, _) = self.register_infer_ok_obligations(ok);
         self.apply_adjustments(expr, adjustments);
-        Ok(if expr_ty.references_error() { self.tcx.ty_error() } else { target })
+        Ok(if let Err(guar) = expr_ty.error_reported() { self.tcx.ty_error(guar) } else { target })
     }
 
     /// Same as `try_coerce()`, but without side-effects.
@@ -1434,8 +1434,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
 
         // If we see any error types, just propagate that error
         // upwards.
-        if expression_ty.references_error() || self.merged_ty().references_error() {
-            self.final_ty = Some(fcx.tcx.ty_error());
+        if let Err(guar) = (expression_ty, self.merged_ty()).error_reported() {
+            self.final_ty = Some(fcx.tcx.ty_error(guar));
             return;
         }
 
@@ -1620,7 +1620,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
 
                 let reported = err.emit_unless(unsized_return);
 
-                self.final_ty = Some(fcx.tcx.ty_error_with_guaranteed(reported));
+                self.final_ty = Some(fcx.tcx.ty_error(reported));
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index e90c4a4cb53..6d54f6948c8 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -88,7 +88,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return if let [Adjustment { kind: Adjust::NeverToAny, target }] = &adjustments[..] {
                     target.to_owned()
                 } else {
-                    self.tcx().ty_error_with_guaranteed(reported)
+                    self.tcx().ty_error(reported)
                 };
             }
 
@@ -313,7 +313,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     tcx.types.never
                 } else {
                     // There was an error; make type-check fail.
-                    tcx.ty_error()
+                    tcx.ty_error_misc()
                 }
             }
             ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
@@ -354,7 +354,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::Field(base, field) => self.check_field(expr, &base, field, expected),
             ExprKind::Index(base, idx) => self.check_expr_index(base, idx, expr),
             ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src),
-            hir::ExprKind::Err => tcx.ty_error(),
+            hir::ExprKind::Err => tcx.ty_error_misc(),
         }
     }
 
@@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         {
                             err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
                         }
-                        oprnd_t = tcx.ty_error_with_guaranteed(err.emit());
+                        oprnd_t = tcx.ty_error(err.emit());
                     }
                 }
                 hir::UnOp::Not => {
@@ -452,7 +452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let tm = ty::TypeAndMut { ty, mutbl };
         match kind {
-            _ if tm.ty.references_error() => self.tcx.ty_error(),
+            _ if tm.ty.references_error() => self.tcx.ty_error_misc(),
             hir::BorrowKind::Raw => {
                 self.check_named_place_expr(oprnd);
                 self.tcx.mk_ptr(tm)
@@ -531,11 +531,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let e =
                     self.tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
                 self.set_tainted_by_errors(e);
-                tcx.ty_error_with_guaranteed(e)
+                tcx.ty_error(e)
             }
             Res::Def(DefKind::Variant, _) => {
                 let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value");
-                tcx.ty_error_with_guaranteed(e)
+                tcx.ty_error(e)
             }
             _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
         };
@@ -634,7 +634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // If the loop context is not a `loop { }`, then break with
                 // a value is illegal, and `opt_coerce_to` will be `None`.
                 // Just set expectation to error in that case.
-                let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error());
+                let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error_misc());
 
                 // Recurse without `enclosing_breakables` borrowed.
                 e_ty = self.check_expr_with_hint(e, coerce_to);
@@ -1033,7 +1033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let result_ty = coerce.complete(self);
-        if cond_ty.references_error() { self.tcx.ty_error() } else { result_ty }
+        if let Err(guar) = cond_ty.error_reported() { self.tcx.ty_error(guar) } else { result_ty }
     }
 
     /// Type check assignment expression `expr` of form `lhs = rhs`.
@@ -1109,7 +1109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // If the assignment expression itself is ill-formed, don't
             // bother emitting another error
             let reported = err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error());
-            return self.tcx.ty_error_with_guaranteed(reported);
+            return self.tcx.ty_error(reported);
         }
 
         let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
@@ -1155,8 +1155,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
 
-        if lhs_ty.references_error() || rhs_ty.references_error() {
-            self.tcx.ty_error()
+        if let Err(guar) = (lhs_ty, rhs_ty).error_reported() {
+            self.tcx.ty_error(guar)
         } else {
             self.tcx.mk_unit()
         }
@@ -1274,8 +1274,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let t_expr = self.resolve_vars_if_possible(t_expr);
 
         // Eagerly check for some obvious errors.
-        if t_expr.references_error() || t_cast.references_error() {
-            self.tcx.ty_error()
+        if let Err(guar) = (t_expr, t_cast).error_reported() {
+            self.tcx.ty_error(guar)
         } else {
             // Defer other checks until we're done type checking.
             let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
@@ -1296,7 +1296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     deferred_cast_checks.push(cast_check);
                     t_cast
                 }
-                Err(_) => self.tcx.ty_error(),
+                Err(guar) => self.tcx.ty_error(guar),
             }
         }
     }
@@ -1423,8 +1423,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
-        if element_ty.references_error() {
-            return tcx.ty_error();
+        if let Err(guar) = element_ty.error_reported() {
+            return tcx.ty_error(guar);
         }
 
         self.check_repeat_element_needs_copy_bound(element, count, element_ty);
@@ -1493,8 +1493,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => self.check_expr_with_expectation(&e, NoExpectation),
         });
         let tuple = self.tcx.mk_tup(elt_ts_iter);
-        if tuple.references_error() {
-            self.tcx.ty_error()
+        if let Err(guar) = tuple.error_reported() {
+            self.tcx.ty_error(guar)
         } else {
             self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
             tuple
@@ -1510,9 +1510,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base_expr: &'tcx Option<&'tcx hir::Expr<'tcx>>,
     ) -> Ty<'tcx> {
         // Find the relevant variant
-        let Some((variant, adt_ty)) = self.check_struct_path(qpath, expr.hir_id) else {
-            self.check_struct_fields_on_error(fields, base_expr);
-            return self.tcx.ty_error();
+        let (variant, adt_ty) = match self.check_struct_path(qpath, expr.hir_id) {
+            Ok(data) => data,
+            Err(guar) => {
+                self.check_struct_fields_on_error(fields, base_expr);
+                return self.tcx.ty_error(guar);
+            }
         };
 
         // Prohibit struct expressions when non-exhaustive flag is set.
@@ -1594,12 +1597,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.field_ty(field.span, v_field, substs)
             } else {
                 error_happened = true;
-                if let Some(prev_span) = seen_fields.get(&ident) {
+                let guar = if let Some(prev_span) = seen_fields.get(&ident) {
                     tcx.sess.emit_err(FieldMultiplySpecifiedInInitializer {
                         span: field.ident.span,
                         prev_span: *prev_span,
                         ident,
-                    });
+                    })
                 } else {
                     self.report_unknown_field(
                         adt_ty,
@@ -1608,10 +1611,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ast_fields,
                         adt.variant_descr(),
                         expr_span,
-                    );
-                }
+                    )
+                };
 
-                tcx.ty_error()
+                tcx.ty_error(guar)
             };
 
             // Make sure to give a type to the field even if there's
@@ -1994,14 +1997,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         skip_fields: &[hir::ExprField<'_>],
         kind_name: &str,
         expr_span: Span,
-    ) {
+    ) -> ErrorGuaranteed {
         if variant.is_recovered() {
-            self.set_tainted_by_errors(
-                self.tcx
-                    .sess
-                    .delay_span_bug(expr_span, "parser recovered but no error was emitted"),
-            );
-            return;
+            let guar = self
+                .tcx
+                .sess
+                .delay_span_bug(expr_span, "parser recovered but no error was emitted");
+            self.set_tainted_by_errors(guar);
+            return guar;
         }
         let mut err = self.err_ctxt().type_error_struct_with_diag(
             field.ident.span,
@@ -2115,7 +2118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 };
             }
         }
-        err.emit();
+        err.emit()
     }
 
     // Return a hint about the closest match in field names
@@ -2256,11 +2259,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // (#90483) apply adjustments to avoid ExprUseVisitor from
             // creating erroneous projection.
             self.apply_adjustments(base, adjustments);
-            self.ban_private_field_access(expr, base_ty, field, did, expected.only_has_type(self));
-            return self.tcx().ty_error();
+            let guar = self.ban_private_field_access(
+                expr,
+                base_ty,
+                field,
+                did,
+                expected.only_has_type(self),
+            );
+            return self.tcx().ty_error(guar);
         }
 
-        if field.name == kw::Empty {
+        let guar = if field.name == kw::Empty {
+            self.tcx.sess.delay_span_bug(field.span, "field name with no name")
         } else if self.method_exists(
             field,
             base_ty,
@@ -2268,9 +2278,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             true,
             expected.only_has_type(self),
         ) {
-            self.ban_take_value_of_method(expr, base_ty, field);
+            self.ban_take_value_of_method(expr, base_ty, field)
         } else if !base_ty.is_primitive_ty() {
-            self.ban_nonexisting_field(field, base, expr, base_ty);
+            self.ban_nonexisting_field(field, base, expr, base_ty)
         } else {
             let field_name = field.to_string();
             let mut err = type_error_struct!(
@@ -2339,10 +2349,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                 }
             }
-            err.emit();
-        }
+            err.emit()
+        };
 
-        self.tcx().ty_error()
+        self.tcx().ty_error(guar)
     }
 
     fn suggest_await_on_field_access(
@@ -2388,7 +2398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base: &'tcx hir::Expr<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
         base_ty: Ty<'tcx>,
-    ) {
+    ) -> ErrorGuaranteed {
         debug!(
             "ban_nonexisting_field: field={:?}, base={:?}, expr={:?}, base_ty={:?}",
             ident, base, expr, base_ty
@@ -2436,7 +2446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
         }
 
-        err.emit();
+        err.emit()
     }
 
     fn ban_private_field_access(
@@ -2446,7 +2456,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         field: Ident,
         base_did: DefId,
         return_ty: Option<Ty<'tcx>>,
-    ) {
+    ) -> ErrorGuaranteed {
         let struct_path = self.tcx().def_path_str(base_did);
         let kind_name = self.tcx().def_descr(base_did);
         let mut err = struct_span_err!(
@@ -2469,10 +2479,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 None,
             );
         }
-        err.emit();
+        err.emit()
     }
 
-    fn ban_take_value_of_method(&self, expr: &hir::Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident) {
+    fn ban_take_value_of_method(
+        &self,
+        expr: &hir::Expr<'tcx>,
+        expr_t: Ty<'tcx>,
+        field: Ident,
+    ) -> ErrorGuaranteed {
         let mut err = type_error_struct!(
             self.tcx().sess,
             field.span,
@@ -2544,7 +2559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.help("methods are immutable and cannot be assigned to");
         }
 
-        err.emit();
+        err.emit()
     }
 
     fn point_at_param_definition(&self, err: &mut Diagnostic, param: ty::ParamTy) {
@@ -2829,7 +2844,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     let reported = err.emit();
-                    self.tcx.ty_error_with_guaranteed(reported)
+                    self.tcx.ty_error(reported)
                 }
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 943dc9b9646..b7ae621c685 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -104,7 +104,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         // type, `?T` is not considered unsolved, but `?I` is. The
         // same is true for float variables.)
         let fallback = match ty.kind() {
-            _ if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
+            _ if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error(e),
             ty::Infer(ty::IntVar(_)) => self.tcx.types.i32,
             ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
             _ => match diverging_fallback.get(&ty) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 67de75301ad..60e55c7b0cf 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -451,7 +451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
         match self.typeck_results.borrow().node_types().get(id) {
             Some(&t) => t,
-            None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error_with_guaranteed(e),
+            None if let Some(e) = self.tainted_by_errors() => self.tcx.ty_error(e),
             None => {
                 bug!(
                     "no type for node {} in fcx {}",
@@ -465,7 +465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn node_ty_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
         match self.typeck_results.borrow().node_types().get(id) {
             Some(&t) => Some(t),
-            None if let Some(e) = self.tainted_by_errors() => Some(self.tcx.ty_error_with_guaranteed(e)),
+            None if let Some(e) = self.tainted_by_errors() => Some(self.tcx.ty_error(e)),
             None => None,
         }
     }
@@ -701,7 +701,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub(in super::super) fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {
-        vec![self.tcx.ty_error(); len]
+        let ty_error = self.tcx.ty_error_misc();
+        vec![ty_error; len]
     }
 
     /// Unifies the output type with the expected type early, for more coercions
@@ -1161,7 +1162,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     let reported = err.emit();
-                    return (tcx.ty_error_with_guaranteed(reported), res);
+                    return (tcx.ty_error(reported), res);
                 }
             }
         } else {
@@ -1417,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true)
                     .emit()
             });
-            let err = self.tcx.ty_error_with_guaranteed(e);
+            let err = self.tcx.ty_error(e);
             self.demand_suptype(sp, err, ty);
             err
         }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 57b6c78a160..99339153de2 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -10,7 +10,9 @@ use crate::{
 };
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
+use rustc_errors::{
+    pluralize, Applicability, Diagnostic, DiagnosticId, ErrorGuaranteed, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -72,7 +74,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
                 let ty = self.resolve_vars_if_possible(ty);
                 if ty.has_non_region_infer() {
-                    self.tcx.ty_error()
+                    self.tcx.ty_error_misc()
                 } else {
                     self.tcx.erase_regions(ty)
                 }
@@ -113,7 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 tuple_arguments,
                 method.ok().map(|method| method.def_id),
             );
-            return self.tcx.ty_error();
+            return self.tcx.ty_error_misc();
         }
 
         let method = method.unwrap();
@@ -533,7 +535,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .typeck_results
                     .borrow()
                     .expr_ty_adjusted_opt(*expr)
-                    .unwrap_or_else(|| tcx.ty_error());
+                    .unwrap_or_else(|| tcx.ty_error_misc());
                 (self.resolve_vars_if_possible(ty), normalize_span(expr.span))
             })
             .collect();
@@ -1286,7 +1288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 opt_ty.unwrap_or_else(|| self.next_float_var())
             }
             ast::LitKind::Bool(_) => tcx.types.bool,
-            ast::LitKind::Err => tcx.ty_error(),
+            ast::LitKind::Err => tcx.ty_error_misc(),
         }
     }
 
@@ -1294,15 +1296,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         qpath: &QPath<'_>,
         hir_id: hir::HirId,
-    ) -> Option<(&'tcx ty::VariantDef, Ty<'tcx>)> {
+    ) -> Result<(&'tcx ty::VariantDef, Ty<'tcx>), ErrorGuaranteed> {
         let path_span = qpath.span();
         let (def, ty) = self.finish_resolving_struct_path(qpath, path_span, hir_id);
         let variant = match def {
             Res::Err => {
-                self.set_tainted_by_errors(
-                    self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted"),
-                );
-                return None;
+                let guar =
+                    self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted");
+                self.set_tainted_by_errors(guar);
+                return Err(guar);
             }
             Res::Def(DefKind::Variant, _) => match ty.normalized.ty_adt_def() {
                 Some(adt) => {
@@ -1330,28 +1332,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Check bounds on type arguments used in the path.
             self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
 
-            Some((variant, ty.normalized))
+            Ok((variant, ty.normalized))
         } else {
-            match ty.normalized.kind() {
-                ty::Error(_) => {
+            Err(match *ty.normalized.kind() {
+                ty::Error(guar) => {
                     // E0071 might be caused by a spelling error, which will have
                     // already caused an error message and probably a suggestion
                     // elsewhere. Refrain from emitting more unhelpful errors here
                     // (issue #88844).
+                    guar
                 }
-                _ => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        path_span,
-                        E0071,
-                        "expected struct, variant or union type, found {}",
-                        ty.normalized.sort_string(self.tcx)
-                    )
-                    .span_label(path_span, "not a struct")
-                    .emit();
-                }
-            }
-            None
+                _ => struct_span_err!(
+                    self.tcx.sess,
+                    path_span,
+                    E0071,
+                    "expected struct, variant or union type, found {}",
+                    ty.normalized.sort_string(self.tcx)
+                )
+                .span_label(path_span, "not a struct")
+                .emit(),
+            })
         }
     }
 
@@ -1715,9 +1715,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         pat: &'tcx hir::Pat<'tcx>,
         ty: Ty<'tcx>,
     ) {
-        if ty.references_error() {
+        if let Err(guar) = ty.error_reported() {
             // Override the types everywhere with `err()` to avoid knock on errors.
-            let err = self.tcx.ty_error();
+            let err = self.tcx.ty_error(guar);
             self.write_ty(hir_id, err);
             self.write_ty(pat.hir_id, err);
             let local_ty = LocalTy { decl_ty: err, revealed_ty: err };
@@ -1746,7 +1746,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let result = self
                     .astconv()
                     .associated_path_to_ty(hir_id, path_span, ty.raw, qself, segment, true);
-                let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
+                let ty =
+                    result.map(|(ty, _, _)| ty).unwrap_or_else(|guar| self.tcx().ty_error(guar));
                 let ty = self.handle_raw_ty(path_span, ty);
                 let result = result.map(|(_, kind, def_id)| (kind, def_id));
 
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index bb9d93d5057..a4b325a9b79 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -297,7 +297,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 method.sig.output()
             }
             // error types are considered "builtin"
-            Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => self.tcx.ty_error(),
+            Err(_) if lhs_ty.references_error() || rhs_ty.references_error() => {
+                self.tcx.ty_error_misc()
+            }
             Err(errors) => {
                 let (_, trait_def_id) =
                     lang_item_for_op(self.tcx, Op::Binary(op, is_assign), op.span);
@@ -518,7 +520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
                 let reported = err.emit();
-                self.tcx.ty_error_with_guaranteed(reported)
+                self.tcx.ty_error(reported)
             }
         };
 
@@ -631,7 +633,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Err(errors) => {
                 let actual = self.resolve_vars_if_possible(operand_ty);
-                if !actual.references_error() {
+                let guar = actual.error_reported().err().unwrap_or_else(|| {
                     let mut err = struct_span_err!(
                         self.tcx.sess,
                         ex.span,
@@ -701,9 +703,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                         }
                     }
-                    err.emit();
-                }
-                self.tcx.ty_error()
+                    err.emit()
+                });
+                self.tcx.ty_error(guar)
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index b739324099d..9d95866fca4 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -475,8 +475,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
             // There exists a side that didn't meet our criteria that the end-point
             // be of a numeric or char type, as checked in `calc_side` above.
-            self.emit_err_pat_range(span, lhs, rhs);
-            return self.tcx.ty_error();
+            let guar = self.emit_err_pat_range(span, lhs, rhs);
+            return self.tcx.ty_error(guar);
         }
 
         // Unify each side with `expected`.
@@ -496,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         demand_eqtype(&mut rhs, lhs);
 
         if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
-            return self.tcx.ty_error();
+            return self.tcx.ty_error_misc();
         }
 
         // Find the unified type and check if it's of numeric or char type again.
@@ -511,8 +511,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if let Some((ref mut fail, _, _)) = rhs {
                 *fail = true;
             }
-            self.emit_err_pat_range(span, lhs, rhs);
-            return self.tcx.ty_error();
+            let guar = self.emit_err_pat_range(span, lhs, rhs);
+            return self.tcx.ty_error(guar);
         }
         ty
     }
@@ -528,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         lhs: Option<(bool, Ty<'tcx>, Span)>,
         rhs: Option<(bool, Ty<'tcx>, Span)>,
-    ) {
+    ) -> ErrorGuaranteed {
         let span = match (lhs, rhs) {
             (Some((true, ..)), Some((true, ..))) => span,
             (Some((true, _, sp)), _) => sp,
@@ -573,7 +573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     type between two end-points, you can use a guard.",
             );
         }
-        err.emit();
+        err.emit()
     }
 
     fn check_pat_ident(
@@ -807,29 +807,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat<'_>) -> bool {
+    pub fn check_dereferenceable(
+        &self,
+        span: Span,
+        expected: Ty<'tcx>,
+        inner: &Pat<'_>,
+    ) -> Result<(), ErrorGuaranteed> {
         if let PatKind::Binding(..) = inner.kind
             && let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
             && let ty::Dynamic(..) = mt.ty.kind()
         {
-                    // This is "x = SomeTrait" being reduced from
-                    // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
-                    let type_str = self.ty_to_string(expected);
-                    let mut err = struct_span_err!(
-                        self.tcx.sess,
-                        span,
-                        E0033,
-                        "type `{}` cannot be dereferenced",
-                        type_str
-                    );
-                    err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
-                    if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                        err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
-                    }
-                    err.emit();
-                    return false;
-                }
-        true
+            // This is "x = SomeTrait" being reduced from
+            // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
+            let type_str = self.ty_to_string(expected);
+            let mut err = struct_span_err!(
+                self.tcx.sess,
+                span,
+                E0033,
+                "type `{}` cannot be dereferenced",
+                type_str
+            );
+            err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
+            if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
+            }
+            return Err(err.emit());
+        }
+        Ok(())
     }
 
     fn check_pat_struct(
@@ -843,13 +847,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ti: TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         // Resolve the path and check the definition for errors.
-        let Some((variant, pat_ty)) = self.check_struct_path(qpath, pat.hir_id) else {
-            let err = self.tcx.ty_error();
-            for field in fields {
-                let ti = ti;
-                self.check_pat(field.pat, err, def_bm, ti);
+        let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
+            Ok(data) => data,
+            Err(guar) => {
+                let err = self.tcx.ty_error(guar);
+                for field in fields {
+                    let ti = ti;
+                    self.check_pat(field.pat, err, def_bm, ti);
+                }
+                return err;
             }
-            return err;
         };
 
         // Type-check the path.
@@ -859,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, def_bm, ti) {
             pat_ty
         } else {
-            self.tcx.ty_error()
+            self.tcx.ty_error_misc()
         }
     }
 
@@ -879,12 +886,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Res::Err => {
                 let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
                 self.set_tainted_by_errors(e);
-                return tcx.ty_error_with_guaranteed(e);
+                return tcx.ty_error(e);
             }
             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
                 let expected = "unit struct, unit variant or constant";
                 let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected);
-                return tcx.ty_error_with_guaranteed(e);
+                return tcx.ty_error(e);
             }
             Res::SelfCtor(..)
             | Res::Def(
@@ -1027,7 +1034,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         let on_error = |e| {
             for pat in subpats {
-                self.check_pat(pat, tcx.ty_error_with_guaranteed(e), def_bm, ti);
+                self.check_pat(pat, tcx.ty_error(e), def_bm, ti);
             }
         };
         let report_unexpected_res = |res: Res| {
@@ -1044,7 +1051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
             self.set_tainted_by_errors(e);
             on_error(e);
-            return tcx.ty_error_with_guaranteed(e);
+            return tcx.ty_error(e);
         }
 
         // Type-check the path.
@@ -1052,7 +1059,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
         if !pat_ty.is_fn() {
             let e = report_unexpected_res(res);
-            return tcx.ty_error_with_guaranteed(e);
+            return tcx.ty_error(e);
         }
 
         let variant = match res {
@@ -1060,11 +1067,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
                 self.set_tainted_by_errors(e);
                 on_error(e);
-                return tcx.ty_error_with_guaranteed(e);
+                return tcx.ty_error(e);
             }
             Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
                 let e = report_unexpected_res(res);
-                return tcx.ty_error_with_guaranteed(e);
+                return tcx.ty_error(e);
             }
             Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
             _ => bug!("unexpected pattern resolution: {:?}", res),
@@ -1105,7 +1112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Pattern has wrong number of fields.
             let e = self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
             on_error(e);
-            return tcx.ty_error_with_guaranteed(e);
+            return tcx.ty_error(e);
         }
         pat_ty
     }
@@ -1301,9 +1308,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let reported = err.emit();
             // Walk subpatterns with an expected type of `err` in this case to silence
             // further errors being emitted when using the bindings. #50333
-            let element_tys_iter = (0..max_len).map(|_| tcx.ty_error_with_guaranteed(reported));
+            let element_tys_iter = (0..max_len).map(|_| tcx.ty_error(reported));
             for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
-                self.check_pat(elem, tcx.ty_error_with_guaranteed(reported), def_bm, ti);
+                self.check_pat(elem, tcx.ty_error(reported), def_bm, ti);
             }
             tcx.mk_tup(element_tys_iter)
         } else {
@@ -1349,9 +1356,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let ident = tcx.adjust_ident(field.ident, variant.def_id);
             let field_ty = match used_fields.entry(ident) {
                 Occupied(occupied) => {
-                    self.error_field_already_bound(span, field.ident, *occupied.get());
                     no_field_errors = false;
-                    tcx.ty_error()
+                    let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
+                    tcx.ty_error(guar)
                 }
                 Vacant(vacant) => {
                     vacant.insert(span);
@@ -1365,7 +1372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .unwrap_or_else(|| {
                             inexistent_fields.push(field);
                             no_field_errors = false;
-                            tcx.ty_error()
+                            tcx.ty_error_misc()
                         })
                 }
             };
@@ -1536,7 +1543,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err.emit();
     }
 
-    fn error_field_already_bound(&self, span: Span, ident: Ident, other_field: Span) {
+    fn error_field_already_bound(
+        &self,
+        span: Span,
+        ident: Ident,
+        other_field: Span,
+    ) -> ErrorGuaranteed {
         struct_span_err!(
             self.tcx.sess,
             span,
@@ -1546,7 +1558,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )
         .span_label(span, format!("multiple uses of `{ident}` in pattern"))
         .span_label(other_field, format!("first use of `{ident}`"))
-        .emit();
+        .emit()
     }
 
     fn error_inexistent_fields(
@@ -1919,19 +1931,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ti: TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        let (box_ty, inner_ty) = if self.check_dereferenceable(span, expected, inner) {
-            // Here, `demand::subtype` is good enough, but I don't
-            // think any errors can be introduced by using `demand::eqtype`.
-            let inner_ty = self.next_ty_var(TypeVariableOrigin {
-                kind: TypeVariableOriginKind::TypeInference,
-                span: inner.span,
-            });
-            let box_ty = tcx.mk_box(inner_ty);
-            self.demand_eqtype_pat(span, expected, box_ty, ti);
-            (box_ty, inner_ty)
-        } else {
-            let err = tcx.ty_error();
-            (err, err)
+        let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
+            Ok(()) => {
+                // Here, `demand::subtype` is good enough, but I don't
+                // think any errors can be introduced by using `demand::eqtype`.
+                let inner_ty = self.next_ty_var(TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::TypeInference,
+                    span: inner.span,
+                });
+                let box_ty = tcx.mk_box(inner_ty);
+                self.demand_eqtype_pat(span, expected, box_ty, ti);
+                (box_ty, inner_ty)
+            }
+            Err(guar) => {
+                let err = tcx.ty_error(guar);
+                (err, err)
+            }
         };
         self.check_pat(inner, inner_ty, def_bm, ti);
         box_ty
@@ -1949,37 +1964,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let expected = self.shallow_resolve(expected);
-        let (ref_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, inner) {
-            // `demand::subtype` would be good enough, but using `eqtype` turns
-            // out to be equally general. See (note_1) for details.
-
-            // Take region, inner-type from expected type if we can,
-            // to avoid creating needless variables. This also helps with
-            // the bad interactions of the given hack detailed in (note_1).
-            debug!("check_pat_ref: expected={:?}", expected);
-            match *expected.kind() {
-                ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
-                _ => {
-                    let inner_ty = self.next_ty_var(TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::TypeInference,
-                        span: inner.span,
-                    });
-                    let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
-                    debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
-                    let err = self.demand_eqtype_pat_diag(pat.span, expected, ref_ty, ti);
-
-                    // Look for a case like `fn foo(&foo: u32)` and suggest
-                    // `fn foo(foo: &u32)`
-                    if let Some(mut err) = err {
-                        self.borrow_pat_suggestion(&mut err, pat);
-                        err.emit();
+        let (ref_ty, inner_ty) = match self.check_dereferenceable(pat.span, expected, inner) {
+            Ok(()) => {
+                // `demand::subtype` would be good enough, but using `eqtype` turns
+                // out to be equally general. See (note_1) for details.
+
+                // Take region, inner-type from expected type if we can,
+                // to avoid creating needless variables. This also helps with
+                // the bad interactions of the given hack detailed in (note_1).
+                debug!("check_pat_ref: expected={:?}", expected);
+                match *expected.kind() {
+                    ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty),
+                    _ => {
+                        let inner_ty = self.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::TypeInference,
+                            span: inner.span,
+                        });
+                        let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty);
+                        debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty);
+                        let err = self.demand_eqtype_pat_diag(pat.span, expected, ref_ty, ti);
+
+                        // Look for a case like `fn foo(&foo: u32)` and suggest
+                        // `fn foo(foo: &u32)`
+                        if let Some(mut err) = err {
+                            self.borrow_pat_suggestion(&mut err, pat);
+                            err.emit();
+                        }
+                        (ref_ty, inner_ty)
                     }
-                    (ref_ty, inner_ty)
                 }
             }
-        } else {
-            let err = tcx.ty_error();
-            (err, err)
+            Err(guar) => {
+                let err = tcx.ty_error(guar);
+                (err, err)
+            }
         };
         self.check_pat(inner, inner_ty, def_bm, ti);
         ref_ty
@@ -2027,10 +2045,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::Slice(element_ty) => (element_ty, Some(expected), expected),
             // The expected type must be an array or slice, but was neither, so error.
             _ => {
-                if !expected.references_error() {
-                    self.error_expected_array_or_slice(span, expected, ti);
-                }
-                let err = self.tcx.ty_error();
+                let guar = expected
+                    .error_reported()
+                    .err()
+                    .unwrap_or_else(|| self.error_expected_array_or_slice(span, expected, ti));
+                let err = self.tcx.ty_error(guar);
                 (err, Some(err), err)
             }
         };
@@ -2063,7 +2082,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         len: ty::Const<'tcx>,
         min_len: u64,
     ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
-        if let Some(len) = len.try_eval_target_usize(self.tcx, self.param_env) {
+        let guar = if let Some(len) = len.try_eval_target_usize(self.tcx, self.param_env) {
             // Now we know the length...
             if slice.is_none() {
                 // ...and since there is no variable-length pattern,
@@ -2073,7 +2092,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     return (None, arr_ty);
                 }
 
-                self.error_scrutinee_inconsistent_length(span, min_len, len);
+                self.error_scrutinee_inconsistent_length(span, min_len, len)
             } else if let Some(pat_len) = len.checked_sub(min_len) {
                 // The variable-length pattern was there,
                 // so it has an array type with the remaining elements left as its size...
@@ -2081,7 +2100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             } else {
                 // ...however, in this case, there were no remaining elements.
                 // That is, the slice pattern requires more than the array type offers.
-                self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len);
+                self.error_scrutinee_with_rest_inconsistent_length(span, min_len, len)
             }
         } else if slice.is_none() {
             // We have a pattern with a fixed length,
@@ -2093,14 +2112,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // We have a variable-length pattern and don't know the array length.
             // This happens if we have e.g.,
             // `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
-            self.error_scrutinee_unfixed_length(span);
-        }
+            self.error_scrutinee_unfixed_length(span)
+        };
 
         // If we get here, we must have emitted an error.
-        (Some(self.tcx.ty_error()), arr_ty)
+        (Some(self.tcx.ty_error(guar)), arr_ty)
     }
 
-    fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
+    fn error_scrutinee_inconsistent_length(
+        &self,
+        span: Span,
+        min_len: u64,
+        size: u64,
+    ) -> ErrorGuaranteed {
         struct_span_err!(
             self.tcx.sess,
             span,
@@ -2111,10 +2135,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             size,
         )
         .span_label(span, format!("expected {} element{}", size, pluralize!(size)))
-        .emit();
+        .emit()
     }
 
-    fn error_scrutinee_with_rest_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
+    fn error_scrutinee_with_rest_inconsistent_length(
+        &self,
+        span: Span,
+        min_len: u64,
+        size: u64,
+    ) -> ErrorGuaranteed {
         struct_span_err!(
             self.tcx.sess,
             span,
@@ -2128,20 +2157,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             span,
             format!("pattern cannot match array of {} element{}", size, pluralize!(size),),
         )
-        .emit();
+        .emit()
     }
 
-    fn error_scrutinee_unfixed_length(&self, span: Span) {
+    fn error_scrutinee_unfixed_length(&self, span: Span) -> ErrorGuaranteed {
         struct_span_err!(
             self.tcx.sess,
             span,
             E0730,
             "cannot pattern-match on an array without a fixed length",
         )
-        .emit();
+        .emit()
     }
 
-    fn error_expected_array_or_slice(&self, span: Span, expected_ty: Ty<'tcx>, ti: TopInfo<'tcx>) {
+    fn error_expected_array_or_slice(
+        &self,
+        span: Span,
+        expected_ty: Ty<'tcx>,
+        ti: TopInfo<'tcx>,
+    ) -> ErrorGuaranteed {
         let mut err = struct_span_err!(
             self.tcx.sess,
             span,
@@ -2185,7 +2219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
         err.span_label(span, format!("pattern cannot match with input type `{expected_ty}`"));
-        err.emit();
+        err.emit()
     }
 
     fn is_slice_or_array_or_vector(&self, ty: Ty<'tcx>) -> (bool, Ty<'tcx>) {
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index ae0df5aa8f1..8fcec3363c0 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -91,10 +91,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
         }
         let reported = err.emit();
-        Some((
-            self.tcx.ty_error_with_guaranteed(reported),
-            self.tcx.ty_error_with_guaranteed(reported),
-        ))
+        Some((self.tcx.ty_error(reported), self.tcx.ty_error(reported)))
     }
 
     /// To type-check `base_expr[index_expr]`, we progressively autoderef
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 0394567cb09..00348f3afdc 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -797,7 +797,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 let e = self.report_error(t);
                 self.replaced_with_error = Some(e);
-                self.interner().ty_error_with_guaranteed(e)
+                self.interner().ty_error(e)
             }
         }
     }
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 4c003789a4e..3e8c2052de8 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -126,7 +126,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
 
             (&ty::Error(e), _) | (_, &ty::Error(e)) => {
                 infcx.set_tainted_by_errors(e);
-                Ok(self.tcx().ty_error_with_guaranteed(e))
+                Ok(self.tcx().ty_error(e))
             }
 
             (
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index b9c5a4e0d0d..df9aa765dc1 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -89,9 +89,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
                 Err(TypeError::Sorts(relate::expected_found(self, a, b)))
             }
 
-            (&ty::Error(guar), _) | (_, &ty::Error(guar)) => {
-                Ok(self.tcx().ty_error_with_guaranteed(guar))
-            }
+            (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
 
             _ => relate::super_relate_tys(self, a, b),
         }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6bf54fa5417..796daa7646f 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -718,13 +718,13 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
     #[track_caller]
-    pub fn ty_error_with_guaranteed(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
+    pub fn ty_error(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
         self.mk_ty(Error(reported))
     }
 
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
     #[track_caller]
-    pub fn ty_error(self) -> Ty<'tcx> {
+    pub fn ty_error_misc(self) -> Ty<'tcx> {
         self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
     }
 
@@ -2458,7 +2458,7 @@ impl<'tcx> TyCtxt<'tcx> {
 impl<'tcx> TyCtxtAt<'tcx> {
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
     #[track_caller]
-    pub fn ty_error(self) -> Ty<'tcx> {
+    pub fn ty_error_misc(self) -> Ty<'tcx> {
         self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
     }
 
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 35c036fef2d..baef4ffeda7 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -101,7 +101,7 @@ impl GenericParamDef {
     ) -> ty::GenericArg<'tcx> {
         match &self.kind {
             ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
-            ty::GenericParamDefKind::Type { .. } => tcx.ty_error().into(),
+            ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
             ty::GenericParamDefKind::Const { .. } => {
                 tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
             }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 7dcc3ff4e7b..c8b1c7f76f4 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -35,6 +35,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
+use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
@@ -1358,7 +1359,7 @@ pub struct OpaqueHiddenType<'tcx> {
 }
 
 impl<'tcx> OpaqueHiddenType<'tcx> {
-    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) {
+    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
         // Found different concrete types for the opaque type.
         let sub_diag = if self.span == other.span {
             TypeMismatchReason::ConflictType { span: self.span }
@@ -1370,7 +1371,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
             other_ty: other.ty,
             other_span: other.span,
             sub: sub_diag,
-        });
+        })
     }
 
     #[instrument(level = "debug", skip(tcx), ret)]
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 195bd8a3818..6463b38c7e1 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -186,7 +186,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
                                 .emit();
                         }
 
-                        self.interner().ty_error()
+                        self.interner().ty_error_misc()
                     }
                 }
             }
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 3dfa5e953b5..735b87d08e3 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -412,7 +412,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
             bug!("bound types encountered in super_relate_tys")
         }
 
-        (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error_with_guaranteed(guar)),
+        (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
 
         (&ty::Never, _)
         | (&ty::Char, _)
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 21f3ef9267f..c4f526dbdc8 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -16,7 +16,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for Ty<'_> {
     fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo<DepKind>]) -> Self {
         // SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
         // FIXME: Represent the above fact in the trait system somehow.
-        unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) }
+        unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error_misc()) }
     }
 }
 
@@ -34,7 +34,7 @@ impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::SymbolName<'_> {
 
 impl<'tcx> Value<TyCtxt<'tcx>, DepKind> for ty::Binder<'_, ty::FnSig<'_>> {
     fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo<DepKind>]) -> Self {
-        let err = tcx.ty_error();
+        let err = tcx.ty_error_misc();
 
         let arity = if let Some(frame) = stack.get(0)
             && frame.query.dep_kind == DepKind::fn_sig
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 53bef1eb772..27536fcddd7 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -639,7 +639,7 @@ fn construct_error(
     let hir_id = tcx.hir().local_def_id_to_hir_id(def);
     let generator_kind = tcx.generator_kind(def);
 
-    let ty = tcx.ty_error();
+    let ty = tcx.ty_error(err);
     let num_params = match body_owner_kind {
         hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(),
         hir::BodyOwnerKind::Closure => {
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 08c24ce13a5..d4fdd545737 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -316,7 +316,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 | ty::Never
                 | ty::Foreign(..) => tcx.types.unit,
 
-                ty::Error(e) => tcx.ty_error_with_guaranteed(*e),
+                ty::Error(e) => tcx.ty_error(*e),
 
                 ty::Str | ty::Slice(_) => tcx.types.usize,
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index f4bbe415677..1272d942b14 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -3534,7 +3534,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         {
             if let hir::Expr { kind: hir::ExprKind::Block(..), .. } = expr {
                 let expr = expr.peel_blocks();
-                let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+                let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc());
                 let span = expr.span;
                 if Some(span) != err.span.primary_span() {
                     err.span_label(
@@ -3637,7 +3637,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let mut assocs = vec![];
         let mut expr = expr;
         let mut prev_ty = self.resolve_vars_if_possible(
-            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+            typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()),
         );
         while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
             // Point at every method call in the chain with the resulting type.
@@ -3648,7 +3648,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
             assocs.push(assocs_in_this_method);
             prev_ty = self.resolve_vars_if_possible(
-                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error()),
+                typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error_misc()),
             );
 
             if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
@@ -3666,7 +3666,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 if let hir::Node::Param(param) = parent {
                     // ...and it is a an fn argument.
                     let prev_ty = self.resolve_vars_if_possible(
-                        typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error()),
+                        typeck_results.node_type_opt(param.hir_id).unwrap_or(tcx.ty_error_misc()),
                     );
                     let assocs_in_this_method = self.probe_assoc_types_at_expr(&type_diffs, param.ty_span, prev_ty, param.hir_id, param_env);
                     if assocs_in_this_method.iter().any(|a| a.is_some()) {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 279725b16d8..14bba00b57e 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1213,8 +1213,8 @@ struct Progress<'tcx> {
 }
 
 impl<'tcx> Progress<'tcx> {
-    fn error(tcx: TyCtxt<'tcx>) -> Self {
-        Progress { term: tcx.ty_error().into(), obligations: vec![] }
+    fn error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
+        Progress { term: tcx.ty_error(guar).into(), obligations: vec![] }
     }
 
     fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
@@ -1240,8 +1240,8 @@ fn project<'cx, 'tcx>(
         )));
     }
 
-    if obligation.predicate.references_error() {
-        return Ok(Projected::Progress(Progress::error(selcx.tcx())));
+    if let Err(guar) = obligation.predicate.error_reported() {
+        return Ok(Projected::Progress(Progress::error(selcx.tcx(), guar)));
     }
 
     let mut candidates = ProjectionCandidateSet::None;
@@ -2097,8 +2097,9 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
 
     let param_env = obligation.param_env;
-    let Ok(assoc_ty) = specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) else {
-        return Progress { term: tcx.ty_error().into(), obligations: nested };
+    let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
+        Ok(assoc_ty) => assoc_ty,
+        Err(guar) => return Progress::error(tcx, guar),
     };
 
     if !assoc_ty.item.defaultness(tcx).has_value() {
@@ -2110,7 +2111,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
             "confirm_impl_candidate: no associated type {:?} for {:?}",
             assoc_ty.item.name, obligation.predicate
         );
-        return Progress { term: tcx.ty_error().into(), obligations: nested };
+        return Progress { term: tcx.ty_error_misc().into(), obligations: nested };
     }
     // If we're trying to normalize `<Vec<u32> as X>::A<S>` using
     //`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
@@ -2194,11 +2195,12 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     let mut obligations = data.nested;
 
     let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
-    let Ok(leaf_def) = specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) else {
-        return Progress { term: tcx.ty_error().into(), obligations };
+    let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
+        Ok(assoc_ty) => assoc_ty,
+        Err(guar) => return Progress::error(tcx, guar),
     };
     if !leaf_def.item.defaultness(tcx).has_value() {
-        return Progress { term: tcx.ty_error().into(), obligations };
+        return Progress { term: tcx.ty_error_misc().into(), obligations };
     }
 
     // Use the default `impl Trait` for the trait, e.g., for a default trait body
@@ -2269,7 +2271,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         obligation.recursion_depth + 1,
         tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id)
             .map_bound(|tys| {
-                tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id])
+                tys.map_or_else(|guar| tcx.ty_error(guar), |tys| tys[&obligation.predicate.def_id])
             })
             .subst(tcx, impl_fn_substs),
         &mut obligations,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e7e0f8838a4..e2fb954e31f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2443,7 +2443,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // the placeholder trait ref may fail due the Generalizer relation
                 // raising a CyclicalTy error due to a sub_root_var relation
                 // for a variable being generalized...
-                self.infcx.tcx.sess.delay_span_bug(
+                let guar = self.infcx.tcx.sess.delay_span_bug(
                     obligation.cause.span,
                     &format!(
                         "Impl {:?} was matchable against {:?} but now is not",
@@ -2451,7 +2451,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ),
                 );
                 let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
-                let err = self.tcx().ty_error();
+                let err = self.tcx().ty_error(guar);
                 let value = value.fold_with(&mut BottomUpFolder {
                     tcx: self.tcx(),
                     ty_op: |_| err,
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index fe80de5a069..50cd1d1c0e8 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -455,7 +455,7 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
                 interner.tcx.mk_alias_ty(assoc_ty.0, substitution.lower_into(interner)),
             ),
             TyKind::Foreign(def_id) => ty::Foreign(def_id.0),
-            TyKind::Error => return interner.tcx.ty_error(),
+            TyKind::Error => return interner.tcx.ty_error_misc(),
             TyKind::Alias(alias_ty) => match alias_ty {
                 chalk_ir::AliasTy::Projection(projection) => ty::Alias(
                     ty::Projection,
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index a47e7ce23e3..853c50f5246 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -98,7 +98,7 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
 fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
     if let Some(def_id) = def_id.as_local() {
         if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
-            return tcx.intern_type_list(&[tcx.ty_error()]);
+            return tcx.intern_type_list(&[tcx.ty_error_misc()]);
         }
     }
     let def = tcx.adt_def(def_id);