From 268decbac8bad298299702a0d17c9213f0a14f2e Mon Sep 17 00:00:00 2001
From: mark <markm@cs.wisc.edu>
Date: Tue, 5 May 2020 23:02:09 -0500
Subject: [PATCH 1/3] make all uses of ty::Error or ConstKind::Error delay a
 span bug

---
 .../debuginfo/type_names.rs                   |  2 +-
 .../infer/canonical/canonicalizer.rs          |  2 +-
 src/librustc_infer/infer/canonical/mod.rs     |  2 +-
 src/librustc_infer/infer/freshen.rs           |  4 +-
 src/librustc_infer/infer/mod.rs               |  3 +-
 src/librustc_infer/infer/resolve.rs           |  8 +--
 src/librustc_infer/infer/sub.rs               |  4 +-
 src/librustc_lint/types.rs                    |  2 +-
 src/librustc_middle/traits/query.rs           |  2 +-
 src/librustc_middle/ty/_match.rs              |  2 +-
 src/librustc_middle/ty/context.rs             | 49 +++++++++++++++--
 src/librustc_middle/ty/error.rs               |  4 +-
 src/librustc_middle/ty/fast_reject.rs         |  2 +-
 src/librustc_middle/ty/flags.rs               |  4 +-
 src/librustc_middle/ty/layout.rs              |  4 +-
 src/librustc_middle/ty/outlives.rs            |  2 +-
 src/librustc_middle/ty/print/mod.rs           |  2 +-
 src/librustc_middle/ty/print/obsolete.rs      |  2 +-
 src/librustc_middle/ty/print/pretty.rs        |  4 +-
 src/librustc_middle/ty/query/values.rs        |  4 +-
 src/librustc_middle/ty/relate.rs              |  4 +-
 src/librustc_middle/ty/structural_impls.rs    |  8 +--
 src/librustc_middle/ty/sty.rs                 | 33 ++++++++----
 src/librustc_middle/ty/util.rs                |  8 +--
 src/librustc_middle/ty/walk.rs                |  4 +-
 .../type_check/free_region_relations.rs       |  2 +-
 .../borrow_check/type_check/mod.rs            |  4 +-
 .../interpret/intrinsics/type_name.rs         |  2 +-
 src/librustc_mir/interpret/operand.rs         |  2 +-
 src/librustc_mir/interpret/validity.rs        |  2 +-
 src/librustc_mir_build/build/mod.rs           |  6 ++-
 src/librustc_mir_build/hair/cx/expr.rs        |  2 +-
 src/librustc_mir_build/hair/pattern/mod.rs    |  6 +--
 src/librustc_passes/intrinsicck.rs            |  4 +-
 src/librustc_privacy/lib.rs                   |  2 +-
 src/librustc_save_analysis/lib.rs             |  2 +-
 src/librustc_symbol_mangling/v0.rs            |  4 +-
 src/librustc_trait_selection/opaque_types.rs  |  6 +--
 .../traits/coherence.rs                       |  2 +-
 .../traits/error_reporting/mod.rs             |  2 +-
 .../traits/error_reporting/suggestions.rs     |  2 +-
 .../traits/project.rs                         | 20 +++----
 .../traits/query/dropck_outlives.rs           |  2 +-
 .../traits/select/mod.rs                      |  6 +--
 .../traits/structural_match.rs                |  2 +-
 src/librustc_trait_selection/traits/wf.rs     |  4 +-
 src/librustc_traits/chalk/lowering.rs         |  4 +-
 src/librustc_traits/dropck_outlives.rs        |  2 +-
 src/librustc_ty/ty.rs                         |  2 +-
 src/librustc_typeck/astconv.rs                | 22 ++++----
 src/librustc_typeck/check/_match.rs           |  2 +-
 src/librustc_typeck/check/callee.rs           |  2 +-
 src/librustc_typeck/check/cast.rs             |  2 +-
 src/librustc_typeck/check/closure.rs          |  4 +-
 src/librustc_typeck/check/coercion.rs         |  8 +--
 src/librustc_typeck/check/expr.rs             | 52 +++++++++----------
 src/librustc_typeck/check/method/confirm.rs   |  3 +-
 src/librustc_typeck/check/method/probe.rs     |  4 +-
 src/librustc_typeck/check/mod.rs              | 28 +++++-----
 src/librustc_typeck/check/op.rs               |  4 +-
 src/librustc_typeck/check/pat.rs              | 43 ++++++++-------
 src/librustc_typeck/check/upvar.rs            |  2 +-
 src/librustc_typeck/check/writeback.rs        |  9 ++--
 src/librustc_typeck/coherence/builtin.rs      |  2 +-
 .../coherence/inherent_impls.rs               |  2 +-
 src/librustc_typeck/collect.rs                | 15 +++---
 src/librustc_typeck/collect/type_of.rs        | 35 ++++++-------
 src/librustc_typeck/variance/constraints.rs   |  2 +-
 src/librustdoc/clean/mod.rs                   |  2 +-
 .../internal-lints/ty_tykind_usage.rs         |  2 +-
 .../internal-lints/ty_tykind_usage.stderr     |  2 +-
 71 files changed, 279 insertions(+), 225 deletions(-)

diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs
index 57a3d8b5edcaf..a64489c04c81d 100644
--- a/src/librustc_codegen_ssa/debuginfo/type_names.rs
+++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs
@@ -195,7 +195,7 @@ pub fn push_debuginfo_type_name<'tcx>(
                 tcx.def_key(def_id).disambiguated_data.disambiguator
             ));
         }
-        ty::Error
+        ty::Error(_)
         | ty::Infer(_)
         | ty::Placeholder(..)
         | ty::Projection(..)
diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs
index c2dae6ba4f83d..427cc55a428ae 100644
--- a/src/librustc_infer/infer/canonical/canonicalizer.rs
+++ b/src/librustc_infer/infer/canonical/canonicalizer.rs
@@ -403,7 +403,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
             | ty::Float(..)
             | ty::Adt(..)
             | ty::Str
-            | ty::Error
+            | ty::Error(_)
             | ty::Array(..)
             | ty::Slice(..)
             | ty::RawPtr(..)
diff --git a/src/librustc_infer/infer/canonical/mod.rs b/src/librustc_infer/infer/canonical/mod.rs
index 7310d2c3bdcf8..2b8c46f1de42d 100644
--- a/src/librustc_infer/infer/canonical/mod.rs
+++ b/src/librustc_infer/infer/canonical/mod.rs
@@ -154,7 +154,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 self.tcx
                     .mk_const(ty::Const {
                         val: ty::ConstKind::Placeholder(placeholder_mapped),
-                        ty: self.tcx.types.err, // FIXME(const_generics)
+                        ty: self.tcx.ty_error(), // FIXME(const_generics)
                     })
                     .into()
             }
diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs
index b4cfcb3a1c325..02bebe10ed04a 100644
--- a/src/librustc_infer/infer/freshen.rs
+++ b/src/librustc_infer/infer/freshen.rs
@@ -192,7 +192,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
             | ty::Float(..)
             | ty::Adt(..)
             | ty::Str
-            | ty::Error
+            | ty::Error(_)
             | ty::Array(..)
             | ty::Slice(..)
             | ty::RawPtr(..)
@@ -250,7 +250,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
             ty::ConstKind::Param(_)
             | ty::ConstKind::Value(_)
             | ty::ConstKind::Unevaluated(..)
-            | ty::ConstKind::Error => {}
+            | ty::ConstKind::Error(_) => {}
         }
 
         ct.super_fold_with(self)
diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs
index 92387f753f55e..91f4b3323f30e 100644
--- a/src/librustc_infer/infer/mod.rs
+++ b/src/librustc_infer/infer/mod.rs
@@ -1751,9 +1751,10 @@ impl<'tcx> TypeTrace<'tcx> {
     }
 
     pub fn dummy(tcx: TyCtxt<'tcx>) -> TypeTrace<'tcx> {
+        let err = tcx.ty_error();
         TypeTrace {
             cause: ObligationCause::dummy(),
-            values: Types(ExpectedFound { expected: tcx.types.err, found: tcx.types.err }),
+            values: Types(ExpectedFound { expected: err, found: err }),
         }
     }
 }
diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs
index e28cf49c7f253..df166d21a36c3 100644
--- a/src/librustc_infer/infer/resolve.rs
+++ b/src/librustc_infer/infer/resolve.rs
@@ -189,15 +189,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
             match t.kind {
                 ty::Infer(ty::TyVar(vid)) => {
                     self.err = Some(FixupError::UnresolvedTy(vid));
-                    self.tcx().types.err
+                    self.tcx().ty_error()
                 }
                 ty::Infer(ty::IntVar(vid)) => {
                     self.err = Some(FixupError::UnresolvedIntTy(vid));
-                    self.tcx().types.err
+                    self.tcx().ty_error()
                 }
                 ty::Infer(ty::FloatVar(vid)) => {
                     self.err = Some(FixupError::UnresolvedFloatTy(vid));
-                    self.tcx().types.err
+                    self.tcx().ty_error()
                 }
                 ty::Infer(_) => {
                     bug!("Unexpected type in full type resolver: {:?}", t);
@@ -228,7 +228,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
             match c.val {
                 ty::ConstKind::Infer(InferConst::Var(vid)) => {
                     self.err = Some(FixupError::UnresolvedConst(vid));
-                    return self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: c.ty });
+                    return self.tcx().const_error(c.ty);
                 }
                 ty::ConstKind::Infer(InferConst::Fresh(_)) => {
                     bug!("Unexpected const in full const resolver: {:?}", c);
diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs
index b51af19883fdd..90962d210b5b4 100644
--- a/src/librustc_infer/infer/sub.rs
+++ b/src/librustc_infer/infer/sub.rs
@@ -119,9 +119,9 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
                 Ok(a)
             }
 
-            (&ty::Error, _) | (_, &ty::Error) => {
+            (&ty::Error(_), _) | (_, &ty::Error(_)) => {
                 infcx.set_tainted_by_errors();
-                Ok(self.tcx().types.err)
+                Ok(self.tcx().ty_error())
             }
 
             _ => {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index a8ecfdd0f3d45..1dd6d837d4eaf 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -889,7 +889,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             ty::Param(..)
             | ty::Infer(..)
             | ty::Bound(..)
-            | ty::Error
+            | ty::Error(_)
             | ty::Closure(..)
             | ty::Generator(..)
             | ty::GeneratorWitness(..)
diff --git a/src/librustc_middle/traits/query.rs b/src/librustc_middle/traits/query.rs
index e030125b5b15c..69696ac9e93c0 100644
--- a/src/librustc_middle/traits/query.rs
+++ b/src/librustc_middle/traits/query.rs
@@ -221,7 +221,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         | ty::Ref(..)
         | ty::Str
         | ty::Foreign(..)
-        | ty::Error => true,
+        | ty::Error(_) => true,
 
         // [T; N] and [T] have same properties as T.
         ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
diff --git a/src/librustc_middle/ty/_match.rs b/src/librustc_middle/ty/_match.rs
index 02abe868f3943..db9229ae3d214 100644
--- a/src/librustc_middle/ty/_match.rs
+++ b/src/librustc_middle/ty/_match.rs
@@ -79,7 +79,7 @@ impl TypeRelation<'tcx> for Match<'tcx> {
                 Err(TypeError::Sorts(relate::expected_found(self, &a, &b)))
             }
 
-            (&ty::Error, _) | (_, &ty::Error) => Ok(self.tcx().types.err),
+            (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(self.tcx().ty_error()),
 
             _ => relate::super_relate_tys(self, a, b),
         }
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index d5be3508d2d80..4fe8173becff9 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -46,7 +46,7 @@ use rustc_session::lint::{Level, Lint};
 use rustc_session::Session;
 use rustc_span::source_map::MultiSpan;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
 
@@ -145,7 +145,6 @@ pub struct CommonTypes<'tcx> {
     pub f64: Ty<'tcx>,
     pub never: Ty<'tcx>,
     pub self_param: Ty<'tcx>,
-    pub err: Ty<'tcx>,
 
     /// Dummy type used for the `Self` of a `TraitRef` created for converting
     /// a trait object, and which gets removed in `ExistentialTraitRef`.
@@ -804,7 +803,6 @@ impl<'tcx> CommonTypes<'tcx> {
             bool: mk(Bool),
             char: mk(Char),
             never: mk(Never),
-            err: mk(Error),
             isize: mk(Int(ast::IntTy::Isize)),
             i8: mk(Int(ast::IntTy::I8)),
             i16: mk(Int(ast::IntTy::I16)),
@@ -1143,6 +1141,49 @@ impl<'tcx> TyCtxt<'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> {
+        self.err_with_message_and_location(
+            DUMMY_SP,
+            "TyKind::Error constructed but no error reported",
+            std::panic::Location::caller(),
+        )
+    }
+
+    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
+    /// ensure it gets used.
+    #[track_caller]
+    pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
+        self.err_with_message_and_location(span, msg, std::panic::Location::caller())
+    }
+
+    pub fn err_with_message_and_location<S: Into<MultiSpan>>(
+        self,
+        span: S,
+        msg: &str,
+        loc: &'static std::panic::Location<'static>,
+    ) -> Ty<'tcx> {
+        self.sess.delay_span_bug(span, &format!("{}: {}", loc, msg));
+        self.mk_ty(Error(super::sty::DelaySpanBugEmitted(())))
+    }
+
+    /// Like `err` but for constants.
+    #[track_caller]
+    pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
+        self.sess.delay_span_bug(
+            DUMMY_SP,
+            &format!(
+                "ty::ConstKind::Error constructed but no error reported. {}",
+                std::panic::Location::caller()
+            ),
+        );
+        self.mk_const(ty::Const {
+            val: ty::ConstKind::Error(super::sty::DelaySpanBugEmitted(())),
+            ty,
+        })
+    }
+
     pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
         let cname = self.crate_name(LOCAL_CRATE).as_str();
         self.sess.consider_optimizing(&cname, msg)
@@ -1846,7 +1887,7 @@ macro_rules! sty_debug_print {
                     let variant = match t.kind {
                         ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
                             ty::Float(..) | ty::Str | ty::Never => continue,
-                        ty::Error => /* unimportant */ continue,
+                        ty::Error(_) => /* unimportant */ continue,
                         $(ty::$variant(..) => &mut $variant,)*
                     };
                     let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs
index be3bf748225b9..6113359ca93a7 100644
--- a/src/librustc_middle/ty/error.rs
+++ b/src/librustc_middle/ty/error.rs
@@ -286,14 +286,14 @@ impl<'tcx> ty::TyS<'tcx> {
             ty::Projection(_) => "associated type".into(),
             ty::Param(p) => format!("type parameter `{}`", p).into(),
             ty::Opaque(..) => "opaque type".into(),
-            ty::Error => "type error".into(),
+            ty::Error(_) => "type error".into(),
         }
     }
 
     pub fn prefix_string(&self) -> Cow<'static, str> {
         match self.kind {
             ty::Infer(_)
-            | ty::Error
+            | ty::Error(_)
             | ty::Bool
             | ty::Char
             | ty::Int(_)
diff --git a/src/librustc_middle/ty/fast_reject.rs b/src/librustc_middle/ty/fast_reject.rs
index 16d8e37940763..b0fb179b18bdf 100644
--- a/src/librustc_middle/ty/fast_reject.rs
+++ b/src/librustc_middle/ty/fast_reject.rs
@@ -104,7 +104,7 @@ pub fn simplify_type(
         }
         ty::Opaque(def_id, _) => Some(OpaqueSimplifiedType(def_id)),
         ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)),
-        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) | ty::Error => None,
+        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
     }
 }
 
diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs
index edcb69c5e8cbd..bee42be8a5388 100644
--- a/src/librustc_middle/ty/flags.rs
+++ b/src/librustc_middle/ty/flags.rs
@@ -70,7 +70,7 @@ impl FlagComputation {
             | &ty::Str
             | &ty::Foreign(..) => {}
 
-            &ty::Error => self.add_flags(TypeFlags::HAS_ERROR),
+            &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
 
             &ty::Param(_) => {
                 self.add_flags(TypeFlags::HAS_TY_PARAM);
@@ -227,7 +227,7 @@ impl FlagComputation {
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Value(_) => {}
-            ty::ConstKind::Error => self.add_flags(TypeFlags::HAS_ERROR),
+            ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
         }
     }
 
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index f5bca90c2bd52..d58ebdc8dfc4d 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -1245,7 +1245,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                 bug!("Layout::compute: unexpected type `{}`", ty)
             }
 
-            ty::Param(_) | ty::Error => {
+            ty::Param(_) | ty::Error(_) => {
                 return Err(LayoutError::Unknown(ty));
             }
         })
@@ -2141,7 +2141,7 @@ where
             | ty::Opaque(..)
             | ty::Param(_)
             | ty::Infer(_)
-            | ty::Error => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
+            | ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
         })
     }
 
diff --git a/src/librustc_middle/ty/outlives.rs b/src/librustc_middle/ty/outlives.rs
index 1da042e161737..1a8693b8df711 100644
--- a/src/librustc_middle/ty/outlives.rs
+++ b/src/librustc_middle/ty/outlives.rs
@@ -171,7 +171,7 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo
             ty::Dynamic(..) |     // OutlivesObject, OutlivesFragment (*)
             ty::Placeholder(..) |
             ty::Bound(..) |
-            ty::Error => {
+            ty::Error(_) => {
                 // (*) Function pointers and trait objects are both binders.
                 // In the RFC, this means we would add the bound regions to
                 // the "bound regions list".  In our representation, no such
diff --git a/src/librustc_middle/ty/print/mod.rs b/src/librustc_middle/ty/print/mod.rs
index 69b36980bd73c..6c8f23c139f6e 100644
--- a/src/librustc_middle/ty/print/mod.rs
+++ b/src/librustc_middle/ty/print/mod.rs
@@ -298,7 +298,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Bound(..)
-        | ty::Error
+        | ty::Error(_)
         | ty::GeneratorWitness(..)
         | ty::Never
         | ty::Float(_) => None,
diff --git a/src/librustc_middle/ty/print/obsolete.rs b/src/librustc_middle/ty/print/obsolete.rs
index 7d9943ab07902..67b6433b61143 100644
--- a/src/librustc_middle/ty/print/obsolete.rs
+++ b/src/librustc_middle/ty/print/obsolete.rs
@@ -144,7 +144,7 @@ impl DefPathBasedNames<'tcx> {
                 let substs = substs.truncate_to(self.tcx, generics);
                 self.push_generic_params(substs, iter::empty(), output, debug);
             }
-            ty::Error
+            ty::Error(_)
             | ty::Bound(..)
             | ty::Infer(_)
             | ty::Placeholder(..)
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index d782dd07a6588..17203fcce5e59 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -518,7 +518,7 @@ pub trait PrettyPrinter<'tcx>:
                     p!(write("{}", infer_ty))
                 }
             }
-            ty::Error => p!(write("[type error]")),
+            ty::Error(_) => p!(write("[type error]")),
             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
                 ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
@@ -919,7 +919,7 @@ pub trait PrettyPrinter<'tcx>:
                 self.pretty_print_bound_var(debruijn, bound_var)?
             }
             ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
-            ty::ConstKind::Error => p!(write("[const error]")),
+            ty::ConstKind::Error(_) => p!(write("[const error]")),
         };
         Ok(self)
     }
diff --git a/src/librustc_middle/ty/query/values.rs b/src/librustc_middle/ty/query/values.rs
index b1f76ff6a03bd..0a0ff101b5203 100644
--- a/src/librustc_middle/ty/query/values.rs
+++ b/src/librustc_middle/ty/query/values.rs
@@ -17,7 +17,7 @@ impl<'tcx> Value<'tcx> for &'_ TyS<'_> {
     fn from_cycle_error(tcx: TyCtxt<'tcx>) -> 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.types.err) }
+        unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) }
     }
 }
 
@@ -33,7 +33,7 @@ impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> {
         // FIXME: Represent the above fact in the trait system somehow.
         unsafe {
             std::mem::transmute::<AdtSizedConstraint<'tcx>, AdtSizedConstraint<'_>>(
-                AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err])),
+                AdtSizedConstraint(tcx.intern_type_list(&[tcx.ty_error()])),
             )
         }
     }
diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs
index cddd7081ca375..14cddd11c438d 100644
--- a/src/librustc_middle/ty/relate.rs
+++ b/src/librustc_middle/ty/relate.rs
@@ -354,7 +354,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
             bug!("bound types encountered in super_relate_tys")
         }
 
-        (&ty::Error, _) | (_, &ty::Error) => Ok(tcx.types.err),
+        (&ty::Error(_), _) | (_, &ty::Error(_)) => Ok(tcx.ty_error()),
 
         (&ty::Never, _)
         | (&ty::Char, _)
@@ -524,7 +524,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
             bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
         }
 
-        (ty::ConstKind::Error, _) | (_, ty::ConstKind::Error) => Ok(ty::ConstKind::Error),
+        (ty::ConstKind::Error(d), _) | (_, ty::ConstKind::Error(d)) => Ok(ty::ConstKind::Error(d)),
 
         (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => {
             return Ok(a);
diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs
index f6f5dfd651612..f04d31601ea5b 100644
--- a/src/librustc_middle/ty/structural_impls.rs
+++ b/src/librustc_middle/ty/structural_impls.rs
@@ -911,7 +911,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             | ty::Int(_)
             | ty::Uint(_)
             | ty::Float(_)
-            | ty::Error
+            | ty::Error(_)
             | ty::Infer(_)
             | ty::Param(..)
             | ty::Bound(..)
@@ -952,7 +952,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             | ty::Int(_)
             | ty::Uint(_)
             | ty::Float(_)
-            | ty::Error
+            | ty::Error(_)
             | ty::Infer(_)
             | ty::Bound(..)
             | ty::Placeholder(..)
@@ -1051,7 +1051,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
             ty::ConstKind::Value(_)
             | ty::ConstKind::Bound(..)
             | ty::ConstKind::Placeholder(..)
-            | ty::ConstKind::Error => *self,
+            | ty::ConstKind::Error(_) => *self,
         }
     }
 
@@ -1063,7 +1063,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
             ty::ConstKind::Value(_)
             | ty::ConstKind::Bound(..)
             | ty::ConstKind::Placeholder(_)
-            | ty::ConstKind::Error => false,
+            | ty::ConstKind::Error(_) => false,
         }
     }
 }
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index fad96aa86cc0a..656c05b5520e8 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -203,9 +203,26 @@ pub enum TyKind<'tcx> {
 
     /// A placeholder for a type which could not be computed; this is
     /// propagated to avoid useless error messages.
-    Error,
+    Error(DelaySpanBugEmitted),
 }
 
+/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
+/// except through `tcx.err*()`.
+#[derive(
+    Copy,
+    Clone,
+    Debug,
+    Eq,
+    Hash,
+    PartialEq,
+    PartialOrd,
+    Ord,
+    RustcEncodable,
+    RustcDecodable,
+    HashStable
+)]
+pub struct DelaySpanBugEmitted(pub(super) ());
+
 // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(TyKind<'_>, 24);
@@ -1984,7 +2001,7 @@ impl<'tcx> TyS<'tcx> {
     #[inline]
     pub fn has_concrete_skeleton(&self) -> bool {
         match self.kind {
-            Param(_) | Infer(_) | Error => false,
+            Param(_) | Infer(_) | Error(_) => false,
             _ => true,
         }
     }
@@ -2016,7 +2033,7 @@ impl<'tcx> TyS<'tcx> {
         match self.kind {
             FnDef(def_id, substs) => tcx.fn_sig(def_id).subst(tcx, substs),
             FnPtr(f) => f,
-            Error => {
+            Error(_) => {
                 // ignore errors (#54954)
                 ty::Binder::dummy(FnSig::fake())
             }
@@ -2140,7 +2157,7 @@ impl<'tcx> TyS<'tcx> {
             // closure type is not yet known
             Bound(..) | Infer(_) => None,
 
-            Error => Some(ty::ClosureKind::Fn),
+            Error(_) => Some(ty::ClosureKind::Fn),
 
             _ => bug!("cannot convert type `{:?}` to a closure kind", self),
         }
@@ -2167,7 +2184,7 @@ impl<'tcx> TyS<'tcx> {
             | ty::Array(..)
             | ty::Closure(..)
             | ty::Never
-            | ty::Error => true,
+            | ty::Error(_) => true,
 
             ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => false,
 
@@ -2372,9 +2389,7 @@ impl<'tcx> Const<'tcx> {
                 // can leak through `val` into the const we return.
                 Ok(val) => Const::from_value(tcx, val, self.ty),
                 Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self,
-                Err(ErrorHandled::Reported(ErrorReported)) => {
-                    tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: self.ty })
-                }
+                Err(ErrorHandled::Reported(ErrorReported)) => tcx.const_error(self.ty),
             }
         } else {
             self
@@ -2434,7 +2449,7 @@ pub enum ConstKind<'tcx> {
 
     /// A placeholder for a const which could not be computed; this is
     /// propagated to avoid useless error messages.
-    Error,
+    Error(DelaySpanBugEmitted),
 }
 
 #[cfg(target_arch = "x86_64")]
diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs
index ff284b709c2cf..47110be53b252 100644
--- a/src/librustc_middle/ty/util.rs
+++ b/src/librustc_middle/ty/util.rs
@@ -176,7 +176,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if let ty::Adt(def, substs) = ty.kind {
             for field in def.all_fields() {
                 let field_ty = field.ty(self, substs);
-                if let Error = field_ty.kind {
+                if let Error(_) = field_ty.kind {
                     return true;
                 }
             }
@@ -731,7 +731,7 @@ impl<'tcx> ty::TyS<'tcx> {
             | ty::Ref(..)
             | ty::RawPtr(_)
             | ty::FnDef(..)
-            | ty::Error
+            | ty::Error(_)
             | ty::FnPtr(_) => true,
             ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_freeze),
             ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(),
@@ -826,7 +826,7 @@ impl<'tcx> ty::TyS<'tcx> {
             // called for known, fully-monomorphized types.
             Projection(_) | Opaque(..) | Param(_) | Bound(..) | Placeholder(_) | Infer(_) => false,
 
-            Foreign(_) | GeneratorWitness(..) | Error => false,
+            Foreign(_) | GeneratorWitness(..) | Error(_) => false,
         }
     }
 
@@ -1109,7 +1109,7 @@ pub fn needs_drop_components(
         // Foreign types can never have destructors.
         ty::Foreign(..) => Ok(SmallVec::new()),
 
-        ty::Dynamic(..) | ty::Error => Err(AlwaysRequiresDrop),
+        ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop),
 
         ty::Slice(ty) => needs_drop_components(ty, target_layout),
         ty::Array(elem_ty, size) => {
diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs
index bf988a4302633..d6f504fdb338b 100644
--- a/src/librustc_middle/ty/walk.rs
+++ b/src/librustc_middle/ty/walk.rs
@@ -108,7 +108,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
             | ty::Infer(_)
             | ty::Param(_)
             | ty::Never
-            | ty::Error
+            | ty::Error(_)
             | ty::Placeholder(..)
             | ty::Bound(..)
             | ty::Foreign(..) => {}
@@ -171,7 +171,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 | ty::ConstKind::Placeholder(_)
                 | ty::ConstKind::Bound(..)
                 | ty::ConstKind::Value(_)
-                | ty::ConstKind::Error => {}
+                | ty::ConstKind::Error(_) => {}
 
                 ty::ConstKind::Unevaluated(_, substs, _) => {
                     stack.extend(substs.iter().rev());
diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index 5707127340d87..beee31812563e 100644
--- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -264,7 +264,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                             .tcx
                             .sess
                             .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
-                        (self.infcx.tcx.types.err, None)
+                        (self.infcx.tcx.ty_error(), None)
                     });
                 let constraints2 = self.add_implied_bounds(ty);
                 normalized_inputs_and_output.push(ty);
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 168612f9beec0..011aeb4b8162b 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -498,7 +498,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
             if place_ty.variant_index.is_none() {
                 if place_ty.ty.references_error() {
                     assert!(self.errors_reported);
-                    return PlaceTy::from_ty(self.tcx().types.err);
+                    return PlaceTy::from_ty(self.tcx().ty_error());
                 }
             }
             place_ty = self.sanitize_projection(place_ty, elem, place, location)
@@ -725,7 +725,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
     fn error(&mut self) -> Ty<'tcx> {
         self.errors_reported = true;
-        self.tcx().types.err
+        self.tcx().ty_error()
     }
 
     fn field_ty(
diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs
index 71cca725982f5..379117f3b846a 100644
--- a/src/librustc_mir/interpret/intrinsics/type_name.rs
+++ b/src/librustc_mir/interpret/intrinsics/type_name.rs
@@ -50,7 +50,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             | ty::Dynamic(_, _) => self.pretty_print_type(ty),
 
             // Placeholders (all printed as `_` to uniformize them).
-            ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error => {
+            ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
                 write!(self, "_")?;
                 Ok(self)
             }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 38f5988d0eb3f..0cb878a49dcf1 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -527,7 +527,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Early-return cases.
         let val_val = match val.val {
             ty::ConstKind::Param(_) => throw_inval!(TooGeneric),
-            ty::ConstKind::Error => throw_inval!(TypeckError(ErrorReported)),
+            ty::ConstKind::Error(_) => throw_inval!(TypeckError(ErrorReported)),
             ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
                 let instance = self.resolve(def_id, substs)?;
                 // We use `const_eval` here and `const_eval_raw` elsewhere in mir interpretation.
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index 7e3b6c08e08f4..999f2fe76b4da 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -561,7 +561,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
             | ty::Generator(..) => Ok(false),
             // Some types only occur during typechecking, they have no layout.
             // We should not see them here and we could not check them anyway.
-            ty::Error
+            ty::Error(_)
             | ty::Infer(..)
             | ty::Placeholder(..)
             | ty::Bound(..)
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index 2efe93d057b9b..e2cf1bce733d6 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -687,7 +687,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t
     let tcx = hir.tcx();
     let owner_id = tcx.hir().body_owner(body_id);
     let span = tcx.hir().span(owner_id);
-    let ty = tcx.types.err;
+    let ty = tcx.ty_error();
     let num_params = match hir.body_owner_kind {
         hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len(),
         hir::BodyOwnerKind::Closure => {
@@ -909,7 +909,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         self.local_decls[local].mutability = mutability;
                         self.local_decls[local].source_info.scope = self.source_scope;
                         self.local_decls[local].local_info = if let Some(kind) = self_binding {
-                            Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind))))
+                            Some(box LocalInfo::User(ClearCrossCrate::Set(
+                                BindingForm::ImplicitSelf(*kind),
+                            )))
                         } else {
                             let binding_mode = ty::BindingMode::BindByValue(mutability);
                             Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index 703f6ef8dc41e..a1796c9433eac 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -478,7 +478,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                                     );
 
                                     // Not a real fn, but we're not reaching codegen anyways...
-                                    ty = cx.tcx.types.err;
+                                    ty = cx.tcx.ty_error();
                                     InlineAsmOperand::SymFn {
                                         expr: Expr {
                                             ty,
diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs
index e9aa7f597beb6..5c30b2a448c6d 100644
--- a/src/librustc_mir_build/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/hair/pattern/mod.rs
@@ -509,7 +509,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         let mut ty = self.tables.node_type(pat.hir_id);
 
-        if let ty::Error = ty.kind {
+        if let ty::Error(_) = ty.kind {
             // Avoid ICEs (e.g., #50577 and #50585).
             return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
         }
@@ -708,7 +708,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 if adt_def.is_enum() {
                     let substs = match ty.kind {
                         ty::Adt(_, substs) | ty::FnDef(_, substs) => substs,
-                        ty::Error => {
+                        ty::Error(_) => {
                             // Avoid ICE (#50585)
                             return PatKind::Wild;
                         }
@@ -1051,7 +1051,7 @@ crate fn compare_const_vals<'tcx>(
     let b_bits = b.try_eval_bits(tcx, param_env, ty);
 
     if let (Some(a), Some(b)) = (a_bits, b_bits) {
-        use ::rustc_apfloat::Float;
+        use rustc_apfloat::Float;
         return match ty.kind {
             ty::Float(ast::FloatTy::F32) => {
                 let l = ::rustc_apfloat::ieee::Single::from_bits(a);
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index e2bfcf18edb17..88fb78f85e423 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -150,7 +150,7 @@ impl ExprVisitor<'tcx> {
             _ => unreachable!(),
         };
         let asm_ty = match ty.kind {
-            ty::Never | ty::Error => return None,
+            ty::Never | ty::Error(_) => return None,
             ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8),
             ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16),
             ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32),
@@ -167,7 +167,7 @@ impl ExprVisitor<'tcx> {
                 let fields = &adt.non_enum_variant().fields;
                 let elem_ty = fields[0].ty(self.tcx, substs);
                 match elem_ty.kind {
-                    ty::Never | ty::Error => return None,
+                    ty::Never | ty::Error(_) => return None,
                     ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => {
                         Some(InlineAsmType::VecI8(fields.len() as u64))
                     }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 3c1b56a9ef40a..9e6e7ea962bc3 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -220,7 +220,7 @@ where
             | ty::Ref(..)
             | ty::FnPtr(..)
             | ty::Param(..)
-            | ty::Error
+            | ty::Error(_)
             | ty::GeneratorWitness(..) => {}
             ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => {
                 bug!("unexpected type: {:?}", ty)
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 12d2c8c7eb9a4..cae501e942b65 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -520,7 +520,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
     pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option<Data> {
         let hir_node = self.tcx.hir().expect_expr(expr.hir_id);
         let ty = self.tables.expr_ty_adjusted_opt(&hir_node);
-        if ty.is_none() || ty.unwrap().kind == ty::Error {
+        if ty.is_none() || matches!(ty.unwrap().kind, ty::Error(_)) {
             return None;
         }
         match expr.kind {
diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs
index 1a536b6a4294f..7d117b77cf5e5 100644
--- a/src/librustc_symbol_mangling/v0.rs
+++ b/src/librustc_symbol_mangling/v0.rs
@@ -345,7 +345,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
             ty::Never => "z",
 
             // Placeholders (should be demangled as `_`).
-            ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error => "p",
+            ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => "p",
 
             _ => "",
         };
@@ -367,7 +367,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
             ty::Tuple(_) if ty.is_unit() => unreachable!(),
 
             // Placeholders, also handled as part of basic types.
-            ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error => {
+            ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => {
                 unreachable!()
             }
 
diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs
index d53a0ec9ef884..adccdd0b2617a 100644
--- a/src/librustc_trait_selection/opaque_types.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -941,7 +941,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                             )
                             .emit();
 
-                        self.tcx().types.err
+                        self.tcx().ty_error()
                     }
                 }
             }
@@ -974,7 +974,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
                             )
                             .emit();
 
-                        self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty })
+                        self.tcx().const_error(ct.ty)
                     }
                 }
             }
@@ -1002,7 +1002,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
             tcx,
             ty_op: |ty| {
                 if ty.references_error() {
-                    return tcx.types.err;
+                    return tcx.ty_error();
                 } else if let ty::Opaque(def_id, substs) = ty.kind {
                     // Check that this is `impl Trait` type is
                     // declared by `parent_def_id` -- i.e., one whose
diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs
index 85c2f9246afcc..706cbf058b713 100644
--- a/src/librustc_trait_selection/traits/coherence.rs
+++ b/src/librustc_trait_selection/traits/coherence.rs
@@ -565,7 +565,7 @@ fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option<Ty<'_>>
             }
         }
 
-        ty::Error => None,
+        ty::Error(_) => None,
 
         ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => {
             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index d31e04cffd55f..e5a6c9a2e391a 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -1246,7 +1246,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                 ty::Generator(..) => Some(18),
                 ty::Foreign(..) => Some(19),
                 ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None,
             }
         }
 
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 8796cfb52165d..f4da25debd7cc 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -948,7 +948,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
              ty| {
                 let ty = self.resolve_vars_if_possible(&ty);
                 same &=
-                    ty.kind != ty::Error
+                    !matches!(ty.kind, ty::Error(_))
                         && last_ty.map_or(true, |last_ty| {
                             // FIXME: ideally we would use `can_coerce` here instead, but `typeck` comes
                             // *after* in the dependency graph.
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index 9492c3c340995..ed108613bfa23 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -784,7 +784,7 @@ struct Progress<'tcx> {
 
 impl<'tcx> Progress<'tcx> {
     fn error(tcx: TyCtxt<'tcx>) -> Self {
-        Progress { ty: tcx.types.err, obligations: vec![] }
+        Progress { ty: tcx.ty_error(), obligations: vec![] }
     }
 
     fn with_addl_obligations(mut self, mut obligations: Vec<PredicateObligation<'tcx>>) -> Self {
@@ -1085,7 +1085,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                     | ty::Bound(..)
                     | ty::Placeholder(..)
                     | ty::Infer(..)
-                    | ty::Error => false,
+                    | ty::Error(_) => false,
                 }
             }
             super::ImplSourceParam(..) => {
@@ -1440,8 +1440,8 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
                 obligation, poly_cache_entry, e,
             );
             debug!("confirm_param_env_candidate: {}", msg);
-            infcx.tcx.sess.delay_span_bug(obligation.cause.span, &msg);
-            Progress { ty: infcx.tcx.types.err, obligations: vec![] }
+            let err = infcx.tcx.ty_error_with_message(obligation.cause.span, &msg);
+            Progress { ty: err, obligations: vec![] }
         }
     }
 }
@@ -1460,7 +1460,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let param_env = obligation.param_env;
     let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) {
         Ok(assoc_ty) => assoc_ty,
-        Err(ErrorReported) => return Progress { ty: tcx.types.err, obligations: nested },
+        Err(ErrorReported) => return Progress { ty: tcx.ty_error(), obligations: nested },
     };
 
     if !assoc_ty.item.defaultness.has_value() {
@@ -1472,16 +1472,18 @@ fn confirm_impl_candidate<'cx, 'tcx>(
             "confirm_impl_candidate: no associated type {:?} for {:?}",
             assoc_ty.item.ident, obligation.predicate
         );
-        return Progress { ty: tcx.types.err, obligations: nested };
+        return Progress { ty: tcx.ty_error(), obligations: nested };
     }
     let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
     let substs =
         translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
     let ty = tcx.type_of(assoc_ty.item.def_id);
     if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
-        tcx.sess
-            .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
-        Progress { ty: tcx.types.err, obligations: nested }
+        let err = tcx.ty_error_with_message(
+            DUMMY_SP,
+            "impl item and trait item have different parameter counts",
+        );
+        Progress { ty: err, obligations: nested }
     } else {
         Progress { ty: ty.subst(tcx, substs), obligations: nested }
     }
diff --git a/src/librustc_trait_selection/traits/query/dropck_outlives.rs b/src/librustc_trait_selection/traits/query/dropck_outlives.rs
index 856a2111fc82c..d07c95270e004 100644
--- a/src/librustc_trait_selection/traits/query/dropck_outlives.rs
+++ b/src/librustc_trait_selection/traits/query/dropck_outlives.rs
@@ -101,7 +101,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
         | ty::Ref(..)
         | ty::Str
         | ty::Foreign(..)
-        | ty::Error => true,
+        | ty::Error(_) => true,
 
         // [T; N] and [T] have same properties as T.
         ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs
index 7ebf30f61c095..3fd566eab437e 100644
--- a/src/librustc_trait_selection/traits/select/mod.rs
+++ b/src/librustc_trait_selection/traits/select/mod.rs
@@ -1569,7 +1569,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Array(..)
             | ty::Closure(..)
             | ty::Never
-            | ty::Error => {
+            | ty::Error(_) => {
                 // safe for everything
                 Where(ty::Binder::dummy(Vec::new()))
             }
@@ -1613,7 +1613,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::Infer(ty::FloatVar(_))
             | ty::FnDef(..)
             | ty::FnPtr(_)
-            | ty::Error => Where(ty::Binder::dummy(Vec::new())),
+            | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())),
 
             ty::Uint(_)
             | ty::Int(_)
@@ -1690,7 +1690,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             | ty::FnDef(..)
             | ty::FnPtr(_)
             | ty::Str
-            | ty::Error
+            | ty::Error(_)
             | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
             | ty::Never
             | ty::Char => Vec::new(),
diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs
index c4deb639140ca..201edf27a655c 100644
--- a/src/librustc_trait_selection/traits/structural_match.rs
+++ b/src/librustc_trait_selection/traits/structural_match.rs
@@ -219,7 +219,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
             ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
                 bug!("unexpected type during structural-match checking: {:?}", ty);
             }
-            ty::Error => {
+            ty::Error(_) => {
                 self.tcx().sess.delay_span_bug(self.span, "ty::Error in structural-match check");
                 // We still want to check other types after encountering an error,
                 // as this may still emit relevant errors.
diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs
index 5024392a0f98d..e2e5f4e7c58bf 100644
--- a/src/librustc_trait_selection/traits/wf.rs
+++ b/src/librustc_trait_selection/traits/wf.rs
@@ -391,7 +391,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                                 ));
                             }
                         }
-                        ty::ConstKind::Error
+                        ty::ConstKind::Error(_)
                         | ty::ConstKind::Param(_)
                         | ty::ConstKind::Bound(..)
                         | ty::ConstKind::Placeholder(..) => {
@@ -411,7 +411,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 | ty::Int(..)
                 | ty::Uint(..)
                 | ty::Float(..)
-                | ty::Error
+                | ty::Error(_)
                 | ty::Str
                 | ty::GeneratorWitness(..)
                 | ty::Never
diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs
index 9530b07e47cdb..c9dd06e9f1ba2 100644
--- a/src/librustc_traits/chalk/lowering.rs
+++ b/src/librustc_traits/chalk/lowering.rs
@@ -168,7 +168,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
             ty::PredicateKind::WellFormed(arg) => match arg.unpack() {
                 GenericArgKind::Type(ty) => match ty.kind {
                     // These types are always WF.
-                    ty::Str | ty::Placeholder(..) | ty::Error | ty::Never => {
+                    ty::Str | ty::Placeholder(..) | ty::Error(_) | ty::Never => {
                         chalk_ir::GoalData::All(chalk_ir::Goals::new(interner))
                     }
 
@@ -376,7 +376,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
             })
             .intern(interner),
             Infer(_infer) => unimplemented!(),
-            Error => unimplemented!(),
+            Error(_) => unimplemented!(),
         }
     }
 }
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 11c48559bd683..6339f8288d54e 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -271,7 +271,7 @@ fn dtorck_constraint_for_ty<'tcx>(
             constraints.dtorck_types.push(ty);
         }
 
-        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => {
+        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
             return Err(NoSolution);
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index 99094246a6378..cf70a845af0aa 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -20,7 +20,7 @@ fn sized_constraint_for_ty<'tcx>(
         Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..)
         | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![],
 
-        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error | GeneratorWitness(..) => {
+        Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => {
             // these are never sized - return the target type
             vec![ty]
         }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 267f3d9f3ef6e..7cdcb2face823 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -819,7 +819,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
                     if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) {
                         inferred_params.push(ty.span);
-                        tcx.types.err.into()
+                        tcx.ty_error().into()
                     } else {
                         self.ast_ty_to_ty(&ty).into()
                     }
@@ -845,7 +845,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             // careful!
                             if default_needs_object_self(param) {
                                 missing_type_params.push(param.name.to_string());
-                                tcx.types.err.into()
+                                tcx.ty_error().into()
                             } else {
                                 // This is a default type parameter.
                                 self.normalize_ty(
@@ -865,7 +865,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             self.ty_infer(param, span).into()
                         } else {
                             // We've already errored above about the mismatch.
-                            tcx.types.err.into()
+                            tcx.ty_error().into()
                         }
                     }
                     GenericParamDefKind::Const => {
@@ -876,7 +876,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             self.ct_infer(ty, Some(param), span).into()
                         } else {
                             // We've already errored above about the mismatch.
-                            tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty }).into()
+                            tcx.const_error(ty).into()
                         }
                     }
                 }
@@ -1607,7 +1607,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 "at least one trait is required for an object type"
             )
             .emit();
-            return tcx.types.err;
+            return tcx.ty_error();
         }
 
         // Check that there are no gross object safety violations;
@@ -1624,7 +1624,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     &object_safety_violations[..],
                 )
                 .emit();
-                return tcx.types.err;
+                return tcx.ty_error();
             }
         }
 
@@ -2434,7 +2434,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 &path_str,
                 item_segment.ident.name,
             );
-            return tcx.types.err;
+            return tcx.ty_error();
         };
 
         debug!("qpath_to_ty: self_type={:?}", self_ty);
@@ -2792,7 +2792,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
             Res::Err => {
                 self.set_tainted_by_errors();
-                self.tcx().types.err
+                self.tcx().ty_error()
             }
             _ => span_bug!(span, "unexpected resolution: {:?}", path.res),
         }
@@ -2860,7 +2860,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 };
                 self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, res, segment, false)
                     .map(|(ty, _, _)| ty)
-                    .unwrap_or(tcx.types.err)
+                    .unwrap_or_else(|_| tcx.ty_error())
             }
             hir::TyKind::Array(ref ty, ref length) => {
                 let length_def_id = tcx.hir().local_def_id(length.hir_id);
@@ -2878,7 +2878,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .span_label(ast_ty.span, "reserved keyword")
                 .emit();
 
-                tcx.types.err
+                tcx.ty_error()
             }
             hir::TyKind::Infer => {
                 // Infer also appears as the type of arguments or return
@@ -2887,7 +2887,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.types.err,
+            hir::TyKind::Err => tcx.ty_error(),
         };
 
         debug!("ast_ty_to_ty: result_ty={:?}", result_ty);
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index fb139b5033b3b..9e23f5df3c6a8 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -105,7 +105,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && i != 0
                 && self.if_fallback_coercion(expr.span, &arms[0].body, &mut coercion)
             {
-                tcx.types.err
+                tcx.ty_error()
             } else {
                 // Only call this if this is not an `if` expr with an expected type and no `else`
                 // clause to avoid duplicated type errors. (#60254)
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index aa316105f7f11..13695be83a9da 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -383,7 +383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (
                     ty::Binder::bind(self.tcx.mk_fn_sig(
                         self.err_args(arg_exprs.len()).into_iter(),
-                        self.tcx.types.err,
+                        self.tcx.ty_error(),
                         false,
                         hir::Unsafety::Normal,
                         abi::Abi::Rust,
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 46d6706cbf429..c55f0cf1fcb68 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -135,7 +135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | ty::Generator(..)
             | ty::Adt(..)
             | ty::Never
-            | ty::Error => {
+            | ty::Error(_) => {
                 self.tcx
                     .sess
                     .delay_span_bug(span, &format!("`{:?}` should be sized but is not?", t));
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 206619588c71d..6d09ddc925ffe 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -700,7 +700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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.types.err
+            self.tcx.ty_error()
         });
 
         if let hir::FnRetTy::Return(ref output) = decl.output {
@@ -709,7 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let result = ty::Binder::bind(self.tcx.mk_fn_sig(
             supplied_arguments,
-            self.tcx.types.err,
+            self.tcx.ty_error(),
             decl.c_variadic,
             hir::Unsafety::Normal,
             Abi::RustCall,
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 15ec92568fb4d..dd3f292fb5684 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -162,7 +162,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         // Just ignore error types.
         if a.references_error() || b.references_error() {
-            return success(vec![], self.fcx.tcx.types.err, vec![]);
+            return success(vec![], self.fcx.tcx.ty_error(), vec![]);
         }
 
         if a.is_never() {
@@ -864,7 +864,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.types.err } else { target })
+        Ok(if expr_ty.references_error() { self.tcx.ty_error() } else { target })
     }
 
     /// Same as `try_coerce()`, but without side-effects.
@@ -1239,7 +1239,7 @@ 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.types.err);
+            self.final_ty = Some(fcx.tcx.ty_error());
             return;
         }
 
@@ -1396,7 +1396,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
 
                 err.emit_unless(assign_to_bool || unsized_return);
 
-                self.final_ty = Some(fcx.tcx.types.err);
+                self.final_ty = Some(fcx.tcx.ty_error());
             }
         }
     }
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index bc3ef73d851eb..69cfafc21648f 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     tcx.types.never
                 } else {
                     // There was an error; make type-check fail.
-                    tcx.types.err
+                    tcx.ty_error()
                 }
             }
             ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr),
@@ -284,7 +284,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::Field(ref base, field) => self.check_field(expr, needs, &base, field),
             ExprKind::Index(ref base, ref idx) => self.check_expr_index(base, idx, needs, expr),
             ExprKind::Yield(ref value, ref src) => self.check_expr_yield(value, expr, src),
-            hir::ExprKind::Err => tcx.types.err,
+            hir::ExprKind::Err => tcx.ty_error(),
         }
     }
 
@@ -360,7 +360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp, None);
                         }
                         err.emit();
-                        oprnd_t = tcx.types.err;
+                        oprnd_t = tcx.ty_error();
                     }
                 }
                 hir::UnOp::UnNot => {
@@ -410,7 +410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let tm = ty::TypeAndMut { ty, mutbl };
         match kind {
-            _ if tm.ty.references_error() => self.tcx.types.err,
+            _ if tm.ty.references_error() => self.tcx.ty_error(),
             hir::BorrowKind::Raw => {
                 self.check_named_place_expr(oprnd);
                 self.tcx.mk_ptr(tm)
@@ -476,11 +476,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = match res {
             Res::Err => {
                 self.set_tainted_by_errors();
-                tcx.types.err
+                tcx.ty_error()
             }
             Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
                 report_unexpected_variant_res(tcx, res, expr.span);
-                tcx.types.err
+                tcx.ty_error()
             }
             _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
         };
@@ -560,11 +560,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Some(ctxt) => ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()),
                         None => {
                             // Avoid ICE when `break` is inside a closure (#65383).
-                            self.tcx.sess.delay_span_bug(
+                            return tcx.ty_error_with_message(
                                 expr.span,
                                 "break was outside loop, but no error was emitted",
                             );
-                            return tcx.types.err;
                         }
                     }
                 };
@@ -572,7 +571,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(tcx.types.err);
+                let coerce_to = opt_coerce_to.unwrap_or_else(|| tcx.ty_error());
 
                 // Recurse without `enclosing_breakables` borrowed.
                 e_ty = self.check_expr_with_hint(e, coerce_to);
@@ -592,11 +591,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(ctxt) => ctxt,
                 None => {
                     // Avoid ICE when `break` is inside a closure (#65383).
-                    self.tcx.sess.delay_span_bug(
+                    return tcx.ty_error_with_message(
                         expr.span,
                         "break was outside loop, but no error was emitted",
                     );
-                    return tcx.types.err;
                 }
             };
 
@@ -649,14 +647,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // this can only happen if the `break` was not
             // inside a loop at all, which is caught by the
             // loop-checking pass.
-            self.tcx
-                .sess
-                .delay_span_bug(expr.span, "break was outside loop, but no error was emitted");
+            let err = self.tcx.ty_error_with_message(
+                expr.span,
+                "break was outside loop, but no error was emitted",
+            );
 
             // We still need to assign a type to the inner expression to
             // prevent the ICE in #43162.
             if let Some(ref e) = expr_opt {
-                self.check_expr_with_hint(e, tcx.types.err);
+                self.check_expr_with_hint(e, err);
 
                 // ... except when we try to 'break rust;'.
                 // ICE this expression in particular (see #43162).
@@ -666,8 +665,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
             }
+
             // There was an error; make type-check fail.
-            tcx.types.err
+            err
         }
     }
 
@@ -803,7 +803,7 @@ 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.types.err
+            self.tcx.ty_error()
         } else {
             self.tcx.mk_unit()
         }
@@ -957,7 +957,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Eagerly check for some obvious errors.
         if t_expr.references_error() || t_cast.references_error() {
-            self.tcx.types.err
+            self.tcx.ty_error()
         } else {
             // Defer other checks until we're done type checking.
             let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
@@ -966,7 +966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     deferred_cast_checks.push(cast_check);
                     t_cast
                 }
-                Err(ErrorReported) => self.tcx.types.err,
+                Err(ErrorReported) => self.tcx.ty_error(),
             }
         }
     }
@@ -1041,7 +1041,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         if element_ty.references_error() {
-            return tcx.types.err;
+            return tcx.ty_error();
         }
 
         tcx.mk_ty(ty::Array(t, count))
@@ -1071,7 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         });
         let tuple = self.tcx.mk_tup(elt_ts_iter);
         if tuple.references_error() {
-            self.tcx.types.err
+            self.tcx.ty_error()
         } else {
             self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
             tuple
@@ -1092,7 +1092,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             variant_ty
         } else {
             self.check_struct_fields_on_error(fields, base_expr);
-            return self.tcx.types.err;
+            return self.tcx.ty_error();
         };
 
         let path_span = match *qpath {
@@ -1233,7 +1233,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span);
                 }
 
-                tcx.types.err
+                tcx.ty_error()
             };
 
             // Make sure to give a type to the field even if there's
@@ -1519,7 +1519,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .emit();
         }
 
-        self.tcx().types.err
+        self.tcx().ty_error()
     }
 
     fn ban_nonexisting_field(
@@ -1775,7 +1775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                     err.emit();
-                    self.tcx.types.err
+                    self.tcx.ty_error()
                 }
             }
         }
@@ -1887,7 +1887,7 @@ pub(super) fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
         ty::Char => "'a'",
         ty::Int(_) | ty::Uint(_) => "42",
         ty::Float(_) => "3.14159",
-        ty::Error | ty::Never => return None,
+        ty::Error(_) | ty::Never => return None,
         _ => "value",
     })
 }
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 007794ce1b7ff..8651c643cee87 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -141,11 +141,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         let (_, n) = match autoderef.nth(pick.autoderefs) {
             Some(n) => n,
             None => {
-                self.tcx.sess.delay_span_bug(
+                return self.tcx.ty_error_with_message(
                     rustc_span::DUMMY_SP,
                     &format!("failed autoderef {}", pick.autoderefs),
                 );
-                return self.tcx.types.err;
             }
         };
         assert_eq!(n, pick.autoderefs);
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 37652330108c9..93bcd5cf29149 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -400,7 +400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .probe_instantiate_query_response(span, &orig_values, ty)
                     .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
                 let ty = self.structurally_resolved_type(span, ty.value);
-                assert_eq!(ty, self.tcx.types.err);
+                assert!(matches!(ty.kind, ty::Error(_)));
                 return Err(MethodError::NoMatch(NoMatchData::new(
                     Vec::new(),
                     Vec::new(),
@@ -478,7 +478,7 @@ fn method_autoderef_steps<'tcx>(
 
         let final_ty = autoderef.maybe_ambiguous_final_ty();
         let opt_bad_ty = match final_ty.kind {
-            ty::Infer(ty::TyVar(_)) | ty::Error => Some(MethodAutoderefBadTy {
+            ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
                 reached_raw_pointer,
                 ty: infcx
                     .make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a409e20953da1..96f1c6ff16104 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -967,8 +967,7 @@ fn diagnostic_only_typeck_tables_of<'tcx>(
 ) -> &ty::TypeckTables<'tcx> {
     let fallback = move || {
         let span = tcx.hir().span(tcx.hir().as_local_hir_id(def_id));
-        tcx.sess.delay_span_bug(span, "diagnostic only typeck table used");
-        tcx.types.err
+        tcx.ty_error_with_message(span, "diagnostic only typeck table used")
     };
     typeck_tables_of_with_fallback(tcx, def_id, fallback)
 }
@@ -3387,7 +3386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
         match self.tables.borrow().node_types().get(id) {
             Some(&t) => t,
-            None if self.is_tainted_by_errors() => self.tcx.types.err,
+            None if self.is_tainted_by_errors() => self.tcx.ty_error(),
             None => {
                 bug!(
                     "no type for node {}: {} in fcx {}",
@@ -3501,7 +3500,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         assert!(ty.is_ty_infer());
         let fallback = match self.type_is_unconstrained_numeric(ty) {
-            _ if self.is_tainted_by_errors() => self.tcx().types.err,
+            _ if self.is_tainted_by_errors() => self.tcx().ty_error(),
             UnconstrainedInt => self.tcx.types.i32,
             UnconstrainedFloat => self.tcx.types.f64,
             Neither if self.type_var_diverges(ty) => self.tcx.mk_diverging_default(),
@@ -3774,7 +3773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 tuple_arguments,
                 None,
             );
-            return self.tcx.types.err;
+            return self.tcx.ty_error();
         }
 
         let method = method.unwrap();
@@ -4161,7 +4160,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     fn err_args(&self, len: usize) -> Vec<Ty<'tcx>> {
-        vec![self.tcx.types.err; len]
+        vec![self.tcx.ty_error(); len]
     }
 
     /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
@@ -4305,7 +4304,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.types.err,
+            ast::LitKind::Err(_) => tcx.ty_error(),
         }
     }
 
@@ -4442,7 +4441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 };
                 let result =
                     AstConv::associated_path_to_ty(self, hir_id, path_span, ty, res, segment, true);
-                let ty = result.map(|(ty, _, _)| ty).unwrap_or(self.tcx().types.err);
+                let ty = result.map(|(ty, _, _)| ty).unwrap_or_else(|_| self.tcx().ty_error());
                 let result = result.map(|(_, kind, def_id)| (kind, def_id));
 
                 // Write back the new resolution.
@@ -4570,7 +4569,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ty: Ty<'tcx>,
     ) {
         if ty.references_error() {
-            // Override the types everywhere with `types.err` to avoid knock on errors.
+            // Override the types everywhere with `err()` to avoid knock on errors.
             self.write_ty(local.hir_id, ty);
             self.write_ty(local.pat.hir_id, ty);
             let local_ty = LocalTy { decl_ty, revealed_ty: ty };
@@ -4790,7 +4789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut ty = ctxt.coerce.unwrap().complete(self);
 
         if self.has_errors.get() || ty.references_error() {
-            ty = self.tcx.types.err
+            ty = self.tcx.ty_error()
         }
 
         self.write_ty(blk.hir_id, ty);
@@ -5378,7 +5377,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => return None,
         };
         let last_expr_ty = self.node_ty(last_expr.hir_id);
-        if matches!(last_expr_ty.kind, ty::Error)
+        if matches!(last_expr_ty.kind, ty::Error(_))
             || self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err()
         {
             return None;
@@ -5538,7 +5537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     err.emit();
 
-                    return (tcx.types.err, res);
+                    return (tcx.ty_error(), res);
                 }
             }
         } else {
@@ -5731,8 +5730,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .note("type must be known at this point")
                     .emit();
             }
-            self.demand_suptype(sp, self.tcx.types.err, ty);
-            self.tcx.types.err
+            let err = self.tcx.ty_error();
+            self.demand_suptype(sp, err, ty);
+            err
         }
     }
 
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index a3a27dc138be9..fe50870911647 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -497,7 +497,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         }
                     }
                 }
-                self.tcx.types.err
+                self.tcx.ty_error()
             }
         };
 
@@ -709,7 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     err.emit();
                 }
-                self.tcx.types.err
+                self.tcx.ty_error()
             }
         }
     }
diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs
index 8a10427260eee..7965c9c9ce12a 100644
--- a/src/librustc_typeck/check/pat.rs
+++ b/src/librustc_typeck/check/pat.rs
@@ -442,7 +442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // 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.types.err;
+            return self.tcx.ty_error();
         }
 
         // Now that we know the types can be unified we find the unified type
@@ -673,11 +673,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             variant_ty
         } else {
+            let err = self.tcx.ty_error();
             for field in fields {
                 let ti = TopInfo { parent_pat: Some(&pat), ..ti };
-                self.check_pat(&field.pat, self.tcx.types.err, def_bm, ti);
+                self.check_pat(&field.pat, err, def_bm, ti);
             }
-            return self.tcx.types.err;
+            return err;
         };
 
         // Type-check the path.
@@ -687,7 +688,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, etc, def_bm, ti) {
             pat_ty
         } else {
-            self.tcx.types.err
+            self.tcx.ty_error()
         }
     }
 
@@ -705,11 +706,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match res {
             Res::Err => {
                 self.set_tainted_by_errors();
-                return tcx.types.err;
+                return tcx.ty_error();
             }
             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => {
                 report_unexpected_variant_res(tcx, res, pat.span);
-                return tcx.types.err;
+                return tcx.ty_error();
             }
             Res::SelfCtor(..)
             | Res::Def(
@@ -788,7 +789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let on_error = || {
             let parent_pat = Some(pat);
             for pat in subpats {
-                self.check_pat(&pat, tcx.types.err, def_bm, TopInfo { parent_pat, ..ti });
+                self.check_pat(&pat, tcx.ty_error(), def_bm, TopInfo { parent_pat, ..ti });
             }
         };
         let report_unexpected_res = |res: Res| {
@@ -824,7 +825,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if res == Res::Err {
             self.set_tainted_by_errors();
             on_error();
-            return self.tcx.types.err;
+            return self.tcx.ty_error();
         }
 
         // Type-check the path.
@@ -832,18 +833,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
         if !pat_ty.is_fn() {
             report_unexpected_res(res);
-            return tcx.types.err;
+            return tcx.ty_error();
         }
 
         let variant = match res {
             Res::Err => {
                 self.set_tainted_by_errors();
                 on_error();
-                return tcx.types.err;
+                return tcx.ty_error();
             }
             Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
                 report_unexpected_res(res);
-                return tcx.types.err;
+                return tcx.ty_error();
             }
             Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
             _ => bug!("unexpected pattern resolution: {:?}", res),
@@ -880,7 +881,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Pattern has wrong number of fields.
             self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
             on_error();
-            return tcx.types.err;
+            return tcx.ty_error();
         }
         pat_ty
     }
@@ -1001,9 +1002,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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.types.err);
+            let element_tys_iter = (0..max_len).map(|_| tcx.ty_error());
             for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
-                self.check_pat(elem, &tcx.types.err, def_bm, ti);
+                self.check_pat(elem, &tcx.ty_error(), def_bm, ti);
             }
             tcx.mk_tup(element_tys_iter)
         } else {
@@ -1052,7 +1053,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Occupied(occupied) => {
                     self.error_field_already_bound(span, field.ident, *occupied.get());
                     no_field_errors = false;
-                    tcx.types.err
+                    tcx.ty_error()
                 }
                 Vacant(vacant) => {
                     vacant.insert(span);
@@ -1066,7 +1067,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .unwrap_or_else(|| {
                             inexistent_fields.push(field.ident);
                             no_field_errors = false;
-                            tcx.types.err
+                            tcx.ty_error()
                         })
                 }
             };
@@ -1281,7 +1282,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.demand_eqtype_pat(span, expected, box_ty, ti);
             (box_ty, inner_ty)
         } else {
-            (tcx.types.err, tcx.types.err)
+            let err = tcx.ty_error();
+            (err, err)
         };
         self.check_pat(&inner, inner_ty, def_bm, ti);
         box_ty
@@ -1327,7 +1329,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
         } else {
-            (tcx.types.err, tcx.types.err)
+            let err = tcx.ty_error();
+            (err, err)
         };
         self.check_pat(&inner, inner_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti });
         rptr_ty
@@ -1378,7 +1381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if !expected.references_error() {
                     self.error_expected_array_or_slice(span, expected);
                 }
-                let err = self.tcx.types.err;
+                let err = self.tcx.ty_error();
                 (err, Some(err), err)
             }
         };
@@ -1445,7 +1448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // If we get here, we must have emitted an error.
-        (Some(self.tcx.types.err), arr_ty)
+        (Some(self.tcx.ty_error()), arr_ty)
     }
 
     fn error_scrutinee_inconsistent_length(&self, span: Span, min_len: u64, size: u64) {
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 19a23e5a59478..8403c99f01bb5 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -91,7 +91,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let (closure_def_id, substs) = match ty.kind {
             ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
             ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
-            ty::Error => {
+            ty::Error(_) => {
                 // #51714: skip analysis when we have already encountered type errors
                 return;
             }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 159d3d7a538a6..ba806430f17fd 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -208,11 +208,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     // to access an unexistend index. We assume that more relevant errors will
                     // already have been emitted, so we only gate on this with an ICE if no
                     // error has been emitted. (#64638)
-                    self.tcx().sess.delay_span_bug(
+                    self.fcx.tcx.ty_error_with_message(
                         e.span,
                         &format!("bad index {:?} for base: `{:?}`", index, base),
-                    );
-                    self.fcx.tcx.types.err
+                    )
                 });
                 let index_ty = self.fcx.resolve_vars_if_possible(&index_ty);
 
@@ -681,7 +680,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 self.report_type_error(t);
                 self.replaced_with_error = true;
-                self.tcx().types.err
+                self.tcx().ty_error()
             }
         }
     }
@@ -698,7 +697,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 self.report_const_error(ct);
                 self.replaced_with_error = true;
-                self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty })
+                self.tcx().const_error(ct.ty)
             }
         }
     }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index c5dd314dc6558..8c6161a626473 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -50,7 +50,7 @@ impl<'tcx> Checker<'tcx> {
 
 fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     // Destructors only work on nominal types.
-    if let ty::Adt(..) | ty::Error = tcx.type_of(impl_did).kind {
+    if let ty::Adt(..) | ty::Error(_) = tcx.type_of(impl_did).kind {
         return;
     }
 
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index 653b7b8f2a5ba..93ee87f6c572e 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -296,7 +296,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
                     item.span,
                 );
             }
-            ty::Error => {}
+            ty::Error(_) => {}
             _ => {
                 struct_span_err!(
                     self.tcx.sess,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 1d59d749634ee..3bd75095bb602 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -307,8 +307,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
     }
 
     fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
-        self.tcx().sess.delay_span_bug(span, "bad placeholder type");
-        self.tcx().types.err
+        self.tcx().ty_error_with_message(span, "bad_placeholder_type")
     }
 
     fn ct_infer(
@@ -318,8 +317,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
         span: Span,
     ) -> &'tcx Const<'tcx> {
         bad_placeholder_type(self.tcx(), vec![span]).emit();
-
-        self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty })
+        self.tcx().const_error(ty)
     }
 
     fn projected_ty_from_poly_trait_ref(
@@ -419,7 +417,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
                 _ => {}
             }
             err.emit();
-            self.tcx().types.err
+            self.tcx().ty_error()
         }
     }
 
@@ -1465,7 +1463,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
                     visitor.visit_ty(ty);
                     let mut diag = bad_placeholder_type(tcx, visitor.0);
                     let ret_ty = fn_sig.output();
-                    if ret_ty != tcx.types.err {
+                    if ret_ty != tcx.ty_error() {
                         diag.span_suggestion(
                             ty.span,
                             "replace with the correct return type",
@@ -2004,12 +2002,11 @@ fn associated_item_predicates(
             // once they are handled by the trait system.
             ty::GenericParamDefKind::Type { .. } => {
                 unimplemented_error("type");
-                tcx.types.err.into()
+                tcx.ty_error().into()
             }
             ty::GenericParamDefKind::Const => {
                 unimplemented_error("const");
-                tcx.mk_const(ty::Const { val: ty::ConstKind::Error, ty: tcx.type_of(param.def_id) })
-                    .into()
+                tcx.const_error(tcx.type_of(param.def_id)).into()
             }
         }
     };
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index 549a20531e299..cf5f2ec69d8d8 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -127,7 +127,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                                 // Some error in the
                                 // owner fn prevented us from populating
                                 // the `concrete_opaque_types` table.
-                                tcx.types.err
+                                tcx.ty_error()
                             } else {
                                 // We failed to resolve the opaque type or it
                                 // resolves to itself. Return the non-revealed
@@ -217,11 +217,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         })
                         | Node::TraitRef(&TraitRef { path, .. }) => &*path,
                         _ => {
-                            tcx.sess.delay_span_bug(
+                            return tcx.ty_error_with_message(
                                 DUMMY_SP,
                                 &format!("unexpected const parent path {:?}", parent_node),
                             );
-                            return tcx.types.err;
                         }
                     };
 
@@ -254,14 +253,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         }
                         Res::Def(_, def_id) => tcx.generics_of(def_id),
                         res => {
-                            tcx.sess.delay_span_bug(
+                            return tcx.ty_error_with_message(
                                 DUMMY_SP,
                                 &format!(
                                     "unexpected anon const res {:?} in path: {:?}",
                                     res, path,
                                 ),
-                            );
-                            return tcx.types.err;
+                                );
                         }
                     };
 
@@ -283,24 +281,21 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     } else {
                         // This is no generic parameter associated with the arg. This is
                         // probably from an extra arg where one is not needed.
-                        tcx.sess.delay_span_bug(
+                        tcx.ty_error_with_message(
                             DUMMY_SP,
                             &format!(
-                                "missing generic parameter for `AnonConst`, parent: {:?}, res: {:?}",
+                                "missing generic parameter for `AnonConst`, \
+                                 parent: {:?}, res: {:?}",
                                 parent_node, res
                             ),
-                        );
-                        tcx.types.err
+                        )
                     }
                 }
 
-                x => {
-                    tcx.sess.delay_span_bug(
-                        DUMMY_SP,
-                        &format!("unexpected const parent in type_of_def_id(): {:?}", x),
-                    );
-                    tcx.types.err
-                }
+                x => tcx.ty_error_with_message(
+                    DUMMY_SP,
+                    &format!("unexpected const parent in type_of_def_id(): {:?}", x),
+                ),
             }
         }
 
@@ -568,7 +563,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
         None => {
             let span = tcx.def_span(def_id);
             tcx.sess.span_err(span, "could not find defining uses");
-            tcx.types.err
+            tcx.ty_error()
         }
     }
 }
@@ -605,7 +600,7 @@ fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty
             if let Some(ErrorReported) = owner_tables.tainted_by_errors {
                 // Some error in the owner fn prevented us from populating the
                 // `concrete_opaque_types` table.
-                tcx.types.err
+                tcx.ty_error()
             } else {
                 // We failed to resolve the opaque type or it resolves to
                 // itself. Return the non-revealed type, which should result in
@@ -655,7 +650,7 @@ fn infer_placeholder_type(
         }
         None => {
             let mut diag = bad_placeholder_type(tcx, vec![span]);
-            if ty != tcx.types.err {
+            if !matches!(ty.kind, ty::Error(_)) {
                 diag.span_suggestion(
                     span,
                     "replace `_` with the correct type",
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index eee0f764373a4..cae09267994e3 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -339,7 +339,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_sig(current, sig, variance);
             }
 
-            ty::Error => {
+            ty::Error(_) => {
                 // we encounter this when walking the trait references for object
                 // types, where we use Error as the Self type
             }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index adb2ae9a5d660..73fe87b05d477 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1717,7 +1717,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             ty::Placeholder(..) => panic!("Placeholder"),
             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
             ty::Infer(..) => panic!("Infer"),
-            ty::Error => panic!("Error"),
+            ty::Error(_) => panic!("Error"),
         }
     }
 }
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
index 27fe432e96ded..973294e985f7a 100644
--- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
@@ -37,7 +37,7 @@ fn main() {
         TyKind::Bound(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Placeholder(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
         TyKind::Infer(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
-        TyKind::Error => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Error(_) => (), //~ ERROR usage of `ty::TyKind::<kind>`
     }
 
     if let ty::Int(int_ty) = kind {}
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
index 0486c90a5a07a..d6e4c85c190d5 100644
--- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
@@ -169,7 +169,7 @@ LL |         TyKind::Infer(..) => (),
 error: usage of `ty::TyKind::<kind>`
   --> $DIR/ty_tykind_usage.rs:40:9
    |
-LL |         TyKind::Error => (),
+LL |         TyKind::Error(_) => (),
    |         ^^^^^^ help: try using ty::<kind> directly: `ty`
 
 error: usage of `ty::TyKind::<kind>`

From e855b90a8e159d27e014847ef50d9536aa1249d0 Mon Sep 17 00:00:00 2001
From: mark <markm@cs.wisc.edu>
Date: Tue, 26 May 2020 12:49:11 -0500
Subject: [PATCH 2/3] track caller for delay_span_bug

---
 src/librustc_errors/lib.rs        |  4 ++++
 src/librustc_middle/ty/context.rs | 26 ++++----------------------
 2 files changed, 8 insertions(+), 22 deletions(-)

diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 7261c638ce013..0c1418d3cad27 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -5,6 +5,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(crate_visibility_modifier)]
 #![feature(nll)]
+#![feature(track_caller)]
 
 pub use emitter::ColorConfig;
 
@@ -621,6 +622,7 @@ impl Handler {
         self.inner.borrow_mut().span_bug(span, msg)
     }
 
+    #[track_caller]
     pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) {
         self.inner.borrow_mut().delay_span_bug(span, msg)
     }
@@ -873,6 +875,7 @@ impl HandlerInner {
         self.emit_diagnostic(diag.set_span(sp));
     }
 
+    #[track_caller]
     fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
         // This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
         // incrementing `err_count` by one, so we need to +1 the comparing.
@@ -883,6 +886,7 @@ impl HandlerInner {
         }
         let mut diagnostic = Diagnostic::new(Level::Bug, msg);
         diagnostic.set_span(sp.into());
+        diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
         self.delay_as_bug(diagnostic)
     }
 
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index 4fe8173becff9..1715b545662b8 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1144,40 +1144,22 @@ impl<'tcx> TyCtxt<'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> {
-        self.err_with_message_and_location(
-            DUMMY_SP,
-            "TyKind::Error constructed but no error reported",
-            std::panic::Location::caller(),
-        )
+        self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
     }
 
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
     /// ensure it gets used.
     #[track_caller]
     pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
-        self.err_with_message_and_location(span, msg, std::panic::Location::caller())
-    }
-
-    pub fn err_with_message_and_location<S: Into<MultiSpan>>(
-        self,
-        span: S,
-        msg: &str,
-        loc: &'static std::panic::Location<'static>,
-    ) -> Ty<'tcx> {
-        self.sess.delay_span_bug(span, &format!("{}: {}", loc, msg));
+        self.sess.delay_span_bug(span, msg);
         self.mk_ty(Error(super::sty::DelaySpanBugEmitted(())))
     }
 
     /// Like `err` but for constants.
     #[track_caller]
     pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
-        self.sess.delay_span_bug(
-            DUMMY_SP,
-            &format!(
-                "ty::ConstKind::Error constructed but no error reported. {}",
-                std::panic::Location::caller()
-            ),
-        );
+        self.sess
+            .delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported.");
         self.mk_const(ty::Const {
             val: ty::ConstKind::Error(super::sty::DelaySpanBugEmitted(())),
             ty,

From cfdbbb5600c0a9f95dd662ce98f463d921e30cf0 Mon Sep 17 00:00:00 2001
From: Who? Me?! <mark-i-m@users.noreply.github.com>
Date: Tue, 16 Jun 2020 09:41:05 -0500
Subject: [PATCH 3/3] format derives

Co-authored-by: lzutao <taolzu@gmail.com>
---
 src/librustc_middle/ty/sty.rs | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 656c05b5520e8..cf11adb0285ac 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -208,19 +208,8 @@ pub enum TyKind<'tcx> {
 
 /// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
 /// except through `tcx.err*()`.
-#[derive(
-    Copy,
-    Clone,
-    Debug,
-    Eq,
-    Hash,
-    PartialEq,
-    PartialOrd,
-    Ord,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub struct DelaySpanBugEmitted(pub(super) ());
 
 // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.